mirror of
https://github.com/boostorg/python.git
synced 2026-01-19 16:32:16 +00:00
Compare commits
112 Commits
boost-1.37
...
svn-branch
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
a51e081097 | ||
|
|
e14c702a40 | ||
|
|
d303ea16fc | ||
|
|
65114d8637 | ||
|
|
597dfc586b | ||
|
|
6a3085ad5d | ||
|
|
190d0d7ea6 | ||
|
|
8b915a15ff | ||
|
|
90c5c19220 | ||
|
|
cfe6f96f69 | ||
|
|
77907c5369 | ||
|
|
512b30c971 | ||
|
|
f005518686 | ||
|
|
274a219965 | ||
|
|
abc4abf84a | ||
|
|
94a3ced83a | ||
|
|
7eb0c678ee | ||
|
|
92460adce6 | ||
|
|
8cfd3fb2ef | ||
|
|
62ef542eaf | ||
|
|
5809078ba9 | ||
|
|
04e54d670c | ||
|
|
dd7c0a7f3d | ||
|
|
71f54cc920 | ||
|
|
9de994c0d1 | ||
|
|
e9caacc428 | ||
|
|
5070e84f70 | ||
|
|
fe23d9885f | ||
|
|
e7ee17b71b | ||
|
|
5edb63d01c | ||
|
|
f4b3aab7d4 | ||
|
|
6af67d1a4c | ||
|
|
16d975ba5c | ||
|
|
4fc5cafd40 | ||
|
|
1b5cd10f7c | ||
|
|
0f91872518 | ||
|
|
dc6b2979e4 | ||
|
|
50034140c4 | ||
|
|
08a6f35ec2 | ||
|
|
67236ffbad | ||
|
|
96ab7a80a4 | ||
|
|
d8c3ff199e | ||
|
|
0c4ebef579 | ||
|
|
8fe9d41b58 | ||
|
|
8a4590b2ef | ||
|
|
d67b040683 | ||
|
|
2db61657f2 | ||
|
|
6d2ee96ba3 | ||
|
|
a74c8e3da3 | ||
|
|
9f4d39d9fe | ||
|
|
31c19644ed | ||
|
|
600d444136 | ||
|
|
c3bd0fcbad | ||
|
|
991a7c198a | ||
|
|
9b67f0447d | ||
|
|
b714f6cc23 | ||
|
|
479a6ba4fc | ||
|
|
d78836b828 | ||
|
|
7a59131d37 | ||
|
|
5ab00bc9c8 | ||
|
|
94500ae36d | ||
|
|
5e5d34cc36 | ||
|
|
c6f2aa4ef2 | ||
|
|
c7fb2f7047 | ||
|
|
afedc1cd9a | ||
|
|
070e02d7d5 | ||
|
|
ccc56c2a4c | ||
|
|
e00a88ff49 | ||
|
|
e527bc860f | ||
|
|
921e306b9a | ||
|
|
bed1d26904 | ||
|
|
41a342f026 | ||
|
|
cee8e07046 | ||
|
|
0806e89964 | ||
|
|
f5421ca6b2 | ||
|
|
eea7697175 | ||
|
|
777ce7b561 | ||
|
|
864ece5539 | ||
|
|
2610eb9acb | ||
|
|
567a2c7b89 | ||
|
|
05070faf12 | ||
|
|
ad8069314d | ||
|
|
9366c48351 | ||
|
|
5a14319753 | ||
|
|
279a4f7888 | ||
|
|
d3418d494c | ||
|
|
c839427246 | ||
|
|
dd3a136b18 | ||
|
|
48696918de | ||
|
|
88be35ddc2 | ||
|
|
9ee0d36a1d | ||
|
|
f240e0bab6 | ||
|
|
4081605e4b | ||
|
|
f332ff2d89 | ||
|
|
ec77608840 | ||
|
|
f5a69a1dab | ||
|
|
a1e865061c | ||
|
|
596e92404a | ||
|
|
2640f5af94 | ||
|
|
0605e9fdcf | ||
|
|
cf68da0b19 | ||
|
|
d3c474b295 | ||
|
|
c9300e07c2 | ||
|
|
cab94a7bba | ||
|
|
caa9cb8268 | ||
|
|
66ac61450e | ||
|
|
59f81def56 | ||
|
|
92862028b7 | ||
|
|
b0ba7dfc50 | ||
|
|
fe3abeda9f | ||
|
|
3fdfb30e33 | ||
|
|
cdcf8633bb |
Binary file not shown.
@@ -22,11 +22,12 @@ if ! [ python.configured ] && ! ( --without-python in [ modules.peek : ARGV ] )
|
||||
}
|
||||
}
|
||||
|
||||
if [ python.configured ] {
|
||||
|
||||
project boost/python
|
||||
: source-location ../src
|
||||
;
|
||||
: source-location ../src
|
||||
;
|
||||
|
||||
rule cond ( test ? : yes * : no * ) { if $(test) { return $(yes) ; } else { return $(no) ; } }
|
||||
rule unless ( test ? : yes * : no * ) { if ! $(test) { return $(yes) ; } else { return $(no) ; } }
|
||||
|
||||
lib boost_python
|
||||
: # sources
|
||||
@@ -58,6 +59,7 @@ lib boost_python
|
||||
wrapper.cpp
|
||||
import.cpp
|
||||
exec.cpp
|
||||
object/function_doc_signature.cpp
|
||||
: # requirements
|
||||
<link>static:<define>BOOST_PYTHON_STATIC_LIB
|
||||
<define>BOOST_PYTHON_SOURCE
|
||||
@@ -74,19 +76,19 @@ lib boost_python
|
||||
# python_for_extensions is a target defined by Boost.Build to
|
||||
# provide the Python include paths, and on Windows, the Python
|
||||
# import library, as usage requirements.
|
||||
<library>/python//python_for_extensions
|
||||
|
||||
[ cond [ python.configured ] : <library>/python//python_for_extensions ]
|
||||
|
||||
# we prevent building when there is no python available
|
||||
# as it's not possible anyway, and to cause dependents to
|
||||
# fail to build
|
||||
[ unless [ python.configured ] : <build>no ]
|
||||
|
||||
<python-debugging>on:<define>BOOST_DEBUG_PYTHON
|
||||
|
||||
: # default build
|
||||
<link>shared
|
||||
: # usage requirements
|
||||
<link>static:<define>BOOST_PYTHON_STATIC_LIB
|
||||
<python-debugging>on:<define>BOOST_DEBUG_PYTHON
|
||||
;
|
||||
}
|
||||
else
|
||||
{
|
||||
ECHO "warning: Python location is not configured" ;
|
||||
ECHO "warning: the Boost.Python library won't be built" ;
|
||||
}
|
||||
|
||||
boost-install boost_python ;
|
||||
|
||||
File diff suppressed because it is too large
Load Diff
@@ -620,7 +620,7 @@ python and associated libraries are built by adding
|
||||
Windows, the debugging version of Python is generated by
|
||||
the "Win32 Debug" target of the Visual Studio project in the
|
||||
PCBuild subdirectory of a full Python source code distribution.
|
||||
You may also find</td></tr>
|
||||
</td></tr>
|
||||
</tbody>
|
||||
</table>
|
||||
</div>
|
||||
|
||||
@@ -678,4 +678,3 @@ __ http://www.python.org/doc/current/inst/index.html
|
||||
Windows, the debugging version of Python is generated by
|
||||
the "Win32 Debug" target of the Visual Studio project in the
|
||||
PCBuild subdirectory of a full Python source code distribution.
|
||||
You may also find
|
||||
@@ -32,7 +32,43 @@
|
||||
<hr>
|
||||
|
||||
<dl class="page-index">
|
||||
<dt>Current CVS</dt>
|
||||
<dt>Current SVN</dt>
|
||||
|
||||
<dd>
|
||||
<ul>
|
||||
<li>Pythonic signatures are now automatically appended to the
|
||||
docstrings.
|
||||
|
||||
<li>Use <a href="v2/docstring_options.html"
|
||||
><code>docstring_options.hpp</code></a> header
|
||||
control the content of docstrings.
|
||||
|
||||
<li>This new feature increases the size of the modules by about 14%.
|
||||
If this is not acceptable it can be turned off by defining the macro
|
||||
BOOST_PYTHON_NO_PY_SIGNATURES. Modules compiled with and without the macro
|
||||
defined are compatible.
|
||||
</li>
|
||||
<li> If BOOST_PYTHON_NO_PY_SIGNATURES is undefined, this version defines the
|
||||
macro BOOST_PYTHON_SUPPORTS_PY_SIGNATURES. This allows writing code that will compile
|
||||
with older version of Boost.Python (see <a href="v2/pytype_function.html#examples">here</a>).
|
||||
</li>
|
||||
<li>By defining BOOST_PYTHON_PY_SIGNATURES_PROPER_INIT_SELF_TYPE, and at a cost
|
||||
of another 14% size increase, proper pythonic type is generated for the "self"
|
||||
parameter of the __init__ methods.
|
||||
</li>
|
||||
|
||||
<li> To support this new feature changes were made to the
|
||||
<a href="v2/to_python_converter.html"><code>to_python_converter.hpp</code></a>,
|
||||
<a href="v2/default_call_policies.html"><code>default_call_policies</code></a>,
|
||||
<a href="v2/ResultConverter.html"><code>ResultConverter</code></a>,
|
||||
<a href="v2/CallPolicies.html"><code>CallPolicies</code></a> and some others.
|
||||
Efforts were made not to have interface breaking changes.
|
||||
</li>
|
||||
|
||||
</ul>
|
||||
</dd>
|
||||
|
||||
<dt>12 May 2007 - 1.34.0 release</dt>
|
||||
|
||||
<dd>
|
||||
<ul>
|
||||
|
||||
@@ -1,511 +0,0 @@
|
||||
/*=============================================================================
|
||||
Copyright (c) 2004 Joel de Guzman
|
||||
http://spirit.sourceforge.net/
|
||||
|
||||
Use, modification and distribution is subject to the Boost Software
|
||||
License, Version 1.0. (See accompanying file LICENSE_1_0.txt or copy at
|
||||
http://www.boost.org/LICENSE_1_0.txt)
|
||||
=============================================================================*/
|
||||
|
||||
/*=============================================================================
|
||||
Body defaults
|
||||
=============================================================================*/
|
||||
|
||||
body
|
||||
{
|
||||
margin: 1em;
|
||||
font-family: sans-serif;
|
||||
}
|
||||
|
||||
/*=============================================================================
|
||||
Paragraphs
|
||||
=============================================================================*/
|
||||
|
||||
p
|
||||
{
|
||||
text-align: left;
|
||||
font-size: 10pt;
|
||||
line-height: 1.15;
|
||||
}
|
||||
|
||||
/*=============================================================================
|
||||
Program listings
|
||||
=============================================================================*/
|
||||
|
||||
/* Code on paragraphs */
|
||||
p tt.computeroutput
|
||||
{
|
||||
font-size: 9pt;
|
||||
}
|
||||
|
||||
pre.synopsis
|
||||
{
|
||||
font-size: 90%;
|
||||
margin: 1pc 4% 0pc 4%;
|
||||
padding: 0.5pc 0.5pc 0.5pc 0.5pc;
|
||||
}
|
||||
|
||||
.programlisting,
|
||||
.screen
|
||||
{
|
||||
font-size: 9pt;
|
||||
display: block;
|
||||
margin: 1pc 4% 0pc 4%;
|
||||
padding: 0.5pc 0.5pc 0.5pc 0.5pc;
|
||||
}
|
||||
|
||||
/* Program listings in tables don't get borders */
|
||||
td .programlisting,
|
||||
td .screen
|
||||
{
|
||||
margin: 0pc 0pc 0pc 0pc;
|
||||
padding: 0pc 0pc 0pc 0pc;
|
||||
}
|
||||
|
||||
/*=============================================================================
|
||||
Headings
|
||||
=============================================================================*/
|
||||
|
||||
h1, h2, h3, h4, h5, h6
|
||||
{
|
||||
text-align: left;
|
||||
margin: 1em 0em 0.5em 0em;
|
||||
font-weight: bold;
|
||||
}
|
||||
|
||||
h1 { font: 140% }
|
||||
h2 { font: bold 140% }
|
||||
h3 { font: bold 130% }
|
||||
h4 { font: bold 120% }
|
||||
h5 { font: italic 110% }
|
||||
h6 { font: italic 100% }
|
||||
|
||||
/* Top page titles */
|
||||
title,
|
||||
h1.title,
|
||||
h2.title
|
||||
h3.title,
|
||||
h4.title,
|
||||
h5.title,
|
||||
h6.title,
|
||||
.refentrytitle
|
||||
{
|
||||
font-weight: bold;
|
||||
margin-bottom: 1pc;
|
||||
}
|
||||
|
||||
h1.title { font-size: 140% }
|
||||
h2.title { font-size: 140% }
|
||||
h3.title { font-size: 130% }
|
||||
h4.title { font-size: 120% }
|
||||
h5.title { font-size: 110% }
|
||||
h6.title { font-size: 100% }
|
||||
|
||||
.section h1
|
||||
{
|
||||
margin: 0em 0em 0.5em 0em;
|
||||
font-size: 140%;
|
||||
}
|
||||
|
||||
.section h2 { font-size: 140% }
|
||||
.section h3 { font-size: 130% }
|
||||
.section h4 { font-size: 120% }
|
||||
.section h5 { font-size: 110% }
|
||||
.section h6 { font-size: 100% }
|
||||
|
||||
/* Code on titles */
|
||||
h1 tt.computeroutput { font-size: 140% }
|
||||
h2 tt.computeroutput { font-size: 140% }
|
||||
h3 tt.computeroutput { font-size: 130% }
|
||||
h4 tt.computeroutput { font-size: 120% }
|
||||
h5 tt.computeroutput { font-size: 110% }
|
||||
h6 tt.computeroutput { font-size: 100% }
|
||||
|
||||
/*=============================================================================
|
||||
Author
|
||||
=============================================================================*/
|
||||
|
||||
h3.author
|
||||
{
|
||||
font-size: 100%
|
||||
}
|
||||
|
||||
/*=============================================================================
|
||||
Lists
|
||||
=============================================================================*/
|
||||
|
||||
li
|
||||
{
|
||||
font-size: 10pt;
|
||||
line-height: 1.3;
|
||||
}
|
||||
|
||||
/* Unordered lists */
|
||||
ul
|
||||
{
|
||||
text-align: left;
|
||||
}
|
||||
|
||||
/* Ordered lists */
|
||||
ol
|
||||
{
|
||||
text-align: left;
|
||||
}
|
||||
|
||||
/*=============================================================================
|
||||
Links
|
||||
=============================================================================*/
|
||||
|
||||
a
|
||||
{
|
||||
text-decoration: none; /* no underline */
|
||||
}
|
||||
|
||||
a:hover
|
||||
{
|
||||
text-decoration: underline;
|
||||
}
|
||||
|
||||
/*=============================================================================
|
||||
Spirit style navigation
|
||||
=============================================================================*/
|
||||
|
||||
.spirit-nav
|
||||
{
|
||||
text-align: right;
|
||||
}
|
||||
|
||||
.spirit-nav a
|
||||
{
|
||||
color: white;
|
||||
padding-left: 0.5em;
|
||||
}
|
||||
|
||||
.spirit-nav img
|
||||
{
|
||||
border-width: 0px;
|
||||
}
|
||||
|
||||
/*=============================================================================
|
||||
Table of contents
|
||||
=============================================================================*/
|
||||
|
||||
.toc
|
||||
{
|
||||
margin: 1pc 4% 0pc 4%;
|
||||
padding: 0.1pc 1pc 0.1pc 1pc;
|
||||
font-size: 80%;
|
||||
line-height: 1.15;
|
||||
}
|
||||
|
||||
.boost-toc
|
||||
{
|
||||
float: right;
|
||||
padding: 0.5pc;
|
||||
}
|
||||
|
||||
/*=============================================================================
|
||||
Tables
|
||||
=============================================================================*/
|
||||
|
||||
.table-title,
|
||||
div.table p.title
|
||||
{
|
||||
margin-left: 4%;
|
||||
padding-right: 0.5em;
|
||||
padding-left: 0.5em;
|
||||
}
|
||||
|
||||
.informaltable table,
|
||||
.table table
|
||||
{
|
||||
width: 92%;
|
||||
margin-left: 4%;
|
||||
margin-right: 4%;
|
||||
}
|
||||
|
||||
div.informaltable table,
|
||||
div.table table
|
||||
{
|
||||
padding: 4px;
|
||||
}
|
||||
|
||||
/* Table Cells */
|
||||
div.informaltable table tr td,
|
||||
div.table table tr td
|
||||
{
|
||||
padding: 0.5em;
|
||||
text-align: left;
|
||||
font-size: 9pt;
|
||||
}
|
||||
|
||||
div.informaltable table tr th,
|
||||
div.table table tr th
|
||||
{
|
||||
padding: 0.5em 0.5em 0.5em 0.5em;
|
||||
border: 1pt solid white;
|
||||
font-size: 80%;
|
||||
}
|
||||
|
||||
/*=============================================================================
|
||||
Blurbs
|
||||
=============================================================================*/
|
||||
|
||||
div.note,
|
||||
div.tip,
|
||||
div.important,
|
||||
div.caution,
|
||||
div.warning,
|
||||
p.blurb
|
||||
{
|
||||
font-size: 9pt; /* A little bit smaller than the main text */
|
||||
line-height: 1.2;
|
||||
display: block;
|
||||
margin: 1pc 4% 0pc 4%;
|
||||
padding: 0.5pc 0.5pc 0.5pc 0.5pc;
|
||||
}
|
||||
|
||||
p.blurb img
|
||||
{
|
||||
padding: 1pt;
|
||||
}
|
||||
|
||||
/*=============================================================================
|
||||
Variable Lists
|
||||
=============================================================================*/
|
||||
|
||||
/* Make the terms in definition lists bold */
|
||||
div.variablelist dl dt,
|
||||
span.term
|
||||
{
|
||||
font-weight: bold;
|
||||
font-size: 10pt;
|
||||
}
|
||||
|
||||
div.variablelist table tbody tr td
|
||||
{
|
||||
text-align: left;
|
||||
vertical-align: top;
|
||||
padding: 0em 2em 0em 0em;
|
||||
font-size: 10pt;
|
||||
margin: 0em 0em 0.5em 0em;
|
||||
line-height: 1;
|
||||
}
|
||||
|
||||
div.variablelist dl dt
|
||||
{
|
||||
margin-bottom: 0.2em;
|
||||
}
|
||||
|
||||
div.variablelist dl dd
|
||||
{
|
||||
margin: 0em 0em 0.5em 2em;
|
||||
font-size: 10pt;
|
||||
}
|
||||
|
||||
div.variablelist table tbody tr td p,
|
||||
div.variablelist dl dd p
|
||||
{
|
||||
margin: 0em 0em 0.5em 0em;
|
||||
line-height: 1;
|
||||
}
|
||||
|
||||
/*=============================================================================
|
||||
Misc
|
||||
=============================================================================*/
|
||||
|
||||
/* Title of books and articles in bibliographies */
|
||||
span.title
|
||||
{
|
||||
font-style: italic;
|
||||
}
|
||||
|
||||
span.underline
|
||||
{
|
||||
text-decoration: underline;
|
||||
}
|
||||
|
||||
span.strikethrough
|
||||
{
|
||||
text-decoration: line-through;
|
||||
}
|
||||
|
||||
/* Copyright, Legal Notice */
|
||||
div div.legalnotice p
|
||||
{
|
||||
text-align: left
|
||||
}
|
||||
|
||||
/*=============================================================================
|
||||
Colors
|
||||
=============================================================================*/
|
||||
|
||||
@media screen
|
||||
{
|
||||
/* Links */
|
||||
a
|
||||
{
|
||||
color: #005a9c;
|
||||
}
|
||||
|
||||
a:visited
|
||||
{
|
||||
color: #9c5a9c;
|
||||
}
|
||||
|
||||
h1 a, h2 a, h3 a, h4 a, h5 a, h6 a,
|
||||
h1 a:hover, h2 a:hover, h3 a:hover, h4 a:hover, h5 a:hover, h6 a:hover,
|
||||
h1 a:visited, h2 a:visited, h3 a:visited, h4 a:visited, h5 a:visited, h6 a:visited
|
||||
{
|
||||
text-decoration: none; /* no underline */
|
||||
color: #000000;
|
||||
}
|
||||
|
||||
/* Syntax Highlighting */
|
||||
.keyword { color: #0000AA; }
|
||||
.identifier { color: #000000; }
|
||||
.special { color: #707070; }
|
||||
.preprocessor { color: #402080; }
|
||||
.char { color: teal; }
|
||||
.comment { color: #800000; }
|
||||
.string { color: teal; }
|
||||
.number { color: teal; }
|
||||
.white_bkd { background-color: #FFFFFF; }
|
||||
.dk_grey_bkd { background-color: #999999; }
|
||||
|
||||
/* Copyright, Legal Notice */
|
||||
.copyright
|
||||
{
|
||||
color: #666666;
|
||||
font-size: small;
|
||||
}
|
||||
|
||||
div div.legalnotice p
|
||||
{
|
||||
color: #666666;
|
||||
}
|
||||
|
||||
/* Program listing */
|
||||
pre.synopsis
|
||||
{
|
||||
border: 1px solid #DCDCDC;
|
||||
}
|
||||
|
||||
.programlisting,
|
||||
.screen
|
||||
{
|
||||
border: 1px solid #DCDCDC;
|
||||
}
|
||||
|
||||
td .programlisting,
|
||||
td .screen
|
||||
{
|
||||
border: 0px solid #DCDCDC;
|
||||
}
|
||||
|
||||
/* Blurbs */
|
||||
div.note,
|
||||
div.tip,
|
||||
div.important,
|
||||
div.caution,
|
||||
div.warning,
|
||||
p.blurb
|
||||
{
|
||||
border: 1px solid #DCDCDC;
|
||||
}
|
||||
|
||||
/* Table of contents */
|
||||
.toc
|
||||
{
|
||||
border: 1px solid #DCDCDC;
|
||||
}
|
||||
|
||||
/* Tables */
|
||||
div.informaltable table tr td,
|
||||
div.table table tr td
|
||||
{
|
||||
border: 1px solid #DCDCDC;
|
||||
}
|
||||
|
||||
div.informaltable table tr th,
|
||||
div.table table tr th
|
||||
{
|
||||
background-color: #F0F0F0;
|
||||
border: 1px solid #DCDCDC;
|
||||
}
|
||||
|
||||
/* Misc */
|
||||
span.highlight
|
||||
{
|
||||
color: #00A000;
|
||||
}
|
||||
}
|
||||
|
||||
@media print
|
||||
{
|
||||
/* Links */
|
||||
a
|
||||
{
|
||||
color: black;
|
||||
}
|
||||
|
||||
a:visited
|
||||
{
|
||||
color: black;
|
||||
}
|
||||
|
||||
.spirit-nav
|
||||
{
|
||||
display: none;
|
||||
}
|
||||
|
||||
/* Program listing */
|
||||
pre.synopsis
|
||||
{
|
||||
border: 1px solid gray;
|
||||
}
|
||||
|
||||
.programlisting,
|
||||
.screen
|
||||
{
|
||||
border: 1px solid gray;
|
||||
}
|
||||
|
||||
td .programlisting,
|
||||
td .screen
|
||||
{
|
||||
border: 0px solid #DCDCDC;
|
||||
}
|
||||
|
||||
/* Table of contents */
|
||||
.toc
|
||||
{
|
||||
border: 1px solid gray;
|
||||
}
|
||||
|
||||
.informaltable table,
|
||||
.table table
|
||||
{
|
||||
border: 1px solid gray;
|
||||
border-collapse: collapse;
|
||||
}
|
||||
|
||||
/* Tables */
|
||||
div.informaltable table tr td,
|
||||
div.table table tr td
|
||||
{
|
||||
border: 1px solid gray;
|
||||
}
|
||||
|
||||
div.informaltable table tr th,
|
||||
div.table table tr th
|
||||
{
|
||||
border: 1px solid gray;
|
||||
}
|
||||
|
||||
/* Misc */
|
||||
span.highlight
|
||||
{
|
||||
font-weight: bold;
|
||||
}
|
||||
}
|
||||
@@ -2,22 +2,22 @@
|
||||
<head>
|
||||
<meta http-equiv="Content-Type" content="text/html; charset=ISO-8859-1">
|
||||
<title>Chapter 1. python 1.0</title>
|
||||
<link rel="stylesheet" href="boostbook.css" type="text/css">
|
||||
<meta name="generator" content="DocBook XSL Stylesheets V1.72.0">
|
||||
<link rel="stylesheet" href="../../../../../../doc/html/boostbook.css" type="text/css">
|
||||
<meta name="generator" content="DocBook XSL Stylesheets V1.66.1">
|
||||
<link rel="start" href="index.html" title="Chapter 1. python 1.0">
|
||||
<link rel="next" href="python/hello.html" title="Building Hello World">
|
||||
<link rel="next" href="python/hello.html" title=" Building Hello World">
|
||||
</head>
|
||||
<body bgcolor="white" text="black" link="#0000FF" vlink="#840084" alink="#0000FF">
|
||||
<table cellpadding="2" width="100%">
|
||||
<table cellpadding="2" width="100%"><tr>
|
||||
<td valign="top"><img alt="Boost C++ Libraries" width="277" height="86" src="../../../../../../boost.png"></td>
|
||||
<td align="center"><a href="../../../../../../index.htm">Home</a></td>
|
||||
<td align="center"><a href="../../../../../../libs/libraries.htm">Libraries</a></td>
|
||||
<td align="center"><a href="../../../../../../people/people.htm">People</a></td>
|
||||
<td align="center"><a href="../../../../../../more/faq.htm">FAQ</a></td>
|
||||
<td align="center"><a href="../../../../../../more/index.htm">More</a></td>
|
||||
</table>
|
||||
</tr></table>
|
||||
<hr>
|
||||
<div class="spirit-nav"><a accesskey="n" href="python/hello.html"><img src="images/next.png" alt="Next"></a></div>
|
||||
<div class="spirit-nav"><a accesskey="n" href="python/hello.html"><img src="../../../../../../doc/html/images/next.png" alt="Next"></a></div>
|
||||
<div class="chapter" lang="en">
|
||||
<div class="titlepage"><div>
|
||||
<div><h2 class="title">
|
||||
@@ -31,7 +31,7 @@
|
||||
<div><p class="copyright">Copyright © 2002-2005 Joel
|
||||
de Guzman, David Abrahams</p></div>
|
||||
<div><div class="legalnotice">
|
||||
<a name="id3128483"></a><p>
|
||||
<a name="id387671"></a><p>
|
||||
Distributed under the Boost Software License, Version 1.0. (See accompanying
|
||||
file LICENSE_1_0.txt or copy at <a href="http://www.boost.org/LICENSE_1_0.txt" target="_top">
|
||||
http://www.boost.org/LICENSE_1_0.txt </a>)
|
||||
@@ -93,10 +93,10 @@
|
||||
code takes on the look of a kind of declarative interface definition language
|
||||
(IDL).
|
||||
</p>
|
||||
<a name="quickstart.hello_world"></a><h3>
|
||||
<a name="id3090903"></a>
|
||||
<a name="quickstart.hello_world"></a><h2>
|
||||
<a name="id385737"></a>
|
||||
Hello World
|
||||
</h3>
|
||||
</h2>
|
||||
<p>
|
||||
Following C/C++ tradition, let's start with the "hello, world". A
|
||||
C++ Function:
|
||||
@@ -112,10 +112,10 @@
|
||||
</p>
|
||||
<pre class="programlisting">
|
||||
<span class="preprocessor">#include</span> <span class="special"><</span><span class="identifier">boost</span><span class="special">/</span><span class="identifier">python</span><span class="special">.</span><span class="identifier">hpp</span><span class="special">></span>
|
||||
<span class="keyword">using</span> <span class="keyword">namespace</span> <span class="identifier">boost</span><span class="special">::</span><span class="identifier">python</span><span class="special">;</span>
|
||||
|
||||
<span class="identifier">BOOST_PYTHON_MODULE</span><span class="special">(</span><span class="identifier">hello</span><span class="special">)</span>
|
||||
<span class="identifier">BOOST_PYTHON_MODULE</span><span class="special">(</span><span class="identifier">hello_ext</span><span class="special">)</span>
|
||||
<span class="special">{</span>
|
||||
<span class="keyword">using</span> <span class="keyword">namespace</span> <span class="identifier">boost</span><span class="special">::</span><span class="identifier">python</span><span class="special">;</span>
|
||||
<span class="identifier">def</span><span class="special">(</span><span class="string">"greet"</span><span class="special">,</span> <span class="identifier">greet</span><span class="special">);</span>
|
||||
<span class="special">}</span>
|
||||
</pre>
|
||||
@@ -126,23 +126,29 @@
|
||||
<p>
|
||||
</p>
|
||||
<pre class="programlisting">
|
||||
<span class="special">>>></span> <span class="keyword">import</span> <span class="identifier">hello</span>
|
||||
<span class="special">>>></span> <span class="keyword">import</span> <span class="identifier">hello_ext</span>
|
||||
<span class="special">>>></span> <span class="keyword">print</span> <span class="identifier">hello</span><span class="special">.</span><span class="identifier">greet</span><span class="special">()</span>
|
||||
<span class="identifier">hello</span><span class="special">,</span> <span class="identifier">world</span>
|
||||
</pre>
|
||||
<p>
|
||||
</p>
|
||||
<div class="blockquote"><blockquote class="blockquote"><p>
|
||||
<span class="emphasis"><em><span class="bold"><strong>Next stop... Building your Hello World module
|
||||
from start to finish...</strong></span></em></span>
|
||||
</p></blockquote></div>
|
||||
<div class="blockquote"><blockquote class="blockquote">
|
||||
<p>
|
||||
</p>
|
||||
<p>
|
||||
<span class="emphasis"><em><span class="bold"><b>Next stop... Building your Hello World
|
||||
module from start to finish...</b></span></em></span>
|
||||
</p>
|
||||
<p>
|
||||
</p>
|
||||
</blockquote></div>
|
||||
</div>
|
||||
</div>
|
||||
<table xmlns:rev="http://www.cs.rpi.edu/~gregod/boost/tools/doc/revision" width="100%"><tr>
|
||||
<td align="left"><small><p>Last revised: May 18, 2007 at 15:45:45 GMT</p></small></td>
|
||||
<td align="right"><small></small></td>
|
||||
<td align="left"><p><small>Last revised: November 07, 2007 at 03:34:24 GMT</small></p></td>
|
||||
<td align="right"><div class="copyright-footer"><small></small></div></td>
|
||||
</tr></table>
|
||||
<hr>
|
||||
<div class="spirit-nav"><a accesskey="n" href="python/hello.html"><img src="images/next.png" alt="Next"></a></div>
|
||||
<div class="spirit-nav"><a accesskey="n" href="python/hello.html"><img src="../../../../../../doc/html/images/next.png" alt="Next"></a></div>
|
||||
</body>
|
||||
</html>
|
||||
|
||||
@@ -2,25 +2,25 @@
|
||||
<head>
|
||||
<meta http-equiv="Content-Type" content="text/html; charset=ISO-8859-1">
|
||||
<title>Embedding</title>
|
||||
<link rel="stylesheet" href="../boostbook.css" type="text/css">
|
||||
<meta name="generator" content="DocBook XSL Stylesheets V1.72.0">
|
||||
<link rel="stylesheet" href="../../../../../../../doc/html/boostbook.css" type="text/css">
|
||||
<meta name="generator" content="DocBook XSL Stylesheets V1.66.1">
|
||||
<link rel="start" href="../index.html" title="Chapter 1. python 1.0">
|
||||
<link rel="up" href="../index.html" title="Chapter 1. python 1.0">
|
||||
<link rel="prev" href="object.html" title="Object Interface">
|
||||
<link rel="prev" href="object.html" title=" Object Interface">
|
||||
<link rel="next" href="iterators.html" title="Iterators">
|
||||
</head>
|
||||
<body bgcolor="white" text="black" link="#0000FF" vlink="#840084" alink="#0000FF">
|
||||
<table cellpadding="2" width="100%">
|
||||
<table cellpadding="2" width="100%"><tr>
|
||||
<td valign="top"><img alt="Boost C++ Libraries" width="277" height="86" src="../../../../../../../boost.png"></td>
|
||||
<td align="center"><a href="../../../../../../../index.htm">Home</a></td>
|
||||
<td align="center"><a href="../../../../../../../libs/libraries.htm">Libraries</a></td>
|
||||
<td align="center"><a href="../../../../../../../people/people.htm">People</a></td>
|
||||
<td align="center"><a href="../../../../../../../more/faq.htm">FAQ</a></td>
|
||||
<td align="center"><a href="../../../../../../../more/index.htm">More</a></td>
|
||||
</table>
|
||||
</tr></table>
|
||||
<hr>
|
||||
<div class="spirit-nav">
|
||||
<a accesskey="p" href="object.html"><img src="../images/prev.png" alt="Prev"></a><a accesskey="u" href="../index.html"><img src="../images/up.png" alt="Up"></a><a accesskey="h" href="../index.html"><img src="../images/home.png" alt="Home"></a><a accesskey="n" href="iterators.html"><img src="../images/next.png" alt="Next"></a>
|
||||
<a accesskey="p" href="object.html"><img src="../../../../../../../doc/html/images/prev.png" alt="Prev"></a><a accesskey="u" href="../index.html"><img src="../../../../../../../doc/html/images/up.png" alt="Up"></a><a accesskey="h" href="../index.html"><img src="../../../../../../../doc/html/images/home.png" alt="Home"></a><a accesskey="n" href="iterators.html"><img src="../../../../../../../doc/html/images/next.png" alt="Next"></a>
|
||||
</div>
|
||||
<div class="section" lang="en">
|
||||
<div class="titlepage"><div><div><h2 class="title" style="clear: both">
|
||||
@@ -39,28 +39,28 @@
|
||||
a lot easier and, in a future version, it may become unnecessary to touch the
|
||||
Python/C API at all. So stay tuned... <span class="inlinemediaobject"><img src="../images/smiley.png" alt="smiley"></span>
|
||||
</p>
|
||||
<a name="embedding.building_embedded_programs"></a><h3>
|
||||
<a name="id3150903"></a>
|
||||
<a name="embedding.building_embedded_programs"></a><h2>
|
||||
<a name="id471189"></a>
|
||||
Building embedded programs
|
||||
</h3>
|
||||
</h2>
|
||||
<p>
|
||||
To be able to embed python into your programs, you have to link to both Boost.Python's
|
||||
as well as Python's own runtime library.
|
||||
</p>
|
||||
<p>
|
||||
Boost.Python's library comes in two variants. Both are located in Boost's
|
||||
<code class="literal">/libs/python/build/bin-stage</code> subdirectory. On Windows, the
|
||||
variants are called <code class="literal">boost_python.lib</code> (for release builds)
|
||||
and <code class="literal">boost_python_debug.lib</code> (for debugging). If you can't
|
||||
<tt class="literal">/libs/python/build/bin-stage</tt> subdirectory. On Windows, the
|
||||
variants are called <tt class="literal">boost_python.lib</tt> (for release builds)
|
||||
and <tt class="literal">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" target="_top">Building and Testing</a> on how to do this.
|
||||
</p>
|
||||
<p>
|
||||
Python's library can be found in the <code class="literal">/libs</code> subdirectory
|
||||
Python's library can be found in the <tt class="literal">/libs</tt> subdirectory
|
||||
of your Python directory. On Windows it is called pythonXY.lib where X.Y is
|
||||
your major Python version number.
|
||||
</p>
|
||||
<p>
|
||||
Additionally, Python's <code class="literal">/include</code> subdirectory has to be added
|
||||
Additionally, Python's <tt class="literal">/include</tt> subdirectory has to be added
|
||||
to your include path.
|
||||
</p>
|
||||
<p>
|
||||
@@ -81,60 +81,67 @@ exe embedded_program # name of the executable
|
||||
<library-path>$(PYTHON_LIB_PATH)
|
||||
<find-library>$(PYTHON_EMBEDDED_LIBRARY) ;
|
||||
</pre>
|
||||
<a name="embedding.getting_started"></a><h3>
|
||||
<a name="id3150996"></a>
|
||||
<a name="embedding.getting_started"></a><h2>
|
||||
<a name="id471294"></a>
|
||||
Getting started
|
||||
</h3>
|
||||
</h2>
|
||||
<p>
|
||||
Being able to build is nice, but there is nothing to build yet. Embedding the
|
||||
Python interpreter into one of your C++ programs requires these 4 steps:
|
||||
</p>
|
||||
<div class="orderedlist"><ol type="1">
|
||||
<li>
|
||||
|
||||
#include
|
||||
<code class="literal"><boost/python.hpp></code><br><br>
|
||||
#include <tt class="literal"><boost/python.hpp></tt>
|
||||
</li>
|
||||
<li>
|
||||
Call <a href="http://www.python.org/doc/current/api/initialization.html#l2h-652" target="_top">Py_Initialize</a>()
|
||||
to start the interpreter and create the <code class="literal"><span class="underline">_main</span>_</code>
|
||||
module.<br><br>
|
||||
</li>
|
||||
to start the interpreter and create the <tt class="literal"><span class="underline">_main</span>_</tt>
|
||||
module.
|
||||
</li>
|
||||
<li>
|
||||
Call other Python C API routines to use the interpreter.<br><br>
|
||||
</li>
|
||||
Call other Python C API routines to use the interpreter.
|
||||
</li>
|
||||
</ol></div>
|
||||
<div class="informaltable"><table class="table">
|
||||
<colgroup><col></colgroup>
|
||||
<tbody><tr><td class="blurb"> <span class="inlinemediaobject"><img src="../images/note.png" alt="note"></span> <span class="bold"><strong>Note that at this time
|
||||
you must not call <a href="http://www.python.org/doc/current/api/initialization.html#l2h-656" target="_top">Py_Finalize</a>()
|
||||
to stop the interpreter. This may be fixed in a future version of boost.python.</strong></span>
|
||||
</td></tr></tbody>
|
||||
<div class="note"><table border="0" summary="Note">
|
||||
<tr>
|
||||
<td rowspan="2" align="center" valign="top" width="25"><img alt="[Note]" src="../../../../../../../doc/html/images/note.png"></td>
|
||||
<th align="left">Note</th>
|
||||
</tr>
|
||||
<tr><td colspan="2" align="left" valign="top"><p>
|
||||
<span class="bold"><b>Note that at this time you must not call <a href="http://www.python.org/doc/current/api/initialization.html#l2h-656" target="_top">Py_Finalize</a>()
|
||||
to stop the interpreter. This may be fixed in a future version of boost.python.</b></span>
|
||||
</p></td></tr>
|
||||
</table></div>
|
||||
<p>
|
||||
(Of course, there can be other C++ code between all of these steps.)
|
||||
</p>
|
||||
<div class="blockquote"><blockquote class="blockquote"><p>
|
||||
<span class="emphasis"><em><span class="bold"><strong>Now that we can embed the interpreter in
|
||||
our programs, lets see how to put it to use...</strong></span></em></span>
|
||||
</p></blockquote></div>
|
||||
<div class="blockquote"><blockquote class="blockquote">
|
||||
<p>
|
||||
</p>
|
||||
<p>
|
||||
<span class="emphasis"><em><span class="bold"><b>Now that we can embed the interpreter in
|
||||
our programs, lets see how to put it to use...</b></span></em></span>
|
||||
</p>
|
||||
<p>
|
||||
</p>
|
||||
</blockquote></div>
|
||||
<div class="section" lang="en">
|
||||
<div class="titlepage"><div><div><h3 class="title">
|
||||
<a name="python.using_the_interpreter"></a>Using the interpreter</h3></div></div></div>
|
||||
<p>
|
||||
As you probably already know, objects in Python are reference-counted. Naturally,
|
||||
the <code class="literal">PyObject</code>s of the Python/C API are also reference-counted.
|
||||
the <tt class="literal">PyObject</tt>s of the Python/C API are also reference-counted.
|
||||
There is a difference however. While the reference-counting is fully automatic
|
||||
in Python, the Python/C API requires you to do it <a href="http://www.python.org/doc/current/api/refcounts.html" target="_top">by
|
||||
hand</a>. This is messy and especially hard to get right in the presence
|
||||
in Python, the Python<span class="emphasis"><em>C API requires you to do it [@http:</em></span>/www.python.org/doc/current/api/refcounts.html
|
||||
by hand]. This is messy and especially hard to get right in the presence
|
||||
of C++ exceptions. Fortunately Boost.Python provides the <a href="../../../../v2/handle.html" target="_top">handle</a>
|
||||
and <a href="../../../../v2/object.html" target="_top">object</a> class templates to
|
||||
automate the process.
|
||||
</p>
|
||||
<a name="using_the_interpreter.running_python_code"></a><h3>
|
||||
<a name="id3151190"></a>
|
||||
<a name="using_the_interpreter.running_python_code"></a><h2>
|
||||
<a name="id471457"></a>
|
||||
Running Python code
|
||||
</h3>
|
||||
</h2>
|
||||
<p>
|
||||
Boost.python provides three related functions to run Python code from C++.
|
||||
</p>
|
||||
@@ -149,10 +156,10 @@ exe embedded_program # name of the executable
|
||||
and exec_file executes the code contained in the given file.
|
||||
</p>
|
||||
<p>
|
||||
The <code class="literal">globals</code> and <code class="literal">locals</code> parameters are
|
||||
The <tt class="literal">globals</tt> and <tt class="literal">locals</tt> parameters are
|
||||
Python dictionaries containing the globals and locals of the context in which
|
||||
to run the code. For most intents and purposes you can use the namespace
|
||||
dictionary of the <code class="literal"><span class="underline">_main</span>_</code>
|
||||
dictionary of the <tt class="literal"><span class="underline">_main</span>_</tt>
|
||||
module for both parameters.
|
||||
</p>
|
||||
<p>
|
||||
@@ -166,7 +173,7 @@ exe embedded_program # name of the executable
|
||||
first), and returns it.
|
||||
</p>
|
||||
<p>
|
||||
Let's import the <code class="literal"><span class="underline">_main</span>_</code>
|
||||
Let's import the <tt class="literal"><span class="underline">_main</span>_</tt>
|
||||
module and run some Python code in its namespace:
|
||||
</p>
|
||||
<pre class="programlisting">
|
||||
@@ -182,15 +189,15 @@ exe embedded_program # name of the executable
|
||||
This should create a file called 'hello.txt' in the current directory containing
|
||||
a phrase that is well-known in programming circles.
|
||||
</p>
|
||||
<a name="using_the_interpreter.manipulating_python_objects"></a><h3>
|
||||
<a name="id3151717"></a>
|
||||
<a name="using_the_interpreter.manipulating_python_objects"></a><h2>
|
||||
<a name="id472045"></a>
|
||||
Manipulating Python objects
|
||||
</h3>
|
||||
</h2>
|
||||
<p>
|
||||
Often we'd like to have a class to manipulate Python objects. But we have
|
||||
already seen such a class above, and in the <a href="object.html" target="_top">previous
|
||||
section</a>: the aptly named <code class="literal">object</code> class and its
|
||||
derivatives. We've already seen that they can be constructed from a <code class="literal">handle</code>.
|
||||
section</a>: the aptly named <tt class="literal">object</tt> class and its
|
||||
derivatives. We've already seen that they can be constructed from a <tt class="literal">handle</tt>.
|
||||
The following examples should further illustrate this fact:
|
||||
</p>
|
||||
<pre class="programlisting">
|
||||
@@ -200,7 +207,7 @@ exe embedded_program # name of the executable
|
||||
<span class="keyword">int</span> <span class="identifier">five_squared</span> <span class="special">=</span> <span class="identifier">extract</span><span class="special"><</span><span class="keyword">int</span><span class="special">>(</span><span class="identifier">main_namespace</span><span class="special">[</span><span class="string">"result"</span><span class="special">]);</span>
|
||||
</pre>
|
||||
<p>
|
||||
Here we create a dictionary object for the <code class="literal"><span class="underline">_main</span>_</code>
|
||||
Here we create a dictionary object for the <tt class="literal"><span class="underline">_main</span>_</tt>
|
||||
module's namespace. Then we assign 5 squared to the result variable and read
|
||||
this variable from the dictionary. Another way to achieve the same result
|
||||
is to use eval instead, which returns the result directly:
|
||||
@@ -209,10 +216,10 @@ exe embedded_program # name of the executable
|
||||
<span class="identifier">object</span> <span class="identifier">result</span> <span class="special">=</span> <span class="identifier">eval</span><span class="special">(</span><span class="string">"5 ** 2"</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">result</span><span class="special">);</span>
|
||||
</pre>
|
||||
<a name="using_the_interpreter.exception_handling"></a><h3>
|
||||
<a name="id3152050"></a>
|
||||
<a name="using_the_interpreter.exception_handling"></a><h2>
|
||||
<a name="id472417"></a>
|
||||
Exception handling
|
||||
</h3>
|
||||
</h2>
|
||||
<p>
|
||||
If an exception occurs in the evaluation of the python expression, <a href="../../../../v2/errors.html#error_already_set-spec" target="_top">error_already_set</a>
|
||||
is thrown:
|
||||
@@ -230,13 +237,13 @@ exe embedded_program # name of the executable
|
||||
</span><span class="special">}</span>
|
||||
</pre>
|
||||
<p>
|
||||
The <code class="literal">error_already_set</code> exception class doesn't carry any
|
||||
The <tt class="literal">error_already_set</tt> exception class doesn't carry any
|
||||
information in itself. To find out more about the Python exception that occurred,
|
||||
you need to use the <a href="http://www.python.org/doc/api/exceptionHandling.html" target="_top">exception
|
||||
handling functions</a> of the Python/C API in your catch-statement. This
|
||||
can be as simple as calling <a href="http://www.python.org/doc/api/exceptionHandling.html#l2h-70" target="_top">PyErr_Print()</a>
|
||||
to print the exception's traceback to the console, or comparing the type
|
||||
of the exception with those of the <a href="http://www.python.org/doc/api/standardExceptions.html" target="_top">standard
|
||||
handling functions</a> of the Python<span class="emphasis"><em>C API in your catch-statement.
|
||||
This can be as simple as calling [@http:</em></span>/www.python.org/doc/api/exceptionHandling.html#l2h-70
|
||||
PyErr_Print()] to print the exception's traceback to the console, or comparing
|
||||
the type of the exception with those of the <a href="http://www.python.org/doc/api/standardExceptions.html" target="_top">standard
|
||||
exceptions</a>:
|
||||
</p>
|
||||
<pre class="programlisting">
|
||||
@@ -261,12 +268,16 @@ exe embedded_program # name of the executable
|
||||
</div>
|
||||
<table xmlns:rev="http://www.cs.rpi.edu/~gregod/boost/tools/doc/revision" width="100%"><tr>
|
||||
<td align="left"></td>
|
||||
<td align="right"><small>Copyright © 2002-2005 Joel
|
||||
de Guzman, David Abrahams</small></td>
|
||||
<td align="right"><div class="copyright-footer"><small>Copyright © 2002-2005 Joel
|
||||
de Guzman, David Abrahams<p>
|
||||
Distributed under the Boost Software License, Version 1.0. (See accompanying
|
||||
file LICENSE_1_0.txt or copy at <a href="http://www.boost.org/LICENSE_1_0.txt" target="_top">
|
||||
http://www.boost.org/LICENSE_1_0.txt </a>)
|
||||
</p></small></div></td>
|
||||
</tr></table>
|
||||
<hr>
|
||||
<div class="spirit-nav">
|
||||
<a accesskey="p" href="object.html"><img src="../images/prev.png" alt="Prev"></a><a accesskey="u" href="../index.html"><img src="../images/up.png" alt="Up"></a><a accesskey="h" href="../index.html"><img src="../images/home.png" alt="Home"></a><a accesskey="n" href="iterators.html"><img src="../images/next.png" alt="Next"></a>
|
||||
<a accesskey="p" href="object.html"><img src="../../../../../../../doc/html/images/prev.png" alt="Prev"></a><a accesskey="u" href="../index.html"><img src="../../../../../../../doc/html/images/up.png" alt="Up"></a><a accesskey="h" href="../index.html"><img src="../../../../../../../doc/html/images/home.png" alt="Home"></a><a accesskey="n" href="iterators.html"><img src="../../../../../../../doc/html/images/next.png" alt="Next"></a>
|
||||
</div>
|
||||
</body>
|
||||
</html>
|
||||
|
||||
@@ -1,26 +1,26 @@
|
||||
<html>
|
||||
<head>
|
||||
<meta http-equiv="Content-Type" content="text/html; charset=ISO-8859-1">
|
||||
<title>Exception Translation</title>
|
||||
<link rel="stylesheet" href="../boostbook.css" type="text/css">
|
||||
<meta name="generator" content="DocBook XSL Stylesheets V1.72.0">
|
||||
<title> Exception Translation</title>
|
||||
<link rel="stylesheet" href="../../../../../../../doc/html/boostbook.css" type="text/css">
|
||||
<meta name="generator" content="DocBook XSL Stylesheets V1.66.1">
|
||||
<link rel="start" href="../index.html" title="Chapter 1. python 1.0">
|
||||
<link rel="up" href="../index.html" title="Chapter 1. python 1.0">
|
||||
<link rel="prev" href="iterators.html" title="Iterators">
|
||||
<link rel="next" href="techniques.html" title="General Techniques">
|
||||
<link rel="next" href="techniques.html" title=" General Techniques">
|
||||
</head>
|
||||
<body bgcolor="white" text="black" link="#0000FF" vlink="#840084" alink="#0000FF">
|
||||
<table cellpadding="2" width="100%">
|
||||
<table cellpadding="2" width="100%"><tr>
|
||||
<td valign="top"><img alt="Boost C++ Libraries" width="277" height="86" src="../../../../../../../boost.png"></td>
|
||||
<td align="center"><a href="../../../../../../../index.htm">Home</a></td>
|
||||
<td align="center"><a href="../../../../../../../libs/libraries.htm">Libraries</a></td>
|
||||
<td align="center"><a href="../../../../../../../people/people.htm">People</a></td>
|
||||
<td align="center"><a href="../../../../../../../more/faq.htm">FAQ</a></td>
|
||||
<td align="center"><a href="../../../../../../../more/index.htm">More</a></td>
|
||||
</table>
|
||||
</tr></table>
|
||||
<hr>
|
||||
<div class="spirit-nav">
|
||||
<a accesskey="p" href="iterators.html"><img src="../images/prev.png" alt="Prev"></a><a accesskey="u" href="../index.html"><img src="../images/up.png" alt="Up"></a><a accesskey="h" href="../index.html"><img src="../images/home.png" alt="Home"></a><a accesskey="n" href="techniques.html"><img src="../images/next.png" alt="Next"></a>
|
||||
<a accesskey="p" href="iterators.html"><img src="../../../../../../../doc/html/images/prev.png" alt="Prev"></a><a accesskey="u" href="../index.html"><img src="../../../../../../../doc/html/images/up.png" alt="Up"></a><a accesskey="h" href="../index.html"><img src="../../../../../../../doc/html/images/home.png" alt="Home"></a><a accesskey="n" href="techniques.html"><img src="../../../../../../../doc/html/images/next.png" alt="Next"></a>
|
||||
</div>
|
||||
<div class="section" lang="en">
|
||||
<div class="titlepage"><div><div><h2 class="title" style="clear: both">
|
||||
@@ -49,12 +49,16 @@
|
||||
</div>
|
||||
<table xmlns:rev="http://www.cs.rpi.edu/~gregod/boost/tools/doc/revision" width="100%"><tr>
|
||||
<td align="left"></td>
|
||||
<td align="right"><small>Copyright © 2002-2005 Joel
|
||||
de Guzman, David Abrahams</small></td>
|
||||
<td align="right"><div class="copyright-footer"><small>Copyright © 2002-2005 Joel
|
||||
de Guzman, David Abrahams<p>
|
||||
Distributed under the Boost Software License, Version 1.0. (See accompanying
|
||||
file LICENSE_1_0.txt or copy at <a href="http://www.boost.org/LICENSE_1_0.txt" target="_top">
|
||||
http://www.boost.org/LICENSE_1_0.txt </a>)
|
||||
</p></small></div></td>
|
||||
</tr></table>
|
||||
<hr>
|
||||
<div class="spirit-nav">
|
||||
<a accesskey="p" href="iterators.html"><img src="../images/prev.png" alt="Prev"></a><a accesskey="u" href="../index.html"><img src="../images/up.png" alt="Up"></a><a accesskey="h" href="../index.html"><img src="../images/home.png" alt="Home"></a><a accesskey="n" href="techniques.html"><img src="../images/next.png" alt="Next"></a>
|
||||
<a accesskey="p" href="iterators.html"><img src="../../../../../../../doc/html/images/prev.png" alt="Prev"></a><a accesskey="u" href="../index.html"><img src="../../../../../../../doc/html/images/up.png" alt="Up"></a><a accesskey="h" href="../index.html"><img src="../../../../../../../doc/html/images/home.png" alt="Home"></a><a accesskey="n" href="techniques.html"><img src="../../../../../../../doc/html/images/next.png" alt="Next"></a>
|
||||
</div>
|
||||
</body>
|
||||
</html>
|
||||
|
||||
@@ -1,26 +1,26 @@
|
||||
<html>
|
||||
<head>
|
||||
<meta http-equiv="Content-Type" content="text/html; charset=ISO-8859-1">
|
||||
<title>Exposing Classes</title>
|
||||
<link rel="stylesheet" href="../boostbook.css" type="text/css">
|
||||
<meta name="generator" content="DocBook XSL Stylesheets V1.72.0">
|
||||
<title> Exposing Classes</title>
|
||||
<link rel="stylesheet" href="../../../../../../../doc/html/boostbook.css" type="text/css">
|
||||
<meta name="generator" content="DocBook XSL Stylesheets V1.66.1">
|
||||
<link rel="start" href="../index.html" title="Chapter 1. python 1.0">
|
||||
<link rel="up" href="../index.html" title="Chapter 1. python 1.0">
|
||||
<link rel="prev" href="hello.html" title="Building Hello World">
|
||||
<link rel="prev" href="hello.html" title=" Building Hello World">
|
||||
<link rel="next" href="functions.html" title="Functions">
|
||||
</head>
|
||||
<body bgcolor="white" text="black" link="#0000FF" vlink="#840084" alink="#0000FF">
|
||||
<table cellpadding="2" width="100%">
|
||||
<table cellpadding="2" width="100%"><tr>
|
||||
<td valign="top"><img alt="Boost C++ Libraries" width="277" height="86" src="../../../../../../../boost.png"></td>
|
||||
<td align="center"><a href="../../../../../../../index.htm">Home</a></td>
|
||||
<td align="center"><a href="../../../../../../../libs/libraries.htm">Libraries</a></td>
|
||||
<td align="center"><a href="../../../../../../../people/people.htm">People</a></td>
|
||||
<td align="center"><a href="../../../../../../../more/faq.htm">FAQ</a></td>
|
||||
<td align="center"><a href="../../../../../../../more/index.htm">More</a></td>
|
||||
</table>
|
||||
</tr></table>
|
||||
<hr>
|
||||
<div class="spirit-nav">
|
||||
<a accesskey="p" href="hello.html"><img src="../images/prev.png" alt="Prev"></a><a accesskey="u" href="../index.html"><img src="../images/up.png" alt="Up"></a><a accesskey="h" href="../index.html"><img src="../images/home.png" alt="Home"></a><a accesskey="n" href="functions.html"><img src="../images/next.png" alt="Next"></a>
|
||||
<a accesskey="p" href="hello.html"><img src="../../../../../../../doc/html/images/prev.png" alt="Prev"></a><a accesskey="u" href="../index.html"><img src="../../../../../../../doc/html/images/up.png" alt="Up"></a><a accesskey="h" href="../index.html"><img src="../../../../../../../doc/html/images/home.png" alt="Home"></a><a accesskey="n" href="functions.html"><img src="../../../../../../../doc/html/images/next.png" alt="Next"></a>
|
||||
</div>
|
||||
<div class="section" lang="en">
|
||||
<div class="titlepage"><div><div><h2 class="title" style="clear: both">
|
||||
@@ -64,9 +64,9 @@
|
||||
<span class="special">}</span>
|
||||
</pre>
|
||||
<p>
|
||||
Here, we wrote a C++ class wrapper that exposes the member functions <code class="literal">greet</code>
|
||||
and <code class="literal">set</code>. Now, after building our module as a shared library,
|
||||
we may use our class <code class="literal">World</code> in Python. Here's a sample Python
|
||||
Here, we wrote a C++ class wrapper that exposes the member functions <tt class="literal">greet</tt>
|
||||
and <tt class="literal">set</tt>. Now, after building our module as a shared library,
|
||||
we may use our class <tt class="literal">World</tt> in Python. Here's a sample Python
|
||||
session:
|
||||
</p>
|
||||
<p>
|
||||
@@ -82,7 +82,7 @@
|
||||
<div class="titlepage"><div><div><h3 class="title">
|
||||
<a name="python.constructors"></a>Constructors</h3></div></div></div>
|
||||
<p>
|
||||
Our previous example didn't have any explicit constructors. Since <code class="literal">World</code>
|
||||
Our previous example didn't have any explicit constructors. Since <tt class="literal">World</tt>
|
||||
is declared as a plain struct, it has an implicit default constructor. Boost.Python
|
||||
exposes the default constructor by default, which is why we were able to
|
||||
write
|
||||
@@ -106,9 +106,9 @@
|
||||
<span class="special">};</span>
|
||||
</pre>
|
||||
<p>
|
||||
This time <code class="literal">World</code> has no default constructor; our previous
|
||||
This time <tt class="literal">World</tt> has no default constructor; our previous
|
||||
wrapping code would fail to compile when the library tried to expose it.
|
||||
We have to tell <code class="literal">class_<World></code> about the constructor
|
||||
We have to tell <tt class="literal">class_<World></tt> about the constructor
|
||||
we want to expose instead.
|
||||
</p>
|
||||
<pre class="programlisting">
|
||||
@@ -124,13 +124,13 @@
|
||||
<span class="special">}</span>
|
||||
</pre>
|
||||
<p>
|
||||
<code class="literal">init<std::string>()</code> exposes the constructor taking
|
||||
in a <code class="literal">std::string</code> (in Python, constructors are spelled
|
||||
"<code class="literal">"<span class="underline">_init</span>_"</code>").
|
||||
<tt class="literal">init<std::string>()</tt> exposes the constructor taking
|
||||
in a <tt class="literal">std::string</tt> (in Python, constructors are spelled
|
||||
"<tt class="literal">"<span class="underline">_init</span>_"</tt>").
|
||||
</p>
|
||||
<p>
|
||||
We can expose additional constructors by passing more <code class="literal">init<...></code>s
|
||||
to the <code class="literal">def()</code> member function. Say for example we have
|
||||
We can expose additional constructors by passing more <tt class="literal">init<...></tt>s
|
||||
to the <tt class="literal">def()</tt> member function. Say for example we have
|
||||
another World constructor taking in two doubles:
|
||||
</p>
|
||||
<pre class="programlisting">
|
||||
@@ -142,13 +142,13 @@
|
||||
</pre>
|
||||
<p>
|
||||
On the other hand, if we do not wish to expose any constructors at all, we
|
||||
may use <code class="literal">no_init</code> instead:
|
||||
may use <tt class="literal">no_init</tt> instead:
|
||||
</p>
|
||||
<pre class="programlisting">
|
||||
<span class="identifier">class_</span><span class="special"><</span><span class="identifier">Abstract</span><span class="special">>(</span><span class="string">"Abstract"</span><span class="special">,</span> <span class="identifier">no_init</span><span class="special">)</span>
|
||||
</pre>
|
||||
<p>
|
||||
This actually adds an <code class="literal"><span class="underline">_init</span>_</code>
|
||||
This actually adds an <tt class="literal"><span class="underline">_init</span>_</tt>
|
||||
method which always raises a Python RuntimeError exception.
|
||||
</p>
|
||||
</div>
|
||||
@@ -158,8 +158,8 @@
|
||||
<p>
|
||||
Data members may also be exposed to Python so that they can be accessed as
|
||||
attributes of the corresponding Python class. Each data member that we wish
|
||||
to be exposed may be regarded as <span class="bold"><strong>read-only</strong></span>
|
||||
or <span class="bold"><strong>read-write</strong></span>. Consider this class <code class="literal">Var</code>:
|
||||
to be exposed may be regarded as <span class="bold"><b>read-only</b></span>
|
||||
or <span class="bold"><b>read-write</b></span>. Consider this class <tt class="literal">Var</tt>:
|
||||
</p>
|
||||
<pre class="programlisting">
|
||||
<span class="keyword">struct</span> <span class="identifier">Var</span>
|
||||
@@ -170,7 +170,7 @@
|
||||
<span class="special">};</span>
|
||||
</pre>
|
||||
<p>
|
||||
Our C++ <code class="literal">Var</code> class and its data members can be exposed
|
||||
Our C++ <tt class="literal">Var</tt> class and its data members can be exposed
|
||||
to Python:
|
||||
</p>
|
||||
<pre class="programlisting">
|
||||
@@ -191,8 +191,8 @@
|
||||
<span class="identifier">pi</span> <span class="keyword">is</span> <span class="identifier">around</span> <span class="number">3.14</span>
|
||||
</pre>
|
||||
<p>
|
||||
Note that <code class="literal">name</code> is exposed as <span class="bold"><strong>read-only</strong></span>
|
||||
while <code class="literal">value</code> is exposed as <span class="bold"><strong>read-write</strong></span>.
|
||||
Note that <tt class="literal">name</tt> is exposed as <span class="bold"><b>read-only</b></span>
|
||||
while <tt class="literal">value</tt> is exposed as <span class="bold"><b>read-write</b></span>.
|
||||
</p>
|
||||
<pre class="programlisting">
|
||||
<span class="special">>>></span> <span class="identifier">x</span><span class="special">.</span><span class="identifier">name</span> <span class="special">=</span> <span class="string">'e'</span> <span class="comment"># can't change name
|
||||
@@ -224,7 +224,7 @@
|
||||
<p>
|
||||
However, in Python attribute access is fine; it doesn't neccessarily break
|
||||
encapsulation to let users handle attributes directly, because the attributes
|
||||
can just be a different syntax for a method call. Wrapping our <code class="literal">Num</code>
|
||||
can just be a different syntax for a method call. Wrapping our <tt class="literal">Num</tt>
|
||||
class using Boost.Python:
|
||||
</p>
|
||||
<pre class="programlisting">
|
||||
@@ -245,8 +245,8 @@
|
||||
<span class="special">>>></span> <span class="identifier">x</span><span class="special">.</span><span class="identifier">rovalue</span> <span class="special">=</span> <span class="number">2.17</span> <span class="comment"># error!
|
||||
</span></pre>
|
||||
<p>
|
||||
Take note that the class property <code class="literal">rovalue</code> is exposed as
|
||||
<span class="bold"><strong>read-only</strong></span> since the <code class="literal">rovalue</code>
|
||||
Take note that the class property <tt class="literal">rovalue</tt> is exposed as
|
||||
<span class="bold"><b>read-only</b></span> since the <tt class="literal">rovalue</tt>
|
||||
setter member function is not passed in:
|
||||
</p>
|
||||
<p>
|
||||
@@ -273,7 +273,7 @@
|
||||
<span class="keyword">struct</span> <span class="identifier">Derived</span> <span class="special">:</span> <span class="identifier">Base</span> <span class="special">{};</span>
|
||||
</pre>
|
||||
<p>
|
||||
And a set of C++ functions operating on <code class="literal">Base</code> and <code class="literal">Derived</code>
|
||||
And a set of C++ functions operating on <tt class="literal">Base</tt> and <tt class="literal">Derived</tt>
|
||||
object instances:
|
||||
</p>
|
||||
<pre class="programlisting">
|
||||
@@ -282,7 +282,7 @@
|
||||
<span class="identifier">Base</span><span class="special">*</span> <span class="identifier">factory</span><span class="special">()</span> <span class="special">{</span> <span class="keyword">return</span> <span class="keyword">new</span> <span class="identifier">Derived</span><span class="special">;</span> <span class="special">}</span>
|
||||
</pre>
|
||||
<p>
|
||||
We've seen how we can wrap the base class <code class="literal">Base</code>:
|
||||
We've seen how we can wrap the base class <tt class="literal">Base</tt>:
|
||||
</p>
|
||||
<pre class="programlisting">
|
||||
<span class="identifier">class_</span><span class="special"><</span><span class="identifier">Base</span><span class="special">>(</span><span class="string">"Base"</span><span class="special">)</span>
|
||||
@@ -290,8 +290,8 @@
|
||||
<span class="special">;</span>
|
||||
</pre>
|
||||
<p>
|
||||
Now we can inform Boost.Python of the inheritance relationship between <code class="literal">Derived</code>
|
||||
and its base class <code class="literal">Base</code>. Thus:
|
||||
Now we can inform Boost.Python of the inheritance relationship between <tt class="literal">Derived</tt>
|
||||
and its base class <tt class="literal">Base</tt>. Thus:
|
||||
</p>
|
||||
<pre class="programlisting">
|
||||
<span class="identifier">class_</span><span class="special"><</span><span class="identifier">Derived</span><span class="special">,</span> <span class="identifier">bases</span><span class="special"><</span><span class="identifier">Base</span><span class="special">></span> <span class="special">>(</span><span class="string">"Derived"</span><span class="special">)</span>
|
||||
@@ -307,15 +307,15 @@
|
||||
member functions)
|
||||
</li>
|
||||
<li>
|
||||
<span class="bold"><strong>If</strong></span> Base is polymorphic, <code class="literal">Derived</code>
|
||||
<span class="bold"><b>If</b></span> Base is polymorphic, <tt class="literal">Derived</tt>
|
||||
objects which have been passed to Python via a pointer or reference to
|
||||
<code class="literal">Base</code> can be passed where a pointer or reference to
|
||||
<code class="literal">Derived</code> is expected.
|
||||
<tt class="literal">Base</tt> can be passed where a pointer or reference to
|
||||
<tt class="literal">Derived</tt> is expected.
|
||||
</li>
|
||||
</ol></div>
|
||||
<p>
|
||||
Now, we shall expose the C++ free functions <code class="literal">b</code> and <code class="literal">d</code>
|
||||
and <code class="literal">factory</code>:
|
||||
Now, we will expose the C++ free functions <tt class="literal">b</tt> and <tt class="literal">d</tt>
|
||||
and <tt class="literal">factory</tt>:
|
||||
</p>
|
||||
<pre class="programlisting">
|
||||
<span class="identifier">def</span><span class="special">(</span><span class="string">"b"</span><span class="special">,</span> <span class="identifier">b</span><span class="special">);</span>
|
||||
@@ -323,12 +323,12 @@
|
||||
<span class="identifier">def</span><span class="special">(</span><span class="string">"factory"</span><span class="special">,</span> <span class="identifier">factory</span><span class="special">);</span>
|
||||
</pre>
|
||||
<p>
|
||||
Note that free function <code class="literal">factory</code> is being used to generate
|
||||
new instances of class <code class="literal">Derived</code>. In such cases, we use
|
||||
<code class="literal">return_value_policy<manage_new_object></code> to instruct
|
||||
Python to adopt the pointer to <code class="literal">Base</code> and hold the instance
|
||||
in a new Python <code class="literal">Base</code> object until the the Python object
|
||||
is destroyed. We shall see more of Boost.Python <a href="functions.html#python.call_policies" title="Call Policies">call
|
||||
Note that free function <tt class="literal">factory</tt> is being used to generate
|
||||
new instances of class <tt class="literal">Derived</tt>. In such cases, we use
|
||||
<tt class="literal">return_value_policy<manage_new_object></tt> to instruct
|
||||
Python to adopt the pointer to <tt class="literal">Base</tt> and hold the instance
|
||||
in a new Python <tt class="literal">Base</tt> object until the the Python object
|
||||
is destroyed. We will see more of Boost.Python <a href="functions.html#python.call_policies" title="Call Policies">call
|
||||
policies</a> later.
|
||||
</p>
|
||||
<pre class="programlisting">
|
||||
@@ -341,9 +341,9 @@
|
||||
<div class="titlepage"><div><div><h3 class="title">
|
||||
<a name="python.class_virtual_functions"></a>Class Virtual Functions</h3></div></div></div>
|
||||
<p>
|
||||
In this section, we shall learn how to make functions behave polymorphically
|
||||
In this section, we will learn how to make functions behave polymorphically
|
||||
through virtual functions. Continuing our example, let us add a virtual function
|
||||
to our <code class="literal">Base</code> class:
|
||||
to our <tt class="literal">Base</tt> class:
|
||||
</p>
|
||||
<pre class="programlisting">
|
||||
<span class="keyword">struct</span> <span class="identifier">Base</span>
|
||||
@@ -356,11 +356,11 @@
|
||||
One of the goals of Boost.Python is to be minimally intrusive on an existing
|
||||
C++ design. In principle, it should be possible to expose the interface for
|
||||
a 3rd party library without changing it. It is not ideal to add anything
|
||||
to our class <code class="computeroutput"><span class="identifier">Base</span></code>. Yet, when
|
||||
to our class <tt class="computeroutput"><span class="identifier">Base</span></tt>. Yet, when
|
||||
you have a virtual function that's going to be overridden in Python and called
|
||||
polymorphically <span class="bold"><strong>from C++</strong></span>, we'll need to
|
||||
polymorphically <span class="bold"><b>from C++</b></span>, we'll need to
|
||||
add some scaffoldings to make things work properly. What we'll do is write
|
||||
a class wrapper that derives from <code class="computeroutput"><span class="identifier">Base</span></code>
|
||||
a class wrapper that derives from <tt class="computeroutput"><span class="identifier">Base</span></tt>
|
||||
that will unintrusively hook into the virtual functions so that a Python
|
||||
override may be called:
|
||||
</p>
|
||||
@@ -374,24 +374,28 @@
|
||||
<span class="special">};</span>
|
||||
</pre>
|
||||
<p>
|
||||
Notice too that in addition to inheriting from <code class="computeroutput"><span class="identifier">Base</span></code>,
|
||||
we also multiply- inherited <code class="computeroutput"><span class="identifier">wrapper</span><span class="special"><</span><span class="identifier">Base</span><span class="special">></span></code> (See <a href="../../../../v2/wrapper.html" target="_top">Wrapper</a>).
|
||||
The <code class="computeroutput"><span class="identifier">wrapper</span></code> template makes
|
||||
Notice too that in addition to inheriting from <tt class="computeroutput"><span class="identifier">Base</span></tt>,
|
||||
we also multiply- inherited <tt class="computeroutput"><span class="identifier">wrapper</span><span class="special"><</span><span class="identifier">Base</span><span class="special">></span></tt> (See <a href="../../../../v2/wrapper.html" target="_top">Wrapper</a>).
|
||||
The <tt class="computeroutput"><span class="identifier">wrapper</span></tt> template makes
|
||||
the job of wrapping classes that are meant to overridden in Python, easier.
|
||||
</p>
|
||||
<div class="informaltable"><table class="table">
|
||||
<colgroup><col></colgroup>
|
||||
<tbody><tr><td class="blurb"> <span class="inlinemediaobject"><img src="../images/alert.png" alt="alert"></span> <span class="bold"><strong>MSVC6/7 Workaround</strong></span><br>
|
||||
<br> If you are using Microsoft Visual C++ 6 or 7, you have to write
|
||||
<code class="computeroutput"><span class="identifier">f</span></code> as:<br> <br>
|
||||
<code class="computeroutput"><span class="keyword">return</span> <span class="identifier">call</span><span class="special"><</span><span class="keyword">int</span><span class="special">>(</span><span class="keyword">this</span><span class="special">-></span><span class="identifier">get_override</span><span class="special">(</span><span class="string">"f"</span><span class="special">).</span><span class="identifier">ptr</span><span class="special">());</span></code>.</td></tr></tbody>
|
||||
</table></div>
|
||||
<div class="sidebar">
|
||||
<p>
|
||||
BaseWrap's overridden virtual member function <code class="computeroutput"><span class="identifier">f</span></code>
|
||||
in effect calls the corresponding method of the Python object through <code class="computeroutput"><span class="identifier">get_override</span></code>.
|
||||
<span class="inlinemediaobject"><img src="../images/alert.png" alt="alert"></span> <span class="bold"><b>MSVC6/7 Workaround</b></span>
|
||||
</p>
|
||||
<p>
|
||||
Finally, exposing <code class="computeroutput"><span class="identifier">Base</span></code>:
|
||||
If you are using Microsoft Visual C++ 6 or 7, you have to write <tt class="computeroutput"><span class="identifier">f</span></tt> as:
|
||||
</p>
|
||||
<p>
|
||||
<tt class="computeroutput"><span class="keyword">return</span> <span class="identifier">call</span><span class="special"><</span><span class="keyword">int</span><span class="special">>(</span><span class="keyword">this</span><span class="special">-></span><span class="identifier">get_override</span><span class="special">(</span><span class="string">"f"</span><span class="special">).</span><span class="identifier">ptr</span><span class="special">());</span></tt>.
|
||||
</p>
|
||||
</div>
|
||||
<p>
|
||||
BaseWrap's overridden virtual member function <tt class="computeroutput"><span class="identifier">f</span></tt>
|
||||
in effect calls the corresponding method of the Python object through <tt class="computeroutput"><span class="identifier">get_override</span></tt>.
|
||||
</p>
|
||||
<p>
|
||||
Finally, exposing <tt class="computeroutput"><span class="identifier">Base</span></tt>:
|
||||
</p>
|
||||
<pre class="programlisting">
|
||||
<span class="identifier">class_</span><span class="special"><</span><span class="identifier">BaseWrap</span><span class="special">,</span> <span class="identifier">boost</span><span class="special">::</span><span class="identifier">noncopyable</span><span class="special">>(</span><span class="string">"Base"</span><span class="special">)</span>
|
||||
@@ -399,17 +403,24 @@
|
||||
<span class="special">;</span>
|
||||
</pre>
|
||||
<p>
|
||||
<code class="computeroutput"><span class="identifier">pure_virtual</span></code> signals Boost.Python
|
||||
that the function <code class="computeroutput"><span class="identifier">f</span></code> is a
|
||||
<tt class="computeroutput"><span class="identifier">pure_virtual</span></tt> signals Boost.Python
|
||||
that the function <tt class="computeroutput"><span class="identifier">f</span></tt> is a
|
||||
pure virtual function.
|
||||
</p>
|
||||
<div class="informaltable"><table class="table">
|
||||
<colgroup><col></colgroup>
|
||||
<tbody><tr><td class="blurb"> <span class="inlinemediaobject"><img src="../images/note.png" alt="note"></span> <span class="bold"><strong>member function and
|
||||
methods</strong></span><br> <br> Python, like many object oriented languages
|
||||
uses the term <span class="bold"><strong>methods</strong></span>. Methods correspond
|
||||
roughly to C++'s <span class="bold"><strong>member functions</strong></span>
|
||||
</td></tr></tbody>
|
||||
<div class="note"><table border="0" summary="Note">
|
||||
<tr>
|
||||
<td rowspan="2" align="center" valign="top" width="25"><img alt="[Note]" src="../../../../../../../doc/html/images/note.png"></td>
|
||||
<th align="left">Note</th>
|
||||
</tr>
|
||||
<tr><td colspan="2" align="left" valign="top">
|
||||
<p>
|
||||
<span class="bold"><b>member function and methods</b></span>
|
||||
</p>
|
||||
<p>
|
||||
Python, like many object oriented languages uses the term <span class="bold"><b>methods</b></span>.
|
||||
Methods correspond roughly to C++'s <span class="bold"><b>member functions</b></span>
|
||||
</p>
|
||||
</td></tr>
|
||||
</table></div>
|
||||
</div>
|
||||
<div class="section" lang="en">
|
||||
@@ -418,7 +429,7 @@
|
||||
<p>
|
||||
We've seen in the previous section how classes with pure virtual functions
|
||||
are wrapped using Boost.Python's <a href="../../../../v2/wrapper.html" target="_top">class
|
||||
wrapper</a> facilities. If we wish to wrap <span class="bold"><strong>non</strong></span>-pure-virtual
|
||||
wrapper</a> facilities. If we wish to wrap <span class="bold"><b>non</b></span>-pure-virtual
|
||||
functions instead, the mechanism is a bit different.
|
||||
</p>
|
||||
<p>
|
||||
@@ -433,8 +444,8 @@
|
||||
<span class="special">};</span>
|
||||
</pre>
|
||||
<p>
|
||||
had a pure virtual function <code class="literal">f</code>. If, however, its member
|
||||
function <code class="literal">f</code> was not declared as pure virtual:
|
||||
had a pure virtual function <tt class="literal">f</tt>. If, however, its member
|
||||
function <tt class="literal">f</tt> was not declared as pure virtual:
|
||||
</p>
|
||||
<pre class="programlisting">
|
||||
<span class="keyword">struct</span> <span class="identifier">Base</span>
|
||||
@@ -460,16 +471,22 @@
|
||||
<span class="special">};</span>
|
||||
</pre>
|
||||
<p>
|
||||
Notice how we implemented <code class="computeroutput"><span class="identifier">BaseWrap</span><span class="special">::</span><span class="identifier">f</span></code>. Now,
|
||||
we have to check if there is an override for <code class="computeroutput"><span class="identifier">f</span></code>.
|
||||
If none, then we call <code class="computeroutput"><span class="identifier">Base</span><span class="special">::</span><span class="identifier">f</span><span class="special">()</span></code>.
|
||||
Notice how we implemented <tt class="computeroutput"><span class="identifier">BaseWrap</span><span class="special">::</span><span class="identifier">f</span></tt>. Now,
|
||||
we have to check if there is an override for <tt class="computeroutput"><span class="identifier">f</span></tt>.
|
||||
If none, then we call <tt class="computeroutput"><span class="identifier">Base</span><span class="special">::</span><span class="identifier">f</span><span class="special">()</span></tt>.
|
||||
</p>
|
||||
<div class="informaltable"><table class="table">
|
||||
<colgroup><col></colgroup>
|
||||
<tbody><tr><td class="blurb"> <span class="inlinemediaobject"><img src="../images/alert.png" alt="alert"></span> <span class="bold"><strong>MSVC6/7 Workaround</strong></span><br>
|
||||
<br> If you are using Microsoft Visual C++ 6 or 7, you have to rewrite
|
||||
the line with the <code class="computeroutput"><span class="special">*</span><span class="identifier">note</span><span class="special">*</span></code> as:<br> <br> <code class="computeroutput"><span class="keyword">return</span> <span class="identifier">call</span><span class="special"><</span><span class="keyword">char</span> <span class="keyword">const</span><span class="special">*>(</span><span class="identifier">f</span><span class="special">.</span><span class="identifier">ptr</span><span class="special">());</span></code>.</td></tr></tbody>
|
||||
</table></div>
|
||||
<div class="sidebar">
|
||||
<p>
|
||||
<span class="inlinemediaobject"><img src="../images/alert.png" alt="alert"></span> <span class="bold"><b>MSVC6/7 Workaround</b></span>
|
||||
</p>
|
||||
<p>
|
||||
If you are using Microsoft Visual C++ 6 or 7, you have to rewrite the line
|
||||
with the <tt class="computeroutput"><span class="special">*</span><span class="identifier">note</span><span class="special">*</span></tt> as:
|
||||
</p>
|
||||
<p>
|
||||
<tt class="computeroutput"><span class="keyword">return</span> <span class="identifier">call</span><span class="special"><</span><span class="keyword">char</span> <span class="keyword">const</span><span class="special">*>(</span><span class="identifier">f</span><span class="special">.</span><span class="identifier">ptr</span><span class="special">());</span></tt>.
|
||||
</p>
|
||||
</div>
|
||||
<p>
|
||||
Finally, exposing:
|
||||
</p>
|
||||
@@ -479,10 +496,10 @@
|
||||
<span class="special">;</span>
|
||||
</pre>
|
||||
<p>
|
||||
Take note that we expose both <code class="computeroutput"><span class="special">&</span><span class="identifier">Base</span><span class="special">::</span><span class="identifier">f</span></code> and <code class="computeroutput"><span class="special">&</span><span class="identifier">BaseWrap</span><span class="special">::</span><span class="identifier">default_f</span></code>. Boost.Python needs to keep track
|
||||
of 1) the dispatch function <code class="literal">f</code> and 2) the forwarding function
|
||||
to its default implementation <code class="literal">default_f</code>. There's a special
|
||||
<code class="literal">def</code> function for this purpose.
|
||||
Take note that we expose both <tt class="computeroutput"><span class="special">&</span><span class="identifier">Base</span><span class="special">::</span><span class="identifier">f</span></tt> and <tt class="computeroutput"><span class="special">&</span><span class="identifier">BaseWrap</span><span class="special">::</span><span class="identifier">default_f</span></tt>. Boost.Python needs to keep track
|
||||
of 1) the dispatch function <tt class="literal">f</tt> and 2) the forwarding function
|
||||
to its default implementation <tt class="literal">default_f</tt>. There's a special
|
||||
<tt class="literal">def</tt> function for this purpose.
|
||||
</p>
|
||||
<p>
|
||||
In Python, the results would be as expected:
|
||||
@@ -498,14 +515,14 @@
|
||||
<span class="special">>>></span> <span class="identifier">derived</span> <span class="special">=</span> <span class="identifier">Derived</span><span class="special">()</span>
|
||||
</pre>
|
||||
<p>
|
||||
Calling <code class="literal">base.f()</code>:
|
||||
Calling <tt class="literal">base.f()</tt>:
|
||||
</p>
|
||||
<pre class="programlisting">
|
||||
<span class="special">>>></span> <span class="identifier">base</span><span class="special">.</span><span class="identifier">f</span><span class="special">()</span>
|
||||
<span class="number">0</span>
|
||||
</pre>
|
||||
<p>
|
||||
Calling <code class="literal">derived.f()</code>:
|
||||
Calling <tt class="literal">derived.f()</tt>:
|
||||
</p>
|
||||
<pre class="programlisting">
|
||||
<span class="special">>>></span> <span class="identifier">derived</span><span class="special">.</span><span class="identifier">f</span><span class="special">()</span>
|
||||
@@ -515,17 +532,17 @@
|
||||
<div class="section" lang="en">
|
||||
<div class="titlepage"><div><div><h3 class="title">
|
||||
<a name="python.class_operators_special_functions"></a>Class Operators/Special Functions</h3></div></div></div>
|
||||
<a name="class_operators_special_functions.python_operators"></a><h3>
|
||||
<a name="id3142031"></a>
|
||||
<a name="class_operators_special_functions.python_operators"></a><h2>
|
||||
<a name="id461478"></a>
|
||||
Python Operators
|
||||
</h3>
|
||||
</h2>
|
||||
<p>
|
||||
C is well known for the abundance of operators. C++ extends this to the extremes
|
||||
by allowing operator overloading. Boost.Python takes advantage of this and
|
||||
makes it easy to wrap C++ operator-powered classes.
|
||||
</p>
|
||||
<p>
|
||||
Consider a file position class <code class="literal">FilePos</code> and a set of operators
|
||||
Consider a file position class <tt class="literal">FilePos</tt> and a set of operators
|
||||
that take on FilePos instances:
|
||||
</p>
|
||||
<p>
|
||||
@@ -558,16 +575,16 @@
|
||||
<p>
|
||||
The code snippet above is very clear and needs almost no explanation at all.
|
||||
It is virtually the same as the operators' signatures. Just take note that
|
||||
<code class="literal">self</code> refers to FilePos object. Also, not every class
|
||||
<code class="literal">T</code> that you might need to interact with in an operator
|
||||
expression is (cheaply) default-constructible. You can use <code class="literal">other<T>()</code>
|
||||
in place of an actual <code class="literal">T</code> instance when writing "self
|
||||
<tt class="literal">self</tt> refers to FilePos object. Also, not every class
|
||||
<tt class="literal">T</tt> that you might need to interact with in an operator
|
||||
expression is (cheaply) default-constructible. You can use <tt class="literal">other<T>()</tt>
|
||||
in place of an actual <tt class="literal">T</tt> instance when writing "self
|
||||
expressions".
|
||||
</p>
|
||||
<a name="class_operators_special_functions.special_methods"></a><h3>
|
||||
<a name="id3142715"></a>
|
||||
<a name="class_operators_special_functions.special_methods"></a><h2>
|
||||
<a name="id462235"></a>
|
||||
Special Methods
|
||||
</h3>
|
||||
</h2>
|
||||
<p>
|
||||
Python has a few more <span class="emphasis"><em>Special Methods</em></span>. Boost.Python
|
||||
supports all of the standard special method names supported by real Python
|
||||
@@ -593,21 +610,30 @@
|
||||
<p>
|
||||
Need we say more?
|
||||
</p>
|
||||
<div class="informaltable"><table class="table">
|
||||
<colgroup><col></colgroup>
|
||||
<tbody><tr><td class="blurb"> <span class="inlinemediaobject"><img src="../images/note.png" alt="note"></span> What is the business of <code class="computeroutput"><span class="keyword">operator</span><span class="special"><<</span></code>? Well, the method <code class="computeroutput"><span class="identifier">str</span></code> requires the <code class="computeroutput"><span class="keyword">operator</span><span class="special"><<</span></code> to do its work (i.e. <code class="computeroutput"><span class="keyword">operator</span><span class="special"><<</span></code>
|
||||
is used by the method defined by <code class="computeroutput"><span class="identifier">def</span><span class="special">(</span><span class="identifier">str</span><span class="special">(</span><span class="identifier">self</span><span class="special">))</span></code>.</td></tr></tbody>
|
||||
<div class="note"><table border="0" summary="Note">
|
||||
<tr>
|
||||
<td rowspan="2" align="center" valign="top" width="25"><img alt="[Note]" src="../../../../../../../doc/html/images/note.png"></td>
|
||||
<th align="left">Note</th>
|
||||
</tr>
|
||||
<tr><td colspan="2" align="left" valign="top"><p>
|
||||
What is the business of <tt class="computeroutput"><span class="keyword">operator</span><span class="special"><<</span></tt>? Well, the method <tt class="computeroutput"><span class="identifier">str</span></tt> requires the <tt class="computeroutput"><span class="keyword">operator</span><span class="special"><<</span></tt> to do its work (i.e. <tt class="computeroutput"><span class="keyword">operator</span><span class="special"><<</span></tt>
|
||||
is used by the method defined by <tt class="computeroutput"><span class="identifier">def</span><span class="special">(</span><span class="identifier">str</span><span class="special">(</span><span class="identifier">self</span><span class="special">))</span></tt>.
|
||||
</p></td></tr>
|
||||
</table></div>
|
||||
</div>
|
||||
</div>
|
||||
<table xmlns:rev="http://www.cs.rpi.edu/~gregod/boost/tools/doc/revision" width="100%"><tr>
|
||||
<td align="left"></td>
|
||||
<td align="right"><small>Copyright © 2002-2005 Joel
|
||||
de Guzman, David Abrahams</small></td>
|
||||
<td align="right"><div class="copyright-footer"><small>Copyright © 2002-2005 Joel
|
||||
de Guzman, David Abrahams<p>
|
||||
Distributed under the Boost Software License, Version 1.0. (See accompanying
|
||||
file LICENSE_1_0.txt or copy at <a href="http://www.boost.org/LICENSE_1_0.txt" target="_top">
|
||||
http://www.boost.org/LICENSE_1_0.txt </a>)
|
||||
</p></small></div></td>
|
||||
</tr></table>
|
||||
<hr>
|
||||
<div class="spirit-nav">
|
||||
<a accesskey="p" href="hello.html"><img src="../images/prev.png" alt="Prev"></a><a accesskey="u" href="../index.html"><img src="../images/up.png" alt="Up"></a><a accesskey="h" href="../index.html"><img src="../images/home.png" alt="Home"></a><a accesskey="n" href="functions.html"><img src="../images/next.png" alt="Next"></a>
|
||||
<a accesskey="p" href="hello.html"><img src="../../../../../../../doc/html/images/prev.png" alt="Prev"></a><a accesskey="u" href="../index.html"><img src="../../../../../../../doc/html/images/up.png" alt="Up"></a><a accesskey="h" href="../index.html"><img src="../../../../../../../doc/html/images/home.png" alt="Home"></a><a accesskey="n" href="functions.html"><img src="../../../../../../../doc/html/images/next.png" alt="Next"></a>
|
||||
</div>
|
||||
</body>
|
||||
</html>
|
||||
|
||||
@@ -2,25 +2,25 @@
|
||||
<head>
|
||||
<meta http-equiv="Content-Type" content="text/html; charset=ISO-8859-1">
|
||||
<title>Functions</title>
|
||||
<link rel="stylesheet" href="../boostbook.css" type="text/css">
|
||||
<meta name="generator" content="DocBook XSL Stylesheets V1.72.0">
|
||||
<link rel="stylesheet" href="../../../../../../../doc/html/boostbook.css" type="text/css">
|
||||
<meta name="generator" content="DocBook XSL Stylesheets V1.66.1">
|
||||
<link rel="start" href="../index.html" title="Chapter 1. python 1.0">
|
||||
<link rel="up" href="../index.html" title="Chapter 1. python 1.0">
|
||||
<link rel="prev" href="exposing.html" title="Exposing Classes">
|
||||
<link rel="next" href="object.html" title="Object Interface">
|
||||
<link rel="prev" href="exposing.html" title=" Exposing Classes">
|
||||
<link rel="next" href="object.html" title=" Object Interface">
|
||||
</head>
|
||||
<body bgcolor="white" text="black" link="#0000FF" vlink="#840084" alink="#0000FF">
|
||||
<table cellpadding="2" width="100%">
|
||||
<table cellpadding="2" width="100%"><tr>
|
||||
<td valign="top"><img alt="Boost C++ Libraries" width="277" height="86" src="../../../../../../../boost.png"></td>
|
||||
<td align="center"><a href="../../../../../../../index.htm">Home</a></td>
|
||||
<td align="center"><a href="../../../../../../../libs/libraries.htm">Libraries</a></td>
|
||||
<td align="center"><a href="../../../../../../../people/people.htm">People</a></td>
|
||||
<td align="center"><a href="../../../../../../../more/faq.htm">FAQ</a></td>
|
||||
<td align="center"><a href="../../../../../../../more/index.htm">More</a></td>
|
||||
</table>
|
||||
</tr></table>
|
||||
<hr>
|
||||
<div class="spirit-nav">
|
||||
<a accesskey="p" href="exposing.html"><img src="../images/prev.png" alt="Prev"></a><a accesskey="u" href="../index.html"><img src="../images/up.png" alt="Up"></a><a accesskey="h" href="../index.html"><img src="../images/home.png" alt="Home"></a><a accesskey="n" href="object.html"><img src="../images/next.png" alt="Next"></a>
|
||||
<a accesskey="p" href="exposing.html"><img src="../../../../../../../doc/html/images/prev.png" alt="Prev"></a><a accesskey="u" href="../index.html"><img src="../../../../../../../doc/html/images/up.png" alt="Up"></a><a accesskey="h" href="../index.html"><img src="../../../../../../../doc/html/images/home.png" alt="Home"></a><a accesskey="n" href="object.html"><img src="../../../../../../../doc/html/images/next.png" alt="Next"></a>
|
||||
</div>
|
||||
<div class="section" lang="en">
|
||||
<div class="titlepage"><div><div><h2 class="title" style="clear: both">
|
||||
@@ -33,17 +33,23 @@
|
||||
</dl></div>
|
||||
<p>
|
||||
In this chapter, we'll look at Boost.Python powered functions in closer detail.
|
||||
We shall see some facilities to make exposing C++ functions to Python safe
|
||||
from potential pifalls such as dangling pointers and references. We shall also
|
||||
see facilities that will make it even easier for us to expose C++ functions
|
||||
that take advantage of C++ features such as overloading and default arguments.
|
||||
We will see some facilities to make exposing C++ functions to Python safe from
|
||||
potential pifalls such as dangling pointers and references. We will also see
|
||||
facilities that will make it even easier for us to expose C++ functions that
|
||||
take advantage of C++ features such as overloading and default arguments.
|
||||
</p>
|
||||
<div class="blockquote"><blockquote class="blockquote"><p>
|
||||
<span class="emphasis"><em>Read on...</em></span>
|
||||
</p></blockquote></div>
|
||||
<div class="blockquote"><blockquote class="blockquote">
|
||||
<p>
|
||||
</p>
|
||||
<p>
|
||||
<span class="emphasis"><em>Read on...</em></span>
|
||||
</p>
|
||||
<p>
|
||||
</p>
|
||||
</blockquote></div>
|
||||
<p>
|
||||
But before you do, you might want to fire up Python 2.2 or later and type
|
||||
<code class="literal">>>> import this</code>.
|
||||
<tt class="literal">>>> import this</tt>.
|
||||
</p>
|
||||
<pre class="programlisting">>>> import this
|
||||
The Zen of Python, by Tim Peters
|
||||
@@ -62,7 +68,7 @@ In the face of ambiguity, refuse the temptation to guess.
|
||||
There should be one-- and preferably only one --obvious way to do it
|
||||
Although that way may not be obvious at first unless you're Dutch.
|
||||
Now is better than never.
|
||||
Although never is often better than <span class="bold"><strong>right</strong></span> now.
|
||||
Although never is often better than <span class="bold"><b>right</b></span> now.
|
||||
If the implementation is hard to explain, it's a bad idea.
|
||||
If the implementation is easy to explain, it may be a good idea.
|
||||
Namespaces are one honking great idea -- let's do more of those!
|
||||
@@ -90,9 +96,9 @@ Namespaces are one honking great idea -- let's do more of those!
|
||||
Here's an example where it didn't
|
||||
</p>
|
||||
<pre class="programlisting">
|
||||
<span class="special">>>></span> <span class="identifier">x</span> <span class="special">=</span> <span class="identifier">f</span><span class="special">(</span><span class="identifier">y</span><span class="special">,</span> <span class="identifier">z</span><span class="special">)</span> # <span class="identifier">x</span> <span class="identifier">refers</span> <span class="identifier">to</span> <span class="identifier">some</span> <span class="identifier">C</span><span class="special">++</span> <span class="identifier">X</span>
|
||||
<span class="special">>>></span> <span class="identifier">x</span> <span class="special">=</span> <span class="identifier">f</span><span class="special">(</span><span class="identifier">y</span><span class="special">,</span> <span class="identifier">z</span><span class="special">)</span> <span class="preprocessor"># x</span> <span class="identifier">refers</span> <span class="identifier">to</span> <span class="identifier">some</span> <span class="identifier">C</span><span class="special">++</span> <span class="identifier">X</span>
|
||||
<span class="special">>>></span> <span class="identifier">del</span> <span class="identifier">y</span>
|
||||
<span class="special">>>></span> <span class="identifier">x</span><span class="special">.</span><span class="identifier">some_method</span><span class="special">()</span> # <span class="identifier">CRASH</span><span class="special">!</span>
|
||||
<span class="special">>>></span> <span class="identifier">x</span><span class="special">.</span><span class="identifier">some_method</span><span class="special">()</span> <span class="preprocessor"># CRASH</span><span class="special">!</span>
|
||||
</pre>
|
||||
<p>
|
||||
What's the problem?
|
||||
@@ -120,19 +126,19 @@ Namespaces are one honking great idea -- let's do more of those!
|
||||
</p>
|
||||
<div class="orderedlist"><ol type="1">
|
||||
<li>
|
||||
<code class="literal">f</code> is called passing in a reference to <code class="literal">y</code>
|
||||
and a pointer to <code class="literal">z</code>
|
||||
<tt class="literal">f</tt> is called passing in a reference to <tt class="literal">y</tt>
|
||||
and a pointer to <tt class="literal">z</tt>
|
||||
</li>
|
||||
<li>
|
||||
A reference to <code class="literal">y.x</code> is returned
|
||||
A reference to <tt class="literal">y.x</tt> is returned
|
||||
</li>
|
||||
<li>
|
||||
<code class="literal">y</code> is deleted. <code class="literal">x</code> is a dangling reference
|
||||
<tt class="literal">y</tt> is deleted. <tt class="literal">x</tt> is a dangling reference
|
||||
</li>
|
||||
<li>
|
||||
<code class="literal">x.some_method()</code> is called
|
||||
<tt class="literal">x.some_method()</tt> is called
|
||||
</li>
|
||||
<li><span class="bold"><strong>BOOM!</strong></span></li>
|
||||
<li><span class="bold"><b>BOOM!</b></span></li>
|
||||
</ol></div>
|
||||
<p>
|
||||
We could copy result into a new object:
|
||||
@@ -162,16 +168,16 @@ Namespaces are one honking great idea -- let's do more of those!
|
||||
<span class="special">};</span>
|
||||
</pre>
|
||||
<p>
|
||||
Notice that the data member <code class="literal">z</code> is held by class Y using
|
||||
Notice that the data member <tt class="literal">z</tt> is held by class Y using
|
||||
a raw pointer. Now we have a potential dangling pointer problem inside Y:
|
||||
</p>
|
||||
<pre class="programlisting">
|
||||
<span class="special">>>></span> <span class="identifier">x</span> <span class="special">=</span> <span class="identifier">f</span><span class="special">(</span><span class="identifier">y</span><span class="special">,</span> <span class="identifier">z</span><span class="special">)</span> # <span class="identifier">y</span> <span class="identifier">refers</span> <span class="identifier">to</span> <span class="identifier">z</span>
|
||||
<span class="special">>>></span> <span class="identifier">del</span> <span class="identifier">z</span> # <span class="identifier">Kill</span> <span class="identifier">the</span> <span class="identifier">z</span> <span class="identifier">object</span>
|
||||
<span class="special">>>></span> <span class="identifier">y</span><span class="special">.</span><span class="identifier">z_value</span><span class="special">()</span> # <span class="identifier">CRASH</span><span class="special">!</span>
|
||||
<span class="special">>>></span> <span class="identifier">x</span> <span class="special">=</span> <span class="identifier">f</span><span class="special">(</span><span class="identifier">y</span><span class="special">,</span> <span class="identifier">z</span><span class="special">)</span> <span class="preprocessor"># y</span> <span class="identifier">refers</span> <span class="identifier">to</span> <span class="identifier">z</span>
|
||||
<span class="special">>>></span> <span class="identifier">del</span> <span class="identifier">z</span> <span class="preprocessor"># Kill</span> <span class="identifier">the</span> <span class="identifier">z</span> <span class="identifier">object</span>
|
||||
<span class="special">>>></span> <span class="identifier">y</span><span class="special">.</span><span class="identifier">z_value</span><span class="special">()</span> <span class="preprocessor"># CRASH</span><span class="special">!</span>
|
||||
</pre>
|
||||
<p>
|
||||
For reference, here's the implementation of <code class="literal">f</code> again:
|
||||
For reference, here's the implementation of <tt class="literal">f</tt> again:
|
||||
</p>
|
||||
<pre class="programlisting">
|
||||
<span class="identifier">X</span><span class="special">&</span> <span class="identifier">f</span><span class="special">(</span><span class="identifier">Y</span><span class="special">&</span> <span class="identifier">y</span><span class="special">,</span> <span class="identifier">Z</span><span class="special">*</span> <span class="identifier">z</span><span class="special">)</span>
|
||||
@@ -185,33 +191,33 @@ Namespaces are one honking great idea -- let's do more of those!
|
||||
</p>
|
||||
<div class="orderedlist"><ol type="1">
|
||||
<li>
|
||||
<code class="literal">f</code> is called passing in a reference to <code class="literal">y</code>
|
||||
and a pointer to <code class="literal">z</code>
|
||||
<tt class="literal">f</tt> is called passing in a reference to <tt class="literal">y</tt>
|
||||
and a pointer to <tt class="literal">z</tt>
|
||||
</li>
|
||||
<li>
|
||||
A pointer to <code class="literal">z</code> is held by <code class="literal">y</code>
|
||||
A pointer to <tt class="literal">z</tt> is held by <tt class="literal">y</tt>
|
||||
</li>
|
||||
<li>
|
||||
A reference to <code class="literal">y.x</code> is returned
|
||||
A reference to <tt class="literal">y.x</tt> is returned
|
||||
</li>
|
||||
<li>
|
||||
<code class="literal">z</code> is deleted. <code class="literal">y.z</code> is a dangling pointer
|
||||
<tt class="literal">z</tt> is deleted. <tt class="literal">y.z</tt> is a dangling pointer
|
||||
</li>
|
||||
<li>
|
||||
<code class="literal">y.z_value()</code> is called
|
||||
<tt class="literal">y.z_value()</tt> is called
|
||||
</li>
|
||||
<li>
|
||||
<code class="literal">z->value()</code> is called
|
||||
<tt class="literal">z->value()</tt> is called
|
||||
</li>
|
||||
<li><span class="bold"><strong>BOOM!</strong></span></li>
|
||||
<li><span class="bold"><b>BOOM!</b></span></li>
|
||||
</ol></div>
|
||||
<a name="call_policies.call_policies"></a><h3>
|
||||
<a name="id3144432"></a>
|
||||
<a name="call_policies.call_policies"></a><h2>
|
||||
<a name="id464095"></a>
|
||||
Call Policies
|
||||
</h3>
|
||||
</h2>
|
||||
<p>
|
||||
Call Policies may be used in situations such as the example detailed above.
|
||||
In our example, <code class="literal">return_internal_reference</code> and <code class="literal">with_custodian_and_ward</code>
|
||||
In our example, <tt class="literal">return_internal_reference</tt> and <tt class="literal">with_custodian_and_ward</tt>
|
||||
are our friends:
|
||||
</p>
|
||||
<pre class="programlisting">
|
||||
@@ -220,27 +226,27 @@ Namespaces are one honking great idea -- let's do more of those!
|
||||
<span class="identifier">with_custodian_and_ward</span><span class="special"><</span><span class="number">1</span><span class="special">,</span> <span class="number">2</span><span class="special">></span> <span class="special">>());</span>
|
||||
</pre>
|
||||
<p>
|
||||
What are the <code class="literal">1</code> and <code class="literal">2</code> parameters, you
|
||||
What are the <tt class="literal">1</tt> and <tt class="literal">2</tt> parameters, you
|
||||
ask?
|
||||
</p>
|
||||
<pre class="programlisting">
|
||||
<span class="identifier">return_internal_reference</span><span class="special"><</span><span class="number">1</span>
|
||||
</pre>
|
||||
<p>
|
||||
Informs Boost.Python that the first argument, in our case <code class="literal">Y&
|
||||
y</code>, is the owner of the returned reference: <code class="literal">X&</code>.
|
||||
The "<code class="literal">1</code>" simply specifies the first argument.
|
||||
In short: "return an internal reference <code class="literal">X&</code> owned
|
||||
by the 1st argument <code class="literal">Y& y</code>".
|
||||
Informs Boost.Python that the first argument, in our case <tt class="literal">Y&
|
||||
y</tt>, is the owner of the returned reference: <tt class="literal">X&</tt>.
|
||||
The "<tt class="literal">1</tt>" simply specifies the first argument.
|
||||
In short: "return an internal reference <tt class="literal">X&</tt> owned
|
||||
by the 1st argument <tt class="literal">Y& y</tt>".
|
||||
</p>
|
||||
<pre class="programlisting">
|
||||
<span class="identifier">with_custodian_and_ward</span><span class="special"><</span><span class="number">1</span><span class="special">,</span> <span class="number">2</span><span class="special">></span>
|
||||
</pre>
|
||||
<p>
|
||||
Informs Boost.Python that the lifetime of the argument indicated by ward
|
||||
(i.e. the 2nd argument: <code class="literal">Z* z</code>) is dependent on the lifetime
|
||||
of the argument indicated by custodian (i.e. the 1st argument: <code class="literal">Y&
|
||||
y</code>).
|
||||
(i.e. the 2nd argument: <tt class="literal">Z* z</tt>) is dependent on the lifetime
|
||||
of the argument indicated by custodian (i.e. the 1st argument: <tt class="literal">Y&
|
||||
y</tt>).
|
||||
</p>
|
||||
<p>
|
||||
It is also important to note that we have defined two policies above. Two
|
||||
@@ -257,43 +263,48 @@ Namespaces are one honking great idea -- let's do more of those!
|
||||
</p>
|
||||
<div class="itemizedlist"><ul type="disc">
|
||||
<li>
|
||||
<span class="bold"><strong>with_custodian_and_ward</strong></span><br> Ties lifetimes
|
||||
<span class="bold"><b>with_custodian_and_ward</b></span>: Ties lifetimes
|
||||
of the arguments
|
||||
</li>
|
||||
<li>
|
||||
<span class="bold"><strong>with_custodian_and_ward_postcall</strong></span><br>
|
||||
Ties lifetimes of the arguments and results
|
||||
<span class="bold"><b>with_custodian_and_ward_postcall</b></span>: Ties
|
||||
lifetimes of the arguments and results
|
||||
</li>
|
||||
<li>
|
||||
<span class="bold"><strong>return_internal_reference</strong></span><br> Ties lifetime
|
||||
<span class="bold"><b>return_internal_reference</b></span>: Ties lifetime
|
||||
of one argument to that of result
|
||||
</li>
|
||||
<li>
|
||||
<span class="bold"><strong>return_value_policy<T> with T one of:</strong></span><br>
|
||||
</li>
|
||||
<span class="bold"><b>return_value_policy<T> with T one of:</b></span><div class="itemizedlist"><ul type="circle">
|
||||
<li>
|
||||
<span class="bold"><strong>reference_existing_object</strong></span><br> naive
|
||||
(dangerous) approach
|
||||
</li>
|
||||
<span class="bold"><b>reference_existing_object</b></span>: naive (dangerous)
|
||||
approach
|
||||
</li>
|
||||
<li>
|
||||
<span class="bold"><strong>copy_const_reference</strong></span><br> Boost.Python
|
||||
v1 approach
|
||||
</li>
|
||||
<span class="bold"><b>copy_const_reference</b></span>: Boost.Python
|
||||
v1 approach
|
||||
</li>
|
||||
<li>
|
||||
<span class="bold"><strong>copy_non_const_reference</strong></span><br>
|
||||
</li>
|
||||
<span class="bold"><b>copy_non_const_reference</b></span>:
|
||||
</li>
|
||||
<li>
|
||||
<span class="bold"><strong>manage_new_object</strong></span><br> Adopt a pointer
|
||||
and hold the instance
|
||||
</li>
|
||||
<span class="bold"><b>manage_new_object</b></span>: Adopt a pointer
|
||||
and hold the instance
|
||||
</li>
|
||||
</ul></div>
|
||||
<div class="informaltable"><table class="table">
|
||||
<colgroup><col></colgroup>
|
||||
<tbody><tr><td class="blurb"> <span class="inlinemediaobject"><img src="../images/smiley.png" alt="smiley"></span> <span class="bold"><strong>Remember the Zen, Luke:</strong></span><br>
|
||||
<br> "Explicit is better than implicit"<br> "In
|
||||
the face of ambiguity, refuse the temptation to guess"<br>
|
||||
</td></tr></tbody>
|
||||
</table></div>
|
||||
</li>
|
||||
</ul></div>
|
||||
<div class="sidebar">
|
||||
<p>
|
||||
<span class="inlinemediaobject"><img src="../images/smiley.png" alt="smiley"></span> <span class="bold"><b>Remember the Zen, Luke:</b></span>
|
||||
</p>
|
||||
<p>
|
||||
"Explicit is better than implicit"
|
||||
</p>
|
||||
<p>
|
||||
"In the face of ambiguity, refuse the temptation to guess"
|
||||
</p>
|
||||
</div>
|
||||
</div>
|
||||
<div class="section" lang="en">
|
||||
<div class="titlepage"><div><div><h3 class="title">
|
||||
@@ -331,7 +342,7 @@ Namespaces are one honking great idea -- let's do more of those!
|
||||
<span class="special">};</span>
|
||||
</pre>
|
||||
<p>
|
||||
Class X has 4 overloaded functions. We shall start by introducing some member
|
||||
Class X has 4 overloaded functions. We will start by introducing some member
|
||||
function pointer variables:
|
||||
</p>
|
||||
<pre class="programlisting">
|
||||
@@ -355,21 +366,21 @@ Namespaces are one honking great idea -- let's do more of those!
|
||||
<a name="python.default_arguments"></a>Default Arguments</h3></div></div></div>
|
||||
<p>
|
||||
Boost.Python wraps (member) function pointers. Unfortunately, C++ function
|
||||
pointers carry no default argument info. Take a function <code class="literal">f</code>
|
||||
pointers carry no default argument info. Take a function <tt class="literal">f</tt>
|
||||
with default arguments:
|
||||
</p>
|
||||
<pre class="programlisting">
|
||||
<span class="keyword">int</span> <span class="identifier">f</span><span class="special">(</span><span class="keyword">int</span><span class="special">,</span> <span class="keyword">double</span> <span class="special">=</span> <span class="number">3.14</span><span class="special">,</span> <span class="keyword">char</span> <span class="keyword">const</span><span class="special">*</span> <span class="special">=</span> <span class="string">"hello"</span><span class="special">);</span>
|
||||
</pre>
|
||||
<p>
|
||||
But the type of a pointer to the function <code class="literal">f</code> has no information
|
||||
But the type of a pointer to the function <tt class="literal">f</tt> has no information
|
||||
about its default arguments:
|
||||
</p>
|
||||
<pre class="programlisting">
|
||||
<span class="keyword">int</span><span class="special">(*</span><span class="identifier">g</span><span class="special">)(</span><span class="keyword">int</span><span class="special">,</span><span class="keyword">double</span><span class="special">,</span><span class="keyword">char</span> <span class="keyword">const</span><span class="special">*)</span> <span class="special">=</span> <span class="identifier">f</span><span class="special">;</span> <span class="comment">// defaults lost!
|
||||
</span></pre>
|
||||
<p>
|
||||
When we pass this function pointer to the <code class="literal">def</code> function,
|
||||
When we pass this function pointer to the <tt class="literal">def</tt> function,
|
||||
there is no way to retrieve the default arguments:
|
||||
</p>
|
||||
<pre class="programlisting">
|
||||
@@ -403,10 +414,10 @@ Namespaces are one honking great idea -- let's do more of those!
|
||||
are overloaded with a common sequence of initial arguments
|
||||
</li>
|
||||
</ul></div>
|
||||
<a name="default_arguments.boost_python_function_overloads"></a><h3>
|
||||
<a name="id3146300"></a>
|
||||
<a name="default_arguments.boost_python_function_overloads"></a><h2>
|
||||
<a name="id466136"></a>
|
||||
BOOST_PYTHON_FUNCTION_OVERLOADS
|
||||
</h3>
|
||||
</h2>
|
||||
<p>
|
||||
Boost.Python now has a way to make it easier. For instance, given a function:
|
||||
</p>
|
||||
@@ -424,19 +435,19 @@ Namespaces are one honking great idea -- let's do more of those!
|
||||
</pre>
|
||||
<p>
|
||||
will automatically create the thin wrappers for us. This macro will create
|
||||
a class <code class="literal">foo_overloads</code> that can be passed on to <code class="literal">def(...)</code>.
|
||||
a class <tt class="literal">foo_overloads</tt> that can be passed on to <tt class="literal">def(...)</tt>.
|
||||
The third and fourth macro argument are the minimum arguments and maximum
|
||||
arguments, respectively. In our <code class="literal">foo</code> function the minimum
|
||||
number of arguments is 1 and the maximum number of arguments is 4. The <code class="literal">def(...)</code>
|
||||
arguments, respectively. In our <tt class="literal">foo</tt> function the minimum
|
||||
number of arguments is 1 and the maximum number of arguments is 4. The <tt class="literal">def(...)</tt>
|
||||
function will automatically add all the foo variants for us:
|
||||
</p>
|
||||
<pre class="programlisting">
|
||||
<span class="identifier">def</span><span class="special">(</span><span class="string">"foo"</span><span class="special">,</span> <span class="identifier">foo</span><span class="special">,</span> <span class="identifier">foo_overloads</span><span class="special">());</span>
|
||||
</pre>
|
||||
<a name="default_arguments.boost_python_member_function_overloads"></a><h3>
|
||||
<a name="id3146587"></a>
|
||||
<a name="default_arguments.boost_python_member_function_overloads"></a><h2>
|
||||
<a name="id466454"></a>
|
||||
BOOST_PYTHON_MEMBER_FUNCTION_OVERLOADS
|
||||
</h3>
|
||||
</h2>
|
||||
<p>
|
||||
Objects here, objects there, objects here there everywhere. More frequently
|
||||
than anything else, we need to expose member functions of our classes to
|
||||
@@ -445,7 +456,7 @@ Namespaces are one honking great idea -- let's do more of those!
|
||||
play. Another macro is provided to make this a breeze.
|
||||
</p>
|
||||
<p>
|
||||
Like <code class="literal">BOOST_PYTHON_FUNCTION_OVERLOADS</code>, <code class="literal">BOOST_PYTHON_MEMBER_FUNCTION_OVERLOADS</code>
|
||||
Like <tt class="literal">BOOST_PYTHON_FUNCTION_OVERLOADS</tt>, <tt class="literal">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>
|
||||
@@ -466,11 +477,11 @@ Namespaces are one honking great idea -- let's do more of those!
|
||||
<span class="identifier">BOOST_PYTHON_MEMBER_FUNCTION_OVERLOADS</span><span class="special">(</span><span class="identifier">george_overloads</span><span class="special">,</span> <span class="identifier">wack_em</span><span class="special">,</span> <span class="number">1</span><span class="special">,</span> <span class="number">3</span><span class="special">)</span>
|
||||
</pre>
|
||||
<p>
|
||||
will generate a set of thin wrappers for george's <code class="literal">wack_em</code>
|
||||
will generate a set of thin wrappers for george's <tt class="literal">wack_em</tt>
|
||||
member function accepting a minimum of 1 and a maximum of 3 arguments (i.e.
|
||||
the third and fourth macro argument). The thin wrappers are all enclosed
|
||||
in a class named <code class="literal">george_overloads</code> that can then be used
|
||||
as an argument to <code class="literal">def(...)</code>:
|
||||
in a class named <tt class="literal">george_overloads</tt> that can then be used
|
||||
as an argument to <tt class="literal">def(...)</tt>:
|
||||
</p>
|
||||
<pre class="programlisting">
|
||||
<span class="special">.</span><span class="identifier">def</span><span class="special">(</span><span class="string">"wack_em"</span><span class="special">,</span> <span class="special">&</span><span class="identifier">george</span><span class="special">::</span><span class="identifier">wack_em</span><span class="special">,</span> <span class="identifier">george_overloads</span><span class="special">());</span>
|
||||
@@ -479,13 +490,13 @@ Namespaces are one honking great idea -- let's do more of those!
|
||||
See the <a href="../../../../v2/overloads.html#BOOST_PYTHON_FUNCTION_OVERLOADS-spec" target="_top">overloads
|
||||
reference</a> for details.
|
||||
</p>
|
||||
<a name="default_arguments.init_and_optional"></a><h3>
|
||||
<a name="id3146923"></a>
|
||||
<a name="default_arguments.init_and_optional"></a><h2>
|
||||
<a name="id466818"></a>
|
||||
init and optional
|
||||
</h3>
|
||||
</h2>
|
||||
<p>
|
||||
A similar facility is provided for class constructors, again, with default
|
||||
arguments or a sequence of overloads. Remember <code class="literal">init<...></code>?
|
||||
arguments or a sequence of overloads. Remember <tt class="literal">init<...></tt>?
|
||||
For example, given a class X with a constructor:
|
||||
</p>
|
||||
<pre class="programlisting">
|
||||
@@ -502,7 +513,7 @@ Namespaces are one honking great idea -- let's do more of those!
|
||||
<span class="special">.</span><span class="identifier">def</span><span class="special">(</span><span class="identifier">init</span><span class="special"><</span><span class="keyword">int</span><span class="special">,</span> <span class="identifier">optional</span><span class="special"><</span><span class="keyword">char</span><span class="special">,</span> <span class="identifier">std</span><span class="special">::</span><span class="identifier">string</span><span class="special">,</span> <span class="keyword">double</span><span class="special">></span> <span class="special">>())</span>
|
||||
</pre>
|
||||
<p>
|
||||
Notice the use of <code class="literal">init<...></code> and <code class="literal">optional<...></code>
|
||||
Notice the use of <tt class="literal">init<...></tt> and <tt class="literal">optional<...></tt>
|
||||
to signify the default (optional arguments).
|
||||
</p>
|
||||
</div>
|
||||
@@ -510,8 +521,8 @@ Namespaces are one honking great idea -- let's do more of those!
|
||||
<div class="titlepage"><div><div><h3 class="title">
|
||||
<a name="python.auto_overloading"></a>Auto-Overloading</h3></div></div></div>
|
||||
<p>
|
||||
It was mentioned in passing in the previous section that <code class="literal">BOOST_PYTHON_FUNCTION_OVERLOADS</code>
|
||||
and <code class="literal">BOOST_PYTHON_MEMBER_FUNCTION_OVERLOADS</code> can also be
|
||||
It was mentioned in passing in the previous section that <tt class="literal">BOOST_PYTHON_FUNCTION_OVERLOADS</tt>
|
||||
and <tt class="literal">BOOST_PYTHON_MEMBER_FUNCTION_OVERLOADS</tt> can also be
|
||||
used for overloaded functions and member functions with a common sequence
|
||||
of initial arguments. Here is an example:
|
||||
</p>
|
||||
@@ -553,24 +564,24 @@ Namespaces are one honking great idea -- let's do more of those!
|
||||
Notice though that we have a situation now where we have a minimum of zero
|
||||
(0) arguments and a maximum of 3 arguments.
|
||||
</p>
|
||||
<a name="auto_overloading.manual_wrapping"></a><h3>
|
||||
<a name="id3147627"></a>
|
||||
<a name="auto_overloading.manual_wrapping"></a><h2>
|
||||
<a name="id467599"></a>
|
||||
Manual Wrapping
|
||||
</h3>
|
||||
</h2>
|
||||
<p>
|
||||
It is important to emphasize however that <span class="bold"><strong>the overloaded
|
||||
functions must have a common sequence of initial arguments</strong></span>. Otherwise,
|
||||
It is important to emphasize however that <span class="bold"><b>the overloaded
|
||||
functions must have a common sequence of initial arguments</b></span>. Otherwise,
|
||||
our scheme above will not work. If this is not the case, we have to wrap
|
||||
our functions <a href="functions.html#python.overloading" title="Overloading">manually</a>.
|
||||
</p>
|
||||
<p>
|
||||
Actually, we can mix and match manual wrapping of overloaded functions and
|
||||
automatic wrapping through <code class="literal">BOOST_PYTHON_MEMBER_FUNCTION_OVERLOADS</code>
|
||||
and its sister, <code class="literal">BOOST_PYTHON_FUNCTION_OVERLOADS</code>. Following
|
||||
automatic wrapping through <tt class="literal">BOOST_PYTHON_MEMBER_FUNCTION_OVERLOADS</tt>
|
||||
and its sister, <tt class="literal">BOOST_PYTHON_FUNCTION_OVERLOADS</tt>. Following
|
||||
up on our example presented in the section <a href="functions.html#python.overloading" title="Overloading">on
|
||||
overloading</a>, since the first 4 overload functins have a common sequence
|
||||
of initial arguments, we can use <code class="literal">BOOST_PYTHON_MEMBER_FUNCTION_OVERLOADS</code>
|
||||
to automatically wrap the first three of the <code class="literal">def</code>s and
|
||||
of initial arguments, we can use <tt class="literal">BOOST_PYTHON_MEMBER_FUNCTION_OVERLOADS</tt>
|
||||
to automatically wrap the first three of the <tt class="literal">def</tt>s and
|
||||
manually wrap just the last. Here's how we'll do this:
|
||||
</p>
|
||||
<pre class="programlisting">
|
||||
@@ -594,12 +605,16 @@ Namespaces are one honking great idea -- let's do more of those!
|
||||
</div>
|
||||
<table xmlns:rev="http://www.cs.rpi.edu/~gregod/boost/tools/doc/revision" width="100%"><tr>
|
||||
<td align="left"></td>
|
||||
<td align="right"><small>Copyright © 2002-2005 Joel
|
||||
de Guzman, David Abrahams</small></td>
|
||||
<td align="right"><div class="copyright-footer"><small>Copyright © 2002-2005 Joel
|
||||
de Guzman, David Abrahams<p>
|
||||
Distributed under the Boost Software License, Version 1.0. (See accompanying
|
||||
file LICENSE_1_0.txt or copy at <a href="http://www.boost.org/LICENSE_1_0.txt" target="_top">
|
||||
http://www.boost.org/LICENSE_1_0.txt </a>)
|
||||
</p></small></div></td>
|
||||
</tr></table>
|
||||
<hr>
|
||||
<div class="spirit-nav">
|
||||
<a accesskey="p" href="exposing.html"><img src="../images/prev.png" alt="Prev"></a><a accesskey="u" href="../index.html"><img src="../images/up.png" alt="Up"></a><a accesskey="h" href="../index.html"><img src="../images/home.png" alt="Home"></a><a accesskey="n" href="object.html"><img src="../images/next.png" alt="Next"></a>
|
||||
<a accesskey="p" href="exposing.html"><img src="../../../../../../../doc/html/images/prev.png" alt="Prev"></a><a accesskey="u" href="../index.html"><img src="../../../../../../../doc/html/images/up.png" alt="Up"></a><a accesskey="h" href="../index.html"><img src="../../../../../../../doc/html/images/home.png" alt="Home"></a><a accesskey="n" href="object.html"><img src="../../../../../../../doc/html/images/next.png" alt="Next"></a>
|
||||
</div>
|
||||
</body>
|
||||
</html>
|
||||
|
||||
@@ -1,82 +1,71 @@
|
||||
<html>
|
||||
<head>
|
||||
<meta http-equiv="Content-Type" content="text/html; charset=ISO-8859-1">
|
||||
<title>Building Hello World</title>
|
||||
<link rel="stylesheet" href="../boostbook.css" type="text/css">
|
||||
<meta name="generator" content="DocBook XSL Stylesheets V1.72.0">
|
||||
<title> Building Hello World</title>
|
||||
<link rel="stylesheet" href="../../../../../../../doc/html/boostbook.css" type="text/css">
|
||||
<meta name="generator" content="DocBook XSL Stylesheets V1.66.1">
|
||||
<link rel="start" href="../index.html" title="Chapter 1. python 1.0">
|
||||
<link rel="up" href="../index.html" title="Chapter 1. python 1.0">
|
||||
<link rel="prev" href="../index.html" title="Chapter 1. python 1.0">
|
||||
<link rel="next" href="exposing.html" title="Exposing Classes">
|
||||
<link rel="next" href="exposing.html" title=" Exposing Classes">
|
||||
</head>
|
||||
<body bgcolor="white" text="black" link="#0000FF" vlink="#840084" alink="#0000FF">
|
||||
<table cellpadding="2" width="100%">
|
||||
<table cellpadding="2" width="100%"><tr>
|
||||
<td valign="top"><img alt="Boost C++ Libraries" width="277" height="86" src="../../../../../../../boost.png"></td>
|
||||
<td align="center"><a href="../../../../../../../index.htm">Home</a></td>
|
||||
<td align="center"><a href="../../../../../../../libs/libraries.htm">Libraries</a></td>
|
||||
<td align="center"><a href="../../../../../../../people/people.htm">People</a></td>
|
||||
<td align="center"><a href="../../../../../../../more/faq.htm">FAQ</a></td>
|
||||
<td align="center"><a href="../../../../../../../more/index.htm">More</a></td>
|
||||
</table>
|
||||
</tr></table>
|
||||
<hr>
|
||||
<div class="spirit-nav">
|
||||
<a accesskey="p" href="../index.html"><img src="../images/prev.png" alt="Prev"></a><a accesskey="u" href="../index.html"><img src="../images/up.png" alt="Up"></a><a accesskey="h" href="../index.html"><img src="../images/home.png" alt="Home"></a><a accesskey="n" href="exposing.html"><img src="../images/next.png" alt="Next"></a>
|
||||
<a accesskey="p" href="../index.html"><img src="../../../../../../../doc/html/images/prev.png" alt="Prev"></a><a accesskey="u" href="../index.html"><img src="../../../../../../../doc/html/images/up.png" alt="Up"></a><a accesskey="h" href="../index.html"><img src="../../../../../../../doc/html/images/home.png" alt="Home"></a><a accesskey="n" href="exposing.html"><img src="../../../../../../../doc/html/images/next.png" alt="Next"></a>
|
||||
</div>
|
||||
<div class="section" lang="en">
|
||||
<div class="titlepage"><div><div><h2 class="title" style="clear: both">
|
||||
<a name="python.hello"></a> Building Hello World</h2></div></div></div>
|
||||
<a name="hello.from_start_to_finish"></a><h3>
|
||||
<a name="id3091224"></a>
|
||||
<a name="hello.from_start_to_finish"></a><h2>
|
||||
<a name="id385425"></a>
|
||||
From Start To Finish
|
||||
</h3>
|
||||
</h2>
|
||||
<p>
|
||||
Now the first thing you'd want to do is to build the Hello World module and
|
||||
try it for yourself in Python. In this section, we shall outline the steps
|
||||
necessary to achieve that. We shall use the build tool that comes bundled with
|
||||
every boost distribution: <span class="bold"><strong>bjam</strong></span>.
|
||||
try it for yourself in Python. In this section, we will outline the steps necessary
|
||||
to achieve that. We will use the build tool that comes bundled with every boost
|
||||
distribution: <span class="bold"><b>bjam</b></span>.
|
||||
</p>
|
||||
<div class="informaltable"><table class="table">
|
||||
<colgroup><col></colgroup>
|
||||
<tbody><tr><td class="blurb"> <span class="inlinemediaobject"><img src="../images/note.png" alt="note"></span> <span class="bold"><strong>Building without bjam</strong></span><br>
|
||||
<br> Besides bjam, there are of course other ways to get your module
|
||||
built. What's written here should not be taken as "the one and only
|
||||
way". There are of course other build tools apart from <code class="literal">bjam</code>.<br>
|
||||
<br> 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></tbody>
|
||||
<div class="note"><table border="0" summary="Note">
|
||||
<tr>
|
||||
<td rowspan="2" align="center" valign="top" width="25"><img alt="[Note]" src="../../../../../../../doc/html/images/note.png"></td>
|
||||
<th align="left">Note</th>
|
||||
</tr>
|
||||
<tr><td colspan="2" align="left" valign="top">
|
||||
<p>
|
||||
<span class="bold"><b>Building without bjam</b></span>
|
||||
</p>
|
||||
<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 class="literal">bjam</tt>.
|
||||
</p>
|
||||
<p>
|
||||
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.
|
||||
</p>
|
||||
</td></tr>
|
||||
</table></div>
|
||||
<p>
|
||||
We shall skip over the details. Our objective will be to simply create the
|
||||
hello world module and run it in Python. For a complete reference to building
|
||||
Boost.Python, check out: <a href="../../../../building.html" target="_top">building.html</a>.
|
||||
After this brief <span class="emphasis"><em>bjam</em></span> tutorial, we should have built two
|
||||
DLLs:
|
||||
</p>
|
||||
<div class="itemizedlist"><ul type="disc">
|
||||
<li>
|
||||
boost_python.dll
|
||||
</li>
|
||||
<li>
|
||||
hello.pyd
|
||||
</li>
|
||||
</ul></div>
|
||||
<p>
|
||||
if you are on Windows, and
|
||||
</p>
|
||||
<div class="itemizedlist"><ul type="disc">
|
||||
<li>
|
||||
libboost_python.so
|
||||
</li>
|
||||
<li>
|
||||
hello.so
|
||||
</li>
|
||||
</ul></div>
|
||||
<p>
|
||||
if you are on Unix.
|
||||
We will skip over the details. Our objective will be to simply create the hello
|
||||
world module and run it in Python. For a complete reference to building Boost.Python,
|
||||
check out: <a href="../../../../building.html" target="_top">building.html</a>. After
|
||||
this brief <span class="emphasis"><em>bjam</em></span> tutorial, we should have built the DLLs
|
||||
and run a python program using the extension.
|
||||
</p>
|
||||
<p>
|
||||
The tutorial example can be found in the directory: <code class="literal">libs/python/example/tutorial</code>.
|
||||
The tutorial example can be found in the directory: <tt class="literal">libs/python/example/tutorial</tt>.
|
||||
There, you can find:
|
||||
</p>
|
||||
<div class="itemizedlist"><ul type="disc">
|
||||
@@ -84,206 +73,135 @@
|
||||
hello.cpp
|
||||
</li>
|
||||
<li>
|
||||
Jamfile
|
||||
hello.py
|
||||
</li>
|
||||
<li>
|
||||
Jamroot
|
||||
</li>
|
||||
</ul></div>
|
||||
<p>
|
||||
The <code class="literal">hello.cpp</code> file is our C++ hello world example. The
|
||||
<code class="literal">Jamfile</code> is a minimalist <span class="emphasis"><em>bjam</em></span> script
|
||||
that builds the DLLs for us.
|
||||
The <tt class="literal">hello.cpp</tt> file is our C++ hello world example. The
|
||||
<tt class="literal">Jamroot</tt> is a minimalist <span class="emphasis"><em>bjam</em></span> script
|
||||
that builds the DLLs for us. Finally, <tt class="literal">hello.py</tt> is our Python
|
||||
program that uses the extension in <tt class="literal">hello.cpp</tt>.
|
||||
</p>
|
||||
<p>
|
||||
Before anything else, you should have the bjam executable in your boost directory
|
||||
or somewhere in your path such that <code class="literal">bjam</code> can be executed
|
||||
or somewhere in your path such that <tt class="literal">bjam</tt> can be executed
|
||||
in the command line. Pre-built Boost.Jam executables are available for most
|
||||
platforms. The complete list of Bjam executables can be found <a href="http://sourceforge.net/project/showfiles.php?group_id=7586" target="_top">here</a>.
|
||||
</p>
|
||||
<a name="hello.let_s_jam_"></a><h3>
|
||||
<a name="id3091427"></a>
|
||||
<a name="hello.let_s_jam_"></a><h2>
|
||||
<a name="id385582"></a>
|
||||
Let's Jam!
|
||||
</h3>
|
||||
</h2>
|
||||
<p>
|
||||
<span class="inlinemediaobject"><img src="../images/jam.png" alt="jam"></span>
|
||||
</p>
|
||||
<p>
|
||||
Here is our minimalist Jamfile:
|
||||
</p>
|
||||
<pre class="programlisting"># This is the top of our own project tree
|
||||
project-root ;
|
||||
|
||||
import python ;
|
||||
|
||||
extension hello # Declare a Python extension called hello
|
||||
: hello.cpp # source
|
||||
# requirements and dependencies for Boost.Python extensions
|
||||
<template>@boost/libs/python/build/extension
|
||||
;
|
||||
</pre>
|
||||
<p>
|
||||
First, we need to specify our location. You may place your project anywhere.
|
||||
<code class="literal">project-root</code> allows you to do that.
|
||||
</p>
|
||||
<pre class="programlisting">project-root ;
|
||||
</pre>
|
||||
<p>
|
||||
By doing so, you'll need a Jamrules file. Simply copy the one in the <a href="../../../../../example/tutorial/Jamrules" target="_top">example/tutorial directory</a>
|
||||
and tweak the <code class="literal">path-global BOOST_ROOT</code> to where your boost
|
||||
root directory is. The file has <a href="../../../../../example/tutorial/Jamrules" target="_top">detailed
|
||||
instructions</a> you can follow.
|
||||
<a href="../../../../../example/tutorial/Jamroot" target="_top">Here</a> is our minimalist
|
||||
Jamroot file. Simply copy the file and tweak <tt class="literal">use-project boost</tt>
|
||||
to where your boost root directory is and your OK.
|
||||
</p>
|
||||
<p>
|
||||
Then we will import the definitions needed by Python modules:
|
||||
The comments contained in the Jamrules file above should be sufficient to get
|
||||
you going.
|
||||
</p>
|
||||
<pre class="programlisting">import python ;
|
||||
</pre>
|
||||
<p>
|
||||
Finally we declare our <code class="literal">hello</code> extension:
|
||||
</p>
|
||||
<pre class="programlisting">extension hello # Declare a Python extension called hello
|
||||
: hello.cpp # source
|
||||
|
||||
# requirements and dependencies for Boost.Python extensions
|
||||
<template>@boost/libs/python/build/extension
|
||||
;
|
||||
</pre>
|
||||
<p>
|
||||
The last part tells BJam that we are depending on the Boost Python Library.
|
||||
</p>
|
||||
<a name="hello.running_bjam"></a><h3>
|
||||
<a name="id3091556"></a>
|
||||
<a name="hello.running_bjam"></a><h2>
|
||||
<a name="id386137"></a>
|
||||
Running bjam
|
||||
</h3>
|
||||
</h2>
|
||||
<p>
|
||||
<span class="emphasis"><em>bjam</em></span> is run using your operating system's command line
|
||||
interpreter.
|
||||
</p>
|
||||
<div class="blockquote"><blockquote class="blockquote"><p>
|
||||
Start it up.
|
||||
</p></blockquote></div>
|
||||
<div class="blockquote"><blockquote class="blockquote">
|
||||
<p>
|
||||
Make sure that the environment is set so that we can invoke the C++ compiler.
|
||||
With MSVC, that would mean running the <code class="literal">Vcvars32.bat</code> batch
|
||||
file. For instance:
|
||||
</p>
|
||||
<p>
|
||||
Start it up.
|
||||
</p>
|
||||
<p>
|
||||
</p>
|
||||
</blockquote></div>
|
||||
<p>
|
||||
A file called user-config.jam in your home directory is used to configure your
|
||||
tools. In Windows, your home directory can be found by typing:
|
||||
</p>
|
||||
<pre class="programlisting">C:\Program Files\Microsoft Visual Studio .NET 2003\Common7\Tools\vsvars32.bat
|
||||
<pre class="programlisting">ECHO %HOMEDRIVE%%HOMEPATH%
|
||||
</pre>
|
||||
<p>
|
||||
Some environment variables will have to be setup for proper building of our
|
||||
Python modules. Example:
|
||||
into a command prompt window. Your file should at least have the rules for
|
||||
your compiler and your python installation. A specific example of this on Windows
|
||||
would be:
|
||||
</p>
|
||||
<pre class="programlisting">set PYTHON_ROOT=c:/dev/tools/python
|
||||
set PYTHON_VERSION=2.2
|
||||
<pre class="programlisting"># MSVC configuration
|
||||
using msvc : 8.0 ;
|
||||
|
||||
# Python configuration
|
||||
using python : 2.4 : C:/dev/tools<span class="emphasis"><em>Python</em></span> ;
|
||||
</pre>
|
||||
<p>
|
||||
The above assumes that the Python installation is in <code class="literal">c:/dev/tools/python</code>
|
||||
and that we are using Python version 2.2. You'll have to tweak these appropriately.
|
||||
</p>
|
||||
<div class="informaltable"><table class="table">
|
||||
<colgroup><col></colgroup>
|
||||
<tbody><tr><td class="blurb"> <span class="inlinemediaobject"><img src="../images/tip.png" alt="tip"></span> Be sure not to include a third number, e.g. <span class="bold"><strong>not</strong></span> "2.2.1", even if that's the version
|
||||
you have.</td></tr></tbody>
|
||||
</table></div>
|
||||
<p>
|
||||
Take note that you may also do that through the Jamrules file we put in our
|
||||
project as detailed above. The file has <a href="../../../../../example/tutorial/Jamrules" target="_top">detailed
|
||||
instructions</a> you can follow.
|
||||
The first rule tells Bjam to use the MSVC 8.0 compiler and associated tools.
|
||||
The second rule provides information on Python, its version and where it is
|
||||
located. The above assumes that the Python installation is in <tt class="literal">C:/dev/tools/Python/</tt>.
|
||||
If you have one fairly "standard" python installation for your platform,
|
||||
you might not need to do this.
|
||||
</p>
|
||||
<p>
|
||||
Now we are ready... Be sure to <code class="literal">cd</code> to <code class="literal">libs/python/example/tutorial</code>
|
||||
where the tutorial <code class="literal">"hello.cpp"</code> and the <code class="literal">"Jamfile"</code>
|
||||
Now we are ready... Be sure to <tt class="literal">cd</tt> to <tt class="literal">libs/python/example/tutorial</tt>
|
||||
where the tutorial <tt class="literal">"hello.cpp"</tt> and the <tt class="literal">"Jamroot"</tt>
|
||||
is situated.
|
||||
</p>
|
||||
<p>
|
||||
Finally:
|
||||
</p>
|
||||
<pre class="programlisting">
|
||||
<span class="identifier">bjam</span> <span class="special">-</span><span class="identifier">sTOOLS</span><span class="special">=</span><span class="identifier">vc</span><span class="special">-</span><span class="number">7</span><span class="identifier">_1</span>
|
||||
<span class="identifier">bjam</span>
|
||||
</pre>
|
||||
<p>
|
||||
We are again assuming that we are using Microsoft Visual C++ version 7.1. If
|
||||
not, then you will have to specify the appropriate tool. See <a href="../../../../../../../tools/build/index.html" target="_top">Building
|
||||
Boost Libraries</a> for further details.
|
||||
</p>
|
||||
<p>
|
||||
It should be building now:
|
||||
</p>
|
||||
<pre class="programlisting">cd C:\dev\boost\libs\python\example\tutorial
|
||||
bjam -sTOOLS=msvc
|
||||
bjam
|
||||
...patience...
|
||||
...found 1703 targets...
|
||||
...updating 40 targets...
|
||||
...found 1101 targets...
|
||||
...updating 35 targets...
|
||||
</pre>
|
||||
<p>
|
||||
And so on... Finally:
|
||||
</p>
|
||||
<pre class="programlisting">Creating library bin\boost\libs\python\build\boost_python.dll\vc-7_1\debug\th
|
||||
reading-multi\boost_python.lib and object bin\boost\libs\python\build\boost_pyth
|
||||
on.dll\vc-7_1\debug\threading-multi\boost_python.exp
|
||||
vc-C++ bin\tutorial\hello.pyd\vc-7_1\debug\threading-multi\hello.obj
|
||||
hello.cpp
|
||||
vc-Link bin\tutorial\hello.pyd\vc-7_1\debug\threading-multi\hello.pyd bin\tutori
|
||||
al\hello.pyd\vc-7_1\debug\threading-multi\hello.lib
|
||||
Creating library bin\tutorial\hello.pyd\vc-7_1\debug\threading-multi\hello.li
|
||||
b and object bin\tutorial\hello.pyd\vc-7_1\debug\threading-multi\hello.exp
|
||||
...updated 31 targets...
|
||||
<pre class="programlisting">Creating library <span class="emphasis"><em>path-to-boost_python.dll</em></span>
|
||||
Creating library <span class="emphasis"><em>path-to-'''hello_ext'''.exp</em></span>
|
||||
**passed** ... hello.test
|
||||
...updated 35 targets...
|
||||
</pre>
|
||||
<p>
|
||||
If all is well, you should now have:
|
||||
Or something similar. If all is well, you should now have built the DLLs and
|
||||
run the Python program.
|
||||
</p>
|
||||
<div class="itemizedlist"><ul type="disc">
|
||||
<li>
|
||||
boost_python.dll
|
||||
</li>
|
||||
<li>
|
||||
hello.pyd
|
||||
</li>
|
||||
</ul></div>
|
||||
<div class="blockquote"><blockquote class="blockquote">
|
||||
<p>
|
||||
if you are on Windows, and
|
||||
</p>
|
||||
<div class="itemizedlist"><ul type="disc">
|
||||
<li>
|
||||
libboost_python.so
|
||||
</li>
|
||||
<li>
|
||||
hello.so
|
||||
</li>
|
||||
</ul></div>
|
||||
</p>
|
||||
<p>
|
||||
if you are on Unix.
|
||||
</p>
|
||||
<span class="bold"><b>There you go... Have fun!</b></span>
|
||||
</p>
|
||||
<p>
|
||||
<code class="literal">boost_python.dll</code> and <code class="literal">hello.pyd</code> can be
|
||||
found somewhere in your project's <code class="literal">bin</code> directory. After a
|
||||
successful build, you make it possible for the system to find boost_python.dll
|
||||
or libboost_python.so (usually done with LD_LIBRARY_PATH, DYLD_LIBRARY_PATH,
|
||||
or some other variable on *nix and with PATH on Windows) and for Python to
|
||||
find the hello module (Done with PYTHONPATH on all systems.)
|
||||
</p>
|
||||
<p>
|
||||
You may now fire up Python and run our hello module:
|
||||
</p>
|
||||
<p>
|
||||
</p>
|
||||
<pre class="programlisting">
|
||||
<span class="special">>>></span> <span class="keyword">import</span> <span class="identifier">hello</span>
|
||||
<span class="special">>>></span> <span class="keyword">print</span> <span class="identifier">hello</span><span class="special">.</span><span class="identifier">greet</span><span class="special">()</span>
|
||||
<span class="identifier">hello</span><span class="special">,</span> <span class="identifier">world</span>
|
||||
</pre>
|
||||
<p>
|
||||
</p>
|
||||
<div class="blockquote"><blockquote class="blockquote"><p>
|
||||
<span class="bold"><strong>There you go... Have fun!</strong></span>
|
||||
</p></blockquote></div>
|
||||
</p>
|
||||
</blockquote></div>
|
||||
</div>
|
||||
<table xmlns:rev="http://www.cs.rpi.edu/~gregod/boost/tools/doc/revision" width="100%"><tr>
|
||||
<td align="left"></td>
|
||||
<td align="right"><small>Copyright © 2002-2005 Joel
|
||||
de Guzman, David Abrahams</small></td>
|
||||
<td align="right"><div class="copyright-footer"><small>Copyright © 2002-2005 Joel
|
||||
de Guzman, David Abrahams<p>
|
||||
Distributed under the Boost Software License, Version 1.0. (See accompanying
|
||||
file LICENSE_1_0.txt or copy at <a href="http://www.boost.org/LICENSE_1_0.txt" target="_top">
|
||||
http://www.boost.org/LICENSE_1_0.txt </a>)
|
||||
</p></small></div></td>
|
||||
</tr></table>
|
||||
<hr>
|
||||
<div class="spirit-nav">
|
||||
<a accesskey="p" href="../index.html"><img src="../images/prev.png" alt="Prev"></a><a accesskey="u" href="../index.html"><img src="../images/up.png" alt="Up"></a><a accesskey="h" href="../index.html"><img src="../images/home.png" alt="Home"></a><a accesskey="n" href="exposing.html"><img src="../images/next.png" alt="Next"></a>
|
||||
<a accesskey="p" href="../index.html"><img src="../../../../../../../doc/html/images/prev.png" alt="Prev"></a><a accesskey="u" href="../index.html"><img src="../../../../../../../doc/html/images/up.png" alt="Up"></a><a accesskey="h" href="../index.html"><img src="../../../../../../../doc/html/images/home.png" alt="Home"></a><a accesskey="n" href="exposing.html"><img src="../../../../../../../doc/html/images/next.png" alt="Next"></a>
|
||||
</div>
|
||||
</body>
|
||||
</html>
|
||||
|
||||
@@ -2,25 +2,25 @@
|
||||
<head>
|
||||
<meta http-equiv="Content-Type" content="text/html; charset=ISO-8859-1">
|
||||
<title>Iterators</title>
|
||||
<link rel="stylesheet" href="../boostbook.css" type="text/css">
|
||||
<meta name="generator" content="DocBook XSL Stylesheets V1.72.0">
|
||||
<link rel="stylesheet" href="../../../../../../../doc/html/boostbook.css" type="text/css">
|
||||
<meta name="generator" content="DocBook XSL Stylesheets V1.66.1">
|
||||
<link rel="start" href="../index.html" title="Chapter 1. python 1.0">
|
||||
<link rel="up" href="../index.html" title="Chapter 1. python 1.0">
|
||||
<link rel="prev" href="embedding.html" title="Embedding">
|
||||
<link rel="next" href="exception.html" title="Exception Translation">
|
||||
<link rel="next" href="exception.html" title=" Exception Translation">
|
||||
</head>
|
||||
<body bgcolor="white" text="black" link="#0000FF" vlink="#840084" alink="#0000FF">
|
||||
<table cellpadding="2" width="100%">
|
||||
<table cellpadding="2" width="100%"><tr>
|
||||
<td valign="top"><img alt="Boost C++ Libraries" width="277" height="86" src="../../../../../../../boost.png"></td>
|
||||
<td align="center"><a href="../../../../../../../index.htm">Home</a></td>
|
||||
<td align="center"><a href="../../../../../../../libs/libraries.htm">Libraries</a></td>
|
||||
<td align="center"><a href="../../../../../../../people/people.htm">People</a></td>
|
||||
<td align="center"><a href="../../../../../../../more/faq.htm">FAQ</a></td>
|
||||
<td align="center"><a href="../../../../../../../more/index.htm">More</a></td>
|
||||
</table>
|
||||
</tr></table>
|
||||
<hr>
|
||||
<div class="spirit-nav">
|
||||
<a accesskey="p" href="embedding.html"><img src="../images/prev.png" alt="Prev"></a><a accesskey="u" href="../index.html"><img src="../images/up.png" alt="Up"></a><a accesskey="h" href="../index.html"><img src="../images/home.png" alt="Home"></a><a accesskey="n" href="exception.html"><img src="../images/next.png" alt="Next"></a>
|
||||
<a accesskey="p" href="embedding.html"><img src="../../../../../../../doc/html/images/prev.png" alt="Prev"></a><a accesskey="u" href="../index.html"><img src="../../../../../../../doc/html/images/up.png" alt="Up"></a><a accesskey="h" href="../index.html"><img src="../../../../../../../doc/html/images/home.png" alt="Home"></a><a accesskey="n" href="exception.html"><img src="../../../../../../../doc/html/images/next.png" alt="Next"></a>
|
||||
</div>
|
||||
<div class="section" lang="en">
|
||||
<div class="titlepage"><div><div><h2 class="title" style="clear: both">
|
||||
@@ -30,7 +30,7 @@
|
||||
iterators, but these are two very different beasts.
|
||||
</p>
|
||||
<p>
|
||||
<span class="bold"><strong>C++ iterators:</strong></span>
|
||||
<span class="bold"><b>C++ iterators:</b></span>
|
||||
</p>
|
||||
<div class="itemizedlist"><ul type="disc">
|
||||
<li>
|
||||
@@ -45,7 +45,7 @@
|
||||
</li>
|
||||
</ul></div>
|
||||
<p>
|
||||
<span class="bold"><strong>Python Iterators:</strong></span>
|
||||
<span class="bold"><b>Python Iterators:</b></span>
|
||||
</p>
|
||||
<div class="itemizedlist"><ul type="disc">
|
||||
<li>
|
||||
@@ -59,8 +59,8 @@
|
||||
</li>
|
||||
</ul></div>
|
||||
<p>
|
||||
The typical Python iteration protocol: <code class="literal"><span class="bold"><strong>for y
|
||||
in x...</strong></span></code> is as follows:
|
||||
The typical Python iteration protocol: <tt class="literal"><span class="bold"><b>for y
|
||||
in x...</b></span></tt> is as follows:
|
||||
</p>
|
||||
<p>
|
||||
</p>
|
||||
@@ -74,7 +74,7 @@
|
||||
</span></pre>
|
||||
<p>
|
||||
Boost.Python provides some mechanisms to make C++ iterators play along nicely
|
||||
as Python iterators. What we need to do is to produce appropriate <code class="computeroutput"><span class="identifier">__iter__</span></code> function from C++ iterators that
|
||||
as Python iterators. What we need to do is to produce appropriate <tt class="computeroutput"><span class="identifier">__iter__</span></tt> function from C++ iterators that
|
||||
is compatible with the Python iteration protocol. For example:
|
||||
</p>
|
||||
<p>
|
||||
@@ -91,7 +91,7 @@
|
||||
<span class="special">.</span><span class="identifier">def</span><span class="special">(</span><span class="string">"__iter__"</span><span class="special">,</span> <span class="identifier">iterator</span><span class="special"><</span><span class="identifier">vector</span><span class="special"><</span><span class="keyword">int</span><span class="special">></span> <span class="special">>())</span>
|
||||
</pre>
|
||||
<p>
|
||||
<span class="bold"><strong>range</strong></span>
|
||||
<span class="bold"><b>range</b></span>
|
||||
</p>
|
||||
<p>
|
||||
We can create a Python savvy iterator using the range function:
|
||||
@@ -119,14 +119,14 @@
|
||||
</li>
|
||||
</ul></div>
|
||||
<p>
|
||||
<span class="bold"><strong>iterator</strong></span>
|
||||
<span class="bold"><b>iterator</b></span>
|
||||
</p>
|
||||
<div class="itemizedlist"><ul type="disc"><li>
|
||||
iterator<T, Policies>()
|
||||
</li></ul></div>
|
||||
<p>
|
||||
Given a container <code class="literal">T</code>, iterator is a shortcut that simply
|
||||
calls <code class="literal">range</code> with &T::begin, &T::end.
|
||||
Given a container <tt class="literal">T</tt>, iterator is a shortcut that simply
|
||||
calls <tt class="literal">range</tt> with &T::begin, &T::end.
|
||||
</p>
|
||||
<p>
|
||||
Let's put this into action... Here's an example from some hypothetical bogon
|
||||
@@ -152,14 +152,14 @@
|
||||
<span class="special">.</span><span class="identifier">property</span><span class="special">(</span><span class="string">"bogons"</span><span class="special">,</span> <span class="identifier">range</span><span class="special">(&</span><span class="identifier">F</span><span class="special">::</span><span class="identifier">b_begin</span><span class="special">,</span> <span class="special">&</span><span class="identifier">F</span><span class="special">::</span><span class="identifier">b_end</span><span class="special">));</span>
|
||||
</pre>
|
||||
<p>
|
||||
<span class="bold"><strong>stl_input_iterator</strong></span>
|
||||
<span class="bold"><b>stl_input_iterator</b></span>
|
||||
</p>
|
||||
<p>
|
||||
So far, we have seen how to expose C++ iterators and ranges to Python. Sometimes
|
||||
we wish to go the other way, though: we'd like to pass a Python sequence to
|
||||
an STL algorithm or use it to initialize an STL container. We need to make
|
||||
a Python iterator look like an STL iterator. For that, we use <code class="computeroutput"><span class="identifier">stl_input_iterator</span><span class="special"><></span></code>.
|
||||
Consider how we might implement a function that exposes <code class="computeroutput"><span class="identifier">std</span><span class="special">::</span><span class="identifier">list</span><span class="special"><</span><span class="keyword">int</span><span class="special">>::</span><span class="identifier">assign</span><span class="special">()</span></code> to Python:
|
||||
a Python iterator look like an STL iterator. For that, we use <tt class="computeroutput"><span class="identifier">stl_input_iterator</span><span class="special"><></span></tt>.
|
||||
Consider how we might implement a function that exposes <tt class="computeroutput"><span class="identifier">std</span><span class="special">::</span><span class="identifier">list</span><span class="special"><</span><span class="keyword">int</span><span class="special">>::</span><span class="identifier">assign</span><span class="special">()</span></tt> to Python:
|
||||
</p>
|
||||
<p>
|
||||
</p>
|
||||
@@ -178,7 +178,7 @@
|
||||
</span> <span class="special">;</span>
|
||||
</pre>
|
||||
<p>
|
||||
Now in Python, we can assign any integer sequence to <code class="computeroutput"><span class="identifier">list_int</span></code>
|
||||
Now in Python, we can assign any integer sequence to <tt class="computeroutput"><span class="identifier">list_int</span></tt>
|
||||
objects:
|
||||
</p>
|
||||
<p>
|
||||
@@ -190,12 +190,16 @@
|
||||
</div>
|
||||
<table xmlns:rev="http://www.cs.rpi.edu/~gregod/boost/tools/doc/revision" width="100%"><tr>
|
||||
<td align="left"></td>
|
||||
<td align="right"><small>Copyright © 2002-2005 Joel
|
||||
de Guzman, David Abrahams</small></td>
|
||||
<td align="right"><div class="copyright-footer"><small>Copyright © 2002-2005 Joel
|
||||
de Guzman, David Abrahams<p>
|
||||
Distributed under the Boost Software License, Version 1.0. (See accompanying
|
||||
file LICENSE_1_0.txt or copy at <a href="http://www.boost.org/LICENSE_1_0.txt" target="_top">
|
||||
http://www.boost.org/LICENSE_1_0.txt </a>)
|
||||
</p></small></div></td>
|
||||
</tr></table>
|
||||
<hr>
|
||||
<div class="spirit-nav">
|
||||
<a accesskey="p" href="embedding.html"><img src="../images/prev.png" alt="Prev"></a><a accesskey="u" href="../index.html"><img src="../images/up.png" alt="Up"></a><a accesskey="h" href="../index.html"><img src="../images/home.png" alt="Home"></a><a accesskey="n" href="exception.html"><img src="../images/next.png" alt="Next"></a>
|
||||
<a accesskey="p" href="embedding.html"><img src="../../../../../../../doc/html/images/prev.png" alt="Prev"></a><a accesskey="u" href="../index.html"><img src="../../../../../../../doc/html/images/up.png" alt="Up"></a><a accesskey="h" href="../index.html"><img src="../../../../../../../doc/html/images/home.png" alt="Home"></a><a accesskey="n" href="exception.html"><img src="../../../../../../../doc/html/images/next.png" alt="Next"></a>
|
||||
</div>
|
||||
</body>
|
||||
</html>
|
||||
|
||||
@@ -1,26 +1,26 @@
|
||||
<html>
|
||||
<head>
|
||||
<meta http-equiv="Content-Type" content="text/html; charset=ISO-8859-1">
|
||||
<title>Object Interface</title>
|
||||
<link rel="stylesheet" href="../boostbook.css" type="text/css">
|
||||
<meta name="generator" content="DocBook XSL Stylesheets V1.72.0">
|
||||
<title> Object Interface</title>
|
||||
<link rel="stylesheet" href="../../../../../../../doc/html/boostbook.css" type="text/css">
|
||||
<meta name="generator" content="DocBook XSL Stylesheets V1.66.1">
|
||||
<link rel="start" href="../index.html" title="Chapter 1. python 1.0">
|
||||
<link rel="up" href="../index.html" title="Chapter 1. python 1.0">
|
||||
<link rel="prev" href="functions.html" title="Functions">
|
||||
<link rel="next" href="embedding.html" title="Embedding">
|
||||
</head>
|
||||
<body bgcolor="white" text="black" link="#0000FF" vlink="#840084" alink="#0000FF">
|
||||
<table cellpadding="2" width="100%">
|
||||
<table cellpadding="2" width="100%"><tr>
|
||||
<td valign="top"><img alt="Boost C++ Libraries" width="277" height="86" src="../../../../../../../boost.png"></td>
|
||||
<td align="center"><a href="../../../../../../../index.htm">Home</a></td>
|
||||
<td align="center"><a href="../../../../../../../libs/libraries.htm">Libraries</a></td>
|
||||
<td align="center"><a href="../../../../../../../people/people.htm">People</a></td>
|
||||
<td align="center"><a href="../../../../../../../more/faq.htm">FAQ</a></td>
|
||||
<td align="center"><a href="../../../../../../../more/index.htm">More</a></td>
|
||||
</table>
|
||||
</tr></table>
|
||||
<hr>
|
||||
<div class="spirit-nav">
|
||||
<a accesskey="p" href="functions.html"><img src="../images/prev.png" alt="Prev"></a><a accesskey="u" href="../index.html"><img src="../images/up.png" alt="Up"></a><a accesskey="h" href="../index.html"><img src="../images/home.png" alt="Home"></a><a accesskey="n" href="embedding.html"><img src="../images/next.png" alt="Next"></a>
|
||||
<a accesskey="p" href="functions.html"><img src="../../../../../../../doc/html/images/prev.png" alt="Prev"></a><a accesskey="u" href="../index.html"><img src="../../../../../../../doc/html/images/up.png" alt="Up"></a><a accesskey="h" href="../index.html"><img src="../../../../../../../doc/html/images/home.png" alt="Home"></a><a accesskey="n" href="embedding.html"><img src="../../../../../../../doc/html/images/next.png" alt="Next"></a>
|
||||
</div>
|
||||
<div class="section" lang="en">
|
||||
<div class="titlepage"><div><div><h2 class="title" style="clear: both">
|
||||
@@ -35,13 +35,13 @@
|
||||
Python is dynamically typed, unlike C++ which is statically typed. Python variables
|
||||
may hold an integer, a float, list, dict, tuple, str, long etc., among other
|
||||
things. In the viewpoint of Boost.Python and C++, these Pythonic variables
|
||||
are just instances of class <code class="literal">object</code>. We shall see in this
|
||||
are just instances of class <tt class="literal">object</tt>. We will see in this
|
||||
chapter how to deal with Python objects.
|
||||
</p>
|
||||
<p>
|
||||
As mentioned, one of the goals of Boost.Python is to provide a bidirectional
|
||||
mapping between C++ and Python while maintaining the Python feel. Boost.Python
|
||||
C++ <code class="literal">object</code>s are as close as possible to Python. This should
|
||||
C++ <tt class="literal">object</tt>s are as close as possible to Python. This should
|
||||
minimize the learning curve significantly.
|
||||
</p>
|
||||
<p>
|
||||
@@ -51,10 +51,10 @@
|
||||
<div class="titlepage"><div><div><h3 class="title">
|
||||
<a name="python.basic_interface"></a>Basic Interface</h3></div></div></div>
|
||||
<p>
|
||||
Class <code class="literal">object</code> wraps <code class="literal">PyObject*</code>. All the
|
||||
intricacies of dealing with <code class="literal">PyObject</code>s such as managing
|
||||
reference counting are handled by the <code class="literal">object</code> class. C++
|
||||
object interoperability is seamless. Boost.Python C++ <code class="literal">object</code>s
|
||||
Class <tt class="literal">object</tt> wraps <tt class="literal">PyObject*</tt>. All the
|
||||
intricacies of dealing with <tt class="literal">PyObject</tt>s such as managing
|
||||
reference counting are handled by the <tt class="literal">object</tt> class. C++
|
||||
object interoperability is seamless. Boost.Python C++ <tt class="literal">object</tt>s
|
||||
can in fact be explicitly constructed from any C++ object.
|
||||
</p>
|
||||
<p>
|
||||
@@ -99,7 +99,7 @@
|
||||
<div class="titlepage"><div><div><h3 class="title">
|
||||
<a name="python.derived_object_types"></a>Derived Object types</h3></div></div></div>
|
||||
<p>
|
||||
Boost.Python comes with a set of derived <code class="literal">object</code> types
|
||||
Boost.Python comes with a set of derived <tt class="literal">object</tt> types
|
||||
corresponding to that of Python's:
|
||||
</p>
|
||||
<div class="itemizedlist"><ul type="disc">
|
||||
@@ -123,32 +123,32 @@
|
||||
</li>
|
||||
</ul></div>
|
||||
<p>
|
||||
These derived <code class="literal">object</code> types act like real Python types.
|
||||
These derived <tt class="literal">object</tt> types act like real Python types.
|
||||
For instance:
|
||||
</p>
|
||||
<pre class="programlisting">
|
||||
<span class="identifier">str</span><span class="special">(</span><span class="number">1</span><span class="special">)</span> <span class="special">==></span> <span class="string">"1"</span>
|
||||
</pre>
|
||||
<p>
|
||||
Wherever appropriate, a particular derived <code class="literal">object</code> has
|
||||
corresponding Python type's methods. For instance, <code class="literal">dict</code>
|
||||
has a <code class="literal">keys()</code> method:
|
||||
Wherever appropriate, a particular derived <tt class="literal">object</tt> has
|
||||
corresponding Python type's methods. For instance, <tt class="literal">dict</tt>
|
||||
has a <tt class="literal">keys()</tt> method:
|
||||
</p>
|
||||
<pre class="programlisting">
|
||||
<span class="identifier">d</span><span class="special">.</span><span class="identifier">keys</span><span class="special">()</span>
|
||||
</pre>
|
||||
<p>
|
||||
<code class="literal">make_tuple</code> is provided for declaring <span class="emphasis"><em>tuple literals</em></span>.
|
||||
<tt class="literal">make_tuple</tt> is provided for declaring <span class="emphasis"><em>tuple literals</em></span>.
|
||||
Example:
|
||||
</p>
|
||||
<pre class="programlisting">
|
||||
<span class="identifier">make_tuple</span><span class="special">(</span><span class="number">123</span><span class="special">,</span> <span class="char">'D'</span><span class="special">,</span> <span class="string">"Hello, World"</span><span class="special">,</span> <span class="number">0.0</span><span class="special">);</span>
|
||||
</pre>
|
||||
<p>
|
||||
In C++, when Boost.Python <code class="literal">object</code>s are used as arguments
|
||||
In C++, when Boost.Python <tt class="literal">object</tt>s are used as arguments
|
||||
to functions, subtype matching is required. For example, when a function
|
||||
<code class="literal">f</code>, as declared below, is wrapped, it will only accept
|
||||
instances of Python's <code class="literal">str</code> type and subtypes.
|
||||
<tt class="literal">f</tt>, as declared below, is wrapped, it will only accept
|
||||
instances of Python's <tt class="literal">str</tt> type and subtypes.
|
||||
</p>
|
||||
<pre class="programlisting">
|
||||
<span class="keyword">void</span> <span class="identifier">f</span><span class="special">(</span><span class="identifier">str</span> <span class="identifier">name</span><span class="special">)</span>
|
||||
@@ -172,16 +172,15 @@
|
||||
<span class="identifier">object</span> <span class="identifier">msg</span> <span class="special">=</span> <span class="string">"%s is bigger than %s"</span> <span class="special">%</span> <span class="identifier">make_tuple</span><span class="special">(</span><span class="identifier">NAME</span><span class="special">,</span><span class="identifier">name</span><span class="special">);</span>
|
||||
</pre>
|
||||
<p>
|
||||
Demonstrates that you can write the C++ equivalent of <code class="literal">"format"
|
||||
% x,y,z</code> in Python, which is useful since there's no easy way to
|
||||
Demonstrates that you can write the C++ equivalent of <tt class="literal">"format"
|
||||
% x,y,z</tt> in Python, which is useful since there's no easy way to
|
||||
do that in std C++.
|
||||
</p>
|
||||
<div class="informaltable"><table class="table">
|
||||
<colgroup><col></colgroup>
|
||||
<tbody><tr><td class="blurb"> <span class="inlinemediaobject"><img src="../images/alert.png" alt="alert"></span> <span class="bold"><strong>Beware</strong></span> the
|
||||
common pitfall of forgetting that the constructors of most of Python's
|
||||
mutable types make copies, just as in Python. </td></tr></tbody>
|
||||
</table></div>
|
||||
<div class="sidebar"><p>
|
||||
<span class="inlinemediaobject"><img src="../images/alert.png" alt="alert"></span> <span class="bold"><b>Beware</b></span> the common pitfall
|
||||
of forgetting that the constructors of most of Python's mutable types make
|
||||
copies, just as in Python.
|
||||
</p></div>
|
||||
<p>
|
||||
Python:
|
||||
</p>
|
||||
@@ -196,12 +195,12 @@
|
||||
<span class="identifier">dict</span> <span class="identifier">d</span><span class="special">(</span><span class="identifier">x</span><span class="special">.</span><span class="identifier">attr</span><span class="special">(</span><span class="string">"__dict__"</span><span class="special">));</span> <span class="comment">// copies x.__dict__
|
||||
</span><span class="identifier">d</span><span class="special">[</span><span class="char">'whatever'</span><span class="special">]</span> <span class="special">=</span> <span class="number">3</span><span class="special">;</span> <span class="comment">// modifies the copy
|
||||
</span></pre>
|
||||
<a name="derived_object_types.class__lt_t_gt__as_objects"></a><h3>
|
||||
<a name="id3149441"></a>
|
||||
<a name="derived_object_types.class__lt_t_gt__as_objects"></a><h2>
|
||||
<a name="id469604"></a>
|
||||
class_<T> as objects
|
||||
</h3>
|
||||
</h2>
|
||||
<p>
|
||||
Due to the dynamic nature of Boost.Python objects, any <code class="literal">class_<T></code>
|
||||
Due to the dynamic nature of Boost.Python objects, any <tt class="literal">class_<T></tt>
|
||||
may also be one of these types! The following code snippet wraps the class
|
||||
(type) object.
|
||||
</p>
|
||||
@@ -223,15 +222,15 @@
|
||||
<a name="python.extracting_c___objects"></a>Extracting C++ objects</h3></div></div></div>
|
||||
<p>
|
||||
At some point, we will need to get C++ values out of object instances. This
|
||||
can be achieved with the <code class="literal">extract<T></code> function. Consider
|
||||
can be achieved with the <tt class="literal">extract<T></tt> function. Consider
|
||||
the following:
|
||||
</p>
|
||||
<pre class="programlisting">
|
||||
<span class="keyword">double</span> <span class="identifier">x</span> <span class="special">=</span> <span class="identifier">o</span><span class="special">.</span><span class="identifier">attr</span><span class="special">(</span><span class="string">"length"</span><span class="special">);</span> <span class="comment">// compile error
|
||||
</span></pre>
|
||||
<p>
|
||||
In the code above, we got a compiler error because Boost.Python <code class="literal">object</code>
|
||||
can't be implicitly converted to <code class="literal">double</code>s. Instead, what
|
||||
In the code above, we got a compiler error because Boost.Python <tt class="literal">object</tt>
|
||||
can't be implicitly converted to <tt class="literal">double</tt>s. Instead, what
|
||||
we wanted to do above can be achieved by writing:
|
||||
</p>
|
||||
<pre class="programlisting">
|
||||
@@ -241,14 +240,14 @@
|
||||
</pre>
|
||||
<p>
|
||||
The first line attempts to extract the "length" attribute of the
|
||||
Boost.Python <code class="literal">object</code>. The second line attempts to <span class="emphasis"><em>extract</em></span>
|
||||
the <code class="literal">Vec2</code> object from held by the Boost.Python <code class="literal">object</code>.
|
||||
Boost.Python <tt class="literal">object</tt>. The second line attempts to <span class="emphasis"><em>extract</em></span>
|
||||
the <tt class="literal">Vec2</tt> object from held by the Boost.Python <tt class="literal">object</tt>.
|
||||
</p>
|
||||
<p>
|
||||
Take note that we said "attempt to" above. What if the Boost.Python
|
||||
<code class="literal">object</code> does not really hold a <code class="literal">Vec2</code>
|
||||
<tt class="literal">object</tt> does not really hold a <tt class="literal">Vec2</tt>
|
||||
type? This is certainly a possibility considering the dynamic nature of Python
|
||||
<code class="literal">object</code>s. To be on the safe side, if the C++ type can't
|
||||
<tt class="literal">object</tt>s. To be on the safe side, if the C++ type can't
|
||||
be extracted, an appropriate exception is thrown. To avoid an exception,
|
||||
we need to test for extractibility:
|
||||
</p>
|
||||
@@ -258,7 +257,7 @@
|
||||
<span class="identifier">Vec2</span><span class="special">&</span> <span class="identifier">v</span> <span class="special">=</span> <span class="identifier">x</span><span class="special">();</span> <span class="special">...</span>
|
||||
</pre>
|
||||
<p>
|
||||
<span class="inlinemediaobject"><img src="../images/tip.png" alt="tip"></span> The astute reader might have noticed that the <code class="literal">extract<T></code>
|
||||
<span class="inlinemediaobject"><img src="../images/tip.png" alt="tip"></span> The astute reader might have noticed that the <tt class="literal">extract<T></tt>
|
||||
facility in fact solves the mutable copying problem:
|
||||
</p>
|
||||
<pre class="programlisting">
|
||||
@@ -271,8 +270,8 @@
|
||||
<a name="python.enums"></a>Enums</h3></div></div></div>
|
||||
<p>
|
||||
Boost.Python has a nifty facility to capture and wrap C++ enums. While Python
|
||||
has no <code class="literal">enum</code> type, we'll often want to expose our C++ enums
|
||||
to Python as an <code class="literal">int</code>. Boost.Python's enum facility makes
|
||||
has no <tt class="literal">enum</tt> type, we'll often want to expose our C++ enums
|
||||
to Python as an <tt class="literal">int</tt>. Boost.Python's enum facility makes
|
||||
this easy while taking care of the proper conversions from Python's dynamic
|
||||
typing to C++'s strong static typing (in C++, ints cannot be implicitly converted
|
||||
to enums). To illustrate, given a C++ enum:
|
||||
@@ -291,17 +290,25 @@
|
||||
</pre>
|
||||
<p>
|
||||
can be used to expose to Python. The new enum type is created in the current
|
||||
<code class="literal">scope()</code>, which is usually the current module. The snippet
|
||||
above creates a Python class derived from Python's <code class="literal">int</code>
|
||||
<tt class="literal">scope()</tt>, which is usually the current module. The snippet
|
||||
above creates a Python class derived from Python's <tt class="literal">int</tt>
|
||||
type which is associated with the C++ type passed as its first parameter.
|
||||
</p>
|
||||
<div class="informaltable"><table class="table">
|
||||
<colgroup><col></colgroup>
|
||||
<tbody><tr><td class="blurb"> <span class="inlinemediaobject"><img src="../images/note.png" alt="note"></span> <span class="bold"><strong>what is a scope?</strong></span><br>
|
||||
<br> The scope is a class that has an associated global Python object
|
||||
which controls the Python namespace in which new extension classes
|
||||
and wrapped functions will be defined as attributes. Details can be
|
||||
found <a href="../../../../v2/scope.html" target="_top">here</a>.</td></tr></tbody>
|
||||
<div class="note"><table border="0" summary="Note">
|
||||
<tr>
|
||||
<td rowspan="2" align="center" valign="top" width="25"><img alt="[Note]" src="../../../../../../../doc/html/images/note.png"></td>
|
||||
<th align="left">Note</th>
|
||||
</tr>
|
||||
<tr><td colspan="2" align="left" valign="top">
|
||||
<p>
|
||||
<span class="bold"><b>what is a scope?</b></span>
|
||||
</p>
|
||||
<p>
|
||||
The scope is a class that has an associated global Python object which
|
||||
controls the Python namespace in which new extension classes and wrapped
|
||||
functions will be defined as attributes. Details can be found <a href="../../../../v2/scope.html" target="_top">here</a>.
|
||||
</p>
|
||||
</td></tr>
|
||||
</table></div>
|
||||
<p>
|
||||
You can access those values in Python as
|
||||
@@ -334,12 +341,16 @@
|
||||
</div>
|
||||
<table xmlns:rev="http://www.cs.rpi.edu/~gregod/boost/tools/doc/revision" width="100%"><tr>
|
||||
<td align="left"></td>
|
||||
<td align="right"><small>Copyright © 2002-2005 Joel
|
||||
de Guzman, David Abrahams</small></td>
|
||||
<td align="right"><div class="copyright-footer"><small>Copyright © 2002-2005 Joel
|
||||
de Guzman, David Abrahams<p>
|
||||
Distributed under the Boost Software License, Version 1.0. (See accompanying
|
||||
file LICENSE_1_0.txt or copy at <a href="http://www.boost.org/LICENSE_1_0.txt" target="_top">
|
||||
http://www.boost.org/LICENSE_1_0.txt </a>)
|
||||
</p></small></div></td>
|
||||
</tr></table>
|
||||
<hr>
|
||||
<div class="spirit-nav">
|
||||
<a accesskey="p" href="functions.html"><img src="../images/prev.png" alt="Prev"></a><a accesskey="u" href="../index.html"><img src="../images/up.png" alt="Up"></a><a accesskey="h" href="../index.html"><img src="../images/home.png" alt="Home"></a><a accesskey="n" href="embedding.html"><img src="../images/next.png" alt="Next"></a>
|
||||
<a accesskey="p" href="functions.html"><img src="../../../../../../../doc/html/images/prev.png" alt="Prev"></a><a accesskey="u" href="../index.html"><img src="../../../../../../../doc/html/images/up.png" alt="Up"></a><a accesskey="h" href="../index.html"><img src="../../../../../../../doc/html/images/home.png" alt="Home"></a><a accesskey="n" href="embedding.html"><img src="../../../../../../../doc/html/images/next.png" alt="Next"></a>
|
||||
</div>
|
||||
</body>
|
||||
</html>
|
||||
|
||||
@@ -1,25 +1,25 @@
|
||||
<html>
|
||||
<head>
|
||||
<meta http-equiv="Content-Type" content="text/html; charset=ISO-8859-1">
|
||||
<title>General Techniques</title>
|
||||
<link rel="stylesheet" href="../boostbook.css" type="text/css">
|
||||
<meta name="generator" content="DocBook XSL Stylesheets V1.72.0">
|
||||
<title> General Techniques</title>
|
||||
<link rel="stylesheet" href="../../../../../../../doc/html/boostbook.css" type="text/css">
|
||||
<meta name="generator" content="DocBook XSL Stylesheets V1.66.1">
|
||||
<link rel="start" href="../index.html" title="Chapter 1. python 1.0">
|
||||
<link rel="up" href="../index.html" title="Chapter 1. python 1.0">
|
||||
<link rel="prev" href="exception.html" title="Exception Translation">
|
||||
<link rel="prev" href="exception.html" title=" Exception Translation">
|
||||
</head>
|
||||
<body bgcolor="white" text="black" link="#0000FF" vlink="#840084" alink="#0000FF">
|
||||
<table cellpadding="2" width="100%">
|
||||
<table cellpadding="2" width="100%"><tr>
|
||||
<td valign="top"><img alt="Boost C++ Libraries" width="277" height="86" src="../../../../../../../boost.png"></td>
|
||||
<td align="center"><a href="../../../../../../../index.htm">Home</a></td>
|
||||
<td align="center"><a href="../../../../../../../libs/libraries.htm">Libraries</a></td>
|
||||
<td align="center"><a href="../../../../../../../people/people.htm">People</a></td>
|
||||
<td align="center"><a href="../../../../../../../more/faq.htm">FAQ</a></td>
|
||||
<td align="center"><a href="../../../../../../../more/index.htm">More</a></td>
|
||||
</table>
|
||||
</tr></table>
|
||||
<hr>
|
||||
<div class="spirit-nav">
|
||||
<a accesskey="p" href="exception.html"><img src="../images/prev.png" alt="Prev"></a><a accesskey="u" href="../index.html"><img src="../images/up.png" alt="Up"></a><a accesskey="h" href="../index.html"><img src="../images/home.png" alt="Home"></a>
|
||||
<a accesskey="p" href="exception.html"><img src="../../../../../../../doc/html/images/prev.png" alt="Prev"></a><a accesskey="u" href="../index.html"><img src="../../../../../../../doc/html/images/up.png" alt="Up"></a><a accesskey="h" href="../index.html"><img src="../../../../../../../doc/html/images/home.png" alt="Home"></a>
|
||||
</div>
|
||||
<div class="section" lang="en">
|
||||
<div class="titlepage"><div><div><h2 class="title" style="clear: both">
|
||||
@@ -50,7 +50,7 @@
|
||||
<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)
|
||||
<code class="literal">sounds</code>. Our library already has a neat C++ namespace hierarchy,
|
||||
<tt class="literal">sounds</tt>. Our library already has a neat C++ namespace hierarchy,
|
||||
like so:
|
||||
</p>
|
||||
<pre class="programlisting">
|
||||
@@ -93,15 +93,20 @@
|
||||
<span class="special">}</span>
|
||||
</pre>
|
||||
<p>
|
||||
Compiling these files will generate the following Python extensions: <code class="literal">core.pyd</code>,
|
||||
<code class="literal">io.pyd</code> and <code class="literal">filters.pyd</code>.
|
||||
Compiling these files will generate the following Python extensions: <tt class="literal">core.pyd</tt>,
|
||||
<tt class="literal">io.pyd</tt> and <tt class="literal">filters.pyd</tt>.
|
||||
</p>
|
||||
<div class="informaltable"><table class="table">
|
||||
<colgroup><col></colgroup>
|
||||
<tbody><tr><td class="blurb"> <span class="inlinemediaobject"><img src="../images/note.png" alt="note"></span> The extension <code class="literal">.pyd</code> is used
|
||||
for python extension modules, which are just shared libraries. Using
|
||||
the default for your system, like <code class="literal">.so</code> for Unix and
|
||||
<code class="literal">.dll</code> for Windows, works just as well.</td></tr></tbody>
|
||||
<div class="note"><table border="0" summary="Note">
|
||||
<tr>
|
||||
<td rowspan="2" align="center" valign="top" width="25"><img alt="[Note]" src="../../../../../../../doc/html/images/note.png"></td>
|
||||
<th align="left">Note</th>
|
||||
</tr>
|
||||
<tr><td colspan="2" align="left" valign="top"><p>
|
||||
The extension <tt class="literal">.pyd</tt> is used for python extension modules,
|
||||
which are just shared libraries. Using the default for your system, like
|
||||
<tt class="literal">.so</tt> for Unix and <tt class="literal">.dll</tt> for Windows,
|
||||
works just as well.
|
||||
</p></td></tr>
|
||||
</table></div>
|
||||
<p>
|
||||
Now, we create this directory structure for our Python package:
|
||||
@@ -113,12 +118,12 @@
|
||||
io.pyd
|
||||
</pre>
|
||||
<p>
|
||||
The file <code class="literal">__init__.py</code> is what tells Python that the directory
|
||||
<code class="literal">sounds/</code> is actually a Python package. It can be a empty
|
||||
The file <tt class="literal">__init__.py</tt> is what tells Python that the directory
|
||||
<tt class="literal">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 <code class="literal">sounds</code>
|
||||
Now our package is ready. All the user has to do is put <tt class="literal">sounds</tt>
|
||||
into his <a href="http://www.python.org/doc/current/tut/node8.html#SECTION008110000000000000000" target="_top">PYTHONPATH</a>
|
||||
and fire up the interpreter:
|
||||
</p>
|
||||
@@ -157,7 +162,7 @@
|
||||
</pre>
|
||||
<p>
|
||||
Note that we added an underscore to the module name. The filename will have
|
||||
to be changed to <code class="literal">_core.pyd</code> as well, and we do the same
|
||||
to be changed to <tt class="literal">_core.pyd</tt> as well, and we do the same
|
||||
to the other extension modules. Now, we change our package hierarchy like
|
||||
so:
|
||||
</p>
|
||||
@@ -165,12 +170,12 @@
|
||||
__init__.py
|
||||
core/
|
||||
__init__.py
|
||||
_core.pyd
|
||||
<span class="underline">core.pyd
|
||||
filters/
|
||||
__init__.py
|
||||
_filters.pyd
|
||||
\</span>_init__.py
|
||||
<span class="underline">filters.pyd
|
||||
io/
|
||||
__init__.py
|
||||
\</span>_init__.py
|
||||
_io.pyd
|
||||
</pre>
|
||||
<p>
|
||||
@@ -185,11 +190,11 @@
|
||||
<span class="special">>>></span> <span class="identifier">sounds</span><span class="special">.</span><span class="identifier">core</span><span class="special">.</span><span class="identifier">_core</span><span class="special">.</span><span class="identifier">foo</span><span class="special">(...)</span>
|
||||
</pre>
|
||||
<p>
|
||||
which is not what we want. But here enters the <code class="literal">__init__.py</code>
|
||||
magic: everything that is brought to the <code class="literal">__init__.py</code> namespace
|
||||
which is not what we want. But here enters the <tt class="literal">__init__.py</tt>
|
||||
magic: everything that is brought to the <tt class="literal">__init__.py</tt> namespace
|
||||
can be accessed directly by the user. So, all we have to do is bring the
|
||||
entire namespace from <code class="literal">_core.pyd</code> to <code class="literal">core/__init__.py</code>.
|
||||
So add this line of code to <code class="literal">sounds<span class="emphasis"><em>core</em></span>__init__.py</code>:
|
||||
entire namespace from <tt class="literal">_core.pyd</tt> to <tt class="literal">core/__init__.py</tt>.
|
||||
So add this line of code to <tt class="literal">sounds<span class="emphasis"><em>core</em></span>__init__.py</tt>:
|
||||
</p>
|
||||
<pre class="programlisting">
|
||||
<span class="keyword">from</span> <span class="identifier">_core</span> <span class="keyword">import</span> <span class="special">*</span>
|
||||
@@ -206,10 +211,10 @@
|
||||
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 <span class="emphasis"><em>pure</em></span>
|
||||
Python function, <code class="literal">echo_noise</code>, to the <code class="literal">filters</code>
|
||||
package. This function applies both the <code class="literal">echo</code> and <code class="literal">noise</code>
|
||||
filters in sequence in the given <code class="literal">sound</code> object. We create
|
||||
a file named <code class="literal">sounds/filters/echo_noise.py</code> and code our
|
||||
Python function, <tt class="literal">echo_noise</tt>, to the <tt class="literal">filters</tt>
|
||||
package. This function applies both the <tt class="literal">echo</tt> and <tt class="literal">noise</tt>
|
||||
filters in sequence in the given <tt class="literal">sound</tt> object. We create
|
||||
a file named <tt class="literal">sounds/filters/echo_noise.py</tt> and code our
|
||||
function:
|
||||
</p>
|
||||
<pre class="programlisting">
|
||||
@@ -220,14 +225,14 @@
|
||||
<span class="keyword">return</span> <span class="identifier">s</span>
|
||||
</pre>
|
||||
<p>
|
||||
Next, we add this line to <code class="literal">sounds<span class="emphasis"><em>filters</em></span>__init__.py</code>:
|
||||
Next, we add this line to <tt class="literal">sounds<span class="emphasis"><em>filters</em></span>__init__.py</tt>:
|
||||
</p>
|
||||
<pre class="programlisting">
|
||||
<span class="keyword">from</span> <span class="identifier">echo_noise</span> <span class="keyword">import</span> <span class="identifier">echo_noise</span>
|
||||
</pre>
|
||||
<p>
|
||||
And that's it. The user now accesses this function like any other function
|
||||
from the <code class="literal">filters</code> package:
|
||||
from the <tt class="literal">filters</tt> package:
|
||||
</p>
|
||||
<pre class="programlisting">
|
||||
<span class="special">>>></span> <span class="keyword">import</span> <span class="identifier">sounds</span><span class="special">.</span><span class="identifier">filters</span>
|
||||
@@ -261,7 +266,7 @@
|
||||
</p>
|
||||
<p>
|
||||
We can do the same with classes that were wrapped with Boost.Python. Suppose
|
||||
we have a class <code class="literal">point</code> in C++:
|
||||
we have a class <tt class="literal">point</tt> in C++:
|
||||
</p>
|
||||
<p>
|
||||
</p>
|
||||
@@ -275,7 +280,7 @@
|
||||
</pre>
|
||||
<p>
|
||||
If we are using the technique from the previous session, <a href="techniques.html#python.creating_packages" title="Creating Packages">Creating
|
||||
Packages</a>, we can code directly into <code class="literal">geom/__init__.py</code>:
|
||||
Packages</a>, we can code directly into <tt class="literal">geom/__init__.py</tt>:
|
||||
</p>
|
||||
<p>
|
||||
</p>
|
||||
@@ -290,7 +295,7 @@
|
||||
</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>
|
||||
<p>
|
||||
<span class="bold"><strong>All</strong></span> point instances created from C++ will
|
||||
<span class="bold"><b>All</b></span> point instances created from C++ will
|
||||
also have this member function! This technique has several advantages:
|
||||
</p>
|
||||
<div class="itemizedlist"><ul type="disc">
|
||||
@@ -389,7 +394,7 @@
|
||||
<span class="special">}</span>
|
||||
</pre>
|
||||
<p>
|
||||
Now you create a file <code class="literal">main.cpp</code>, which contains the <code class="literal">BOOST_PYTHON_MODULE</code>
|
||||
Now you create a file <tt class="literal">main.cpp</tt>, which contains the <tt class="literal">BOOST_PYTHON_MODULE</tt>
|
||||
macro, and call the various export functions inside it.
|
||||
</p>
|
||||
<pre class="programlisting">
|
||||
@@ -425,29 +430,42 @@
|
||||
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>
|
||||
<div class="informaltable"><table class="table">
|
||||
<colgroup><col></colgroup>
|
||||
<tbody><tr><td class="blurb"> <span class="inlinemediaobject"><img src="../images/note.png" alt="note"></span> If you're exporting your classes with <a href="../../../../../pyste/index.html" target="_top">Pyste</a>,
|
||||
take a look at the <code class="literal">--multiple</code> option, that generates
|
||||
the wrappers in various files as demonstrated here.</td></tr></tbody>
|
||||
<div class="note"><table border="0" summary="Note">
|
||||
<tr>
|
||||
<td rowspan="2" align="center" valign="top" width="25"><img alt="[Note]" src="../../../../../../../doc/html/images/note.png"></td>
|
||||
<th align="left">Note</th>
|
||||
</tr>
|
||||
<tr><td colspan="2" align="left" valign="top"><p>
|
||||
If you're exporting your classes with <a href="../../../../../pyste/index.html" target="_top">Pyste</a>,
|
||||
take a look at the <tt class="literal">--multiple</tt> option, that generates
|
||||
the wrappers in various files as demonstrated here.
|
||||
</p></td></tr>
|
||||
</table></div>
|
||||
<div class="informaltable"><table class="table">
|
||||
<colgroup><col></colgroup>
|
||||
<tbody><tr><td class="blurb"> <span class="inlinemediaobject"><img src="../images/note.png" alt="note"></span> This method is useful too if you are getting the
|
||||
error message <span class="emphasis"><em>"fatal error C1204:Compiler limit:internal
|
||||
structure overflow"</em></span> when compiling a large source file,
|
||||
as explained in the <a href="../../../../v2/faq.html#c1204" target="_top">FAQ</a>.</td></tr></tbody>
|
||||
<div class="note"><table border="0" summary="Note">
|
||||
<tr>
|
||||
<td rowspan="2" align="center" valign="top" width="25"><img alt="[Note]" src="../../../../../../../doc/html/images/note.png"></td>
|
||||
<th align="left">Note</th>
|
||||
</tr>
|
||||
<tr><td colspan="2" align="left" valign="top"><p>
|
||||
This method is useful too if you are getting the error message <span class="emphasis"><em>"fatal
|
||||
error C1204:Compiler limit:internal structure overflow"</em></span>
|
||||
when compiling a large source file, as explained in the <a href="../../../../v2/faq.html#c1204" target="_top">FAQ</a>.
|
||||
</p></td></tr>
|
||||
</table></div>
|
||||
</div>
|
||||
</div>
|
||||
<table xmlns:rev="http://www.cs.rpi.edu/~gregod/boost/tools/doc/revision" width="100%"><tr>
|
||||
<td align="left"></td>
|
||||
<td align="right"><small>Copyright © 2002-2005 Joel
|
||||
de Guzman, David Abrahams</small></td>
|
||||
<td align="right"><div class="copyright-footer"><small>Copyright © 2002-2005 Joel
|
||||
de Guzman, David Abrahams<p>
|
||||
Distributed under the Boost Software License, Version 1.0. (See accompanying
|
||||
file LICENSE_1_0.txt or copy at <a href="http://www.boost.org/LICENSE_1_0.txt" target="_top">
|
||||
http://www.boost.org/LICENSE_1_0.txt </a>)
|
||||
</p></small></div></td>
|
||||
</tr></table>
|
||||
<hr>
|
||||
<div class="spirit-nav">
|
||||
<a accesskey="p" href="exception.html"><img src="../images/prev.png" alt="Prev"></a><a accesskey="u" href="../index.html"><img src="../images/up.png" alt="Up"></a><a accesskey="h" href="../index.html"><img src="../images/home.png" alt="Home"></a>
|
||||
<a accesskey="p" href="exception.html"><img src="../../../../../../../doc/html/images/prev.png" alt="Prev"></a><a accesskey="u" href="../index.html"><img src="../../../../../../../doc/html/images/up.png" alt="Up"></a><a accesskey="h" href="../index.html"><img src="../../../../../../../doc/html/images/home.png" alt="Home"></a>
|
||||
</div>
|
||||
</body>
|
||||
</html>
|
||||
|
||||
@@ -49,10 +49,10 @@ Function:
|
||||
can be exposed to Python by writing a Boost.Python wrapper:
|
||||
|
||||
#include <boost/python.hpp>
|
||||
using namespace boost::python;
|
||||
|
||||
BOOST_PYTHON_MODULE(hello)
|
||||
BOOST_PYTHON_MODULE(hello_ext)
|
||||
{
|
||||
using namespace boost::python;
|
||||
def("greet", greet);
|
||||
}
|
||||
|
||||
@@ -61,7 +61,7 @@ resulting DLL is now visible to Python. Here's a sample Python session:
|
||||
|
||||
[python]
|
||||
|
||||
>>> import hello
|
||||
>>> import hello_ext
|
||||
>>> print hello.greet()
|
||||
hello, world
|
||||
|
||||
@@ -75,43 +75,39 @@ resulting DLL is now visible to Python. Here's a sample Python session:
|
||||
[h2 From Start To Finish]
|
||||
|
||||
Now the first thing you'd want to do is to build the Hello World module and
|
||||
try it for yourself in Python. In this section, we shall outline the steps
|
||||
necessary to achieve that. We shall use the build tool that comes bundled
|
||||
try it for yourself in Python. In this section, we will outline the steps
|
||||
necessary to achieve that. We will use the build tool that comes bundled
|
||||
with every boost distribution: [*bjam].
|
||||
|
||||
[blurb __note__ [*Building without bjam]\n\n
|
||||
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].\n\n
|
||||
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.
|
||||
[note [*Building without 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
|
||||
hello world module and run it in Python. For a complete reference to
|
||||
building Boost.Python, check out: [@../../../building.html building.html].
|
||||
After this brief ['bjam] tutorial, we should have built two DLLs:
|
||||
|
||||
* boost_python.dll
|
||||
* hello.pyd
|
||||
|
||||
if you are on Windows, and
|
||||
|
||||
* libboost_python.so
|
||||
* hello.so
|
||||
|
||||
if you are on Unix.
|
||||
We will skip over the details. Our objective will be to simply create
|
||||
the hello world module and run it in Python. For a complete reference to
|
||||
building Boost.Python, check out: [@../../../building.html
|
||||
building.html]. After this brief ['bjam] tutorial, we should have built
|
||||
the DLLs and run a python program using the extension.
|
||||
|
||||
The tutorial example can be found in the directory:
|
||||
[^libs/python/example/tutorial]. There, you can find:
|
||||
|
||||
* hello.cpp
|
||||
* Jamfile
|
||||
* hello.py
|
||||
* Jamroot
|
||||
|
||||
The [^hello.cpp] file is our C++ hello world example. The [^Jamfile] is a
|
||||
minimalist ['bjam] script that builds the DLLs for us.
|
||||
The [^hello.cpp] file is our C++ hello world example. The [^Jamroot] is
|
||||
a minimalist ['bjam] script that builds the DLLs for us. Finally,
|
||||
[^hello.py] is our Python program that uses the extension in
|
||||
[^hello.cpp].
|
||||
|
||||
Before anything else, you should have the bjam executable in your boost
|
||||
directory or somewhere in your path such that [^bjam] can be executed in
|
||||
@@ -122,51 +118,12 @@ platforms. The complete list of Bjam executables can be found
|
||||
[h2 Let's Jam!]
|
||||
__jam__
|
||||
|
||||
Here is our minimalist Jamfile:
|
||||
[@../../../../example/tutorial/Jamroot Here] is our minimalist Jamroot
|
||||
file. Simply copy the file and tweak [^use-project boost] to where your
|
||||
boost root directory is and your OK.
|
||||
|
||||
[pre
|
||||
# This is the top of our own project tree
|
||||
project-root ;
|
||||
|
||||
import python ;
|
||||
|
||||
extension hello # Declare a Python extension called hello
|
||||
: hello.cpp # source
|
||||
# requirements and dependencies for Boost.Python extensions
|
||||
<template>@boost/libs/python/build/extension
|
||||
;
|
||||
]
|
||||
|
||||
First, we need to specify our location. You may place your project anywhere.
|
||||
[^project-root] allows you to do that.
|
||||
|
||||
[pre
|
||||
project-root ;
|
||||
]
|
||||
|
||||
By doing so, you'll need a Jamrules file. Simply copy the one in the
|
||||
[@../../../../example/tutorial/Jamrules example/tutorial directory] and tweak
|
||||
the [^path-global BOOST_ROOT] to where your boost root directory is. The file
|
||||
has [@../../../../example/tutorial/Jamrules detailed instructions] you can follow.
|
||||
|
||||
Then we will import the definitions needed by Python modules:
|
||||
|
||||
[pre
|
||||
import python ;
|
||||
]
|
||||
|
||||
Finally we declare our [^hello] extension:
|
||||
|
||||
[pre
|
||||
extension hello # Declare a Python extension called hello
|
||||
: hello.cpp # source
|
||||
|
||||
# requirements and dependencies for Boost.Python extensions
|
||||
<template>@boost/libs/python/build/extension
|
||||
;
|
||||
]
|
||||
|
||||
The last part tells BJam that we are depending on the Boost Python Library.
|
||||
The comments contained in the Jamrules file above should be sufficient
|
||||
to get you going.
|
||||
|
||||
[h2 Running bjam]
|
||||
|
||||
@@ -174,98 +131,60 @@ The last part tells BJam that we are depending on the Boost Python Library.
|
||||
|
||||
[:Start it up.]
|
||||
|
||||
Make sure that the environment is set so that we can invoke the C++
|
||||
compiler. With MSVC, that would mean running the [^Vcvars32.bat] batch
|
||||
file. For instance:
|
||||
A file called user-config.jam in your home directory is used to
|
||||
configure your tools. In Windows, your home directory can be found by
|
||||
typing:
|
||||
|
||||
[pre
|
||||
C:\Program Files\Microsoft Visual Studio .NET 2003\Common7\Tools\vsvars32.bat
|
||||
ECHO %HOMEDRIVE%%HOMEPATH%
|
||||
]
|
||||
|
||||
Some environment variables will have to be setup for proper building of our
|
||||
Python modules. Example:
|
||||
into a command prompt window. Your file should at least have the rules
|
||||
for your compiler and your python installation. A specific example of
|
||||
this on Windows would be:
|
||||
|
||||
[pre
|
||||
set PYTHON_ROOT=c:/dev/tools/python
|
||||
set PYTHON_VERSION=2.2
|
||||
# MSVC configuration
|
||||
using msvc : 8.0 ;
|
||||
|
||||
# Python configuration
|
||||
using python : 2.4 : C:/dev/tools/Python/ ;
|
||||
]
|
||||
|
||||
The above assumes that the Python installation is in [^c:/dev/tools/python]
|
||||
and that we are using Python version 2.2. You'll have to tweak these
|
||||
appropriately.
|
||||
|
||||
[blurb __tip__ Be sure not to include a third number, e.g. [*not] "2.2.1",
|
||||
even if that's the version you have.]
|
||||
|
||||
Take note that you may also do that through the Jamrules file we put in
|
||||
our project as detailed above. The file
|
||||
has [@../../../../example/tutorial/Jamrules detailed instructions] you
|
||||
can follow.
|
||||
The first rule tells Bjam to use the MSVC 8.0 compiler and associated
|
||||
tools. The second rule provides information on Python, its version and
|
||||
where it is located. The above assumes that the Python installation is
|
||||
in [^C:/dev/tools\/Python/]. If you have one fairly "standard" python
|
||||
installation for your platform, you might not need to do this.
|
||||
|
||||
Now we are ready... Be sure to [^cd] to [^libs/python/example/tutorial]
|
||||
where the tutorial [^"hello.cpp"] and the [^"Jamfile"] is situated.
|
||||
where the tutorial [^"hello.cpp"] and the [^"Jamroot"] is situated.
|
||||
|
||||
Finally:
|
||||
|
||||
bjam -sTOOLS=vc-7_1
|
||||
|
||||
We are again assuming that we are using Microsoft Visual C++ version 7.1. If
|
||||
not, then you will have to specify the appropriate tool. See
|
||||
[@../../../../../../tools/build/index.html Building Boost Libraries] for
|
||||
further details.
|
||||
bjam
|
||||
|
||||
It should be building now:
|
||||
|
||||
[pre
|
||||
cd C:\dev\boost\libs\python\example\tutorial
|
||||
bjam -sTOOLS=msvc
|
||||
bjam
|
||||
...patience...
|
||||
...found 1703 targets...
|
||||
...updating 40 targets...
|
||||
...found 1101 targets...
|
||||
...updating 35 targets...
|
||||
]
|
||||
|
||||
And so on... Finally:
|
||||
|
||||
[pre
|
||||
Creating library bin\boost\libs\python\build\boost_python.dll\vc-7_1\debug\th
|
||||
reading-multi\boost_python.lib and object bin\boost\libs\python\build\boost_pyth
|
||||
on.dll\vc-7_1\debug\threading-multi\boost_python.exp
|
||||
vc-C++ bin\tutorial\hello.pyd\vc-7_1\debug\threading-multi\hello.obj
|
||||
hello.cpp
|
||||
vc-Link bin\tutorial\hello.pyd\vc-7_1\debug\threading-multi\hello.pyd bin\tutori
|
||||
al\hello.pyd\vc-7_1\debug\threading-multi\hello.lib
|
||||
Creating library bin\tutorial\hello.pyd\vc-7_1\debug\threading-multi\hello.li
|
||||
b and object bin\tutorial\hello.pyd\vc-7_1\debug\threading-multi\hello.exp
|
||||
...updated 31 targets...
|
||||
Creating library /path-to-boost_python.dll/
|
||||
Creating library /path-to-'''hello_ext'''.exp/
|
||||
'''**passed**''' ... hello.test
|
||||
...updated 35 targets...
|
||||
]
|
||||
|
||||
If all is well, you should now have:
|
||||
|
||||
* boost_python.dll
|
||||
* hello.pyd
|
||||
|
||||
if you are on Windows, and
|
||||
|
||||
* libboost_python.so
|
||||
* hello.so
|
||||
|
||||
if you are on Unix.
|
||||
|
||||
[^boost_python.dll] and [^hello.pyd] can be found somewhere in your project's
|
||||
[^bin] directory. After a successful build, you make it possible for the system
|
||||
to find boost_python.dll or libboost_python.so (usually done with LD_LIBRARY_PATH,
|
||||
DYLD_LIBRARY_PATH, or some other variable on *nix and with PATH on Windows) and
|
||||
for Python to find the hello module (Done with PYTHONPATH on all systems.)
|
||||
|
||||
You may now fire up Python and run our hello module:
|
||||
|
||||
[python]
|
||||
|
||||
>>> import hello
|
||||
>>> print hello.greet()
|
||||
hello, world
|
||||
|
||||
[c++]
|
||||
Or something similar. If all is well, you should now have built the DLLs and
|
||||
run the Python program.
|
||||
|
||||
[:[*There you go... Have fun!]]
|
||||
|
||||
@@ -495,7 +414,7 @@ Doing so, we get some things for free:
|
||||
Python via a pointer or reference to [^Base] can be passed where a pointer
|
||||
or reference to [^Derived] is expected.
|
||||
|
||||
Now, we shall expose the C++ free functions [^b] and [^d] and [^factory]:
|
||||
Now, we will expose the C++ free functions [^b] and [^d] and [^factory]:
|
||||
|
||||
def("b", b);
|
||||
def("d", d);
|
||||
@@ -505,7 +424,7 @@ Note that free function [^factory] is being used to generate new
|
||||
instances of class [^Derived]. In such cases, we use
|
||||
[^return_value_policy<manage_new_object>] to instruct Python to adopt
|
||||
the pointer to [^Base] and hold the instance in a new Python [^Base]
|
||||
object until the the Python object is destroyed. We shall see more of
|
||||
object until the the Python object is destroyed. We will see more of
|
||||
Boost.Python [link python.call_policies call policies] later.
|
||||
|
||||
// Tell Python to take ownership of factory's result
|
||||
@@ -516,7 +435,7 @@ Boost.Python [link python.call_policies call policies] later.
|
||||
|
||||
[section Class Virtual Functions]
|
||||
|
||||
In this section, we shall learn how to make functions behave polymorphically
|
||||
In this section, we will learn how to make functions behave polymorphically
|
||||
through virtual functions. Continuing our example, let us add a virtual function
|
||||
to our [^Base] class:
|
||||
|
||||
@@ -526,13 +445,13 @@ to our [^Base] class:
|
||||
virtual int f() = 0;
|
||||
};
|
||||
|
||||
One of the goals of Boost.Python is to be minimally intrusive on an existing C++
|
||||
design. In principle, it should be possible to expose the interface for a 3rd
|
||||
party library without changing it. It is not ideal to add anything to our class
|
||||
`Base`. Yet, when you have a virtual function that's going to be overridden in
|
||||
Python and called polymorphically *from C++*, we'll need to add some
|
||||
scaffoldings to make things work properly. What we'll do is write a class
|
||||
wrapper that derives from `Base` that will unintrusively hook into the virtual
|
||||
One of the goals of Boost.Python is to be minimally intrusive on an existing C++
|
||||
design. In principle, it should be possible to expose the interface for a 3rd
|
||||
party library without changing it. It is not ideal to add anything to our class
|
||||
`Base`. Yet, when you have a virtual function that's going to be overridden in
|
||||
Python and called polymorphically *from C++*, we'll need to add some
|
||||
scaffoldings to make things work properly. What we'll do is write a class
|
||||
wrapper that derives from `Base` that will unintrusively hook into the virtual
|
||||
functions so that a Python override may be called:
|
||||
|
||||
struct BaseWrap : Base, wrapper<Base>
|
||||
@@ -548,8 +467,10 @@ inherited `wrapper<Base>` (See [@../../../v2/wrapper.html Wrapper]). The
|
||||
`wrapper` template makes the job of wrapping classes that are meant to
|
||||
overridden in Python, easier.
|
||||
|
||||
[blurb __alert__ [*MSVC6/7 Workaround]\n\n
|
||||
If you are using Microsoft Visual C++ 6 or 7, you have to write `f` as:\n\n
|
||||
[blurb __alert__ [*MSVC6/7 Workaround]
|
||||
|
||||
If you are using Microsoft Visual C++ 6 or 7, you have to write `f` as:
|
||||
|
||||
`return call<int>(this->get_override("f").ptr());`.]
|
||||
|
||||
BaseWrap's overridden virtual member function `f` in effect calls the
|
||||
@@ -561,24 +482,25 @@ Finally, exposing `Base`:
|
||||
.def("f", pure_virtual(&Base::f))
|
||||
;
|
||||
|
||||
`pure_virtual` signals Boost.Python that the function `f` is a pure virtual
|
||||
`pure_virtual` signals Boost.Python that the function `f` is a pure virtual
|
||||
function.
|
||||
|
||||
[blurb __note__ [*member function and methods]\n\n Python, like
|
||||
many object oriented languages uses the term [*methods]. Methods
|
||||
correspond roughly to C++'s [*member functions]]
|
||||
[note [*member function and methods]
|
||||
|
||||
Python, like many object oriented languages uses the term [*methods].
|
||||
Methods correspond roughly to C++'s [*member functions]]
|
||||
|
||||
[endsect]
|
||||
|
||||
[section Virtual Functions with Default Implementations]
|
||||
|
||||
We've seen in the previous section how classes with pure virtual functions are
|
||||
We've seen in the previous section how classes with pure virtual functions are
|
||||
wrapped using Boost.Python's [@../../../v2/wrapper.html class wrapper]
|
||||
facilities. If we wish to wrap [*non]-pure-virtual functions instead, the
|
||||
facilities. If we wish to wrap [*non]-pure-virtual functions instead, the
|
||||
mechanism is a bit different.
|
||||
|
||||
Recall that in the [link python.class_virtual_functions previous section], we
|
||||
wrapped a class with a pure virtual function that we then implemented in C++, or
|
||||
Recall that in the [link python.class_virtual_functions previous section], we
|
||||
wrapped a class with a pure virtual function that we then implemented in C++, or
|
||||
Python classes derived from it. Our base class:
|
||||
|
||||
struct Base
|
||||
@@ -596,7 +518,7 @@ not declared as pure virtual:
|
||||
};
|
||||
|
||||
We wrap it this way:
|
||||
|
||||
|
||||
struct BaseWrap : Base, wrapper<Base>
|
||||
{
|
||||
int f()
|
||||
@@ -608,24 +530,26 @@ We wrap it this way:
|
||||
|
||||
int default_f() { return this->Base::f(); }
|
||||
};
|
||||
|
||||
Notice how we implemented `BaseWrap::f`. Now, we have to check if there is an
|
||||
|
||||
Notice how we implemented `BaseWrap::f`. Now, we have to check if there is an
|
||||
override for `f`. If none, then we call `Base::f()`.
|
||||
|
||||
[blurb __alert__ [*MSVC6/7 Workaround]\n\n
|
||||
[blurb __alert__ [*MSVC6/7 Workaround]
|
||||
|
||||
If you are using Microsoft Visual C++ 6 or 7, you have to rewrite the line
|
||||
with the `*note*` as:\n\n
|
||||
with the `*note*` as:
|
||||
|
||||
`return call<char const*>(f.ptr());`.]
|
||||
|
||||
Finally, exposing:
|
||||
|
||||
|
||||
class_<BaseWrap, boost::noncopyable>("Base")
|
||||
.def("f", &Base::f, &BaseWrap::default_f)
|
||||
;
|
||||
|
||||
Take note that we expose both `&Base::f` and `&BaseWrap::default_f`.
|
||||
Boost.Python needs to keep track of 1) the dispatch function [^f] and 2) the
|
||||
forwarding function to its default implementation [^default_f]. There's a
|
||||
Take note that we expose both `&Base::f` and `&BaseWrap::default_f`.
|
||||
Boost.Python needs to keep track of 1) the dispatch function [^f] and 2) the
|
||||
forwarding function to its default implementation [^default_f]. There's a
|
||||
special [^def] function for this purpose.
|
||||
|
||||
In Python, the results would be as expected:
|
||||
@@ -715,7 +639,7 @@ that correspond to these Python ['special functions]. Example:
|
||||
|
||||
Need we say more?
|
||||
|
||||
[blurb __note__ What is the business of `operator<<`?
|
||||
[note What is the business of `operator<<`?
|
||||
Well, the method `str` requires the `operator<<` to do its work (i.e.
|
||||
`operator<<` is used by the method defined by `def(str(self))`.]
|
||||
|
||||
@@ -725,9 +649,9 @@ Well, the method `str` requires the `operator<<` to do its work (i.e.
|
||||
[section Functions]
|
||||
|
||||
In this chapter, we'll look at Boost.Python powered functions in closer
|
||||
detail. We shall see some facilities to make exposing C++ functions to
|
||||
detail. We will see some facilities to make exposing C++ functions to
|
||||
Python safe from potential pifalls such as dangling pointers and
|
||||
references. We shall also see facilities that will make it even easier for
|
||||
references. We will also see facilities that will make it even easier for
|
||||
us to expose C++ functions that take advantage of C++ features such as
|
||||
overloading and default arguments.
|
||||
|
||||
@@ -890,18 +814,21 @@ or more policies can be composed by chaining. Here's the general syntax:
|
||||
Here is the list of predefined call policies. A complete reference detailing
|
||||
these can be found [@../../../v2/reference.html#models_of_call_policies here].
|
||||
|
||||
* [*with_custodian_and_ward]\n Ties lifetimes of the arguments
|
||||
* [*with_custodian_and_ward_postcall]\n Ties lifetimes of the arguments and results
|
||||
* [*return_internal_reference]\n Ties lifetime of one argument to that of result
|
||||
* [*return_value_policy<T> with T one of:]\n
|
||||
* [*reference_existing_object]\nnaive (dangerous) approach
|
||||
* [*copy_const_reference]\nBoost.Python v1 approach
|
||||
* [*copy_non_const_reference]\n
|
||||
* [*manage_new_object]\n Adopt a pointer and hold the instance
|
||||
* [*with_custodian_and_ward]: Ties lifetimes of the arguments
|
||||
* [*with_custodian_and_ward_postcall]: Ties lifetimes of the arguments and results
|
||||
* [*return_internal_reference]: Ties lifetime of one argument to that of result
|
||||
* [*return_value_policy<T> with T one of:]
|
||||
* [*reference_existing_object]: naive (dangerous) approach
|
||||
* [*copy_const_reference]: Boost.Python v1 approach
|
||||
* [*copy_non_const_reference]:
|
||||
* [*manage_new_object]: Adopt a pointer and hold the instance
|
||||
|
||||
[blurb :-) [*Remember the Zen, Luke:]\n\n
|
||||
"Explicit is better than implicit"\n
|
||||
"In the face of ambiguity, refuse the temptation to guess"\n]
|
||||
[blurb :-) [*Remember the Zen, Luke:]
|
||||
|
||||
"Explicit is better than implicit"
|
||||
|
||||
"In the face of ambiguity, refuse the temptation to guess"
|
||||
]
|
||||
|
||||
[endsect]
|
||||
[section Overloading]
|
||||
@@ -935,7 +862,7 @@ We have here our C++ class:
|
||||
};
|
||||
};
|
||||
|
||||
Class X has 4 overloaded functions. We shall start by introducing some
|
||||
Class X has 4 overloaded functions. We will start by introducing some
|
||||
member function pointer variables:
|
||||
|
||||
bool (X::*fx1)(int) = &X::f;
|
||||
@@ -1141,7 +1068,7 @@ Then...
|
||||
Python is dynamically typed, unlike C++ which is statically typed. Python
|
||||
variables may hold an integer, a float, list, dict, tuple, str, long etc.,
|
||||
among other things. In the viewpoint of Boost.Python and C++, these
|
||||
Pythonic variables are just instances of class [^object]. We shall see in
|
||||
Pythonic variables are just instances of class [^object]. We will see in
|
||||
this chapter how to deal with Python objects.
|
||||
|
||||
As mentioned, one of the goals of Boost.Python is to provide a
|
||||
@@ -1290,14 +1217,14 @@ we wanted to do above can be achieved by writing:
|
||||
Vec2& v = extract<Vec2&>(o);
|
||||
assert(l == v.length());
|
||||
|
||||
The first line attempts to extract the "length" attribute of the Boost.Python
|
||||
[^object]. The second line attempts to ['extract] the [^Vec2] object from held
|
||||
The first line attempts to extract the "length" attribute of the Boost.Python
|
||||
[^object]. The second line attempts to ['extract] the [^Vec2] object from held
|
||||
by the Boost.Python [^object].
|
||||
|
||||
Take note that we said "attempt to" above. What if the Boost.Python [^object]
|
||||
does not really hold a [^Vec2] type? This is certainly a possibility considering
|
||||
the dynamic nature of Python [^object]s. To be on the safe side, if the C++ type
|
||||
can't be extracted, an appropriate exception is thrown. To avoid an exception,
|
||||
Take note that we said "attempt to" above. What if the Boost.Python [^object]
|
||||
does not really hold a [^Vec2] type? This is certainly a possibility considering
|
||||
the dynamic nature of Python [^object]s. To be on the safe side, if the C++ type
|
||||
can't be extracted, an appropriate exception is thrown. To avoid an exception,
|
||||
we need to test for extractibility:
|
||||
|
||||
extract<Vec2&> x(o);
|
||||
@@ -1335,10 +1262,12 @@ current [^scope()], which is usually the current module. The snippet above
|
||||
creates a Python class derived from Python's [^int] type which is
|
||||
associated with the C++ type passed as its first parameter.
|
||||
|
||||
[blurb __note__ [*what is a scope?]\n\n The scope is a class that has an
|
||||
associated global Python object which controls the Python namespace in
|
||||
which new extension classes and wrapped functions will be defined as
|
||||
attributes. Details can be found [@../../../v2/scope.html here].]
|
||||
[note [*what is a scope?]
|
||||
|
||||
The scope is a class that has an associated global Python object which
|
||||
controls the Python namespace in which new extension classes and wrapped
|
||||
functions will be defined as attributes. Details can be found
|
||||
[@../../../v2/scope.html here].]
|
||||
|
||||
You can access those values in Python as
|
||||
|
||||
@@ -1433,15 +1362,15 @@ Being able to build is nice, but there is nothing to build yet. Embedding
|
||||
the Python interpreter into one of your C++ programs requires these 4
|
||||
steps:
|
||||
|
||||
# '''#include''' [^<boost/python.hpp>]\n\n
|
||||
# '''#include''' [^<boost/python.hpp>]
|
||||
|
||||
# Call Py_Initialize() to start the interpreter and create the [^__main__] module.\n\n
|
||||
# Call Py_Initialize() to start the interpreter and create the [^__main__] module.
|
||||
|
||||
# Call other Python C API routines to use the interpreter.\n\n
|
||||
# Call other Python C API routines to use the interpreter.
|
||||
|
||||
[/ # Call Py_Finalize() to stop the interpreter and release its resources.]
|
||||
|
||||
[blurb __note__ [*Note that at this time you must not call Py_Finalize() to stop the
|
||||
[note [*Note that at this time you must not call Py_Finalize() to stop the
|
||||
interpreter. This may be fixed in a future version of boost.python.]
|
||||
]
|
||||
|
||||
@@ -1499,10 +1428,10 @@ containing a phrase that is well-known in programming circles.
|
||||
|
||||
[h2 Manipulating Python objects]
|
||||
|
||||
Often we'd like to have a class to manipulate Python objects.
|
||||
But we have already seen such a class above, and in the
|
||||
[@python/object.html previous section]: the aptly named [^object] class
|
||||
and its derivatives. We've already seen that they can be constructed from
|
||||
Often we'd like to have a class to manipulate Python objects.
|
||||
But we have already seen such a class above, and in the
|
||||
[@python/object.html previous section]: the aptly named [^object] class
|
||||
and its derivatives. We've already seen that they can be constructed from
|
||||
a [^handle]. The following examples should further illustrate this fact:
|
||||
|
||||
object main_module = import("__main__");
|
||||
@@ -1650,7 +1579,7 @@ So far, we have seen how to expose C++ iterators and ranges to Python.
|
||||
Sometimes we wish to go the other way, though: we'd like to pass a
|
||||
Python sequence to an STL algorithm or use it to initialize an STL
|
||||
container. We need to make a Python iterator look like an STL iterator.
|
||||
For that, we use `stl_input_iterator<>`. Consider how we might
|
||||
For that, we use `stl_input_iterator<>`. Consider how we might
|
||||
implement a function that exposes `std::list<int>::assign()` to
|
||||
Python:
|
||||
|
||||
@@ -1754,7 +1683,7 @@ separately with Boost.Python, like this:
|
||||
Compiling these files will generate the following Python extensions:
|
||||
[^core.pyd], [^io.pyd] and [^filters.pyd].
|
||||
|
||||
[blurb __note__ The extension [^.pyd] is used for python extension modules, which
|
||||
[note The extension [^.pyd] is used for python extension modules, which
|
||||
are just shared libraries. Using the default for your system, like [^.so] for
|
||||
Unix and [^.dll] for Windows, works just as well.]
|
||||
|
||||
@@ -2025,11 +1954,11 @@ 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],
|
||||
[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.]
|
||||
|
||||
[blurb __note__ This method is useful too if you are getting the error message
|
||||
[note This method is useful too if you are getting the error message
|
||||
['"fatal error C1204:Compiler limit:internal structure overflow"] when compiling
|
||||
a large source file, as explained in the [@../../../v2/faq.html#c1204 FAQ].]
|
||||
|
||||
|
||||
@@ -8,7 +8,7 @@
|
||||
<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>
|
||||
<link rel="stylesheet" type="text/css" href="../../../../boost.css">
|
||||
|
||||
<title>Boost.Python - CallPolicies Concept</title>
|
||||
</head>
|
||||
@@ -60,6 +60,7 @@
|
||||
|
||||
<li><code>postcall</code> - Python argument tuple and result management
|
||||
after the wrapped object is invoked</li>
|
||||
<li><code>extract_return_type</code> - metafunction for extracting the return type from a given signature type sequence</li>
|
||||
</ol>
|
||||
|
||||
<h2><a name="composition"></a>CallPolicies Composition</h2>
|
||||
@@ -132,7 +133,16 @@
|
||||
reference count must be decremented; if another existing object is
|
||||
returned, its reference count must be incremented.</td>
|
||||
</tr>
|
||||
</table>
|
||||
<tr>
|
||||
<td valign="top"><code>P::extract_return_type</code></td>
|
||||
|
||||
<td>A model of <a href=
|
||||
"../../../doc/refmanual/metafunction.html">Metafunction</a>.</td>
|
||||
|
||||
<td>An MPL unary <a href=
|
||||
"../../../mpl/doc/refmanual/metafunction.html">Metafunction</a> used extract the return type from a given signature. By default it is derived from mpl::front.</td>
|
||||
</tr>
|
||||
</table>
|
||||
Models of CallPolicies are required to be <a href=
|
||||
"../../../utility/CopyConstructible.html">CopyConstructible</a>.
|
||||
<hr>
|
||||
|
||||
@@ -1,10 +1,12 @@
|
||||
<!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN">
|
||||
|
||||
<!-- Copyright David Abrahams 2006. Distributed under the Boost -->
|
||||
<!-- Software License, Version 1.0. (See accompanying -->
|
||||
<!-- file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) -->
|
||||
<html>
|
||||
<head>
|
||||
<meta http-equiv="Content-Type" content="text/html; charset=iso-8859-1">
|
||||
<link rel="stylesheet" type="text/css" href=../../../../boost.css>
|
||||
<link rel="stylesheet" type="text/css" href="../../../../boost.css">
|
||||
<title>Boost.Python - ResultConverter Concept</title>
|
||||
</head>
|
||||
<body link="#0000ff" vlink="#800080">
|
||||
@@ -24,10 +26,12 @@
|
||||
<dl class="page-index">
|
||||
<dt><a href="#introduction">Introduction</a></dt>
|
||||
<dt><a href="#concept-requirements">Concept Requirements</a></dt>
|
||||
<dl class="page-index">
|
||||
<dt><a href="#ResultConverter-concept">ResultConverter Concept</a></dt>
|
||||
<dt><a href="#ResultConverterGenerator-concept">ResultConverterGenerator Concept</a></dt>
|
||||
</dl>
|
||||
<dd>
|
||||
<dl class="page-index">
|
||||
<dt><a href="#ResultConverter-concept">ResultConverter Concept</a></dt>
|
||||
<dt><a href="#ResultConverterGenerator-concept">ResultConverterGenerator Concept</a></dt>
|
||||
</dl>
|
||||
</dd>
|
||||
</dl>
|
||||
|
||||
<h2><a name="introduction"></a>Introduction</h2>
|
||||
@@ -79,6 +83,13 @@ denotes an object of type <code><b>R</b></code>.
|
||||
href="http://www.python.org/doc/current/api/exceptionHandling.html#l2h-71">PyErr_Occurred</a>
|
||||
should return non-zero.</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td valign="top"><code>c.get_pytype()</code></td>
|
||||
<td><code>PyTypeObject const*</code></td>
|
||||
<td>A pointer to a Python Type object corresponding to result of the conversion,
|
||||
or <code>0</code>. Used for documentation generation. If <code>0</code> is returned
|
||||
the generated type in the documentation will be <b>object</b> .</td>
|
||||
</tr>
|
||||
</table>
|
||||
|
||||
<h3><a name="ResultConverterGenerator-concept"></a>ResultConverterGenerator Concept</h3>
|
||||
|
||||
@@ -139,6 +139,41 @@
|
||||
compares <code>typeid(T).name()</code> instead of using and comparing
|
||||
the <code>std::type_info</code> objects directly.</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td valign="top"><code>BOOST_PYTHON_NO_PY_SIGNATURES</code></td>
|
||||
|
||||
<td valign="top" align="center"><i>not defined</i></td>
|
||||
|
||||
<td valign="top">If defined for a module no pythonic signatures are generated
|
||||
for the docstrings of the module functions, and no python type is associated with any
|
||||
of the converters registered by the module. This also reduces the binary size of the
|
||||
module by about 14% (gcc compiled).<br>
|
||||
If defined for the boost_python runtime library, the default for the
|
||||
<code>docstring_options.enable_py_signatures()</code> is set to <code>false</code>.
|
||||
</td>
|
||||
|
||||
</tr>
|
||||
<tr>
|
||||
<td valign="top"><code>BOOST_PYTHON_SUPPORTS_PY_SIGNATURES</code></td>
|
||||
|
||||
<td valign="top" align="center"><i>defined if <code>BOOST_PYTHON_NO_PY_SIGNATURES</code> is undefined</i></td>
|
||||
|
||||
<td valign="top">This macro is defined to enable a smooth transition from older Boost.Python versions
|
||||
which do not support pythonic signatures. For example usage see
|
||||
<a href="pytype_function.html#examples">here</a>.
|
||||
</td>
|
||||
|
||||
</tr>
|
||||
<tr>
|
||||
<td valign="top"><code>BOOST_PYTHON_PY_SIGNATURES_PROPER_INIT_SELF_TYPE</code></td>
|
||||
|
||||
<td valign="top" align="center"><i>not defined</i></td>
|
||||
|
||||
<td valign="top">If defined the python type of <code>__init__</code> method "self" parameters
|
||||
is properly generated, otherwise <code><b>object</b></code> is used. It is undefined
|
||||
by default because it increases the binary size of the module by about 14% (gcc compiled).</td>
|
||||
|
||||
</tr>
|
||||
</table>
|
||||
<hr>
|
||||
|
||||
|
||||
@@ -82,6 +82,7 @@ namespace boost { namespace python
|
||||
static PyObject* postcall(PyObject*, PyObject* result);
|
||||
typedef <a href=
|
||||
"#default_result_converter-spec">default_result_converter</a> result_converter;
|
||||
template <class Sig> struct extract_return_type : mpl::front<Sig>{};
|
||||
};
|
||||
}}
|
||||
</pre>
|
||||
@@ -161,7 +162,7 @@ struct return_value_policy : Base
|
||||
|
||||
<p>Revised
|
||||
<!--webbot bot="Timestamp" S-Type="EDITED" S-Format="%d %B, %Y" startspan -->
|
||||
13 November, 2002
|
||||
11 June, 2007
|
||||
<!--webbot bot="Timestamp" endspan i-checksum="39359" -->
|
||||
|
||||
|
||||
|
||||
@@ -103,6 +103,8 @@ namespace boost { namespace python {
|
||||
|
||||
docstring_options(bool show_user_defined, bool show_signatures);
|
||||
|
||||
docstring_options(bool show_user_defined, bool show_py_signatures, bool show_cpp_signatures);
|
||||
|
||||
~docstring_options();
|
||||
|
||||
void
|
||||
@@ -117,6 +119,18 @@ namespace boost { namespace python {
|
||||
void
|
||||
enable_signatures();
|
||||
|
||||
void
|
||||
disable_py_signatures();
|
||||
|
||||
void
|
||||
enable_py_signatures();
|
||||
|
||||
void
|
||||
disable_cpp_signatures();
|
||||
|
||||
void
|
||||
enable_cpp_signatures();
|
||||
|
||||
void
|
||||
disable_all();
|
||||
|
||||
@@ -139,7 +153,7 @@ docstring_options(bool show_all=true);
|
||||
object which controls the appearance of function and
|
||||
member-function docstrings defined in the code that follows. If
|
||||
<code>show_all</code> is <code>true</code>, both the
|
||||
user-defined docstrings and the automatically generated C++
|
||||
user-defined docstrings and the automatically generated Python and C++
|
||||
signatures are shown. If <code>show_all</code> is
|
||||
<code>false</code> the <code>__doc__</code> attributes are
|
||||
<code>None</code>.</dt>
|
||||
@@ -154,12 +168,29 @@ docstring_options(bool show_user_defined, bool show_signatures);
|
||||
member-function docstrings defined in the code that follows.
|
||||
Iff <code>show_user_defined</code> is <code>true</code>, the
|
||||
user-defined docstrings are shown. Iff
|
||||
<code>show_signatures</code> is <code>true</code>, C++
|
||||
<code>show_signatures</code> is <code>true</code>, Python and C++
|
||||
signatures are automatically added. If both
|
||||
<code>show_user_defined</code> and <code>show_signatures</code>
|
||||
are <code>false</code>, the <code>__doc__</code> attributes are
|
||||
<code>None</code>.</dt>
|
||||
</dl>
|
||||
<pre>
|
||||
docstring_options(bool show_user_defined, bool show_py_signatures, bool show_cpp_signatures);
|
||||
</pre>
|
||||
|
||||
<dl class="function-semantics">
|
||||
<dt><b>Effects:</b> Constructs a <code>docstring_options</code>
|
||||
object which controls the appearance of function and
|
||||
member-function docstrings defined in the code that follows.
|
||||
Iff <code>show_user_defined</code> is <code>true</code>, the
|
||||
user-defined docstrings are shown. Iff
|
||||
<code>show_py_signatures</code> is <code>true</code>, Python
|
||||
signatures are automatically added. Iff
|
||||
<code>show_cpp_signatures</code> is <code>true</code>, C++
|
||||
signatures are automatically added. If all parameters are
|
||||
<code>false</code>, the <code>__doc__</code> attributes are
|
||||
<code>None</code>.</dt>
|
||||
</dl>
|
||||
|
||||
<h4><a name="docstring_options-spec-dtors" id=
|
||||
"docstring_options-spec-dtors"></a>Class
|
||||
@@ -186,6 +217,10 @@ void disable_user_defined();
|
||||
void enable_user_defined();
|
||||
void disable_signatures();
|
||||
void enable_signatures();
|
||||
void disable_py_signatures();
|
||||
void enable_py_signatures();
|
||||
void disable_cpp_signatures();
|
||||
void enable_cpp_signatures();
|
||||
void disable_all();
|
||||
void enable_all();
|
||||
</pre>
|
||||
@@ -196,7 +231,7 @@ void enable_all();
|
||||
<code>*_user_defined()</code> and <code>*_signatures()</code>
|
||||
member functions are provided for fine-grained control. The
|
||||
<code>*_all()</code> member functions are convenient shortcuts
|
||||
to manipulate both settings simultaneously.</dt>
|
||||
to manipulate all settings simultaneously.</dt>
|
||||
</dl>
|
||||
|
||||
<h2><a name="examples" id="examples"></a>Examples</h2>
|
||||
@@ -219,7 +254,7 @@ BOOST_PYTHON_MODULE(demo)
|
||||
<pre>
|
||||
>>> import demo
|
||||
>>> print demo.foo.__doc__
|
||||
foo doc
|
||||
foo() -> None : foo doc
|
||||
C++ signature:
|
||||
foo(void) -> void
|
||||
</pre>If compiled with
|
||||
@@ -253,21 +288,33 @@ BOOST_PYTHON_MODULE(demo)
|
||||
def("foo3", foo3, arg("f"), "foo3 doc");
|
||||
doc_options.enable_user_defined();
|
||||
def("foo4", foo4, arg("d"), "foo4 doc");
|
||||
doc_options.enable_py_signatures();
|
||||
def("foo5", foo4, arg("d"), "foo5 doc");
|
||||
doc_options.disable_py_signatures();
|
||||
doc_options.enable_cpp_signatures();
|
||||
def("foo6", foo4, arg("d"), "foo6 doc");
|
||||
}
|
||||
</pre>Python code:
|
||||
<pre>
|
||||
>>> import demo
|
||||
>>> print demo.foo1.__doc__
|
||||
foo1 doc
|
||||
foo1( (int)i) -> int : foo1 doc
|
||||
C++ signature:
|
||||
foo1(int i) -> int
|
||||
>>> print demo.foo2.__doc__
|
||||
foo2( (int)l) -> int :
|
||||
C++ signature:
|
||||
foo2(long l) -> int
|
||||
>>> print demo.foo3.__doc__
|
||||
None
|
||||
>>> print demo.foo4.__doc__
|
||||
foo4 doc
|
||||
>>> print demo.foo5.__doc__
|
||||
foo5( (float)d) -> int : foo5 doc
|
||||
>>> print demo.foo6.__doc__
|
||||
foo6 doc
|
||||
C++ signature:
|
||||
foo6(double d) -> int
|
||||
</pre>
|
||||
|
||||
<h4>Wrapping from multiple C++ scopes</h4>
|
||||
|
||||
@@ -89,7 +89,7 @@ namespace boost { namespace python
|
||||
template <class T>
|
||||
class enum_ : public <a href="object.html#object-spec">object</a>
|
||||
{
|
||||
enum_(char const* name);
|
||||
enum_(char const* name, char const* doc = 0);
|
||||
enum_<T>& value(char const* name, T);
|
||||
enum_<T>& export_values();
|
||||
};
|
||||
@@ -99,7 +99,7 @@ namespace boost { namespace python
|
||||
<h4><a name="enum_-spec-ctors"></a>Class template <code>enum_</code>
|
||||
constructors</h4>
|
||||
<pre>
|
||||
enum_(char const* name);
|
||||
enum_(char const* name, char const* doc=0);
|
||||
</pre>
|
||||
|
||||
<dl class="function-semantics">
|
||||
@@ -131,7 +131,7 @@ inline enum_<T>& value(char const* name, T x);
|
||||
|
||||
<dt><b>Effects:</b> adds an instance of the wrapped enumeration
|
||||
type with value <code>x</code> to the type's dictionary as the
|
||||
<code>name</code>d attribute</dt>.
|
||||
<code>name</code>d attribute.</dt>
|
||||
|
||||
<dt><b>Returns:</b> <code>*this</code></dt>
|
||||
|
||||
@@ -146,7 +146,7 @@ inline enum_<T>& export_values();
|
||||
<dt><b>Effects:</b> sets attributes in the current <a
|
||||
href="scope.html#scope-spec"><code>scope</code></a> with the
|
||||
same names and values as all enumeration values exposed so far
|
||||
by calling <code>value()</code></dt>.
|
||||
by calling <code>value()</code>.</dt>
|
||||
|
||||
<dt><b>Returns:</b> <code>*this</code></dt>
|
||||
|
||||
|
||||
@@ -127,7 +127,7 @@ void greet()
|
||||
|
||||
// Define greet function in Python.
|
||||
object result = exec(
|
||||
"def greet(self): \n"
|
||||
"def greet(): \n"
|
||||
" return 'Hello from Python!' \n",
|
||||
global, global);
|
||||
|
||||
@@ -144,7 +144,7 @@ void greet()
|
||||
we could also store it in an a file...</para>
|
||||
|
||||
<pre>
|
||||
def greet(self):
|
||||
def greet():
|
||||
return 'Hello from Python!'
|
||||
</pre>
|
||||
<para>... and execute that instead.</para>
|
||||
|
||||
216
doc/v2/function_doc_signature.html
Normal file
216
doc/v2/function_doc_signature.html
Normal file
@@ -0,0 +1,216 @@
|
||||
<!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN">
|
||||
|
||||
<!-- Copyright Nikolay Mladenov 2007. Distributed under the Boost -->
|
||||
<!-- Software License, Version 1.0. (See accompanying -->
|
||||
<!-- file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) -->
|
||||
<html>
|
||||
<head>
|
||||
<meta http-equiv="Content-Type" content=
|
||||
"text/html; charset=us-ascii">
|
||||
<link rel="stylesheet" type="text/css" href="../boost.css">
|
||||
|
||||
<title>Boost.Python -
|
||||
<boost/python/doobject/function_doc_signature.hpp></title>
|
||||
</head>
|
||||
|
||||
<body>
|
||||
<table border="0" cellpadding="7" cellspacing="0" width="100%"
|
||||
summary="header">
|
||||
<tr>
|
||||
<td valign="top" width="300">
|
||||
<h3><a href="../../../../index.htm"><img height="86" width=
|
||||
"277" alt="C++ Boost" src="../../../../boost.png" border=
|
||||
"0"></a></h3>
|
||||
</td>
|
||||
|
||||
<td valign="top">
|
||||
<h1 align="center"><a href=
|
||||
"../index.html">Boost.Python</a></h1>
|
||||
|
||||
<h2 align="center">Header
|
||||
<boost/python/object/function_doc_signature.hpp></h2>
|
||||
</td>
|
||||
</tr>
|
||||
</table>
|
||||
<hr>
|
||||
|
||||
<h2>Contents</h2>
|
||||
|
||||
<dl class="page-index">
|
||||
<dt><a href="#introduction">Introduction</a></dt>
|
||||
|
||||
<dt><a href="#classes">Classes</a></dt>
|
||||
|
||||
<dd>
|
||||
<dl class="page-index">
|
||||
<dt><a href="#function_doc_signature_generator-spec">Class
|
||||
<code>function_doc_signature_generator</code></a></dt>
|
||||
|
||||
<dd>
|
||||
<dl class="page-index">
|
||||
<dt><a href="#function_doc_signature_generator-spec-synopsis">Class
|
||||
<code>function_doc_signature_generator</code> synopsis</a></dt>
|
||||
|
||||
</dl>
|
||||
</dd>
|
||||
</dl>
|
||||
</dd>
|
||||
|
||||
<dt><a href="#examples">Examples</a></dt>
|
||||
</dl>
|
||||
<hr>
|
||||
|
||||
<h2><a name="introduction" id=
|
||||
"introduction"></a>Introduction</h2>
|
||||
|
||||
<p>Boost.Python supports docstrings with automatic
|
||||
appending of Pythonic and C++ signatures. This feature is implemented
|
||||
by <code>class function_doc_signature_generator</code>
|
||||
The class uses all of the overloads, supplied arg names and default values, as well as
|
||||
the user-defined docstrings, to generate documentation for a given function.</p>
|
||||
|
||||
<h2><a name="classes" id="classes"></a>Classes</h2>
|
||||
|
||||
<h3><a name="function_doc_signature_generator-spec" id=
|
||||
"function_doc_signature_generator-spec"></a>Class
|
||||
<code>function_doc_signature_generator</code></h3>
|
||||
|
||||
<p>
|
||||
The class has only one public function which returns a list of strings documenting the
|
||||
overloads of a function.
|
||||
</p>
|
||||
|
||||
<h4><a name="function_doc_signature_generator-spec-synopsis" id=
|
||||
"function_doc_signature_generator-spec-synopsis"></a>Class
|
||||
<code>function_doc_signature_generator</code> synopsis</h4>
|
||||
<pre>
|
||||
namespace boost { namespace python { namespace objects {
|
||||
|
||||
class function_doc_signature_generator
|
||||
{
|
||||
public:
|
||||
static list function_doc_signatures(function const *f);
|
||||
};
|
||||
|
||||
}}}
|
||||
</pre>
|
||||
|
||||
|
||||
<h2><a name="examples" id="examples"></a>Examples</h2>
|
||||
|
||||
<h4>Docstrings generated with <code>function_doc_signature_generator</code></h4>
|
||||
<pre>
|
||||
#include <boost/python/module.hpp>
|
||||
#include <boost/python/def.hpp>
|
||||
#include <boost/python/args.hpp>
|
||||
#include <boost/python/tuple.hpp>
|
||||
#include <boost/python/class.hpp>
|
||||
#include <boost/python/overloads.hpp>
|
||||
#include <boost/python/raw_function.hpp>
|
||||
|
||||
using namespace boost::python;
|
||||
|
||||
tuple f(int x = 1, double y = 4.25, char const* z = "wow")
|
||||
{
|
||||
return make_tuple(x, y, z);
|
||||
}
|
||||
|
||||
BOOST_PYTHON_FUNCTION_OVERLOADS(f_overloads, f, 0, 3)
|
||||
|
||||
|
||||
struct X
|
||||
{
|
||||
tuple f(int x = 1, double y = 4.25, char const* z = "wow")
|
||||
{
|
||||
return make_tuple(x, y, z);
|
||||
}
|
||||
};
|
||||
|
||||
BOOST_PYTHON_MEMBER_FUNCTION_OVERLOADS(X_f_overloads, X::f, 0, 3)
|
||||
|
||||
tuple raw_func(tuple args, dict kw)
|
||||
{
|
||||
return make_tuple(args, kw);
|
||||
}
|
||||
|
||||
BOOST_PYTHON_MODULE(args_ext)
|
||||
{
|
||||
def("f", f, (arg("x")=1, arg("y")=4.25, arg("z")="wow")
|
||||
, "This is f's docstring"
|
||||
);
|
||||
|
||||
def("raw", raw_function(raw_func));
|
||||
|
||||
def("f1", f, f_overloads("f1's docstring", args("x", "y", "z")));
|
||||
|
||||
|
||||
class_<X>("X", "This is X's docstring", init<>(args("self")))
|
||||
.def("f", &X::f
|
||||
, "This is X.f's docstring"
|
||||
, args("self","x", "y", "z"))
|
||||
|
||||
;
|
||||
|
||||
}
|
||||
|
||||
</pre>
|
||||
Python code:
|
||||
<pre>
|
||||
>>> import args_ext
|
||||
>>> help(args_ext)
|
||||
Help on module args_ext:
|
||||
|
||||
NAME
|
||||
args_ext
|
||||
|
||||
FILE
|
||||
args_ext.pyd
|
||||
|
||||
CLASSES
|
||||
Boost.Python.instance(__builtin__.object)
|
||||
X
|
||||
|
||||
class X(Boost.Python.instance)
|
||||
| This is X's docstring
|
||||
|
|
||||
| Method resolution order:
|
||||
| X
|
||||
| Boost.Python.instance
|
||||
| __builtin__.object
|
||||
|
|
||||
| Methods defined here:
|
||||
|
|
||||
| __init__(...)
|
||||
| __init__( (object)self) -> None :
|
||||
| C++ signature:
|
||||
| void __init__(struct _object *)
|
||||
|
|
||||
| f(...)
|
||||
| f( (X)self, (int)x, (float)y, (str)z) -> tuple : This is X.f's docstring
|
||||
| C++ signature:
|
||||
| class boost::python::tuple f(struct X {lvalue},int,double,char const *)
|
||||
|
|
||||
| .................
|
||||
|
|
||||
FUNCTIONS
|
||||
f(...)
|
||||
f([ (int)x=1 [, (float)y=4.25 [, (str)z='wow']]]) -> tuple : This is f's docstring
|
||||
C++ signature:
|
||||
class boost::python::tuple f([ int=1 [,double=4.25 [,char const *='wow']]])
|
||||
|
||||
f1(...)
|
||||
f1([ (int)x [, (float)y [, (str)z]]]) -> tuple : f1's docstring
|
||||
C++ signature:
|
||||
class boost::python::tuple f1([ int [,double [,char const *]]])
|
||||
|
||||
raw(...)
|
||||
object raw(tuple args, dict kwds) :
|
||||
C++ signature:
|
||||
object raw(tuple args, dict kwds)
|
||||
|
||||
|
||||
</pre>
|
||||
|
||||
<p><i>© Copyright <a href="mailto:nickm at sitius dot com">Nikolay Mladenov</a> 2007.</i></p>
|
||||
</body>
|
||||
</html>
|
||||
@@ -214,6 +214,9 @@ namespace boost { namespace python { namespace self_ns {
|
||||
<a href=
|
||||
"#operator_-spec">operator_</a><<i>unspecified</i>> str(self_t);
|
||||
|
||||
<a href=
|
||||
"#operator_-spec">operator_</a><<i>unspecified</i>> repr(self_t);
|
||||
|
||||
}}};
|
||||
</pre>
|
||||
The tables below describe the methods generated when the results of the
|
||||
@@ -765,6 +768,15 @@ namespace boost { namespace python { namespace self_ns {
|
||||
<td><code><a href=
|
||||
"../../../conversion/lexical_cast.htm#lexical_cast">lexical_cast</a><std::string>(x)</code></td>
|
||||
</tr>
|
||||
|
||||
<tr>
|
||||
<td><code>repr</code></td>
|
||||
|
||||
<td><code>__repr__</code></td>
|
||||
|
||||
<td><code><a href=
|
||||
"../../../conversion/lexical_cast.htm#lexical_cast">lexical_cast</a><std::string>(x)</code></td>
|
||||
</tr>
|
||||
</table>
|
||||
|
||||
<h3><a name="other-spec"></a>Class Template <code>other</code></h3>
|
||||
|
||||
370
doc/v2/pytype_function.html
Normal file
370
doc/v2/pytype_function.html
Normal file
@@ -0,0 +1,370 @@
|
||||
<!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN">
|
||||
|
||||
<!-- Copyright Nikolay Mladenov 2007. Distributed under the Boost -->
|
||||
<!-- Software License, Version 1.0. (See accompanying -->
|
||||
<!-- file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) -->
|
||||
<html>
|
||||
<head>
|
||||
<meta http-equiv="Content-Type" content=
|
||||
"text/html; charset=us-ascii">
|
||||
<link rel="stylesheet" type="text/css" href="../boost.css">
|
||||
|
||||
<title>Boost.Python -
|
||||
<boost/python/doobject/pytype_function.hpp></title>
|
||||
</head>
|
||||
|
||||
<body>
|
||||
<table border="0" cellpadding="7" cellspacing="0" width="100%"
|
||||
summary="header">
|
||||
<tr>
|
||||
<td valign="top" width="300">
|
||||
<h3><a href="../../../../index.htm"><img height="86" width=
|
||||
"277" alt="C++ Boost" src="../../../../boost.png" border=
|
||||
"0"></a></h3>
|
||||
</td>
|
||||
|
||||
<td valign="top">
|
||||
<h1 align="center"><a href=
|
||||
"../index.html">Boost.Python</a></h1>
|
||||
|
||||
<h2 align="center">Header
|
||||
<boost/python/converter/pytype_function.hpp></h2>
|
||||
</td>
|
||||
</tr>
|
||||
</table>
|
||||
<hr>
|
||||
|
||||
<h2>Contents</h2>
|
||||
|
||||
<dl class="page-index">
|
||||
<dt><a href="#introduction">Introduction</a></dt>
|
||||
|
||||
<dt><a href="#classes">Classes</a></dt>
|
||||
|
||||
<dd>
|
||||
<dl class="page-index">
|
||||
<dt><a href="#wrap_pytype-spec">Class
|
||||
<code>wrap_pytype</code></a></dt>
|
||||
|
||||
<dd>
|
||||
<dl class="page-index">
|
||||
<dt><a href="#wrap_pytype-spec-synopsis">Class
|
||||
<code>wrap_pytype</code> synopsis</a></dt>
|
||||
|
||||
</dl>
|
||||
</dd>
|
||||
</dl>
|
||||
</dd>
|
||||
|
||||
<dd>
|
||||
<dl class="page-index">
|
||||
<dt><a href="#registered_pytype-spec">Class
|
||||
<code>registered_pytype</code></a></dt>
|
||||
|
||||
<dd>
|
||||
<dl class="page-index">
|
||||
<dt><a href="#registered_pytype-spec-synopsis">Class
|
||||
<code>registered_pytype</code> synopsis</a></dt>
|
||||
|
||||
</dl>
|
||||
</dd>
|
||||
</dl>
|
||||
</dd>
|
||||
|
||||
<dd>
|
||||
<dl class="page-index">
|
||||
<dt><a href="#expected_from_python_type-spec">Class
|
||||
<code>expected_from_python_type</code></a></dt>
|
||||
|
||||
<dd>
|
||||
<dl class="page-index">
|
||||
<dt><a href="#expected_from_python_type-spec-synopsis">Class
|
||||
<code>expected_from_python_type</code> synopsis</a></dt>
|
||||
|
||||
</dl>
|
||||
</dd>
|
||||
</dl>
|
||||
</dd>
|
||||
|
||||
<dd>
|
||||
<dl class="page-index">
|
||||
<dt><a href="#to_python_target_type-spec">Class
|
||||
<code>to_python_target_type</code></a></dt>
|
||||
|
||||
<dd>
|
||||
<dl class="page-index">
|
||||
<dt><a href="#to_python_target_type-spec-synopsis">Class
|
||||
<code>to_python_target_type</code> synopsis</a></dt>
|
||||
|
||||
</dl>
|
||||
</dd>
|
||||
</dl>
|
||||
</dd>
|
||||
|
||||
<dt><a href="#examples">Examples</a></dt>
|
||||
</dl>
|
||||
<hr>
|
||||
|
||||
<h2><a name="introduction" id=
|
||||
"introduction"></a>Introduction</h2>
|
||||
|
||||
<p>To support Pythonic signatures the converters should supply a <code>get_pytype</code> function
|
||||
returning a pointer to the associated <code>PyTypeObject</code>. See for example
|
||||
<a href="ResultConverter.html#ResultConverter-concept">ResultConverter</a> or
|
||||
<a href="to_python_converter.html#to_python_converter-spec">to_python_converter</a>.
|
||||
The classes in this header file are meant to be used when implmenting <code>get_pytype</code>.
|
||||
There are also <code>_direct</code> versions of the templates of <code>class T</code> which
|
||||
should be used with undecorated type parameter, expected to be in the conversion registry when the module loads.
|
||||
</p>
|
||||
|
||||
<h2><a name="classes" id="classes"></a>Classes</h2>
|
||||
|
||||
<h3><a name="wrap_pytype-spec" id=
|
||||
"wrap_pytype-spec"></a>Class
|
||||
<code>wrap_pytype</code></h3>
|
||||
|
||||
<p>
|
||||
This template generates a static <code>get_pytype</code> member returning the template parameter.
|
||||
</p>
|
||||
|
||||
<h4><a name="wrap_pytype-spec-synopsis" id=
|
||||
"wrap_pytype-spec-synopsis"></a>Class
|
||||
<code>wrap_pytype</code> synopsis</h4>
|
||||
<pre>
|
||||
namespace boost { namespace python { namespace converter{
|
||||
|
||||
template < PyTypeObject const *pytype >
|
||||
class wrap_pytype
|
||||
{
|
||||
public:
|
||||
static PyTypeObject const *get_pytype(){return pytype; }
|
||||
};
|
||||
|
||||
}}}
|
||||
</pre>
|
||||
|
||||
|
||||
<h3><a name="registered_pytype-spec" id=
|
||||
"registered_pytype-spec"></a>Class
|
||||
<code>registered_pytype</code></h3>
|
||||
|
||||
<p>
|
||||
This template should be used with template parameters which are (possibly decorated)
|
||||
types exported to python using <a href="class.html"><code>class_</code></a>.
|
||||
The generated a static <code>get_pytype</code> member
|
||||
returns the corresponding python type.
|
||||
</p>
|
||||
|
||||
<h4><a name="registered_pytype-spec-synopsis" id=
|
||||
"registered_pytype-spec-synopsis"></a>Class
|
||||
<code>registered_pytype</code> synopsis</h4>
|
||||
<pre>
|
||||
namespace boost { namespace python { namespace converter{
|
||||
|
||||
template < class T >
|
||||
class registered_pytype
|
||||
{
|
||||
public:
|
||||
static PyTypeObject const *get_pytype();
|
||||
};
|
||||
|
||||
}}}
|
||||
</pre>
|
||||
|
||||
|
||||
<h3><a name="expected_from_python_type-spec" id=
|
||||
"expected_from_python_type-spec"></a>Class
|
||||
<code>expected_from_python_type</code></h3>
|
||||
|
||||
<p>
|
||||
This template generates a static <code>get_pytype</code> member which inspects the registered
|
||||
<code>from_python</code> converters for the type <code>T</code> and returns a matching python type.
|
||||
</p>
|
||||
|
||||
<h4><a name="expected_from_python_type-spec-synopsis" id=
|
||||
"expected_from_python_type-spec-synopsis"></a>Class
|
||||
<code>expected_from_python_type</code> synopsis</h4>
|
||||
<pre>
|
||||
namespace boost { namespace python { namespace converter{
|
||||
|
||||
template < class T >
|
||||
class expected_from_python_type
|
||||
{
|
||||
public:
|
||||
static PyTypeObject const *get_pytype();
|
||||
};
|
||||
|
||||
}}}
|
||||
</pre>
|
||||
|
||||
|
||||
<h3><a name="to_python_target_type-spec" id=
|
||||
"to_python_target_type-spec"></a>Class
|
||||
<code>to_python_target_type</code></h3>
|
||||
|
||||
<p>
|
||||
This template generates a static <code>get_pytype</code> member returning the
|
||||
python type to which T can be converted.
|
||||
</p>
|
||||
|
||||
<h4><a name="to_python_target_type-spec-synopsis" id=
|
||||
"to_python_target_type-spec-synopsis"></a>Class
|
||||
<code>to_python_target_type</code> synopsis</h4>
|
||||
<pre>
|
||||
namespace boost { namespace python { namespace converter{
|
||||
|
||||
template < class T >
|
||||
class to_python_target_type
|
||||
{
|
||||
public:
|
||||
static PyTypeObject const *get_pytype();
|
||||
};
|
||||
|
||||
}}}
|
||||
</pre>
|
||||
|
||||
|
||||
<h2><a name="examples" id="examples"></a>Examples</h2>
|
||||
|
||||
This example presumes that someone has implemented the standard <a href=
|
||||
"http://www.python.org/doc/2.2/ext/dnt-basics.html">noddy example
|
||||
module</a> from the Python documentation, and placed the corresponding
|
||||
declarations in <code>"noddy.h"</code>. Because
|
||||
<code>noddy_NoddyObject</code> is the ultimate trivial extension type,
|
||||
the example is a bit contrived: it wraps a function for which all
|
||||
information is contained in the <i>type</i> of its return value.
|
||||
|
||||
<h3>C++ module definition</h3>
|
||||
<pre>
|
||||
#include <boost/python/reference.hpp>
|
||||
#include <boost/python/module.hpp>
|
||||
#include "noddy.h"
|
||||
|
||||
struct tag {};
|
||||
tag make_tag() { return tag(); }
|
||||
|
||||
using namespace boost::python;
|
||||
|
||||
struct tag_to_noddy
|
||||
#if defined BOOST_PYTHON_SUPPORTS_PY_SIGNATURES //unnecessary overhead if py signatures are not supported
|
||||
: wrap_pytype<&noddy_NoddyType> //inherits get_pytype from wrap_pytype
|
||||
#endif
|
||||
{
|
||||
static PyObject* convert(tag const& x)
|
||||
{
|
||||
return PyObject_New(noddy_NoddyObject, &noddy_NoddyType);
|
||||
}
|
||||
};
|
||||
|
||||
BOOST_PYTHON_MODULE(to_python_converter)
|
||||
{
|
||||
def("make_tag", make_tag);
|
||||
to_python_converter<tag, tag_to_noddy
|
||||
#if defined BOOST_PYTHON_SUPPORTS_PY_SIGNATURES //invalid if py signatures are not supported
|
||||
, true
|
||||
#endif
|
||||
>(); //"true" because tag_to_noddy has member get_pytype
|
||||
}
|
||||
</pre>
|
||||
|
||||
|
||||
<p>The following example registers to and from python converters using the templates
|
||||
<code>expected_from_python_type</code> and <code>to_pyhton_target_type</code>.
|
||||
</p>
|
||||
<pre>
|
||||
#include <boost/python/module.hpp>
|
||||
#include <boost/python/def.hpp>
|
||||
#include <boost/python/extract.hpp>
|
||||
#include <boost/python/to_python_converter.hpp>
|
||||
#include <boost/python/class.hpp>
|
||||
|
||||
using namespace boost::python;
|
||||
|
||||
struct A
|
||||
{
|
||||
};
|
||||
|
||||
struct B
|
||||
{
|
||||
A a;
|
||||
B(const A& a_):a(a_){}
|
||||
};
|
||||
|
||||
// Converter from A to python int
|
||||
struct BToPython
|
||||
#if defined BOOST_PYTHON_SUPPORTS_PY_SIGNATURES //unnecessary overhead if py signatures are not supported
|
||||
: converter::to_python_target_type<A> //inherits get_pytype
|
||||
#endif
|
||||
{
|
||||
static PyObject* convert(const B& b)
|
||||
{
|
||||
return incref(object(b.a).ptr());
|
||||
}
|
||||
};
|
||||
|
||||
// Conversion from python int to A
|
||||
struct BFromPython
|
||||
{
|
||||
BFromPython()
|
||||
{
|
||||
boost::python::converter::registry::push_back
|
||||
( &convertible
|
||||
, &construct
|
||||
, type_id< B >()
|
||||
#if defined BOOST_PYTHON_SUPPORTS_PY_SIGNATURES //invalid if py signatures are not supported
|
||||
, &converter::expected_from_python_type<A>::get_pytype//convertible to A can be converted to B
|
||||
#endif
|
||||
);
|
||||
}
|
||||
|
||||
static void* convertible(PyObject* obj_ptr)
|
||||
{
|
||||
extract<const A&> ex(obj_ptr);
|
||||
if (!ex.check()) return 0;
|
||||
return obj_ptr;
|
||||
}
|
||||
|
||||
static void construct(
|
||||
PyObject* obj_ptr,
|
||||
converter::rvalue_from_python_stage1_data* data)
|
||||
{
|
||||
void* storage = (
|
||||
(converter::rvalue_from_python_storage< B >*)data)-> storage.bytes;
|
||||
|
||||
extract<const A&> ex(obj_ptr);
|
||||
new (storage) B(ex());
|
||||
data->convertible = storage;
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
B func(const B& b) { return b ; }
|
||||
|
||||
BOOST_PYTHON_MODULE(pytype_function_ext)
|
||||
{
|
||||
to_python_converter< B , BToPython
|
||||
#if defined BOOST_PYTHON_SUPPORTS_PY_SIGNATURES //invalid if py signatures are not supported
|
||||
,true
|
||||
#endif
|
||||
>(); //has get_pytype
|
||||
BFromPython();
|
||||
|
||||
class_<A>("A") ;
|
||||
|
||||
def("func", &func);
|
||||
|
||||
}
|
||||
|
||||
|
||||
|
||||
>>> from pytype_function_ext import *
|
||||
>>> print func.__doc__
|
||||
func( (A)arg1) -> A :
|
||||
C++ signature:
|
||||
struct B func(struct B)
|
||||
</pre>
|
||||
|
||||
|
||||
<p><i>© Copyright <a href="mailto:nickm at sitius dot com">Nikolay Mladenov</a> 2007.</i></p>
|
||||
</body>
|
||||
</html>
|
||||
@@ -609,6 +609,66 @@
|
||||
</dl>
|
||||
</dd>
|
||||
|
||||
<dd>
|
||||
<a name="function_documentation"></a>
|
||||
|
||||
<h3>Function documentation</h3>
|
||||
|
||||
<dl class="index">
|
||||
<dt><a href=
|
||||
"function_doc_signature.html">function_doc_signature.hpp</a></dt>
|
||||
|
||||
<dd>
|
||||
<dl class="index">
|
||||
<dt><a href=
|
||||
"function_doc_signature.html#classes">Classes</a></dt>
|
||||
|
||||
<dd>
|
||||
<dl class="index">
|
||||
<dt><a href=
|
||||
"function_doc_signature.html#function_doc_signature_generator-spec">function_doc_signature_generator</a></dt>
|
||||
|
||||
</dl>
|
||||
</dd>
|
||||
</dl>
|
||||
</dd>
|
||||
</dl>
|
||||
<dl class="index">
|
||||
<dt><a href=
|
||||
"pytype_function.html">pytype_function.hpp</a></dt>
|
||||
|
||||
<dd>
|
||||
<dl class="index">
|
||||
<dt><a href=
|
||||
"pytype_function.html#classes">Classes</a></dt>
|
||||
|
||||
<dd>
|
||||
<dl class="index">
|
||||
<dt><a href=
|
||||
"pytype_function.html#wrap_pytype-spec">wrap_pytype</a></dt>
|
||||
|
||||
</dl>
|
||||
<dl class="index">
|
||||
<dt><a href=
|
||||
"pytype_function.html#expected_from_python_type-spec">expected_from_python_type</a></dt>
|
||||
|
||||
</dl>
|
||||
<dl class="index">
|
||||
<dt><a href=
|
||||
"pytype_function.html#to_python_target_type-spec">to_python_target_type</a></dt>
|
||||
|
||||
</dl>
|
||||
<dl class="index">
|
||||
<dt><a href=
|
||||
"pytype_function.html#registered_pytype-spec">registered_pytype</a></dt>
|
||||
|
||||
</dl>
|
||||
</dd>
|
||||
</dl>
|
||||
</dd>
|
||||
</dl>
|
||||
</dd>
|
||||
|
||||
<dd>
|
||||
<a name="models_of_call_policies"></a>
|
||||
|
||||
|
||||
@@ -125,6 +125,8 @@ namespace boost { namespace python
|
||||
{
|
||||
static PyObject* postcall(PyObject*, PyObject* result);
|
||||
struct result_converter{ template <class T> struct apply; };
|
||||
template <class Sig> struct extract_return_type : mpl::at_c<Sig, arg_pos>{};
|
||||
|
||||
};
|
||||
}}
|
||||
</pre>
|
||||
|
||||
@@ -108,6 +108,23 @@
|
||||
<td>A class type whose static member function <code>convert</code>
|
||||
does the real work of the conversion.</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td><code>bool has_get_pytype = false</code></td>
|
||||
|
||||
<td>
|
||||
<code>PyTypeObject const * p = Conversion::get_pytype() </code>.</td>
|
||||
|
||||
<td><b>Optional member</b> - if <code>Conversion</code> has <code>get_pytype</code> member supply
|
||||
<code>true</code> for this parameters.
|
||||
If present <code>get_pytype</code> is used to document the return type
|
||||
of functions using this conversion. The <code>get_pytype</code> may be implemented
|
||||
using the classes and functions
|
||||
from <a href="pytype_function.html"><code>pytype_function.hpp</code></a>
|
||||
<b>NOTE :</b> For backward compatibility this parameter may be passed after
|
||||
checking if <code>BOOST_PYTHON_SUPPORTS_PY_SIGNATURES</code> is defined (see
|
||||
<a href="pytype_function.html#examples">here</a>).
|
||||
</td>
|
||||
</tr>
|
||||
</table>
|
||||
|
||||
<h4><a name="to_python_converter-spec-synopsis"></a>Class template
|
||||
@@ -115,7 +132,7 @@
|
||||
<pre>
|
||||
namespace boost { namespace python
|
||||
{
|
||||
template <class T, class Conversion>
|
||||
template <class T, class Conversion, bool convertion_has_get_pytype_member=false>
|
||||
struct to_python_converter
|
||||
{
|
||||
to_python_converter();
|
||||
@@ -160,12 +177,16 @@ struct tag_to_noddy
|
||||
{
|
||||
return PyObject_New(noddy_NoddyObject, &noddy_NoddyType);
|
||||
}
|
||||
static PyTypeObject const* get_pytype()
|
||||
{
|
||||
return &noddy_NoddyType;
|
||||
}
|
||||
};
|
||||
|
||||
BOOST_PYTHON_MODULE(to_python_converter)
|
||||
{
|
||||
def("make_tag", make_tag);
|
||||
to_python_converter<tag, tag_to_noddy>();
|
||||
to_python_converter<tag, tag_to_noddy, true>(); //"true" because tag_to_noddy has member get_pytype
|
||||
}
|
||||
</pre>
|
||||
|
||||
@@ -195,7 +216,7 @@ BOOST_PYTHON_MODULE(to_python_converter)
|
||||
|
||||
<p>Revised
|
||||
<!--webbot bot="Timestamp" S-Type="EDITED" S-Format="%d %B, %Y" startspan -->
|
||||
13 November, 2002
|
||||
11 June, 2007
|
||||
<!--webbot bot="Timestamp" endspan i-checksum="39359" -->
|
||||
</p>
|
||||
|
||||
|
||||
@@ -18,6 +18,7 @@ namespace { // Avoid cluttering the global namespace.
|
||||
return boost::python::incref(
|
||||
boost::python::make_tuple(p.first, p.second).ptr());
|
||||
}
|
||||
static PyTypeObject const *get_pytype () {return &PyTuple_Type; }
|
||||
};
|
||||
|
||||
// Helper for convenience.
|
||||
@@ -28,7 +29,9 @@ namespace { // Avoid cluttering the global namespace.
|
||||
{
|
||||
boost::python::to_python_converter<
|
||||
std::pair<T1, T2>,
|
||||
std_pair_to_tuple<T1, T2> >();
|
||||
std_pair_to_tuple<T1, T2>,
|
||||
true //std_pair_to_tuple has get_pytype
|
||||
>();
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
@@ -4,7 +4,7 @@
|
||||
|
||||
# Specify the path to the Boost project. If you move this project,
|
||||
# adjust this path to refer to the Boost root directory.
|
||||
use-project boost
|
||||
use-project boost
|
||||
: ../../../.. ;
|
||||
|
||||
# Set up the project-wide requirements that everything uses the
|
||||
@@ -13,6 +13,19 @@ use-project boost
|
||||
project
|
||||
: requirements <library>/boost/python//boost_python ;
|
||||
|
||||
# Declare a Python extension called hello.
|
||||
python-extension hello : hello.cpp ;
|
||||
# Declare the three extension modules. You can specify multiple
|
||||
# source files after the colon separated by spaces.
|
||||
python-extension hello_ext : hello.cpp ;
|
||||
|
||||
# A little "rule" (function) to clean up the syntax of declaring tests
|
||||
# of these extension modules.
|
||||
local rule run-test ( test-name : sources + )
|
||||
{
|
||||
import testing ;
|
||||
testing.make-test run-pyd : $(sources) : : $(test-name) ;
|
||||
}
|
||||
|
||||
# Declare test targets
|
||||
run-test hello : hello_ext hello.py ;
|
||||
|
||||
|
||||
|
||||
@@ -1,20 +1,20 @@
|
||||
// Copyright Joel de Guzman 2002-2004. Distributed under the Boost
|
||||
// Software License, Version 1.0. (See accompanying file LICENSE_1_0.txt
|
||||
// Software License, Version 1.0. (See accompanying file LICENSE_1_0.txt
|
||||
// or copy at http://www.boost.org/LICENSE_1_0.txt)
|
||||
// Hello World Example from the tutorial
|
||||
// [Joel de Guzman 10/9/2002]
|
||||
|
||||
#include <boost/python/module.hpp>
|
||||
#include <boost/python/def.hpp>
|
||||
|
||||
char const* greet()
|
||||
{
|
||||
return "hello, world";
|
||||
}
|
||||
|
||||
#include <boost/python/module.hpp>
|
||||
#include <boost/python/def.hpp>
|
||||
using namespace boost::python;
|
||||
|
||||
BOOST_PYTHON_MODULE(hello)
|
||||
BOOST_PYTHON_MODULE(hello_ext)
|
||||
{
|
||||
using namespace boost::python;
|
||||
def("greet", greet);
|
||||
}
|
||||
|
||||
|
||||
7
example/tutorial/hello.py
Executable file
7
example/tutorial/hello.py
Executable file
@@ -0,0 +1,7 @@
|
||||
# Copyright Joel de Guzman 2002-2007. Distributed under the Boost
|
||||
# Software License, Version 1.0. (See accompanying file LICENSE_1_0.txt
|
||||
# or copy at http://www.boost.org/LICENSE_1_0.txt)
|
||||
# Hello World Example from the tutorial
|
||||
|
||||
import hello_ext
|
||||
print hello_ext.greet()
|
||||
@@ -39,6 +39,9 @@ struct as_to_python_function
|
||||
// but c'est la vie.
|
||||
return ToPython::convert(*const_cast<T*>(static_cast<T const*>(x)));
|
||||
}
|
||||
#ifndef BOOST_PYTHON_NO_PY_SIGNATURES
|
||||
static PyTypeObject const * get_pytype() { return ToPython::get_pytype(); }
|
||||
#endif
|
||||
};
|
||||
|
||||
}}} // namespace boost::python::converter
|
||||
|
||||
@@ -47,7 +47,7 @@ namespace detail
|
||||
}
|
||||
|
||||
// Use expr to create the PyObject corresponding to x
|
||||
# define BOOST_PYTHON_RETURN_TO_PYTHON_BY_VALUE(T, expr) \
|
||||
# define BOOST_PYTHON_RETURN_TO_PYTHON_BY_VALUE(T, expr, pytype)\
|
||||
template <> struct to_python_value<T&> \
|
||||
: detail::builtin_to_python \
|
||||
{ \
|
||||
@@ -55,6 +55,10 @@ namespace detail
|
||||
{ \
|
||||
return (expr); \
|
||||
} \
|
||||
inline PyTypeObject const* get_pytype() const \
|
||||
{ \
|
||||
return (pytype); \
|
||||
} \
|
||||
}; \
|
||||
template <> struct to_python_value<T const&> \
|
||||
: detail::builtin_to_python \
|
||||
@@ -63,6 +67,10 @@ namespace detail
|
||||
{ \
|
||||
return (expr); \
|
||||
} \
|
||||
inline PyTypeObject const* get_pytype() const \
|
||||
{ \
|
||||
return (pytype); \
|
||||
} \
|
||||
};
|
||||
|
||||
# define BOOST_PYTHON_ARG_TO_PYTHON_BY_VALUE(T, expr) \
|
||||
@@ -77,25 +85,25 @@ namespace detail
|
||||
}
|
||||
|
||||
// Specialize argument and return value converters for T using expr
|
||||
# define BOOST_PYTHON_TO_PYTHON_BY_VALUE(T, expr) \
|
||||
BOOST_PYTHON_RETURN_TO_PYTHON_BY_VALUE(T,expr) \
|
||||
# define BOOST_PYTHON_TO_PYTHON_BY_VALUE(T, expr, pytype) \
|
||||
BOOST_PYTHON_RETURN_TO_PYTHON_BY_VALUE(T,expr, pytype) \
|
||||
BOOST_PYTHON_ARG_TO_PYTHON_BY_VALUE(T,expr)
|
||||
|
||||
// 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), &PyInt_Type) \
|
||||
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))
|
||||
: ::PyInt_FromLong(x), &PyInt_Type)
|
||||
|
||||
// Bool is not signed.
|
||||
#if PY_VERSION_HEX >= 0x02030000
|
||||
BOOST_PYTHON_TO_PYTHON_BY_VALUE(bool, ::PyBool_FromLong(x))
|
||||
BOOST_PYTHON_TO_PYTHON_BY_VALUE(bool, ::PyBool_FromLong(x), &PyBool_Type)
|
||||
#else
|
||||
BOOST_PYTHON_TO_PYTHON_BY_VALUE(bool, ::PyInt_FromLong(x))
|
||||
BOOST_PYTHON_TO_PYTHON_BY_VALUE(bool, ::PyInt_FromLong(x), &PyInt_Type)
|
||||
#endif
|
||||
|
||||
// note: handles signed char and unsigned char, but not char (see below)
|
||||
@@ -108,25 +116,25 @@ 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), &PyInt_Type)
|
||||
BOOST_PYTHON_TO_PYTHON_BY_VALUE(unsigned BOOST_PYTHON_LONG_LONG, ::PyLong_FromUnsignedLongLong(x), &PyInt_Type)
|
||||
# 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.data(),implicit_cast<ssize_t>(x.size())))
|
||||
BOOST_PYTHON_TO_PYTHON_BY_VALUE(char, converter::do_return_to_python(x), &PyString_Type)
|
||||
BOOST_PYTHON_TO_PYTHON_BY_VALUE(char const*, converter::do_return_to_python(x), &PyString_Type)
|
||||
BOOST_PYTHON_TO_PYTHON_BY_VALUE(std::string, ::PyString_FromStringAndSize(x.data(),implicit_cast<ssize_t>(x.size())), &PyString_Type)
|
||||
#if defined(Py_USING_UNICODE) && !defined(BOOST_NO_STD_WSTRING)
|
||||
BOOST_PYTHON_TO_PYTHON_BY_VALUE(std::wstring, ::PyUnicode_FromWideChar(x.data(),implicit_cast<ssize_t>(x.size())))
|
||||
BOOST_PYTHON_TO_PYTHON_BY_VALUE(std::wstring, ::PyUnicode_FromWideChar(x.data(),implicit_cast<ssize_t>(x.size())), &PyString_Type)
|
||||
# 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(float, ::PyFloat_FromDouble(x), &PyFloat_Type)
|
||||
BOOST_PYTHON_TO_PYTHON_BY_VALUE(double, ::PyFloat_FromDouble(x), &PyFloat_Type)
|
||||
BOOST_PYTHON_TO_PYTHON_BY_VALUE(long double, ::PyFloat_FromDouble(x), &PyFloat_Type)
|
||||
BOOST_PYTHON_RETURN_TO_PYTHON_BY_VALUE(PyObject*, converter::do_return_to_python(x), 0)
|
||||
BOOST_PYTHON_TO_PYTHON_BY_VALUE(std::complex<float>, ::PyComplex_FromDoubles(x.real(), x.imag()), &PyComplex_Type)
|
||||
BOOST_PYTHON_TO_PYTHON_BY_VALUE(std::complex<double>, ::PyComplex_FromDoubles(x.real(), x.imag()), &PyComplex_Type)
|
||||
BOOST_PYTHON_TO_PYTHON_BY_VALUE(std::complex<long double>, ::PyComplex_FromDoubles(x.real(), x.imag()), &PyComplex_Type)
|
||||
|
||||
# undef BOOST_PYTHON_RETURN_TO_PYTHON_BY_VALUE
|
||||
# undef BOOST_PYTHON_ARG_TO_PYTHON_BY_VALUE
|
||||
|
||||
@@ -18,6 +18,9 @@ struct pyobject_traits<PyObject>
|
||||
// All objects are convertible to PyObject
|
||||
static bool check(PyObject*) { return true; }
|
||||
static PyObject* checked_downcast(PyObject* x) { return x; }
|
||||
#ifndef BOOST_PYTHON_NO_PY_SIGNATURES
|
||||
static PyTypeObject const* get_pytype() { return 0; }
|
||||
#endif
|
||||
};
|
||||
|
||||
//
|
||||
|
||||
@@ -14,7 +14,7 @@ BOOST_PYTHON_DECL PyObject* checked_downcast_impl(PyObject*, PyTypeObject*);
|
||||
// Used as a base class for specializations which need to provide
|
||||
// Python type checking capability.
|
||||
template <class Object, PyTypeObject* pytype>
|
||||
struct pyobject_type
|
||||
struct pyobject_type
|
||||
{
|
||||
static bool check(PyObject* x)
|
||||
{
|
||||
@@ -27,6 +27,9 @@ struct pyobject_type
|
||||
(checked_downcast_impl)(x, pytype)
|
||||
);
|
||||
}
|
||||
#ifndef BOOST_PYTHON_NO_PY_SIGNATURES
|
||||
static PyTypeObject const* get_pytype() { return pytype; }
|
||||
#endif
|
||||
};
|
||||
|
||||
}}} // namespace boost::python::converter
|
||||
|
||||
132
include/boost/python/converter/pytype_function.hpp
Executable file
132
include/boost/python/converter/pytype_function.hpp
Executable file
@@ -0,0 +1,132 @@
|
||||
// Copyright David Abrahams 2002, Nikolay Mladenov 2007.
|
||||
// Distributed under the Boost Software License, Version 1.0. (See
|
||||
// accompanying file LICENSE_1_0.txt or copy at
|
||||
// http://www.boost.org/LICENSE_1_0.txt)
|
||||
#ifndef WRAP_PYTYPE_NM20070606_HPP
|
||||
# define WRAP_PYTYPE_NM20070606_HPP
|
||||
|
||||
# include <boost/python/detail/prefix.hpp>
|
||||
# include <boost/python/converter/registered.hpp>
|
||||
# include <boost/python/detail/unwind_type.hpp>
|
||||
|
||||
|
||||
namespace boost { namespace python {
|
||||
|
||||
namespace converter
|
||||
{
|
||||
template <PyTypeObject const* python_type>
|
||||
struct wrap_pytype
|
||||
{
|
||||
static PyTypeObject const* get_pytype()
|
||||
{
|
||||
return python_type;
|
||||
}
|
||||
};
|
||||
|
||||
typedef PyTypeObject const* (*pytype_function)();
|
||||
|
||||
#ifndef BOOST_PYTHON_NO_PY_SIGNATURES
|
||||
|
||||
|
||||
|
||||
namespace detail
|
||||
{
|
||||
struct unwind_type_id_helper{
|
||||
typedef python::type_info result_type;
|
||||
template <class U>
|
||||
static result_type execute(U* ){
|
||||
return python::type_id<U>();
|
||||
}
|
||||
};
|
||||
|
||||
template <class T>
|
||||
inline python::type_info unwind_type_id_(boost::type<T>* = 0, mpl::false_ * =0)
|
||||
{
|
||||
return boost::python::detail::unwind_type<unwind_type_id_helper, T> ();
|
||||
}
|
||||
|
||||
inline python::type_info unwind_type_id_(boost::type<void>* = 0, mpl::true_* =0)
|
||||
{
|
||||
return type_id<void>();
|
||||
}
|
||||
|
||||
template <class T>
|
||||
inline python::type_info unwind_type_id(boost::type<T>* p= 0)
|
||||
{
|
||||
return unwind_type_id_(p, (mpl::bool_<boost::is_void<T>::value >*)0 );
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
template <class T>
|
||||
struct expected_pytype_for_arg
|
||||
{
|
||||
static PyTypeObject const *get_pytype()
|
||||
{
|
||||
const converter::registration *r=converter::registry::query(
|
||||
detail::unwind_type_id_((boost::type<T>*)0, (mpl::bool_<boost::is_void<T>::value >*)0 )
|
||||
);
|
||||
return r ? r->expected_from_python_type(): 0;
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
template <class T>
|
||||
struct registered_pytype
|
||||
{
|
||||
static PyTypeObject const *get_pytype()
|
||||
{
|
||||
const converter::registration *r=converter::registry::query(
|
||||
detail::unwind_type_id_((boost::type<T>*) 0, (mpl::bool_<boost::is_void<T>::value >*)0 )
|
||||
);
|
||||
return r ? r->m_class_object: 0;
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
template <class T>
|
||||
struct registered_pytype_direct
|
||||
{
|
||||
static PyTypeObject const* get_pytype()
|
||||
{
|
||||
return registered<T>::converters.m_class_object;
|
||||
}
|
||||
};
|
||||
|
||||
template <class T>
|
||||
struct expected_from_python_type : expected_pytype_for_arg<T>{};
|
||||
|
||||
template <class T>
|
||||
struct expected_from_python_type_direct
|
||||
{
|
||||
static PyTypeObject const* get_pytype()
|
||||
{
|
||||
return registered<T>::converters.expected_from_python_type();
|
||||
}
|
||||
};
|
||||
|
||||
template <class T>
|
||||
struct to_python_target_type
|
||||
{
|
||||
static PyTypeObject const *get_pytype()
|
||||
{
|
||||
const converter::registration *r=converter::registry::query(
|
||||
detail::unwind_type_id_((boost::type<T>*)0, (mpl::bool_<boost::is_void<T>::value >*)0 )
|
||||
);
|
||||
return r ? r->to_python_target_type(): 0;
|
||||
}
|
||||
};
|
||||
|
||||
template <class T>
|
||||
struct to_python_target_type_direct
|
||||
{
|
||||
static PyTypeObject const *get_pytype()
|
||||
{
|
||||
return registered<T>::converters.to_python_target_type();
|
||||
}
|
||||
};
|
||||
#endif
|
||||
|
||||
}}} // namespace boost::python
|
||||
|
||||
#endif // WRAP_PYTYPE_NM20070606_HPP
|
||||
@@ -27,6 +27,7 @@ struct rvalue_from_python_chain
|
||||
{
|
||||
convertible_function convertible;
|
||||
constructor_function construct;
|
||||
PyTypeObject const* (*expected_pytype)();
|
||||
rvalue_from_python_chain* next;
|
||||
};
|
||||
|
||||
@@ -34,6 +35,7 @@ struct BOOST_PYTHON_DECL registration
|
||||
{
|
||||
public: // member functions
|
||||
explicit registration(type_info target, bool is_shared_ptr = false);
|
||||
~registration();
|
||||
|
||||
// Convert the appropriately-typed data to Python
|
||||
PyObject* to_python(void const volatile*) const;
|
||||
@@ -42,6 +44,11 @@ struct BOOST_PYTHON_DECL registration
|
||||
// exception if no class has been registered.
|
||||
PyTypeObject* get_class_object() const;
|
||||
|
||||
// Return common denominator of the python class objects,
|
||||
// convertable to target. Inspects the m_class_object and the value_chains.
|
||||
PyTypeObject const* expected_from_python_type() const;
|
||||
PyTypeObject const* to_python_target_type() const;
|
||||
|
||||
public: // data members. So sue me.
|
||||
const python::type_info target_type;
|
||||
|
||||
@@ -56,6 +63,8 @@ struct BOOST_PYTHON_DECL registration
|
||||
|
||||
// The unique to_python converter for the associated C++ type.
|
||||
to_python_function_t m_to_python;
|
||||
PyTypeObject const* (*m_to_python_target_type)();
|
||||
|
||||
|
||||
// True iff this type is a shared_ptr. Needed for special rvalue
|
||||
// from_python handling.
|
||||
@@ -76,6 +85,7 @@ inline registration::registration(type_info target_type, bool is_shared_ptr)
|
||||
, rvalue_chain(0)
|
||||
, m_class_object(0)
|
||||
, m_to_python(0)
|
||||
, m_to_python_target_type(0)
|
||||
, is_shared_ptr(is_shared_ptr)
|
||||
{}
|
||||
|
||||
|
||||
@@ -27,16 +27,17 @@ namespace registry
|
||||
// Return a pointer to the corresponding registration, if one exists
|
||||
BOOST_PYTHON_DECL registration const* query(type_info);
|
||||
|
||||
BOOST_PYTHON_DECL void insert(to_python_function_t, type_info);
|
||||
BOOST_PYTHON_DECL void insert(to_python_function_t, type_info, PyTypeObject const* (*to_python_target_type)() = 0);
|
||||
|
||||
// Insert an lvalue from_python converter
|
||||
BOOST_PYTHON_DECL void insert(void* (*convert)(PyObject*), type_info);
|
||||
BOOST_PYTHON_DECL void insert(void* (*convert)(PyObject*), type_info, PyTypeObject const* (*expected_pytype)() = 0);
|
||||
|
||||
// Insert an rvalue from_python converter
|
||||
BOOST_PYTHON_DECL void insert(
|
||||
convertible_function
|
||||
, constructor_function
|
||||
, type_info
|
||||
, PyTypeObject const* (*expected_pytype)() = 0
|
||||
);
|
||||
|
||||
// Insert an rvalue from_python converter at the tail of the
|
||||
@@ -45,6 +46,7 @@ namespace registry
|
||||
convertible_function
|
||||
, constructor_function
|
||||
, type_info
|
||||
, PyTypeObject const* (*expected_pytype)() = 0
|
||||
);
|
||||
}
|
||||
|
||||
|
||||
@@ -10,6 +10,9 @@
|
||||
# include <boost/python/converter/from_python.hpp>
|
||||
# include <boost/python/converter/rvalue_from_python_data.hpp>
|
||||
# include <boost/python/converter/registered.hpp>
|
||||
#ifndef BOOST_PYTHON_NO_PY_SIGNATURES
|
||||
# include <boost/python/converter/pytype_function.hpp>
|
||||
#endif
|
||||
# include <boost/shared_ptr.hpp>
|
||||
|
||||
namespace boost { namespace python { namespace converter {
|
||||
@@ -19,7 +22,11 @@ struct shared_ptr_from_python
|
||||
{
|
||||
shared_ptr_from_python()
|
||||
{
|
||||
converter::registry::insert(&convertible, &construct, type_id<shared_ptr<T> >());
|
||||
converter::registry::insert(&convertible, &construct, type_id<shared_ptr<T> >()
|
||||
#ifndef BOOST_PYTHON_NO_PY_SIGNATURES
|
||||
, &converter::expected_from_python_type_direct<T>::get_pytype
|
||||
#endif
|
||||
);
|
||||
}
|
||||
|
||||
private:
|
||||
|
||||
@@ -13,6 +13,7 @@
|
||||
# include <boost/type_traits/is_pointer.hpp>
|
||||
# include <boost/type_traits/is_reference.hpp>
|
||||
# include <boost/mpl/or.hpp>
|
||||
# include <boost/mpl/front.hpp>
|
||||
|
||||
namespace boost { namespace python {
|
||||
|
||||
@@ -49,6 +50,12 @@ struct default_call_policies
|
||||
|
||||
typedef default_result_converter result_converter;
|
||||
typedef PyObject* argument_package;
|
||||
|
||||
template <class Sig>
|
||||
struct extract_return_type : mpl::front<Sig>
|
||||
{
|
||||
};
|
||||
|
||||
};
|
||||
|
||||
struct default_result_converter
|
||||
|
||||
@@ -11,12 +11,15 @@
|
||||
# include <boost/python/type_id.hpp>
|
||||
# include <boost/python/handle.hpp>
|
||||
|
||||
# include <boost/detail/indirect_traits.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/python/converter/builtin_converters.hpp>
|
||||
|
||||
# include <boost/preprocessor/iterate.hpp>
|
||||
# include <boost/preprocessor/cat.hpp>
|
||||
@@ -89,6 +92,27 @@ inline ResultConverter create_result_converter(
|
||||
{
|
||||
return ResultConverter();
|
||||
}
|
||||
|
||||
#ifndef BOOST_PYTHON_NO_PY_SIGNATURES
|
||||
template <class ResultConverter>
|
||||
struct converter_target_type
|
||||
{
|
||||
static PyTypeObject const *get_pytype()
|
||||
{
|
||||
return create_result_converter((PyObject*)0, (ResultConverter *)0, (ResultConverter *)0).get_pytype();
|
||||
}
|
||||
};
|
||||
|
||||
template < >
|
||||
struct converter_target_type <void_result_to_python >
|
||||
{
|
||||
static PyTypeObject const *get_pytype()
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
};
|
||||
#endif
|
||||
|
||||
|
||||
template <unsigned> struct caller_arity;
|
||||
|
||||
@@ -203,11 +227,26 @@ struct caller_arity<N>
|
||||
|
||||
static unsigned min_arity() { return N; }
|
||||
|
||||
static signature_element const* signature()
|
||||
static py_func_sig_info signature()
|
||||
{
|
||||
return detail::signature<Sig>::elements();
|
||||
const signature_element * sig = detail::signature<Sig>::elements();
|
||||
#ifndef BOOST_PYTHON_NO_PY_SIGNATURES
|
||||
|
||||
typedef BOOST_DEDUCED_TYPENAME Policies::template extract_return_type<Sig>::type rtype;
|
||||
typedef typename select_result_converter<Policies, rtype>::type result_converter;
|
||||
|
||||
static const signature_element ret = {
|
||||
(boost::is_void<rtype>::value ? "void" : type_id<rtype>().name())
|
||||
, &detail::converter_target_type<result_converter>::get_pytype
|
||||
, boost::detail::indirect_traits::is_reference_to_non_const<rtype>::value
|
||||
};
|
||||
py_func_sig_info res = {sig, &ret };
|
||||
#else
|
||||
py_func_sig_info res = {sig, sig };
|
||||
#endif
|
||||
|
||||
return res;
|
||||
}
|
||||
|
||||
private:
|
||||
compressed_pair<F,Policies> m_data;
|
||||
};
|
||||
|
||||
@@ -134,4 +134,8 @@
|
||||
#include <boost/config/auto_link.hpp>
|
||||
#endif // auto-linking disabled
|
||||
|
||||
#ifndef BOOST_PYTHON_NO_PY_SIGNATURES
|
||||
#define BOOST_PYTHON_SUPPORTS_PY_SIGNATURES // enables smooth transition
|
||||
#endif
|
||||
|
||||
#endif // CONFIG_DWA052200_H_
|
||||
|
||||
@@ -155,7 +155,7 @@ namespace detail
|
||||
, T3 const&
|
||||
, T4 const&
|
||||
, default_call_policies
|
||||
, keywords<0>
|
||||
, detail::keywords<0>
|
||||
, char const*
|
||||
, void(not_specified::*)() // A function pointer type which is never an
|
||||
// appropriate default implementation
|
||||
|
||||
@@ -168,7 +168,7 @@ namespace detail
|
||||
char const* doc)
|
||||
{
|
||||
// define the NTH stub function of stubs
|
||||
define_stub_function<N>::define(name, stubs, kw, policies, name_space, 0);
|
||||
define_stub_function<N>::define(name, stubs, kw, policies, name_space, doc);
|
||||
|
||||
if (kw.second > kw.first)
|
||||
--kw.second;
|
||||
|
||||
@@ -248,7 +248,7 @@ namespace detail
|
||||
BOOST_PYTHON_GEN_MEM_FUNCTION( \
|
||||
fname, void_return_type, n_args, n_dflts, ;) \
|
||||
\
|
||||
BOOST_PYTHON_OVERLOAD_CONSTRUCTORS(fstubs_name, n_args, n_dflts) \
|
||||
BOOST_PYTHON_OVERLOAD_CONSTRUCTORS(fstubs_name, n_args + 1, n_dflts) \
|
||||
};
|
||||
|
||||
# else // !defined(BOOST_NO_VOID_RETURNS)
|
||||
@@ -273,7 +273,7 @@ namespace detail
|
||||
fname, non_void_return_type, n_args, n_dflts, return) \
|
||||
\
|
||||
typedef non_void_return_type void_return_type; \
|
||||
BOOST_PYTHON_OVERLOAD_CONSTRUCTORS(fstubs_name, n_args, n_dflts) \
|
||||
BOOST_PYTHON_OVERLOAD_CONSTRUCTORS(fstubs_name, n_args + 1, n_dflts) \
|
||||
};
|
||||
|
||||
# endif // !defined(BOOST_NO_VOID_RETURNS)
|
||||
|
||||
@@ -57,6 +57,9 @@ object make_keyword_range_constructor(
|
||||
, Holder* = 0
|
||||
, ArgList* = 0, Arity* = 0)
|
||||
{
|
||||
#if !defined( BOOST_PYTHON_NO_PY_SIGNATURES) && defined( BOOST_PYTHON_PY_SYGNATURES_PROPER_INIT_SELF_TYPE)
|
||||
python_class<BOOST_DEDUCED_TYPENAME Holder::value_type>::register_();
|
||||
#endif
|
||||
return detail::make_keyword_range_function(
|
||||
objects::make_holder<Arity::value>
|
||||
::template apply<Holder,ArgList>::execute
|
||||
|
||||
@@ -47,7 +47,8 @@ enum operator_id
|
||||
op_ixor,
|
||||
op_ior,
|
||||
op_complex,
|
||||
op_nonzero
|
||||
op_nonzero,
|
||||
op_repr
|
||||
};
|
||||
|
||||
}}} // namespace boost::python::detail
|
||||
|
||||
37
include/boost/python/detail/python_type.hpp
Executable file
37
include/boost/python/detail/python_type.hpp
Executable file
@@ -0,0 +1,37 @@
|
||||
// Copyright Nikolay Mladenov 2007.
|
||||
// Distributed under the Boost Software License, Version 1.0. (See
|
||||
// accompanying file LICENSE_1_0.txt or copy at
|
||||
// http://www.boost.org/LICENSE_1_0.txt)
|
||||
#ifndef BOOST_PYTHON_OBJECT_PYTHON_TYPE_H
|
||||
#define BOOST_PYTHON_OBJECT_PYTHON_TYPE_H
|
||||
|
||||
#include <boost/python/converter/registered.hpp>
|
||||
|
||||
namespace boost {namespace python {namespace detail{
|
||||
|
||||
|
||||
template <class T> struct python_class : PyObject
|
||||
{
|
||||
typedef python_class<T> this_type;
|
||||
|
||||
typedef T type;
|
||||
|
||||
static void *converter (PyObject *p){
|
||||
return p;
|
||||
}
|
||||
|
||||
static void register_()
|
||||
{
|
||||
static bool first_time = true;
|
||||
|
||||
if ( !first_time ) return;
|
||||
|
||||
first_time = false;
|
||||
converter::registry::insert(&converter, boost::python::type_id<this_type>(), &converter::registered_pytype_direct<T>::get_pytype);
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
}}} //namespace boost :: python :: detail
|
||||
|
||||
#endif //BOOST_PYTHON_OBJECT_PYTHON_TYPE_H
|
||||
@@ -12,6 +12,7 @@
|
||||
|
||||
# include <boost/python/detail/preprocessor.hpp>
|
||||
# include <boost/python/detail/indirect_traits.hpp>
|
||||
# include <boost/python/converter/pytype_function.hpp>
|
||||
|
||||
# include <boost/preprocessor/iterate.hpp>
|
||||
# include <boost/preprocessor/iteration/local.hpp>
|
||||
@@ -24,9 +25,16 @@ namespace boost { namespace python { namespace detail {
|
||||
struct signature_element
|
||||
{
|
||||
char const* basename;
|
||||
converter::pytype_function pytype_f;
|
||||
bool lvalue;
|
||||
};
|
||||
|
||||
struct py_func_sig_info
|
||||
{
|
||||
signature_element const *signature;
|
||||
signature_element const *ret;
|
||||
};
|
||||
|
||||
template <unsigned> struct signature_arity;
|
||||
|
||||
# define BOOST_PP_ITERATION_PARAMS_1 \
|
||||
@@ -68,15 +76,25 @@ struct signature_arity<N>
|
||||
{
|
||||
static signature_element const result[N+2] = {
|
||||
|
||||
#ifndef BOOST_PYTHON_NO_PY_SIGNATURES
|
||||
# define BOOST_PP_LOCAL_MACRO(i) \
|
||||
{ \
|
||||
type_id<BOOST_DEDUCED_TYPENAME mpl::at_c<Sig,i>::type>().name() \
|
||||
, indirect_traits::is_reference_to_non_const<BOOST_DEDUCED_TYPENAME mpl::at_c<Sig,i>::type>::value \
|
||||
},
|
||||
{ \
|
||||
type_id<BOOST_DEDUCED_TYPENAME mpl::at_c<Sig,i>::type>().name() \
|
||||
, &converter::expected_pytype_for_arg<BOOST_DEDUCED_TYPENAME mpl::at_c<Sig,i>::type>::get_pytype \
|
||||
, indirect_traits::is_reference_to_non_const<BOOST_DEDUCED_TYPENAME mpl::at_c<Sig,i>::type>::value \
|
||||
},
|
||||
#else
|
||||
# define BOOST_PP_LOCAL_MACRO(i) \
|
||||
{ \
|
||||
type_id<BOOST_DEDUCED_TYPENAME mpl::at_c<Sig,i>::type>().name() \
|
||||
, 0 \
|
||||
, indirect_traits::is_reference_to_non_const<BOOST_DEDUCED_TYPENAME mpl::at_c<Sig,i>::type>::value \
|
||||
},
|
||||
#endif
|
||||
|
||||
# define BOOST_PP_LOCAL_LIMITS (0, N)
|
||||
# include BOOST_PP_LOCAL_ITERATE()
|
||||
{0,0}
|
||||
{0,0,0}
|
||||
};
|
||||
return result;
|
||||
}
|
||||
|
||||
170
include/boost/python/detail/unwind_type.hpp
Executable file
170
include/boost/python/detail/unwind_type.hpp
Executable file
@@ -0,0 +1,170 @@
|
||||
// Copyright David Abrahams 2002.
|
||||
// Distributed under the Boost Software License, Version 1.0. (See
|
||||
// accompanying file LICENSE_1_0.txt or copy at
|
||||
// http://www.boost.org/LICENSE_1_0.txt)
|
||||
#ifndef UNWIND_TYPE_DWA200222_HPP
|
||||
# define UNWIND_TYPE_DWA200222_HPP
|
||||
|
||||
# include <boost/python/detail/cv_category.hpp>
|
||||
# include <boost/python/detail/indirect_traits.hpp>
|
||||
# include <boost/type_traits/object_traits.hpp>
|
||||
|
||||
namespace boost { namespace python { namespace detail {
|
||||
|
||||
#ifndef _MSC_VER //if forward declared, msvc6.5 does not recognize them as inline
|
||||
// forward declaration, required (at least) by Tru64 cxx V6.5-042
|
||||
template <class Generator, class U>
|
||||
inline typename Generator::result_type
|
||||
unwind_type(U const& p, Generator* = 0);
|
||||
|
||||
// forward declaration, required (at least) by Tru64 cxx V6.5-042
|
||||
template <class Generator, class U>
|
||||
inline typename Generator::result_type
|
||||
unwind_type(boost::type<U>*p = 0, Generator* = 0);
|
||||
#endif
|
||||
|
||||
template <class Generator, class U>
|
||||
inline typename Generator::result_type
|
||||
unwind_type_cv(U* p, cv_unqualified, Generator* = 0)
|
||||
{
|
||||
return Generator::execute(p);
|
||||
}
|
||||
|
||||
template <class Generator, class U>
|
||||
inline typename Generator::result_type
|
||||
unwind_type_cv(U const* p, const_, Generator* = 0)
|
||||
{
|
||||
return unwind_type(const_cast<U*>(p), (Generator*)0);
|
||||
}
|
||||
|
||||
template <class Generator, class U>
|
||||
inline typename Generator::result_type
|
||||
unwind_type_cv(U volatile* p, volatile_, Generator* = 0)
|
||||
{
|
||||
return unwind_type(const_cast<U*>(p), (Generator*)0);
|
||||
}
|
||||
|
||||
template <class Generator, class U>
|
||||
inline typename Generator::result_type
|
||||
unwind_type_cv(U const volatile* p, const_volatile_, Generator* = 0)
|
||||
{
|
||||
return unwind_type(const_cast<U*>(p), (Generator*)0);
|
||||
}
|
||||
|
||||
template <class Generator, class U>
|
||||
inline typename Generator::result_type
|
||||
unwind_ptr_type(U* p, Generator* = 0)
|
||||
{
|
||||
typedef typename cv_category<U>::type tag;
|
||||
return unwind_type_cv<Generator>(p, tag());
|
||||
}
|
||||
|
||||
template <bool is_ptr>
|
||||
struct unwind_helper
|
||||
{
|
||||
template <class Generator, class U>
|
||||
static typename Generator::result_type
|
||||
execute(U p, Generator* = 0)
|
||||
{
|
||||
return unwind_ptr_type(p, (Generator*)0);
|
||||
}
|
||||
};
|
||||
|
||||
template <>
|
||||
struct unwind_helper<false>
|
||||
{
|
||||
template <class Generator, class U>
|
||||
static typename Generator::result_type
|
||||
execute(U& p, Generator* = 0)
|
||||
{
|
||||
return unwind_ptr_type(&p, (Generator*)0);
|
||||
}
|
||||
};
|
||||
|
||||
template <class Generator, class U>
|
||||
inline typename Generator::result_type
|
||||
#ifndef _MSC_VER
|
||||
unwind_type(U const& p, Generator*)
|
||||
#else
|
||||
unwind_type(U const& p, Generator* = 0)
|
||||
#endif
|
||||
{
|
||||
return unwind_helper<is_pointer<U>::value>::execute(p, (Generator*)0);
|
||||
}
|
||||
|
||||
enum { direct_ = 0, pointer_ = 1, reference_ = 2, reference_to_pointer_ = 3 };
|
||||
template <int indirection> struct unwind_helper2;
|
||||
|
||||
template <>
|
||||
struct unwind_helper2<direct_>
|
||||
{
|
||||
template <class Generator, class U>
|
||||
static typename Generator::result_type
|
||||
execute(U(*)(), Generator* = 0)
|
||||
{
|
||||
return unwind_ptr_type((U*)0, (Generator*)0);
|
||||
}
|
||||
};
|
||||
|
||||
template <>
|
||||
struct unwind_helper2<pointer_>
|
||||
{
|
||||
template <class Generator, class U>
|
||||
static typename Generator::result_type
|
||||
execute(U*(*)(), Generator* = 0)
|
||||
{
|
||||
return unwind_ptr_type((U*)0, (Generator*)0);
|
||||
}
|
||||
};
|
||||
|
||||
template <>
|
||||
struct unwind_helper2<reference_>
|
||||
{
|
||||
template <class Generator, class U>
|
||||
static typename Generator::result_type
|
||||
execute(U&(*)(), Generator* = 0)
|
||||
{
|
||||
return unwind_ptr_type((U*)0, (Generator*)0);
|
||||
}
|
||||
};
|
||||
|
||||
template <>
|
||||
struct unwind_helper2<reference_to_pointer_>
|
||||
{
|
||||
template <class Generator, class U>
|
||||
static typename Generator::result_type
|
||||
execute(U&(*)(), Generator* = 0)
|
||||
{
|
||||
return unwind_ptr_type(U(0), (Generator*)0);
|
||||
}
|
||||
};
|
||||
|
||||
// Call this one with both template parameters explicitly specified
|
||||
// and no function arguments:
|
||||
//
|
||||
// return unwind_type<my_generator,T>();
|
||||
//
|
||||
// Doesn't work if T is an array type; we could handle that case, but
|
||||
// why bother?
|
||||
template <class Generator, class U>
|
||||
inline typename Generator::result_type
|
||||
#ifndef _MSC_VER
|
||||
unwind_type(boost::type<U>*p, Generator*)
|
||||
#else
|
||||
unwind_type(boost::type<U>*p =0, Generator* =0)
|
||||
#endif
|
||||
{
|
||||
BOOST_STATIC_CONSTANT(int, indirection
|
||||
= (boost::is_pointer<U>::value ? pointer_ : 0)
|
||||
+ (indirect_traits::is_reference_to_pointer<U>::value
|
||||
? reference_to_pointer_
|
||||
: boost::is_reference<U>::value
|
||||
? reference_
|
||||
: 0));
|
||||
|
||||
return unwind_helper2<indirection>::execute((U(*)())0,(Generator*)0);
|
||||
}
|
||||
|
||||
}}} // namespace boost::python::detail
|
||||
|
||||
#endif // UNWIND_TYPE_DWA200222_HPP
|
||||
@@ -17,23 +17,38 @@ class BOOST_PYTHON_DECL docstring_options : boost::noncopyable
|
||||
docstring_options(bool show_all=true)
|
||||
{
|
||||
previous_show_user_defined_ = show_user_defined_;
|
||||
previous_show_signatures_ = show_signatures_;
|
||||
previous_show_py_signatures_ = show_py_signatures_;
|
||||
previous_show_cpp_signatures_ = show_cpp_signatures_;
|
||||
show_user_defined_ = show_all;
|
||||
show_signatures_ = show_all;
|
||||
show_cpp_signatures_ = show_all;
|
||||
show_py_signatures_ = show_all;
|
||||
}
|
||||
|
||||
docstring_options(bool show_user_defined, bool show_signatures)
|
||||
{
|
||||
previous_show_user_defined_ = show_user_defined_;
|
||||
previous_show_signatures_ = show_signatures_;
|
||||
previous_show_cpp_signatures_ = show_cpp_signatures_;
|
||||
previous_show_py_signatures_ = show_py_signatures_;
|
||||
show_user_defined_ = show_user_defined;
|
||||
show_signatures_ = show_signatures;
|
||||
show_cpp_signatures_ = show_signatures;
|
||||
show_py_signatures_ = show_signatures;
|
||||
}
|
||||
|
||||
docstring_options(bool show_user_defined, bool show_py_signatures, bool show_cpp_signatures)
|
||||
{
|
||||
previous_show_user_defined_ = show_user_defined_;
|
||||
previous_show_cpp_signatures_ = show_cpp_signatures_;
|
||||
previous_show_py_signatures_ = show_py_signatures_;
|
||||
show_user_defined_ = show_user_defined;
|
||||
show_cpp_signatures_ = show_cpp_signatures;
|
||||
show_py_signatures_ = show_py_signatures;
|
||||
}
|
||||
|
||||
~docstring_options()
|
||||
{
|
||||
show_user_defined_ = previous_show_user_defined_;
|
||||
show_signatures_ = previous_show_signatures_;
|
||||
show_cpp_signatures_ = previous_show_cpp_signatures_;
|
||||
show_py_signatures_ = previous_show_py_signatures_;
|
||||
}
|
||||
|
||||
void
|
||||
@@ -43,32 +58,68 @@ class BOOST_PYTHON_DECL docstring_options : boost::noncopyable
|
||||
enable_user_defined() { show_user_defined_ = true; }
|
||||
|
||||
void
|
||||
disable_signatures() { show_signatures_ = false; }
|
||||
disable_py_signatures()
|
||||
{
|
||||
show_py_signatures_ = false;
|
||||
}
|
||||
|
||||
void
|
||||
enable_signatures() { show_signatures_ = true; }
|
||||
enable_py_signatures()
|
||||
{
|
||||
show_py_signatures_ = true;
|
||||
}
|
||||
|
||||
void
|
||||
disable_cpp_signatures()
|
||||
{
|
||||
show_cpp_signatures_ = false;
|
||||
}
|
||||
|
||||
void
|
||||
enable_cpp_signatures()
|
||||
{
|
||||
show_cpp_signatures_ = true;
|
||||
}
|
||||
|
||||
void
|
||||
disable_signatures()
|
||||
{
|
||||
show_cpp_signatures_ = false;
|
||||
show_py_signatures_ = false;
|
||||
}
|
||||
|
||||
void
|
||||
enable_signatures()
|
||||
{
|
||||
show_cpp_signatures_ = true;
|
||||
show_py_signatures_ = true;
|
||||
}
|
||||
|
||||
void
|
||||
disable_all()
|
||||
{
|
||||
show_user_defined_ = false;
|
||||
show_signatures_ = false;
|
||||
show_cpp_signatures_ = false;
|
||||
show_py_signatures_ = false;
|
||||
}
|
||||
|
||||
void
|
||||
enable_all()
|
||||
{
|
||||
show_user_defined_ = true;
|
||||
show_signatures_ = true;
|
||||
show_cpp_signatures_ = true;
|
||||
show_py_signatures_ = true;
|
||||
}
|
||||
|
||||
friend struct objects::function;
|
||||
|
||||
private:
|
||||
static volatile bool show_user_defined_;
|
||||
static volatile bool show_signatures_;
|
||||
static volatile bool show_cpp_signatures_;
|
||||
static volatile bool show_py_signatures_;
|
||||
bool previous_show_user_defined_;
|
||||
bool previous_show_signatures_;
|
||||
bool previous_show_cpp_signatures_;
|
||||
bool previous_show_py_signatures_;
|
||||
};
|
||||
|
||||
}} // namespace boost::python
|
||||
|
||||
@@ -19,7 +19,7 @@ struct enum_ : public objects::enum_base
|
||||
typedef objects::enum_base base;
|
||||
|
||||
// Declare a new enumeration type in the current scope()
|
||||
enum_(char const* name);
|
||||
enum_(char const* name, char const* doc = 0);
|
||||
|
||||
// Add a new enumeration value with the given name and value.
|
||||
inline enum_<T>& value(char const* name, T);
|
||||
@@ -34,13 +34,15 @@ struct enum_ : public objects::enum_base
|
||||
};
|
||||
|
||||
template <class T>
|
||||
inline enum_<T>::enum_(char const* name)
|
||||
inline enum_<T>::enum_(char const* name, char const* doc )
|
||||
: base(
|
||||
name
|
||||
, &enum_<T>::to_python
|
||||
, &enum_<T>::convertible_from_python
|
||||
, &enum_<T>::construct
|
||||
, type_id<T>())
|
||||
, type_id<T>()
|
||||
, doc
|
||||
)
|
||||
{
|
||||
}
|
||||
|
||||
|
||||
@@ -9,6 +9,9 @@
|
||||
# include <boost/type.hpp>
|
||||
# include <boost/python/converter/implicit.hpp>
|
||||
# include <boost/python/converter/registry.hpp>
|
||||
#ifndef BOOST_PYTHON_NO_PY_SIGNATURES
|
||||
# include <boost/python/converter/pytype_function.hpp>
|
||||
#endif
|
||||
# include <boost/python/type_id.hpp>
|
||||
|
||||
namespace boost { namespace python {
|
||||
@@ -21,7 +24,11 @@ void implicitly_convertible(boost::type<Source>* = 0, boost::type<Target>* = 0)
|
||||
converter::registry::push_back(
|
||||
&functions::convertible
|
||||
, &functions::construct
|
||||
, type_id<Target>());
|
||||
, type_id<Target>()
|
||||
#ifndef BOOST_PYTHON_NO_PY_SIGNATURES
|
||||
, &converter::expected_from_python_type_direct<Source>::get_pytype
|
||||
#endif
|
||||
);
|
||||
}
|
||||
|
||||
}} // namespace boost::python
|
||||
|
||||
@@ -245,7 +245,7 @@ class init : public init_base<init<BOOST_PYTHON_OVERLOAD_ARGS> >
|
||||
: base(doc_, kw.range())
|
||||
{
|
||||
typedef typename detail::error::more_keywords_than_init_arguments<
|
||||
N, n_arguments::value
|
||||
N, n_arguments::value + 1
|
||||
>::too_many_keywords assertion;
|
||||
}
|
||||
|
||||
@@ -254,7 +254,7 @@ class init : public init_base<init<BOOST_PYTHON_OVERLOAD_ARGS> >
|
||||
: base(doc_, kw.range())
|
||||
{
|
||||
typedef typename detail::error::more_keywords_than_init_arguments<
|
||||
N, n_arguments::value
|
||||
N, n_arguments::value + 1
|
||||
>::too_many_keywords assertion;
|
||||
}
|
||||
|
||||
@@ -363,7 +363,7 @@ namespace detail
|
||||
, char const* doc
|
||||
, detail::keyword_range keywords)
|
||||
{
|
||||
detail::def_init_aux(cl, args, NArgs(), policies, 0, keywords);
|
||||
detail::def_init_aux(cl, args, NArgs(), policies, doc, keywords);
|
||||
|
||||
if (keywords.second > keywords.first)
|
||||
--keywords.second;
|
||||
|
||||
@@ -6,6 +6,9 @@
|
||||
# define LVALUE_FROM_PYTYPE_DWA2002130_HPP
|
||||
|
||||
# include <boost/python/detail/prefix.hpp>
|
||||
#ifndef BOOST_PYTHON_NO_PY_SIGNATURES
|
||||
# include <boost/python/converter/pytype_function.hpp>
|
||||
#endif
|
||||
|
||||
# include <boost/python/type_id.hpp>
|
||||
# include <boost/python/converter/registry.hpp>
|
||||
@@ -81,12 +84,17 @@ struct extract_identity
|
||||
// Extractor's static execute function from Python objects whose type
|
||||
// object is python_type.
|
||||
template <class Extractor, PyTypeObject const* python_type>
|
||||
struct lvalue_from_pytype
|
||||
struct lvalue_from_pytype
|
||||
{
|
||||
lvalue_from_pytype()
|
||||
{
|
||||
converter::registry::insert(
|
||||
&extract, detail::extractor_type_id(&Extractor::execute));
|
||||
converter::registry::insert
|
||||
( &extract
|
||||
, detail::extractor_type_id(&Extractor::execute)
|
||||
#ifndef BOOST_PYTHON_NO_PY_SIGNATURES
|
||||
, &get_pytype
|
||||
#endif
|
||||
);
|
||||
}
|
||||
private:
|
||||
static void* extract(PyObject* op)
|
||||
@@ -98,6 +106,9 @@ struct lvalue_from_pytype
|
||||
: 0
|
||||
;
|
||||
}
|
||||
#ifndef BOOST_PYTHON_NO_PY_SIGNATURES
|
||||
static PyTypeObject const*get_pytype() { return python_type; }
|
||||
#endif
|
||||
};
|
||||
|
||||
}} // namespace boost::python
|
||||
|
||||
@@ -23,6 +23,7 @@
|
||||
# include <boost/mpl/int.hpp>
|
||||
# include <boost/mpl/push_front.hpp>
|
||||
# include <boost/mpl/pop_front.hpp>
|
||||
# include <boost/mpl/assert.hpp>
|
||||
|
||||
namespace boost { namespace python {
|
||||
|
||||
@@ -103,13 +104,23 @@ namespace detail
|
||||
|
||||
// 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<
|
||||
#if defined _MSC_VER && _MSC_VER < 1300
|
||||
typedef is_same<
|
||||
typename BasePolicy_::result_converter
|
||||
, default_result_converter
|
||||
>::value
|
||||
));
|
||||
|
||||
> same_result_converter;
|
||||
//see above for explanation
|
||||
BOOST_STATIC_ASSERT(same_result_converter::value) ;
|
||||
#else
|
||||
BOOST_MPL_ASSERT_MSG(
|
||||
(is_same<
|
||||
typename BasePolicy_::result_converter
|
||||
, default_result_converter
|
||||
>::value)
|
||||
, MAKE_CONSTRUCTOR_SUPPLIES_ITS_OWN_RESULT_CONVERTER_THAT_WOULD_OVERRIDE_YOURS
|
||||
, (typename BasePolicy_::result_converter)
|
||||
);
|
||||
#endif
|
||||
typedef constructor_result_converter result_converter;
|
||||
typedef offset_args<typename BasePolicy_::argument_package, mpl::int_<1> > argument_package;
|
||||
};
|
||||
|
||||
@@ -92,6 +92,7 @@ namespace aux
|
||||
{
|
||||
static bool check(PyObject* obj);
|
||||
static detail::new_non_null_reference adopt(PyObject* obj);
|
||||
static PyTypeObject const* get_pytype() ;
|
||||
};
|
||||
} // namespace aux
|
||||
|
||||
|
||||
@@ -238,6 +238,14 @@ struct class_metadata
|
||||
//
|
||||
inline static void maybe_register_pointer_to_python(void*,void*,void*) {}
|
||||
|
||||
#ifndef BOOST_PYTHON_NO_PY_SYGNATURES
|
||||
inline static void maybe_register_pointer_to_python(void*,void*,mpl::true_*)
|
||||
{
|
||||
objects::copy_class_object(python::type_id<T>(), python::type_id<back_reference<T const &> >());
|
||||
objects::copy_class_object(python::type_id<T>(), python::type_id<back_reference<T &> >());
|
||||
}
|
||||
#endif
|
||||
|
||||
template <class T2>
|
||||
inline static void maybe_register_pointer_to_python(T2*, mpl::false_*, mpl::false_*)
|
||||
{
|
||||
@@ -247,6 +255,10 @@ struct class_metadata
|
||||
, make_ptr_instance<T2, pointer_holder<held_type, T2> >
|
||||
>()
|
||||
);
|
||||
#ifndef BOOST_PYTHON_NO_PY_SYGNATURES
|
||||
// explicit qualification of type_id makes msvc6 happy
|
||||
objects::copy_class_object(python::type_id<T2>(), python::type_id<held_type>());
|
||||
#endif
|
||||
}
|
||||
//
|
||||
// Support for registering to-python converters
|
||||
@@ -258,6 +270,10 @@ struct class_metadata
|
||||
inline static void maybe_register_class_to_python(T2*, mpl::false_)
|
||||
{
|
||||
python::detail::force_instantiate(class_cref_wrapper<T2, make_instance<T2, holder> >());
|
||||
#ifndef BOOST_PYTHON_NO_PY_SYGNATURES
|
||||
// explicit qualification of type_id makes msvc6 happy
|
||||
objects::copy_class_object(python::type_id<T2>(), python::type_id<held_type>());
|
||||
#endif
|
||||
}
|
||||
|
||||
//
|
||||
|
||||
@@ -6,6 +6,9 @@
|
||||
# define CLASS_WRAPPER_DWA20011221_HPP
|
||||
|
||||
# include <boost/python/to_python_converter.hpp>
|
||||
#ifndef BOOST_PYTHON_NO_PY_SIGNATURES
|
||||
# include <boost/python/converter/pytype_function.hpp>
|
||||
#endif
|
||||
# include <boost/ref.hpp>
|
||||
|
||||
namespace boost { namespace python { namespace objects {
|
||||
@@ -19,22 +22,28 @@ namespace boost { namespace python { namespace objects {
|
||||
|
||||
template <class Src, class MakeInstance>
|
||||
struct class_cref_wrapper
|
||||
: to_python_converter<Src,class_cref_wrapper<Src,MakeInstance> >
|
||||
: to_python_converter<Src,class_cref_wrapper<Src,MakeInstance> ,true>
|
||||
{
|
||||
static PyObject* convert(Src const& x)
|
||||
{
|
||||
return MakeInstance::execute(boost::ref(x));
|
||||
}
|
||||
#ifndef BOOST_PYTHON_NO_PY_SIGNATURES
|
||||
static PyTypeObject const *get_pytype() { return converter::registered_pytype_direct<Src>::get_pytype(); }
|
||||
#endif
|
||||
};
|
||||
|
||||
template <class Src, class MakeInstance>
|
||||
struct class_value_wrapper
|
||||
: to_python_converter<Src,class_value_wrapper<Src,MakeInstance> >
|
||||
: to_python_converter<Src,class_value_wrapper<Src,MakeInstance> ,true>
|
||||
{
|
||||
static PyObject* convert(Src x)
|
||||
{
|
||||
return MakeInstance::execute(x);
|
||||
}
|
||||
#ifndef BOOST_PYTHON_NO_PY_SIGNATURES
|
||||
static PyTypeObject const *get_pytype() { return MakeInstance::get_pytype(); }
|
||||
#endif
|
||||
};
|
||||
|
||||
}}} // namespace boost::python::objects
|
||||
|
||||
@@ -21,7 +21,9 @@ struct BOOST_PYTHON_DECL enum_base : python::api::object
|
||||
, converter::to_python_function_t
|
||||
, converter::convertible_function
|
||||
, converter::constructor_function
|
||||
, type_info);
|
||||
, type_info
|
||||
, const char *doc = 0
|
||||
);
|
||||
|
||||
void add_value(char const* name, long value);
|
||||
void export_values();
|
||||
|
||||
@@ -14,6 +14,7 @@
|
||||
|
||||
namespace boost { namespace python { namespace objects {
|
||||
|
||||
|
||||
struct BOOST_PYTHON_DECL function : PyObject
|
||||
{
|
||||
function(
|
||||
@@ -53,6 +54,7 @@ struct BOOST_PYTHON_DECL function : PyObject
|
||||
object m_doc;
|
||||
object m_arg_names;
|
||||
unsigned m_nkeyword_values;
|
||||
friend class function_doc_signature_generator;
|
||||
};
|
||||
|
||||
//
|
||||
|
||||
36
include/boost/python/object/function_doc_signature.hpp
Executable file
36
include/boost/python/object/function_doc_signature.hpp
Executable file
@@ -0,0 +1,36 @@
|
||||
// Copyright Nikolay Mladenov 2007.
|
||||
// Distributed under the Boost Software License, Version 1.0. (See
|
||||
// accompanying file LICENSE_1_0.txt or copy at
|
||||
// http://www.boost.org/LICENSE_1_0.txt)
|
||||
#ifndef FUNCTION_SIGNATURE_20070531_HPP
|
||||
# define FUNCTION_SIGNATURE_20070531_HPP
|
||||
|
||||
#include <boost/python/object/function.hpp>
|
||||
#include <boost/python/converter/registrations.hpp>
|
||||
#include <boost/python/str.hpp>
|
||||
#include <boost/python/tuple.hpp>
|
||||
|
||||
#include <boost/python/detail/signature.hpp>
|
||||
|
||||
|
||||
#include <vector>
|
||||
|
||||
namespace boost { namespace python { namespace objects {
|
||||
|
||||
class function_doc_signature_generator{
|
||||
static const char * py_type_str(const python::detail::signature_element &s);
|
||||
static bool arity_cmp( function const *f1, function const *f2 );
|
||||
static bool are_seq_overloads( function const *f1, function const *f2 , bool check_docs);
|
||||
static std::vector<function const*> flatten(function const *f);
|
||||
static std::vector<function const*> split_seq_overloads( const std::vector<function const *> &funcs, bool split_on_doc_change);
|
||||
static str raw_function_pretty_signature(function const *f, size_t n_overloads, bool cpp_types = false);
|
||||
static str parameter_string(py_function const &f, size_t n, object arg_names, bool cpp_types);
|
||||
static str pretty_signature(function const *f, size_t n_overloads, bool cpp_types = false);
|
||||
|
||||
public:
|
||||
static list function_doc_signatures( function const * f);
|
||||
};
|
||||
|
||||
}}}//end of namespace boost::python::objects
|
||||
|
||||
#endif //FUNCTION_SIGNATURE_20070531_HPP
|
||||
@@ -11,6 +11,10 @@
|
||||
# include <boost/python/detail/prefix.hpp>
|
||||
|
||||
# include <boost/python/object/instance.hpp>
|
||||
# include <boost/python/converter/registry.hpp>
|
||||
#if !defined( BOOST_PYTHON_NO_PY_SIGNATURES) && defined( BOOST_PYTHON_PY_SYGNATURES_PROPER_INIT_SELF_TYPE)
|
||||
# include <boost/python/detail/python_type.hpp>
|
||||
#endif
|
||||
|
||||
# include <boost/python/object/forward.hpp>
|
||||
# include <boost/python/detail/preprocessor.hpp>
|
||||
@@ -74,7 +78,11 @@ struct make_holder<N>
|
||||
# endif
|
||||
|
||||
static void execute(
|
||||
PyObject* p
|
||||
#if !defined( BOOST_PYTHON_NO_PY_SIGNATURES) && defined( BOOST_PYTHON_PY_SYGNATURES_PROPER_INIT_SELF_TYPE)
|
||||
boost::python::detail::python_class<BOOST_DEDUCED_TYPENAME Holder::value_type> *p
|
||||
#else
|
||||
PyObject *p
|
||||
#endif
|
||||
BOOST_PP_ENUM_TRAILING_BINARY_PARAMS_Z(1, N, t, a))
|
||||
{
|
||||
typedef instance<Holder> instance_t;
|
||||
|
||||
@@ -29,7 +29,12 @@ struct make_ptr_instance
|
||||
{
|
||||
return get_class_object_impl(get_pointer(x));
|
||||
}
|
||||
|
||||
#ifndef BOOST_PYTHON_NO_PY_SIGNATURES
|
||||
static inline PyTypeObject const* get_pytype()
|
||||
{
|
||||
return converter::registered<T>::converters.get_class_object();
|
||||
}
|
||||
#endif
|
||||
private:
|
||||
template <class U>
|
||||
static inline PyTypeObject* get_class_object_impl(U const volatile* p)
|
||||
|
||||
@@ -23,7 +23,7 @@ struct BOOST_PYTHON_DECL py_function_impl_base
|
||||
virtual PyObject* operator()(PyObject*, PyObject*) = 0;
|
||||
virtual unsigned min_arity() const = 0;
|
||||
virtual unsigned max_arity() const;
|
||||
virtual python::detail::signature_element const* signature() const = 0;
|
||||
virtual python::detail::py_func_sig_info signature() const = 0;
|
||||
};
|
||||
|
||||
template <class Caller>
|
||||
@@ -43,7 +43,7 @@ struct caller_py_function_impl : py_function_impl_base
|
||||
return m_caller.min_arity();
|
||||
}
|
||||
|
||||
virtual python::detail::signature_element const* signature() const
|
||||
virtual python::detail::py_func_sig_info signature() const
|
||||
{
|
||||
return m_caller.signature();
|
||||
}
|
||||
@@ -69,9 +69,11 @@ struct signature_py_function_impl : py_function_impl_base
|
||||
return mpl::size<Sig>::value - 1;
|
||||
}
|
||||
|
||||
virtual python::detail::signature_element const* signature() const
|
||||
virtual python::detail::py_func_sig_info signature() const
|
||||
{
|
||||
return python::detail::signature<Sig>::elements();
|
||||
python::detail::signature_element const* sig = python::detail::signature<Sig>::elements();
|
||||
python::detail::py_func_sig_info res = {sig, sig};
|
||||
return res;
|
||||
}
|
||||
|
||||
private:
|
||||
@@ -102,9 +104,11 @@ struct full_py_function_impl : py_function_impl_base
|
||||
return m_max_arity;
|
||||
}
|
||||
|
||||
virtual python::detail::signature_element const* signature() const
|
||||
virtual python::detail::py_func_sig_info signature() const
|
||||
{
|
||||
return python::detail::signature<Sig>::elements();
|
||||
python::detail::signature_element const* sig = python::detail::signature<Sig>::elements();
|
||||
python::detail::py_func_sig_info res = {sig, sig};
|
||||
return res;
|
||||
}
|
||||
|
||||
private:
|
||||
@@ -151,7 +155,12 @@ struct py_function
|
||||
|
||||
python::detail::signature_element const* signature() const
|
||||
{
|
||||
return m_impl->signature();
|
||||
return m_impl->signature().signature;
|
||||
}
|
||||
|
||||
python::detail::signature_element const& get_return_type() const
|
||||
{
|
||||
return *m_impl->signature().ret;
|
||||
}
|
||||
|
||||
private:
|
||||
|
||||
@@ -470,6 +470,9 @@ namespace converter
|
||||
{
|
||||
return python::detail::new_non_null_reference(x);
|
||||
}
|
||||
#ifndef BOOST_PYTHON_NO_PY_SIGNATURES
|
||||
static PyTypeObject const *get_pytype() {return 0;}
|
||||
#endif
|
||||
};
|
||||
}
|
||||
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
// Copyright Gottfried Ganßauge 2003..2006
|
||||
// Copyright Gottfried Ganßauge 2003..2006.
|
||||
// Distributed under the Boost Software License, Version 1.0. (See
|
||||
// accompanying file LICENSE_1_0.txt or copy at
|
||||
// http://www.boost.org/LICENSE_1_0.txt)
|
||||
@@ -93,8 +93,13 @@ private:
|
||||
|
||||
if ((existing == 0) || (existing->m_to_python == 0))
|
||||
{
|
||||
#ifndef BOOST_PYTHON_NO_PY_SIGNATURES
|
||||
converter::registry::insert(&extract, type_id<Pointee>(), &get_pytype);
|
||||
converter::registry::insert(&wrap, type_id<Pointee*>(), &get_pytype);
|
||||
#else
|
||||
converter::registry::insert(&extract, type_id<Pointee>());
|
||||
converter::registry::insert(&wrap, type_id<Pointee*>());
|
||||
#endif
|
||||
}
|
||||
}
|
||||
|
||||
@@ -105,6 +110,9 @@ private:
|
||||
};
|
||||
|
||||
static PyTypeObject type_object;
|
||||
#ifndef BOOST_PYTHON_NO_PY_SIGNATURES
|
||||
static PyTypeObject const *get_pytype(){return &type_object; }
|
||||
#endif
|
||||
};
|
||||
|
||||
template <class Pointee>
|
||||
|
||||
@@ -347,6 +347,7 @@ BOOST_PYTHON_UNARY_OPERATOR(long, PyLong_FromLong, long_)
|
||||
BOOST_PYTHON_UNARY_OPERATOR(float, double, float_)
|
||||
BOOST_PYTHON_UNARY_OPERATOR(complex, std::complex<double>, complex_)
|
||||
BOOST_PYTHON_UNARY_OPERATOR(str, lexical_cast<std::string>, str)
|
||||
BOOST_PYTHON_UNARY_OPERATOR(repr, lexical_cast<std::string>, repr)
|
||||
# undef BOOST_PYTHON_UNARY_OPERATOR
|
||||
|
||||
}} // namespace boost::python
|
||||
@@ -358,6 +359,7 @@ using boost::python::self_ns::long_;
|
||||
using boost::python::self_ns::float_;
|
||||
using boost::python::self_ns::complex_;
|
||||
using boost::python::self_ns::str;
|
||||
using boost::python::self_ns::repr;
|
||||
using boost::python::self_ns::pow;
|
||||
# endif
|
||||
|
||||
|
||||
@@ -8,10 +8,15 @@
|
||||
# include <boost/python/detail/none.hpp>
|
||||
# include <boost/python/detail/value_arg.hpp>
|
||||
|
||||
#ifndef BOOST_PYTHON_NO_PY_SIGNATURES
|
||||
# include <boost/python/converter/pytype_function.hpp>
|
||||
#endif
|
||||
|
||||
# include <boost/type_traits/add_reference.hpp>
|
||||
# include <boost/type_traits/add_const.hpp>
|
||||
|
||||
# include <boost/mpl/int.hpp>
|
||||
# include <boost/mpl/at.hpp>
|
||||
|
||||
# include <boost/static_assert.hpp>
|
||||
# include <boost/python/refcount.hpp>
|
||||
@@ -44,6 +49,9 @@ namespace detail
|
||||
{
|
||||
return none();
|
||||
}
|
||||
#ifndef BOOST_PYTHON_NO_PY_SIGNATURES
|
||||
PyTypeObject const *get_pytype() const { return converter::expected_pytype_for_arg<T>::get_pytype() ; }
|
||||
#endif
|
||||
};
|
||||
};
|
||||
};
|
||||
@@ -82,6 +90,12 @@ struct return_arg : Base
|
||||
Py_DECREF(result);
|
||||
return incref( detail::get(mpl::int_<arg_pos-1>(),args) );
|
||||
}
|
||||
|
||||
template <class Sig>
|
||||
struct extract_return_type : mpl::at_c<Sig, arg_pos>
|
||||
{
|
||||
};
|
||||
|
||||
};
|
||||
|
||||
template <
|
||||
|
||||
@@ -17,73 +17,73 @@
|
||||
# include <boost/type_traits/is_same.hpp>
|
||||
|
||||
namespace boost { namespace python {
|
||||
|
||||
|
||||
// indexing_suite class. This class is the facade class for
|
||||
// the management of C++ containers intended to be integrated
|
||||
// to Python. The objective is make a C++ container look and
|
||||
// feel and behave exactly as we'd expect a Python container.
|
||||
// By default indexed elements are returned by proxy. This can be
|
||||
// disabled by supplying *true* in the NoProxy template parameter.
|
||||
//
|
||||
//
|
||||
// Derived classes provide the hooks needed by the indexing_suite
|
||||
// to do its job:
|
||||
//
|
||||
// static data_type&
|
||||
// static data_type&
|
||||
// get_item(Container& container, index_type i);
|
||||
//
|
||||
// static object
|
||||
// static object
|
||||
// get_slice(Container& container, index_type from, index_type to);
|
||||
//
|
||||
// static void
|
||||
// static void
|
||||
// set_item(Container& container, index_type i, data_type const& v);
|
||||
//
|
||||
// static void
|
||||
// static void
|
||||
// set_slice(
|
||||
// Container& container, index_type from,
|
||||
// Container& container, index_type from,
|
||||
// index_type to, data_type const& v
|
||||
// );
|
||||
//
|
||||
// template <class Iter>
|
||||
// static void
|
||||
// set_slice(Container& container, index_type from,
|
||||
// static void
|
||||
// set_slice(Container& container, index_type from,
|
||||
// index_type to, Iter first, Iter last
|
||||
// );
|
||||
//
|
||||
// static void
|
||||
// static void
|
||||
// delete_item(Container& container, index_type i);
|
||||
//
|
||||
// static void
|
||||
//
|
||||
// static void
|
||||
// delete_slice(Container& container, index_type from, index_type to);
|
||||
//
|
||||
//
|
||||
// static size_t
|
||||
// size(Container& container);
|
||||
//
|
||||
// template <class T>
|
||||
// static bool
|
||||
// contains(Container& container, T const& val);
|
||||
//
|
||||
//
|
||||
// static index_type
|
||||
// convert_index(Container& container, PyObject* i);
|
||||
//
|
||||
//
|
||||
// static index_type
|
||||
// adjust_index(index_type current, index_type from,
|
||||
// adjust_index(index_type current, index_type from,
|
||||
// index_type to, size_type len
|
||||
// );
|
||||
//
|
||||
// Most of these policies are self explanatory. convert_index and
|
||||
// adjust_index, however, deserves some explanation.
|
||||
// Most of these policies are self explanatory. convert_index and
|
||||
// adjust_index, however, deserves some explanation.
|
||||
//
|
||||
// convert_index converts an Python index into a C++ index that the
|
||||
// container can handle. For instance, negative indexes in Python, by
|
||||
// convention, indexes from the right (e.g. C[-1] indexes the rightmost
|
||||
// element in C). convert_index should handle the necessary conversion
|
||||
// convert_index converts an Python index into a C++ index that the
|
||||
// container can handle. For instance, negative indexes in Python, by
|
||||
// convention, indexes from the right (e.g. C[-1] indexes the rightmost
|
||||
// element in C). convert_index should handle the necessary conversion
|
||||
// for the C++ container (e.g. convert -1 to C.size()-1). convert_index
|
||||
// should also be able to convert the type of the index (A dynamic Python
|
||||
// type) to the actual type that the C++ container expects.
|
||||
//
|
||||
// When a container expands or contracts, held indexes to its elements
|
||||
// must be adjusted to follow the movement of data. For instance, if
|
||||
// we erase 3 elements, starting from index 0 from a 5 element vector,
|
||||
// we erase 3 elements, starting from index 0 from a 5 element vector,
|
||||
// what used to be at index 4 will now be at index 1:
|
||||
//
|
||||
// [a][b][c][d][e] ---> [d][e]
|
||||
@@ -104,7 +104,7 @@ namespace boost { namespace python {
|
||||
, class Index = typename Container::size_type
|
||||
, class Key = typename Container::value_type
|
||||
>
|
||||
class indexing_suite
|
||||
class indexing_suite
|
||||
: public def_visitor<
|
||||
indexing_suite<
|
||||
Container
|
||||
@@ -117,7 +117,7 @@ namespace boost { namespace python {
|
||||
> >
|
||||
{
|
||||
private:
|
||||
|
||||
|
||||
typedef mpl::or_<
|
||||
mpl::bool_<NoProxy>
|
||||
, mpl::not_<is_class<Data> >
|
||||
@@ -127,10 +127,10 @@ namespace boost { namespace python {
|
||||
, is_same<Data, std::complex<double> >
|
||||
, is_same<Data, std::complex<long double> > >::type>
|
||||
no_proxy;
|
||||
|
||||
|
||||
typedef detail::container_element<Container, Index, DerivedPolicies>
|
||||
container_element_t;
|
||||
|
||||
|
||||
#if BOOST_WORKAROUND(BOOST_MSVC, < 1300)
|
||||
struct return_policy : return_internal_reference<> {};
|
||||
#else
|
||||
@@ -142,7 +142,7 @@ namespace boost { namespace python {
|
||||
, iterator<Container>
|
||||
, iterator<Container, return_policy> >::type
|
||||
def_iterator;
|
||||
|
||||
|
||||
typedef typename mpl::if_<
|
||||
no_proxy
|
||||
, detail::no_proxy_helper<
|
||||
@@ -172,15 +172,15 @@ namespace boost { namespace python {
|
||||
, Data
|
||||
, Index> >::type
|
||||
slice_handler;
|
||||
|
||||
|
||||
public:
|
||||
|
||||
|
||||
template <class Class>
|
||||
void visit(Class& cl) const
|
||||
{
|
||||
// Hook into the class_ generic visitation .def function
|
||||
proxy_handler::register_container_element();
|
||||
|
||||
|
||||
cl
|
||||
.def("__len__", base_size)
|
||||
.def("__setitem__", &base_set_item)
|
||||
@@ -189,12 +189,12 @@ namespace boost { namespace python {
|
||||
.def("__contains__", &base_contains)
|
||||
.def("__iter__", def_iterator())
|
||||
;
|
||||
|
||||
|
||||
DerivedPolicies::extension_def(cl);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
template <class Class>
|
||||
static void
|
||||
static void
|
||||
extension_def(Class& cl)
|
||||
{
|
||||
// default.
|
||||
@@ -202,24 +202,24 @@ namespace boost { namespace python {
|
||||
}
|
||||
|
||||
private:
|
||||
|
||||
|
||||
static object
|
||||
base_get_item(back_reference<Container&> container, PyObject* i)
|
||||
{
|
||||
{
|
||||
if (PySlice_Check(i))
|
||||
return slice_handler::base_get_slice(
|
||||
container.get(), reinterpret_cast<PySliceObject*>(i));
|
||||
|
||||
container.get(), static_cast<PySliceObject*>(static_cast<void*>(i)));
|
||||
|
||||
return proxy_handler::base_get_item_(container, i);
|
||||
}
|
||||
|
||||
static void
|
||||
|
||||
static void
|
||||
base_set_item(Container& container, PyObject* i, PyObject* v)
|
||||
{
|
||||
if (PySlice_Check(i))
|
||||
{
|
||||
slice_handler::base_set_slice(container,
|
||||
reinterpret_cast<PySliceObject*>(i), v);
|
||||
slice_handler::base_set_slice(container,
|
||||
static_cast<PySliceObject*>(static_cast<void*>(i)), v);
|
||||
}
|
||||
else
|
||||
{
|
||||
@@ -228,7 +228,7 @@ namespace boost { namespace python {
|
||||
if (elem.check())
|
||||
{
|
||||
DerivedPolicies::
|
||||
set_item(container,
|
||||
set_item(container,
|
||||
DerivedPolicies::
|
||||
convert_index(container, i), elem());
|
||||
}
|
||||
@@ -239,7 +239,7 @@ namespace boost { namespace python {
|
||||
if (elem.check())
|
||||
{
|
||||
DerivedPolicies::
|
||||
set_item(container,
|
||||
set_item(container,
|
||||
DerivedPolicies::
|
||||
convert_index(container, i), elem());
|
||||
}
|
||||
@@ -252,20 +252,20 @@ namespace boost { namespace python {
|
||||
}
|
||||
}
|
||||
|
||||
static void
|
||||
static void
|
||||
base_delete_item(Container& container, PyObject* i)
|
||||
{
|
||||
if (PySlice_Check(i))
|
||||
{
|
||||
slice_handler::base_delete_slice(
|
||||
container, reinterpret_cast<PySliceObject*>(i));
|
||||
container, static_cast<PySliceObject*>(static_cast<void*>(i)));
|
||||
return;
|
||||
}
|
||||
|
||||
|
||||
Index index = DerivedPolicies::convert_index(container, i);
|
||||
proxy_handler::base_erase_index(container, index, mpl::bool_<NoSlice>());
|
||||
DerivedPolicies::delete_item(container, index);
|
||||
}
|
||||
}
|
||||
|
||||
static size_t
|
||||
base_size(Container& container)
|
||||
@@ -290,10 +290,10 @@ namespace boost { namespace python {
|
||||
return DerivedPolicies::contains(container, x());
|
||||
else
|
||||
return false;
|
||||
}
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
}} // namespace boost::python
|
||||
|
||||
}} // namespace boost::python
|
||||
|
||||
#endif // INDEXING_SUITE_JDG20036_HPP
|
||||
|
||||
@@ -9,13 +9,67 @@
|
||||
|
||||
# include <boost/python/converter/registry.hpp>
|
||||
# include <boost/python/converter/as_to_python_function.hpp>
|
||||
#ifndef BOOST_PYTHON_NO_PY_SIGNATURES
|
||||
# include <boost/python/converter/pytype_function.hpp>
|
||||
#endif
|
||||
# include <boost/python/type_id.hpp>
|
||||
|
||||
namespace boost { namespace python {
|
||||
|
||||
template <class T, class Conversion>
|
||||
struct to_python_converter
|
||||
#if 0 //get_pytype member detection
|
||||
namespace detail
|
||||
{
|
||||
typedef char yes_type;
|
||||
typedef struct {char a[2]; } no_type;
|
||||
template<PyTypeObject const * (*f)()> struct test_get_pytype1 { };
|
||||
template<PyTypeObject * (*f)()> struct test_get_pytype2 { };
|
||||
|
||||
template<class T> yes_type tester(test_get_pytype1<&T::get_pytype>*);
|
||||
|
||||
template<class T> yes_type tester(test_get_pytype2<&T::get_pytype>*);
|
||||
|
||||
template<class T> no_type tester(...);
|
||||
|
||||
template<class T>
|
||||
struct test_get_pytype_base
|
||||
{
|
||||
BOOST_STATIC_CONSTANT(bool, value= (sizeof(detail::tester<T>(0)) == sizeof(yes_type)));
|
||||
};
|
||||
|
||||
template<class T>
|
||||
struct test_get_pytype : boost::mpl::bool_<test_get_pytype_base<T>::value>
|
||||
{
|
||||
};
|
||||
|
||||
}
|
||||
#endif
|
||||
|
||||
template < class T, class Conversion, bool has_get_pytype=false >
|
||||
struct to_python_converter
|
||||
{
|
||||
#ifndef BOOST_PYTHON_NO_PY_SIGNATURES
|
||||
#if 0 //defined _MSC_VER && _MSC_VER >=1310
|
||||
//probably other compilers could come here as well
|
||||
typedef typename detail::test_get_pytype<Conversion> HasGetPytype;
|
||||
#else
|
||||
typedef boost::mpl::bool_<has_get_pytype> HasGetPytype;
|
||||
#endif
|
||||
|
||||
static PyTypeObject const* get_pytype_1(boost::mpl::true_ *)
|
||||
{
|
||||
return Conversion::get_pytype();
|
||||
}
|
||||
|
||||
static PyTypeObject const* get_pytype_1(boost::mpl::false_ *)
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
static PyTypeObject const* get_pytype_impl()
|
||||
{
|
||||
return get_pytype_1((HasGetPytype*)0);
|
||||
}
|
||||
#endif
|
||||
|
||||
to_python_converter();
|
||||
};
|
||||
|
||||
@@ -23,18 +77,23 @@ struct to_python_converter
|
||||
// implementation
|
||||
//
|
||||
|
||||
template <class T, class Conversion>
|
||||
to_python_converter<T,Conversion>::to_python_converter()
|
||||
template <class T, class Conversion ,bool has_get_pytype>
|
||||
to_python_converter<T,Conversion, has_get_pytype>::to_python_converter()
|
||||
{
|
||||
typedef converter::as_to_python_function<
|
||||
T, Conversion
|
||||
> normalized;
|
||||
|
||||
|
||||
converter::registry::insert(
|
||||
&normalized::convert
|
||||
, type_id<T>());
|
||||
, type_id<T>()
|
||||
#ifndef BOOST_PYTHON_NO_PY_SIGNATURES
|
||||
, &get_pytype_impl
|
||||
#endif
|
||||
);
|
||||
}
|
||||
|
||||
}} // namespace boost::python
|
||||
|
||||
#endif // TO_PYTHON_CONVERTER_DWA200221_HPP
|
||||
|
||||
|
||||
@@ -12,6 +12,10 @@
|
||||
|
||||
# include <boost/python/detail/none.hpp>
|
||||
|
||||
#ifndef BOOST_PYTHON_NO_PY_SIGNATURES
|
||||
# include <boost/python/converter/pytype_function.hpp>
|
||||
#endif
|
||||
|
||||
# include <boost/python/refcount.hpp>
|
||||
|
||||
# include <boost/type_traits/is_pointer.hpp>
|
||||
@@ -36,7 +40,13 @@ struct to_python_indirect
|
||||
{
|
||||
return this->execute(const_cast<U&>(ref), is_pointer<U>());
|
||||
}
|
||||
|
||||
#ifndef BOOST_PYTHON_NO_PY_SIGNATURES
|
||||
inline PyTypeObject const*
|
||||
get_pytype()const
|
||||
{
|
||||
return converter::registered_pytype<T>::get_pytype();
|
||||
}
|
||||
#endif
|
||||
private:
|
||||
template <class U>
|
||||
inline PyObject* execute(U* ptr, mpl::true_) const
|
||||
|
||||
@@ -9,12 +9,12 @@
|
||||
|
||||
# include <boost/python/refcount.hpp>
|
||||
# include <boost/python/tag.hpp>
|
||||
# include <boost/python/handle.hpp>
|
||||
|
||||
# include <boost/python/converter/registry.hpp>
|
||||
# include <boost/python/converter/registered.hpp>
|
||||
# include <boost/python/converter/builtin_converters.hpp>
|
||||
# include <boost/python/converter/object_manager.hpp>
|
||||
# include <boost/python/converter/object_manager.hpp>
|
||||
# include <boost/python/converter/shared_ptr_to_python.hpp>
|
||||
|
||||
# include <boost/python/detail/value_is_shared_ptr.hpp>
|
||||
@@ -24,17 +24,57 @@
|
||||
|
||||
# include <boost/mpl/if.hpp>
|
||||
# include <boost/mpl/or.hpp>
|
||||
# include <boost/type_traits/is_const.hpp>
|
||||
|
||||
namespace boost { namespace python {
|
||||
|
||||
namespace detail
|
||||
{
|
||||
#ifndef BOOST_PYTHON_NO_PY_SIGNATURES
|
||||
|
||||
template <bool is_const_ref>
|
||||
struct object_manager_get_pytype
|
||||
{
|
||||
template <class U>
|
||||
static PyTypeObject const* get( U& (*p)() =0)
|
||||
{
|
||||
return converter::object_manager_traits<U>::get_pytype();
|
||||
}
|
||||
};
|
||||
|
||||
template <>
|
||||
struct object_manager_get_pytype<true>
|
||||
{
|
||||
template <class U>
|
||||
static PyTypeObject const* get( U const& (*p)() =0)
|
||||
{
|
||||
return converter::object_manager_traits<U>::get_pytype();
|
||||
}
|
||||
};
|
||||
|
||||
#endif
|
||||
|
||||
template <class T>
|
||||
struct object_manager_to_python_value
|
||||
{
|
||||
typedef typename value_arg<T>::type argument_type;
|
||||
|
||||
PyObject* operator()(argument_type) const;
|
||||
#ifndef BOOST_PYTHON_NO_PY_SIGNATURES
|
||||
typedef boost::mpl::bool_<is_handle<T>::value> is_t_handle;
|
||||
typedef boost::detail::indirect_traits::is_reference_to_const<T> is_t_const;
|
||||
PyTypeObject const* get_pytype() const {
|
||||
return get_pytype_aux((is_t_handle*)0);
|
||||
}
|
||||
|
||||
inline static PyTypeObject const* get_pytype_aux(mpl::true_*) {return converter::object_manager_traits<T>::get_pytype();}
|
||||
|
||||
inline static PyTypeObject const* get_pytype_aux(mpl::false_* )
|
||||
{
|
||||
return object_manager_get_pytype<is_t_const::value>::get((T(*)())0);
|
||||
}
|
||||
|
||||
#endif
|
||||
|
||||
// This information helps make_getter() decide whether to try to
|
||||
// return an internal reference or not. I don't like it much,
|
||||
@@ -49,6 +89,9 @@ namespace detail
|
||||
typedef typename value_arg<T>::type argument_type;
|
||||
|
||||
PyObject* operator()(argument_type) const;
|
||||
#ifndef BOOST_PYTHON_NO_PY_SIGNATURES
|
||||
PyTypeObject const* get_pytype() const {return converter::registered<T>::converters.to_python_target_type();}
|
||||
#endif
|
||||
|
||||
// This information helps make_getter() decide whether to try to
|
||||
// return an internal reference or not. I don't like it much,
|
||||
@@ -62,11 +105,20 @@ namespace detail
|
||||
typedef typename value_arg<T>::type argument_type;
|
||||
|
||||
PyObject* operator()(argument_type) const;
|
||||
|
||||
#ifndef BOOST_PYTHON_NO_PY_SIGNATURES
|
||||
PyTypeObject const* get_pytype() const {return get_pytype((boost::type<argument_type>*)0);}
|
||||
#endif
|
||||
// This information helps make_getter() decide whether to try to
|
||||
// return an internal reference or not. I don't like it much,
|
||||
// but it will have to serve for now.
|
||||
BOOST_STATIC_CONSTANT(bool, uses_registry = false);
|
||||
private:
|
||||
#ifndef BOOST_PYTHON_NO_PY_SIGNATURES
|
||||
template <class U>
|
||||
PyTypeObject const* get_pytype(boost::type<shared_ptr<U> &> *) const {return converter::registered<U>::converters.to_python_target_type();}
|
||||
template <class U>
|
||||
PyTypeObject const* get_pytype(boost::type<const shared_ptr<U> &> *) const {return converter::registered<U>::converters.to_python_target_type();}
|
||||
#endif
|
||||
};
|
||||
}
|
||||
|
||||
|
||||
@@ -16,6 +16,7 @@
|
||||
#include <boost/python/converter/registry.hpp>
|
||||
#include <boost/python/converter/registrations.hpp>
|
||||
#include <boost/python/converter/shared_ptr_deleter.hpp>
|
||||
#include <boost/python/converter/pytype_function.hpp>
|
||||
|
||||
#include <boost/cast.hpp>
|
||||
#include <string>
|
||||
@@ -56,6 +57,7 @@ namespace
|
||||
&slot_rvalue_from_python<T,SlotPolicy>::convertible
|
||||
, &slot_rvalue_from_python<T,SlotPolicy>::construct
|
||||
, type_id<T>()
|
||||
, &SlotPolicy::get_pytype
|
||||
);
|
||||
}
|
||||
|
||||
@@ -100,6 +102,7 @@ namespace
|
||||
return (PyInt_Check(obj) || PyLong_Check(obj))
|
||||
? &number_methods->nb_int : 0;
|
||||
}
|
||||
static PyTypeObject const* get_pytype() { return &PyInt_Type;}
|
||||
};
|
||||
|
||||
template <class T>
|
||||
@@ -135,6 +138,7 @@ namespace
|
||||
return (PyInt_Check(obj) || PyLong_Check(obj))
|
||||
? &py_object_identity : 0;
|
||||
}
|
||||
static PyTypeObject const* get_pytype() { return &PyInt_Type;}
|
||||
};
|
||||
|
||||
template <class T>
|
||||
@@ -173,6 +177,7 @@ namespace
|
||||
else
|
||||
return 0;
|
||||
}
|
||||
static PyTypeObject const* get_pytype() { return &PyInt_Type;}
|
||||
};
|
||||
|
||||
struct long_long_rvalue_from_python : long_long_rvalue_from_python_base
|
||||
@@ -228,6 +233,15 @@ namespace
|
||||
{
|
||||
return PyObject_IsTrue(intermediate);
|
||||
}
|
||||
|
||||
static PyTypeObject const* get_pytype()
|
||||
{
|
||||
#if PY_VERSION_HEX >= 0x02030000
|
||||
return &PyBool_Type;
|
||||
#else
|
||||
return &PyInt_Type;
|
||||
#endif
|
||||
}
|
||||
};
|
||||
|
||||
// A SlotPolicy for extracting floating types from Python objects.
|
||||
@@ -259,6 +273,7 @@ namespace
|
||||
return PyFloat_AS_DOUBLE(intermediate);
|
||||
}
|
||||
}
|
||||
static PyTypeObject const* get_pytype() { return &PyFloat_Type;}
|
||||
};
|
||||
|
||||
// A SlotPolicy for extracting C++ strings from Python objects.
|
||||
@@ -276,6 +291,7 @@ namespace
|
||||
{
|
||||
return std::string(PyString_AsString(intermediate),PyString_Size(intermediate));
|
||||
}
|
||||
static PyTypeObject const* get_pytype() { return &PyString_Type;}
|
||||
};
|
||||
|
||||
#if defined(Py_USING_UNICODE) && !defined(BOOST_NO_STD_WSTRING)
|
||||
@@ -316,6 +332,7 @@ namespace
|
||||
}
|
||||
return result;
|
||||
}
|
||||
static PyTypeObject const* get_pytype() { return &PyUnicode_Type;}
|
||||
};
|
||||
#endif
|
||||
|
||||
@@ -346,6 +363,7 @@ namespace
|
||||
return PyFloat_AS_DOUBLE(intermediate);
|
||||
}
|
||||
}
|
||||
static PyTypeObject const* get_pytype() { return &PyComplex_Type;}
|
||||
};
|
||||
}
|
||||
|
||||
@@ -411,7 +429,7 @@ void initialize_builtin_converters()
|
||||
slot_rvalue_from_python<std::complex<long double>,complex_rvalue_from_python>();
|
||||
|
||||
// Add an lvalue converter for char which gets us char const*
|
||||
registry::insert(convert_to_cstring,type_id<char>());
|
||||
registry::insert(convert_to_cstring,type_id<char>(),&converter::wrap_pytype<&PyString_Type>::get_pytype);
|
||||
|
||||
// Register by-value converters to std::string, std::wstring
|
||||
#if defined(Py_USING_UNICODE) && !defined(BOOST_NO_STD_WSTRING)
|
||||
|
||||
@@ -20,6 +20,35 @@
|
||||
#endif
|
||||
|
||||
namespace boost { namespace python { namespace converter {
|
||||
BOOST_PYTHON_DECL PyTypeObject const* registration::expected_from_python_type() const
|
||||
{
|
||||
if (this->m_class_object != 0)
|
||||
return this->m_class_object;
|
||||
|
||||
std::set<PyTypeObject const*> pool;
|
||||
|
||||
for(rvalue_from_python_chain* r = rvalue_chain; r ; r=r->next)
|
||||
if(r->expected_pytype)
|
||||
pool.insert(r->expected_pytype());
|
||||
|
||||
//for now I skip the search for common base
|
||||
if (pool.size()==1)
|
||||
return *pool.begin();
|
||||
|
||||
return 0;
|
||||
|
||||
}
|
||||
|
||||
BOOST_PYTHON_DECL PyTypeObject const* registration::to_python_target_type() const
|
||||
{
|
||||
if (this->m_class_object != 0)
|
||||
return this->m_class_object;
|
||||
|
||||
if (this->m_to_python_target_type != 0)
|
||||
return this->m_to_python_target_type();
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
BOOST_PYTHON_DECL PyTypeObject* registration::get_class_object() const
|
||||
{
|
||||
@@ -57,6 +86,24 @@ BOOST_PYTHON_DECL PyObject* registration::to_python(void const volatile* source)
|
||||
: this->m_to_python(const_cast<void*>(source));
|
||||
}
|
||||
|
||||
namespace
|
||||
{
|
||||
template< typename T >
|
||||
void delete_node( T* node )
|
||||
{
|
||||
if( !!node && !!node->next )
|
||||
delete_node( node->next );
|
||||
delete node;
|
||||
}
|
||||
}
|
||||
|
||||
registration::~registration()
|
||||
{
|
||||
delete_node(lvalue_chain);
|
||||
delete_node(rvalue_chain);
|
||||
}
|
||||
|
||||
|
||||
namespace // <unnamed>
|
||||
{
|
||||
typedef registration entry;
|
||||
@@ -150,15 +197,15 @@ namespace // <unnamed>
|
||||
|
||||
namespace registry
|
||||
{
|
||||
void insert(to_python_function_t f, type_info source_t)
|
||||
void insert(to_python_function_t f, type_info source_t, PyTypeObject const* (*to_python_target_type)())
|
||||
{
|
||||
# ifdef BOOST_PYTHON_TRACE_REGISTRY
|
||||
std::cout << "inserting to_python " << source_t << "\n";
|
||||
# endif
|
||||
to_python_function_t& slot = get(source_t)->m_to_python;
|
||||
entry* slot = get(source_t);
|
||||
|
||||
assert(slot == 0); // we have a problem otherwise
|
||||
if (slot != 0)
|
||||
assert(slot->m_to_python == 0); // we have a problem otherwise
|
||||
if (slot->m_to_python != 0)
|
||||
{
|
||||
std::string msg = (
|
||||
std::string("to-Python converter for ")
|
||||
@@ -171,11 +218,12 @@ namespace registry
|
||||
throw_error_already_set();
|
||||
}
|
||||
}
|
||||
slot = f;
|
||||
slot->m_to_python = f;
|
||||
slot->m_to_python_target_type = to_python_target_type;
|
||||
}
|
||||
|
||||
// Insert an lvalue from_python converter
|
||||
void insert(convertible_function convert, type_info key)
|
||||
void insert(convertible_function convert, type_info key, PyTypeObject const* (*exp_pytype)())
|
||||
{
|
||||
# ifdef BOOST_PYTHON_TRACE_REGISTRY
|
||||
std::cout << "inserting lvalue from_python " << key << "\n";
|
||||
@@ -186,13 +234,14 @@ namespace registry
|
||||
registration->next = found->lvalue_chain;
|
||||
found->lvalue_chain = registration;
|
||||
|
||||
insert(convert, 0, key);
|
||||
insert(convert, 0, key,exp_pytype);
|
||||
}
|
||||
|
||||
// Insert an rvalue from_python converter
|
||||
void insert(void* (*convertible)(PyObject*)
|
||||
, constructor_function construct
|
||||
, type_info key)
|
||||
, type_info key
|
||||
, PyTypeObject const* (*exp_pytype)())
|
||||
{
|
||||
# ifdef BOOST_PYTHON_TRACE_REGISTRY
|
||||
std::cout << "inserting rvalue from_python " << key << "\n";
|
||||
@@ -201,6 +250,7 @@ namespace registry
|
||||
rvalue_from_python_chain *registration = new rvalue_from_python_chain;
|
||||
registration->convertible = convertible;
|
||||
registration->construct = construct;
|
||||
registration->expected_pytype = exp_pytype;
|
||||
registration->next = found->rvalue_chain;
|
||||
found->rvalue_chain = registration;
|
||||
}
|
||||
@@ -208,7 +258,8 @@ namespace registry
|
||||
// Insert an rvalue from_python converter
|
||||
void push_back(void* (*convertible)(PyObject*)
|
||||
, constructor_function construct
|
||||
, type_info key)
|
||||
, type_info key
|
||||
, PyTypeObject const* (*exp_pytype)())
|
||||
{
|
||||
# ifdef BOOST_PYTHON_TRACE_REGISTRY
|
||||
std::cout << "push_back rvalue from_python " << key << "\n";
|
||||
@@ -220,6 +271,7 @@ namespace registry
|
||||
rvalue_from_python_chain *registration = new rvalue_from_python_chain;
|
||||
registration->convertible = convertible;
|
||||
registration->construct = construct;
|
||||
registration->expected_pytype = exp_pytype;
|
||||
registration->next = 0;
|
||||
*found = registration;
|
||||
}
|
||||
|
||||
10
src/dict.cpp
10
src/dict.cpp
@@ -171,4 +171,14 @@ list dict_base::values() const
|
||||
}
|
||||
}
|
||||
|
||||
static struct register_dict_pytype_ptr
|
||||
{
|
||||
register_dict_pytype_ptr()
|
||||
{
|
||||
const_cast<converter::registration &>(
|
||||
converter::registry::lookup(boost::python::type_id<boost::python::dict>())
|
||||
).m_class_object = &PyDict_Type;
|
||||
}
|
||||
}register_dict_pytype_ptr_;
|
||||
|
||||
}}} // namespace boost::python
|
||||
|
||||
10
src/list.cpp
10
src/list.cpp
@@ -137,4 +137,14 @@ long list_base::count(object_cref value) const
|
||||
return result;
|
||||
}
|
||||
|
||||
static struct register_list_pytype_ptr
|
||||
{
|
||||
register_list_pytype_ptr()
|
||||
{
|
||||
const_cast<converter::registration &>(
|
||||
converter::registry::lookup(boost::python::type_id<boost::python::list>())
|
||||
).m_class_object = &PyList_Type;
|
||||
}
|
||||
}register_list_pytype_ptr_;
|
||||
|
||||
}}} // namespace boost::python
|
||||
|
||||
@@ -114,6 +114,12 @@ namespace aux
|
||||
pytype_check(downcast<PyTypeObject>(array_type.get()), obj));
|
||||
}
|
||||
|
||||
PyTypeObject const* array_object_manager_traits::get_pytype()
|
||||
{
|
||||
load(false);
|
||||
if(!array_type) return 0;
|
||||
return handle<PyTypeObject>(array_type).get();
|
||||
}
|
||||
|
||||
# define BOOST_PYTHON_AS_OBJECT(z, n, _) object(x##n)
|
||||
# define BOOST_PP_LOCAL_MACRO(n) \
|
||||
|
||||
@@ -532,6 +532,10 @@ namespace objects
|
||||
if (scope().ptr() != Py_None)
|
||||
scope().attr(name) = result;
|
||||
|
||||
// For pickle. Will lead to informative error messages if pickling
|
||||
// is not enabled.
|
||||
result.attr("__reduce__") = object(make_instance_reduce_function());
|
||||
|
||||
return result;
|
||||
}
|
||||
}
|
||||
@@ -629,7 +633,6 @@ namespace objects
|
||||
|
||||
void class_base::enable_pickling_(bool getstate_manages_dict)
|
||||
{
|
||||
setattr("__reduce__", object(make_instance_reduce_function()));
|
||||
setattr("__safe_for_unpickling__", object(true));
|
||||
|
||||
if (getstate_manages_dict)
|
||||
|
||||
@@ -32,10 +32,11 @@ extern "C"
|
||||
{
|
||||
static PyObject* enum_repr(PyObject* self_)
|
||||
{
|
||||
const char *mod = PyString_AsString(PyObject_GetAttrString( self_, "__module__"));
|
||||
enum_object* self = downcast<enum_object>(self_);
|
||||
if (!self->name)
|
||||
{
|
||||
return PyString_FromFormat("%s(%ld)", self_->ob_type->tp_name, PyInt_AS_LONG(self_));
|
||||
return PyString_FromFormat("%s.%s(%ld)", mod, self_->ob_type->tp_name, PyInt_AS_LONG(self_));
|
||||
}
|
||||
else
|
||||
{
|
||||
@@ -43,7 +44,7 @@ extern "C"
|
||||
if (name == 0)
|
||||
return 0;
|
||||
|
||||
return PyString_FromFormat("%s.%s", self_->ob_type->tp_name, name);
|
||||
return PyString_FromFormat("%s.%s.%s", mod, self_->ob_type->tp_name, name);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -120,7 +121,7 @@ object module_prefix();
|
||||
|
||||
namespace
|
||||
{
|
||||
object new_enum_type(char const* name)
|
||||
object new_enum_type(char const* name, char const *doc)
|
||||
{
|
||||
if (enum_type_object.tp_dict == 0)
|
||||
{
|
||||
@@ -141,10 +142,11 @@ namespace
|
||||
|
||||
object module_name = module_prefix();
|
||||
if (module_name)
|
||||
module_name += '.';
|
||||
d["__module__"] = module_name;
|
||||
if (doc)
|
||||
d["__doc__"] = doc;
|
||||
|
||||
object result = (object(metatype))(
|
||||
module_name + name, make_tuple(base), d);
|
||||
object result = (object(metatype))(name, make_tuple(base), d);
|
||||
|
||||
scope().attr(name) = result;
|
||||
|
||||
@@ -158,8 +160,9 @@ enum_base::enum_base(
|
||||
, converter::convertible_function convertible
|
||||
, converter::constructor_function construct
|
||||
, type_info id
|
||||
, char const *doc
|
||||
)
|
||||
: object(new_enum_type(name))
|
||||
: object(new_enum_type(name, doc))
|
||||
{
|
||||
converter::registration& converters
|
||||
= const_cast<converter::registration&>(
|
||||
|
||||
@@ -6,6 +6,7 @@
|
||||
#include <boost/python/docstring_options.hpp>
|
||||
#include <boost/python/object/function_object.hpp>
|
||||
#include <boost/python/object/function_handle.hpp>
|
||||
#include <boost/python/object/function_doc_signature.hpp>
|
||||
#include <boost/python/errors.hpp>
|
||||
#include <boost/python/str.hpp>
|
||||
#include <boost/python/object_attributes.hpp>
|
||||
@@ -17,6 +18,7 @@
|
||||
#include <boost/python/ssize_t.hpp>
|
||||
|
||||
#include <boost/python/detail/signature.hpp>
|
||||
#include <boost/python/detail/none.hpp>
|
||||
#include <boost/mpl/vector/vector10.hpp>
|
||||
|
||||
#include <boost/bind.hpp>
|
||||
@@ -30,7 +32,12 @@
|
||||
|
||||
namespace boost { namespace python {
|
||||
volatile bool docstring_options::show_user_defined_ = true;
|
||||
volatile bool docstring_options::show_signatures_ = true;
|
||||
volatile bool docstring_options::show_cpp_signatures_ = true;
|
||||
#ifndef BOOST_PYTHON_NO_PY_SIGNATURES
|
||||
volatile bool docstring_options::show_py_signatures_ = true;
|
||||
#else
|
||||
volatile bool docstring_options::show_py_signatures_ = false;
|
||||
#endif
|
||||
}}
|
||||
|
||||
namespace boost { namespace python { namespace objects {
|
||||
@@ -411,6 +418,12 @@ void function::add_to_namespace(
|
||||
add_to_namespace(name_space, name_, attribute, 0);
|
||||
}
|
||||
|
||||
namespace detail
|
||||
{
|
||||
extern char py_signature_tag[];
|
||||
extern char cpp_signature_tag[];
|
||||
}
|
||||
|
||||
void function::add_to_namespace(
|
||||
object const& name_space, char const* name_, object const& attribute, char const* doc)
|
||||
{
|
||||
@@ -487,6 +500,7 @@ void function::add_to_namespace(
|
||||
throw_error_already_set();
|
||||
|
||||
object mutable_attribute(attribute);
|
||||
/*
|
||||
if (doc != 0 && docstring_options::show_user_defined_)
|
||||
{
|
||||
// Accumulate documentation
|
||||
@@ -507,7 +521,8 @@ void function::add_to_namespace(
|
||||
{
|
||||
if ( PyObject_HasAttrString(mutable_attribute.ptr(), "__doc__")
|
||||
&& mutable_attribute.attr("__doc__")) {
|
||||
mutable_attribute.attr("__doc__") += "\n";
|
||||
mutable_attribute.attr("__doc__") += (
|
||||
mutable_attribute.attr("__doc__")[-1] != "\n" ? "\n\n" : "\n");
|
||||
}
|
||||
else {
|
||||
mutable_attribute.attr("__doc__") = "";
|
||||
@@ -516,6 +531,25 @@ void function::add_to_namespace(
|
||||
mutable_attribute.attr("__doc__") += str("\n ").join(make_tuple(
|
||||
"C++ signature:", f->signature(true)));
|
||||
}
|
||||
*/
|
||||
str _doc;
|
||||
|
||||
if (docstring_options::show_py_signatures_)
|
||||
{
|
||||
_doc += str(const_cast<const char*>(detail::py_signature_tag));
|
||||
}
|
||||
if (doc != 0 && docstring_options::show_user_defined_)
|
||||
_doc += doc;
|
||||
|
||||
if (docstring_options::show_cpp_signatures_)
|
||||
{
|
||||
_doc += str(const_cast<const char*>(detail::cpp_signature_tag));
|
||||
}
|
||||
if(_doc)
|
||||
{
|
||||
object mutable_attribute(attribute);
|
||||
mutable_attribute.attr("__doc__")= _doc;
|
||||
}
|
||||
}
|
||||
|
||||
BOOST_PYTHON_DECL void add_to_namespace(
|
||||
@@ -590,7 +624,10 @@ extern "C"
|
||||
static PyObject* function_get_doc(PyObject* op, void*)
|
||||
{
|
||||
function* f = downcast<function>(op);
|
||||
return python::incref(f->doc().ptr());
|
||||
list signatures = function_doc_signature_generator::function_doc_signatures(f);
|
||||
if(!signatures) return python::detail::none();
|
||||
signatures.reverse();
|
||||
return python::incref( str("\n").join(signatures).ptr());
|
||||
}
|
||||
|
||||
static int function_set_doc(PyObject* op, PyObject* doc, void*)
|
||||
|
||||
342
src/object/function_doc_signature.cpp
Executable file
342
src/object/function_doc_signature.cpp
Executable file
@@ -0,0 +1,342 @@
|
||||
// Copyright Nikolay Mladenov 2007.
|
||||
// Distributed under the Boost Software License, Version 1.0. (See
|
||||
// accompanying file LICENSE_1_0.txt or copy at
|
||||
// http://www.boost.org/LICENSE_1_0.txt)
|
||||
|
||||
#include <boost/python/converter/registrations.hpp>
|
||||
#include <boost/python/object/function_doc_signature.hpp>
|
||||
#include <boost/python/errors.hpp>
|
||||
#include <boost/python/str.hpp>
|
||||
#include <boost/python/args.hpp>
|
||||
#include <boost/python/tuple.hpp>
|
||||
|
||||
#include <boost/python/detail/signature.hpp>
|
||||
|
||||
|
||||
#include <vector>
|
||||
|
||||
namespace boost { namespace python { namespace objects {
|
||||
|
||||
bool function_doc_signature_generator::arity_cmp( function const *f1, function const *f2 )
|
||||
{
|
||||
return f1->m_fn.max_arity() < f2->m_fn.max_arity();
|
||||
}
|
||||
|
||||
bool function_doc_signature_generator::are_seq_overloads( function const *f1, function const *f2 , bool check_docs)
|
||||
{
|
||||
py_function const & impl1 = f1->m_fn;
|
||||
py_function const & impl2 = f2->m_fn;
|
||||
|
||||
//the number of parameters differs by 1
|
||||
if (impl2.max_arity()-impl1.max_arity() != 1)
|
||||
return false;
|
||||
|
||||
// if check docs then f1 shold not have docstring or have the same docstring as f2
|
||||
if (check_docs && f2->doc() != f1->doc() && f1->doc())
|
||||
return false;
|
||||
|
||||
python::detail::signature_element const* s1 = impl1.signature();
|
||||
python::detail::signature_element const* s2 = impl2.signature();
|
||||
|
||||
unsigned size = impl1.max_arity()+1;
|
||||
|
||||
for (unsigned i = 0; i != size; ++i)
|
||||
{
|
||||
//check if the argument types are the same
|
||||
if (s1[i].basename != s2[i].basename)
|
||||
return false;
|
||||
|
||||
//return type
|
||||
if (!i) continue;
|
||||
|
||||
//check if the argument default values are the same
|
||||
bool f1_has_names = bool(f1->m_arg_names);
|
||||
bool f2_has_names = bool(f2->m_arg_names);
|
||||
if ( f1_has_names && f2_has_names && f2->m_arg_names[i-1]!=f1->m_arg_names[i-1]
|
||||
|| f1_has_names && !f2_has_names
|
||||
|| !f1_has_names && f2_has_names && f2->m_arg_names[i-1]!=python::object()
|
||||
)
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
std::vector<function const*> function_doc_signature_generator::flatten(function const *f)
|
||||
{
|
||||
object name = f->name();
|
||||
|
||||
std::vector<function const*> res;
|
||||
|
||||
while (f) {
|
||||
|
||||
//this if takes out the not_implemented_function
|
||||
if (f->name() == name)
|
||||
res.push_back(f);
|
||||
|
||||
f=f->m_overloads.get();
|
||||
}
|
||||
|
||||
//std::sort(res.begin(),res.end(), &arity_cmp);
|
||||
|
||||
return res;
|
||||
}
|
||||
std::vector<function const*> function_doc_signature_generator::split_seq_overloads( const std::vector<function const *> &funcs, bool split_on_doc_change)
|
||||
{
|
||||
std::vector<function const*> res;
|
||||
|
||||
std::vector<function const*>::const_iterator fi = funcs.begin();
|
||||
|
||||
function const * last = *fi;
|
||||
|
||||
while (++fi != funcs.end()){
|
||||
|
||||
//check if fi starts a new chain of overloads
|
||||
if (!are_seq_overloads( last, *fi, split_on_doc_change ))
|
||||
res.push_back(last);
|
||||
|
||||
last = *fi;
|
||||
}
|
||||
|
||||
if (last)
|
||||
res.push_back(last);
|
||||
|
||||
return res;
|
||||
}
|
||||
|
||||
str function_doc_signature_generator::raw_function_pretty_signature(function const *f, size_t n_overloads, bool cpp_types )
|
||||
{
|
||||
str res("object");
|
||||
|
||||
res = str("%s %s(%s)" % make_tuple( res, f->m_name, str("tuple args, dict kwds")) );
|
||||
|
||||
return res;
|
||||
}
|
||||
|
||||
const char * function_doc_signature_generator::py_type_str(const python::detail::signature_element &s)
|
||||
{
|
||||
if (s.basename==std::string("void")){
|
||||
static const char * none = "None";
|
||||
return none;
|
||||
}
|
||||
|
||||
PyTypeObject const * py_type = s.pytype_f?s.pytype_f():0;
|
||||
if ( py_type )
|
||||
return py_type->tp_name;
|
||||
else{
|
||||
static const char * object = "object";
|
||||
return object;
|
||||
}
|
||||
}
|
||||
|
||||
str function_doc_signature_generator::parameter_string(py_function const &f, size_t n, object arg_names, bool cpp_types)
|
||||
{
|
||||
str param;
|
||||
|
||||
python::detail::signature_element const * s = f.signature();
|
||||
if (cpp_types)
|
||||
{
|
||||
if(!n)
|
||||
s = &f.get_return_type();
|
||||
if (s[n].basename == 0)
|
||||
{
|
||||
return str("...");
|
||||
}
|
||||
|
||||
param = str(s[n].basename);
|
||||
|
||||
if (s[n].lvalue)
|
||||
param += " {lvalue}";
|
||||
|
||||
}
|
||||
else
|
||||
{
|
||||
if (n) //we are processing an argument and trying to come up with a name for it
|
||||
{
|
||||
object kv;
|
||||
if ( arg_names && (kv = arg_names[n-1]) )
|
||||
param = str( " (%s)%s" % make_tuple(py_type_str(s[n]),kv[0]) );
|
||||
else
|
||||
param = str(" (%s)%s%d" % make_tuple(py_type_str(s[n]),"arg", n) );
|
||||
}
|
||||
else //we are processing the return type
|
||||
param = py_type_str(f.get_return_type());
|
||||
}
|
||||
|
||||
//an argument - check for default value and append it
|
||||
if(n && arg_names)
|
||||
{
|
||||
object kv(arg_names[n-1]);
|
||||
if (kv && len(kv) == 2)
|
||||
{
|
||||
param = str("%s=%r" % make_tuple(param, kv[1]));
|
||||
}
|
||||
}
|
||||
return param;
|
||||
}
|
||||
|
||||
str function_doc_signature_generator::pretty_signature(function const *f, size_t n_overloads, bool cpp_types )
|
||||
{
|
||||
py_function
|
||||
const& impl = f->m_fn;
|
||||
;
|
||||
|
||||
|
||||
unsigned arity = impl.max_arity();
|
||||
|
||||
if(arity == unsigned(-1))// is this the proper raw function test?
|
||||
{
|
||||
return raw_function_pretty_signature(f,n_overloads,cpp_types);
|
||||
}
|
||||
|
||||
list formal_params;
|
||||
|
||||
size_t n_extra_default_args=0;
|
||||
|
||||
for (unsigned n = 0; n <= arity; ++n)
|
||||
{
|
||||
str param;
|
||||
|
||||
formal_params.append(
|
||||
parameter_string(impl, n, f->m_arg_names, cpp_types)
|
||||
);
|
||||
|
||||
// find all the arguments with default values preceeding the arity-n_overloads
|
||||
if (n && f->m_arg_names)
|
||||
{
|
||||
object kv(f->m_arg_names[n-1]);
|
||||
|
||||
if (kv && len(kv) == 2)
|
||||
{
|
||||
//default argument preceeding the arity-n_overloads
|
||||
if( n <= arity-n_overloads)
|
||||
++n_extra_default_args;
|
||||
}
|
||||
else
|
||||
//argument without default, preceeding the arity-n_overloads
|
||||
if( n <= arity-n_overloads)
|
||||
n_extra_default_args = 0;
|
||||
}
|
||||
}
|
||||
|
||||
n_overloads+=n_extra_default_args;
|
||||
|
||||
if (!arity && cpp_types)
|
||||
formal_params.append("void");
|
||||
|
||||
str ret_type (formal_params.pop(0));
|
||||
if (cpp_types )
|
||||
{
|
||||
return str(
|
||||
"%s %s(%s%s%s%s)"
|
||||
% make_tuple
|
||||
( ret_type
|
||||
, f->m_name
|
||||
, str(",").join(formal_params.slice(0,arity-n_overloads))
|
||||
, n_overloads ? (n_overloads!=arity?str(" [,"):str("[ ")) : str()
|
||||
, str(" [,").join(formal_params.slice(arity-n_overloads,arity))
|
||||
, std::string(n_overloads,']')
|
||||
));
|
||||
}else{
|
||||
return str(
|
||||
"%s(%s%s%s%s) -> %s"
|
||||
% make_tuple
|
||||
( f->m_name
|
||||
, str(",").join(formal_params.slice(0,arity-n_overloads))
|
||||
, n_overloads ? (n_overloads!=arity?str(" [,"):str("[ ")) : str()
|
||||
, str(" [,").join(formal_params.slice(arity-n_overloads,arity))
|
||||
, std::string(n_overloads,']')
|
||||
, ret_type
|
||||
));
|
||||
}
|
||||
|
||||
return str(
|
||||
"%s %s(%s%s%s%s) %s"
|
||||
% make_tuple
|
||||
( cpp_types?ret_type:str("")
|
||||
, f->m_name
|
||||
, str(",").join(formal_params.slice(0,arity-n_overloads))
|
||||
, n_overloads ? (n_overloads!=arity?str(" [,"):str("[ ")) : str()
|
||||
, str(" [,").join(formal_params.slice(arity-n_overloads,arity))
|
||||
, std::string(n_overloads,']')
|
||||
, cpp_types?str(""):ret_type
|
||||
));
|
||||
|
||||
}
|
||||
|
||||
namespace detail {
|
||||
char py_signature_tag[] = "PY signature :";
|
||||
char cpp_signature_tag[] = "C++ signature :";
|
||||
}
|
||||
|
||||
list function_doc_signature_generator::function_doc_signatures( function const * f)
|
||||
{
|
||||
list signatures;
|
||||
std::vector<function const*> funcs = flatten( f);
|
||||
std::vector<function const*> split_funcs = split_seq_overloads( funcs, true);
|
||||
std::vector<function const*>::const_iterator sfi=split_funcs.begin(), fi;
|
||||
size_t n_overloads=0;
|
||||
for (fi=funcs.begin(); fi!=funcs.end(); ++fi)
|
||||
{
|
||||
if(*sfi == *fi){
|
||||
if((*fi)->doc())
|
||||
{
|
||||
str func_doc = str((*fi)->doc());
|
||||
|
||||
int doc_len = len(func_doc);
|
||||
|
||||
bool show_py_signature = doc_len >= int(sizeof(detail::py_signature_tag)/sizeof(char)-1)
|
||||
&& str(detail::py_signature_tag) == func_doc.slice(0, int(sizeof(detail::py_signature_tag)/sizeof(char))-1);
|
||||
if(show_py_signature)
|
||||
{
|
||||
func_doc = str(func_doc.slice(int(sizeof(detail::py_signature_tag)/sizeof(char))-1, _));
|
||||
doc_len = len(func_doc);
|
||||
}
|
||||
|
||||
bool show_cpp_signature = doc_len >= int(sizeof(detail::cpp_signature_tag)/sizeof(char)-1)
|
||||
&& str(detail::cpp_signature_tag) == func_doc.slice( 1-int(sizeof(detail::cpp_signature_tag)/sizeof(char)), _);
|
||||
|
||||
if(show_cpp_signature)
|
||||
{
|
||||
func_doc = str(func_doc.slice(_, 1-int(sizeof(detail::cpp_signature_tag)/sizeof(char))));
|
||||
doc_len = len(func_doc);
|
||||
}
|
||||
|
||||
str res="\n";
|
||||
str pad = "\n";
|
||||
|
||||
if(show_py_signature)
|
||||
{
|
||||
str sig = pretty_signature(*fi, n_overloads,false);
|
||||
res+=sig;
|
||||
if(doc_len || show_cpp_signature )res+=" :";
|
||||
pad+= str(" ");
|
||||
}
|
||||
|
||||
if(doc_len)
|
||||
{
|
||||
if(show_py_signature)
|
||||
res+=pad;
|
||||
res+= pad.join(func_doc.split("\n"));
|
||||
}
|
||||
|
||||
if( show_cpp_signature)
|
||||
{
|
||||
if(len(res)>1)
|
||||
res+="\n"+pad;
|
||||
res+=detail::cpp_signature_tag+pad+" "+pretty_signature(*fi, n_overloads,true);
|
||||
}
|
||||
|
||||
signatures.append(res);
|
||||
}
|
||||
++sfi;
|
||||
n_overloads = 0;
|
||||
}else
|
||||
++n_overloads ;
|
||||
}
|
||||
|
||||
return signatures;
|
||||
}
|
||||
|
||||
|
||||
}}}
|
||||
|
||||
@@ -8,6 +8,7 @@
|
||||
#include <boost/python/tuple.hpp>
|
||||
#include <boost/python/list.hpp>
|
||||
#include <boost/python/dict.hpp>
|
||||
#include <boost/python/str.hpp>
|
||||
|
||||
namespace boost { namespace python {
|
||||
|
||||
@@ -19,6 +20,22 @@ namespace {
|
||||
object instance_class(instance_obj.attr("__class__"));
|
||||
result.append(instance_class);
|
||||
object none;
|
||||
if (!getattr(instance_obj, "__safe_for_unpickling__", none))
|
||||
{
|
||||
str type_name(getattr(instance_class, "__name__"));
|
||||
str module_name(getattr(instance_class, "__module__", object("")));
|
||||
if (module_name)
|
||||
module_name += ".";
|
||||
|
||||
PyErr_SetObject(
|
||||
PyExc_RuntimeError,
|
||||
( "Pickling of \"%s\" instances is not enabled"
|
||||
" (http://www.boost.org/libs/python/doc/v2/pickle.html)"
|
||||
% (module_name+type_name)).ptr()
|
||||
);
|
||||
|
||||
throw_error_already_set();
|
||||
}
|
||||
object getinitargs = getattr(instance_obj, "__getinitargs__", none);
|
||||
tuple initargs;
|
||||
if (getinitargs.ptr() != none.ptr()) {
|
||||
|
||||
10
src/str.cpp
10
src/str.cpp
@@ -349,5 +349,15 @@ BOOST_PYTHON_DEFINE_STR_METHOD(title, 0)
|
||||
BOOST_PYTHON_DEFINE_STR_METHOD(translate, 1)
|
||||
BOOST_PYTHON_DEFINE_STR_METHOD(translate, 2)
|
||||
BOOST_PYTHON_DEFINE_STR_METHOD(upper, 0)
|
||||
|
||||
static struct register_str_pytype_ptr
|
||||
{
|
||||
register_str_pytype_ptr()
|
||||
{
|
||||
const_cast<converter::registration &>(
|
||||
converter::registry::lookup(boost::python::type_id<boost::python::str>())
|
||||
).m_class_object = &PyString_Type;
|
||||
}
|
||||
}register_str_pytype_ptr_;
|
||||
|
||||
}}} // namespace boost::python
|
||||
|
||||
@@ -21,4 +21,15 @@ tuple_base::tuple_base(object_cref sequence)
|
||||
: object(call(sequence))
|
||||
{}
|
||||
|
||||
static struct register_tuple_pytype_ptr
|
||||
{
|
||||
register_tuple_pytype_ptr()
|
||||
{
|
||||
const_cast<converter::registration &>(
|
||||
converter::registry::lookup(boost::python::type_id<boost::python::tuple>())
|
||||
).m_class_object = &PyTuple_Type;
|
||||
}
|
||||
}register_tuple_pytype_ptr_;
|
||||
|
||||
|
||||
}}} // namespace boost::python
|
||||
|
||||
@@ -2,12 +2,20 @@
|
||||
# Software License, Version 1.0. (See accompanying
|
||||
# file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
|
||||
|
||||
import python ;
|
||||
|
||||
use-project /boost/python : ../build ;
|
||||
project /boost/python/test ;
|
||||
|
||||
local PY = ;
|
||||
if [ python.configured ]
|
||||
{
|
||||
PY = /python//python ;
|
||||
}
|
||||
|
||||
rule py-run ( sources * : input-file ? )
|
||||
{
|
||||
return [ run $(sources) /boost/python//boost_python /python//python
|
||||
return [ run $(sources) /boost/python//boost_python $(PY)
|
||||
: # args
|
||||
: $(input-file)
|
||||
: #requirements
|
||||
@@ -31,7 +39,7 @@ test-suite python
|
||||
:
|
||||
|
||||
[
|
||||
run exec.cpp ../build//boost_python/<link>static /python//python
|
||||
run exec.cpp ../build//boost_python/<link>static $(PY)
|
||||
: # program args
|
||||
: exec.py # input files
|
||||
: # requirements
|
||||
@@ -76,7 +84,7 @@ bpl-test crossmod_exception
|
||||
[ bpl-test minimal ]
|
||||
[ bpl-test args ]
|
||||
[ bpl-test raw_ctor ]
|
||||
[ bpl-test numpy : numpy.py printer.py numeric_tests.py numarray_tests.py numpy.cpp ]
|
||||
[ bpl-test numpy : printer.py numeric_tests.py numarray_tests.py numpy.py numpy.cpp ]
|
||||
[ bpl-test enum ]
|
||||
[ bpl-test exception_translator ]
|
||||
[ bpl-test pearu1 : test_cltree.py cltree.cpp ]
|
||||
@@ -90,6 +98,7 @@ bpl-test crossmod_exception
|
||||
|
||||
[ bpl-test test_pointer_adoption ]
|
||||
[ bpl-test operators ]
|
||||
[ bpl-test operators_wrapper ]
|
||||
[ bpl-test callbacks ]
|
||||
[ bpl-test defaults ]
|
||||
|
||||
@@ -142,6 +151,7 @@ bpl-test crossmod_opaque
|
||||
[ bpl-test nested ]
|
||||
|
||||
[ bpl-test docstring ]
|
||||
[ bpl-test pytype_function ]
|
||||
|
||||
[ bpl-test vector_indexing_suite ]
|
||||
|
||||
@@ -154,11 +164,12 @@ bpl-test crossmod_opaque
|
||||
<toolset>hp_cxx:<build>no ]
|
||||
|
||||
[ python-extension map_indexing_suite_ext
|
||||
: map_indexing_suite.cpp int_map_indexing_suite.cpp
|
||||
: map_indexing_suite.cpp int_map_indexing_suite.cpp a_map_indexing_suite.cpp
|
||||
/boost/python//boost_python ]
|
||||
[ bpl-test
|
||||
map_indexing_suite : map_indexing_suite.py map_indexing_suite_ext ]
|
||||
|
||||
[ py-run import_.cpp : import_.py ]
|
||||
|
||||
# if $(TEST_BIENSTMAN_NON_BUGS)
|
||||
# {
|
||||
# bpl-test bienstman4 ;
|
||||
@@ -188,7 +199,7 @@ bpl-test crossmod_opaque
|
||||
:
|
||||
:
|
||||
: <define>BOOST_PYTHON_STATIC_LIB
|
||||
<use>/python//python
|
||||
<use>$(PY)
|
||||
|
||||
]
|
||||
|
||||
|
||||
84
test/a_map_indexing_suite.cpp
Executable file
84
test/a_map_indexing_suite.cpp
Executable file
@@ -0,0 +1,84 @@
|
||||
// Copyright Joel de Guzman 2004. Distributed under the Boost
|
||||
// Software License, Version 1.0. (See accompanying
|
||||
// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
|
||||
|
||||
#include <boost/python/suite/indexing/map_indexing_suite.hpp>
|
||||
#include <boost/python/module.hpp>
|
||||
#include <boost/python/def.hpp>
|
||||
#include <boost/python/implicit.hpp>
|
||||
|
||||
using namespace boost::python;
|
||||
|
||||
struct A
|
||||
{
|
||||
int value;
|
||||
A() : value(0){};
|
||||
A(int v) : value(v) {};
|
||||
};
|
||||
|
||||
bool operator==(const A& v1, const A& v2)
|
||||
{
|
||||
return (v1.value == v2.value);
|
||||
}
|
||||
|
||||
struct B
|
||||
{
|
||||
A a;
|
||||
};
|
||||
|
||||
// Converter from A to python int
|
||||
struct AToPython
|
||||
{
|
||||
static PyObject* convert(const A& s)
|
||||
{
|
||||
return boost::python::incref(boost::python::object((int)s.value).ptr());
|
||||
}
|
||||
};
|
||||
|
||||
// Conversion from python int to A
|
||||
struct AFromPython
|
||||
{
|
||||
AFromPython()
|
||||
{
|
||||
boost::python::converter::registry::push_back(
|
||||
&convertible,
|
||||
&construct,
|
||||
boost::python::type_id< A >());
|
||||
}
|
||||
|
||||
static void* convertible(PyObject* obj_ptr)
|
||||
{
|
||||
if (!PyInt_Check(obj_ptr)) return 0;
|
||||
return obj_ptr;
|
||||
}
|
||||
|
||||
static void construct(
|
||||
PyObject* obj_ptr,
|
||||
boost::python::converter::rvalue_from_python_stage1_data* data)
|
||||
{
|
||||
void* storage = (
|
||||
(boost::python::converter::rvalue_from_python_storage< A >*)
|
||||
data)-> storage.bytes;
|
||||
|
||||
new (storage) A((int)PyInt_AsLong(obj_ptr));
|
||||
data->convertible = storage;
|
||||
}
|
||||
};
|
||||
|
||||
void a_map_indexing_suite()
|
||||
{
|
||||
|
||||
to_python_converter< A , AToPython >();
|
||||
AFromPython();
|
||||
|
||||
class_< std::map<int, A> >("AMap")
|
||||
.def(map_indexing_suite<std::map<int, A>, true >())
|
||||
;
|
||||
|
||||
class_< B >("B")
|
||||
.add_property("a", make_getter(&B::a, return_value_policy<return_by_value>()),
|
||||
make_setter(&B::a, return_value_policy<return_by_value>()))
|
||||
;
|
||||
}
|
||||
|
||||
|
||||
@@ -51,7 +51,7 @@ tuple raw_func(tuple args, dict kw)
|
||||
|
||||
BOOST_PYTHON_MODULE(args_ext)
|
||||
{
|
||||
def("f", f, args("x", "y", "z")
|
||||
def("f", f, (arg("x")=1, arg("y")=4.25, arg("z")="wow")
|
||||
, "This is f's docstring"
|
||||
);
|
||||
|
||||
@@ -72,23 +72,24 @@ BOOST_PYTHON_MODULE(args_ext)
|
||||
.def("raw", raw_function(raw_func))
|
||||
;
|
||||
|
||||
class_<X>("X", "This is X's docstring")
|
||||
.def(init<int, optional<int> >(args("a0", "a1")))
|
||||
class_<X>("X", "This is X's docstring", init<>(args("self")))
|
||||
.def(init<int, optional<int> >(args("self", "a0", "a1")))
|
||||
.def("f", &X::f
|
||||
, "This is X.f's docstring"
|
||||
, args("x", "y", "z"))
|
||||
, args("self","x", "y", "z"))
|
||||
|
||||
// Just to prove that all the different argument combinations work
|
||||
.def("inner0", &X::inner, return_internal_reference<>(), args("n"), "docstring")
|
||||
.def("inner1", &X::inner, return_internal_reference<>(), "docstring", args("n"))
|
||||
.def("inner0", &X::inner, return_internal_reference<>(), args("self", "n"), "docstring")
|
||||
.def("inner1", &X::inner, return_internal_reference<>(), "docstring", args("self", "n"))
|
||||
|
||||
.def("inner2", &X::inner, args("n"), return_internal_reference<>(), "docstring")
|
||||
.def("inner3", &X::inner, "docstring", return_internal_reference<>(), args("n"))
|
||||
.def("inner2", &X::inner, args("self", "n"), return_internal_reference<>(), "docstring")
|
||||
.def("inner3", &X::inner, "docstring", return_internal_reference<>(), args("self", "n"))
|
||||
|
||||
.def("inner4", &X::inner, args("n"), "docstring", return_internal_reference<>())
|
||||
.def("inner5", &X::inner, "docstring", args("n"), return_internal_reference<>())
|
||||
.def("inner4", &X::inner, args("self", "n"), "docstring", return_internal_reference<>())
|
||||
.def("inner5", &X::inner, "docstring", args("self", "n"), return_internal_reference<>())
|
||||
|
||||
.def("f1", &X::f, X_f_overloads(args("x", "y", "z")))
|
||||
.def("f1", &X::f, X_f_overloads(args("self", "x", "y", "z")))
|
||||
.def("f2", &X::f, X_f_overloads(args("self", "x", "y", "z"), "f2's docstring"))
|
||||
.def("f2", &X::f, X_f_overloads(args("x", "y", "z"), "f2's docstring"))
|
||||
;
|
||||
|
||||
|
||||
67
test/args.py
67
test/args.py
@@ -84,22 +84,27 @@
|
||||
(2, 4.25, 'wow')
|
||||
>>> q.f1()
|
||||
(1, 4.25, 'wow')
|
||||
>>> q.f2.__doc__.splitlines()[1]
|
||||
'f2( (X)self [, (int)x [, (float)y [, (str)z]]]) -> tuple :'
|
||||
|
||||
>>> X.f.__doc__.splitlines()[:2]
|
||||
["This is X.f's docstring", 'C++ signature:']
|
||||
>>> q.f2.__doc__.splitlines()[2]
|
||||
" f2's docstring"
|
||||
|
||||
>>> X.f.__doc__.splitlines()[1:5]
|
||||
['f( (X)self, (int)x, (float)y, (str)z) -> tuple :', " This is X.f's docstring", '', ' C++ signature :']
|
||||
|
||||
>>> xfuncs = (X.inner0, X.inner1, X.inner2, X.inner3, X.inner4, X.inner5)
|
||||
>>> for f in xfuncs:
|
||||
... print f(q,1).value(),
|
||||
... print f(q, n = 1).value(),
|
||||
... print f(q, n = 0).value(),
|
||||
... print f.__doc__.splitlines()[:2]
|
||||
1 1 0 ['docstring', 'C++ signature:']
|
||||
1 1 0 ['docstring', 'C++ signature:']
|
||||
1 1 0 ['docstring', 'C++ signature:']
|
||||
1 1 0 ['docstring', 'C++ signature:']
|
||||
1 1 0 ['docstring', 'C++ signature:']
|
||||
1 1 0 ['docstring', 'C++ signature:']
|
||||
... print f.__doc__.splitlines()[1:5]
|
||||
1 1 0 ['inner0( (X)self, (bool)n) -> Y :', ' docstring', '', ' C++ signature :']
|
||||
1 1 0 ['inner1( (X)self, (bool)n) -> Y :', ' docstring', '', ' C++ signature :']
|
||||
1 1 0 ['inner2( (X)self, (bool)n) -> Y :', ' docstring', '', ' C++ signature :']
|
||||
1 1 0 ['inner3( (X)self, (bool)n) -> Y :', ' docstring', '', ' C++ signature :']
|
||||
1 1 0 ['inner4( (X)self, (bool)n) -> Y :', ' docstring', '', ' C++ signature :']
|
||||
1 1 0 ['inner5( (X)self, (bool)n) -> Y :', ' docstring', '', ' C++ signature :']
|
||||
|
||||
>>> x = X(a1 = 44, a0 = 22)
|
||||
>>> x.inner0(0).value()
|
||||
@@ -134,49 +139,9 @@ if __name__ == '__main__':
|
||||
import sys
|
||||
status = run()[0]
|
||||
if (status == 0): print "Done."
|
||||
import args_ext
|
||||
help(args_ext)
|
||||
sys.exit(status)
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
@@ -64,6 +64,24 @@
|
||||
... except TypeError: pass
|
||||
... else: print 'expected a TypeError exception'
|
||||
|
||||
>>> print look.__doc__.splitlines()[1]
|
||||
look( (X)arg1) -> int :
|
||||
|
||||
>>> print steal.__doc__.splitlines()[1]
|
||||
steal( (X)arg1) -> int :
|
||||
|
||||
>>> print maybe_steal.__doc__.splitlines()[1]
|
||||
maybe_steal( (X)arg1, (bool)arg2) -> int :
|
||||
|
||||
>>> print make.__doc__.splitlines()[1]
|
||||
make() -> X :
|
||||
|
||||
>>> print callback.__doc__.splitlines()[1]
|
||||
callback( (object)arg1) -> X :
|
||||
|
||||
>>> print extract.__doc__.splitlines()[1]
|
||||
extract( (object)arg1) -> X :
|
||||
|
||||
'''
|
||||
|
||||
def run(args = None):
|
||||
|
||||
@@ -16,6 +16,9 @@
|
||||
>>> assert y_identity(y) is y
|
||||
>>> y_equality(y, y)
|
||||
1
|
||||
|
||||
>>> print y_identity.__doc__.splitlines()[1]
|
||||
y_identity( (Y)arg1) -> object :
|
||||
'''
|
||||
|
||||
def run(args = None):
|
||||
|
||||
@@ -12,6 +12,7 @@
|
||||
#include <boost/python/reference_existing_object.hpp>
|
||||
#include <boost/python/call.hpp>
|
||||
#include <boost/python/object.hpp>
|
||||
#define BOOST_ENABLE_ASSERT_HANDLER
|
||||
#include <boost/assert.hpp>
|
||||
|
||||
using namespace boost::python;
|
||||
|
||||
@@ -52,7 +52,7 @@ int Var::static1 = 0;
|
||||
Y Var::static2(0);
|
||||
|
||||
// Compilability regression tests
|
||||
namespace
|
||||
namespace boost_python_test
|
||||
{
|
||||
struct trivial
|
||||
{
|
||||
@@ -86,6 +86,7 @@ namespace
|
||||
|
||||
BOOST_PYTHON_MODULE(data_members_ext)
|
||||
{
|
||||
using namespace boost_python_test;
|
||||
class_<X>("X", init<int>())
|
||||
.def("value", &X::value)
|
||||
.def("set", &X::set)
|
||||
|
||||
@@ -159,10 +159,10 @@ BOOST_PYTHON_MODULE(defaults_ext)
|
||||
.def("get_state", &Y::get_state)
|
||||
;
|
||||
|
||||
class_<X>("X")
|
||||
class_<X>("X",no_init)
|
||||
|
||||
.def(init<int, optional<char, std::string, double> >("doc of init"))
|
||||
.def(init<std::string, bool>()[default_call_policies()]) // what's a good policy here?
|
||||
.def(init<optional<int, char, std::string, double> >("doc of init", args("self", "a", "b", "c", "d")))
|
||||
.def(init<std::string, bool>(args("self", "s", "b"))[default_call_policies()]) // what's a good policy here?
|
||||
.def("get_state", &X::get_state)
|
||||
.def("bar", &X::bar, X_bar_stubs())
|
||||
.def("bar2", &X::bar2, X_bar_stubs2("doc of X::bar2")[return_internal_reference<>()])
|
||||
|
||||
@@ -113,28 +113,22 @@
|
||||
... doc = obj.__doc__.splitlines()
|
||||
... return "\\n".join(["|"+doc[i] for i in args])
|
||||
|
||||
>>> print selected_doc(X.__init__, 0, 2, 4, 6, 8, 9, 10, 12)
|
||||
|C++ signature:
|
||||
|C++ signature:
|
||||
|C++ signature:
|
||||
|C++ signature:
|
||||
|
|
||||
|doc of init
|
||||
|C++ signature:
|
||||
|C++ signature:
|
||||
>>> print selected_doc(X.__init__, 1, 2, 4, 7, 9)
|
||||
|__init__( (object)self [, (int)a [, (str)b [, (str)c [, (float)d]]]]) -> None :
|
||||
| doc of init
|
||||
| C++ signature :
|
||||
|__init__( (object)self, (str)s, (bool)b) -> None :
|
||||
| C++ signature :
|
||||
|
||||
>>> print selected_doc(Y.__init__, 0, 1)
|
||||
|doc of Y init
|
||||
|C++ signature:
|
||||
>>> print selected_doc(Y.__init__, 1, 2, 4)
|
||||
|__init__( (object)arg1) -> None :
|
||||
| doc of Y init
|
||||
| C++ signature :
|
||||
|
||||
>>> print selected_doc(X.bar2, 0, 2, 4, 6, 8, 9, 10)
|
||||
|C++ signature:
|
||||
|C++ signature:
|
||||
|C++ signature:
|
||||
|C++ signature:
|
||||
|
|
||||
|doc of X::bar2
|
||||
|C++ signature:
|
||||
>>> print selected_doc(X.bar2, 1, 2, 4)
|
||||
|bar2( (X)arg1 [, (int)arg2 [, (str)arg3 [, (str)arg4 [, (float)arg5]]]]) -> Y :
|
||||
| doc of X::bar2
|
||||
| C++ signature :
|
||||
|
||||
"""
|
||||
def run(args = None):
|
||||
|
||||
@@ -43,55 +43,74 @@ BOOST_PYTHON_MODULE(docstring_ext)
|
||||
, init<int>(
|
||||
"this is the __init__ function\n"
|
||||
"its documentation has two lines."
|
||||
, args("self", "value")
|
||||
)
|
||||
|
||||
)
|
||||
.def("value", &X::value,
|
||||
"gets the value of the object")
|
||||
"gets the value of the object"
|
||||
, args("self"))
|
||||
.def( "value", &X::value,
|
||||
"also gets the value of the object")
|
||||
"also gets the value of the object"
|
||||
, args("self"))
|
||||
;
|
||||
|
||||
def("create", create, return_value_policy<manage_new_object>(),
|
||||
"creates a new X object");
|
||||
"creates a new X object", args("value"));
|
||||
|
||||
def("fact", fact, "compute the factorial");
|
||||
def("fact", fact, "compute the factorial", args("n"));
|
||||
|
||||
{
|
||||
docstring_options doc_options;
|
||||
doc_options.disable_user_defined();
|
||||
def("fact_usr_off_1", fact, "usr off 1");
|
||||
def("fact_usr_off_1", fact, "usr off 1", args("n"));
|
||||
doc_options.enable_user_defined();
|
||||
def("fact_usr_on_1", fact, "usr on 1");
|
||||
def("fact_usr_on_1", fact, "usr on 1", args("n"));
|
||||
doc_options.disable_user_defined();
|
||||
def("fact_usr_off_2", fact, "usr off 2");
|
||||
def("fact_usr_off_2", fact, "usr off 2", args("n"));
|
||||
}
|
||||
def("fact_usr_on_2", fact, "usr on 2");
|
||||
def("fact_usr_on_2", fact, "usr on 2", args("n"));
|
||||
|
||||
{
|
||||
docstring_options doc_options(true, false);
|
||||
def("fact_sig_off_1", fact, "sig off 1");
|
||||
def("fact_sig_off_1", fact, "sig off 1", args("n"));
|
||||
doc_options.enable_signatures();
|
||||
def("fact_sig_on_1", fact, "sig on 1");
|
||||
def("fact_sig_on_1", fact, "sig on 1", args("n"));
|
||||
doc_options.disable_signatures();
|
||||
def("fact_sig_off_2", fact, "sig off 2");
|
||||
def("fact_sig_off_2", fact, "sig off 2", args("n"));
|
||||
}
|
||||
def("fact_sig_on_2", fact, "sig on 2");
|
||||
def("fact_sig_on_2", fact, "sig on 2", args("n"));
|
||||
|
||||
{
|
||||
docstring_options doc_options(false);
|
||||
def("fact_usr_off_sig_off_1", fact, "usr off sig off 1");
|
||||
def("fact_usr_off_sig_off_1", fact, "usr off sig off 1", args("n"));
|
||||
{
|
||||
docstring_options nested_doc_options;
|
||||
def("fact_usr_on_sig_on_1", fact, "usr on sig on 1");
|
||||
def("fact_usr_on_sig_on_1", fact, "usr on sig on 1", args("n"));
|
||||
nested_doc_options.disable_all();
|
||||
nested_doc_options.enable_user_defined();
|
||||
def("fact_usr_on_sig_off_1", fact, "usr on sig off 1");
|
||||
def("fact_usr_on_sig_off_1", fact, "usr on sig off 1", args("n"));
|
||||
nested_doc_options.enable_all();
|
||||
def("fact_usr_on_sig_on_2", fact, "usr on sig on 2");
|
||||
def("fact_usr_on_sig_on_2", fact, "usr on sig on 2", args("n"));
|
||||
}
|
||||
def("fact_usr_off_sig_off_2", fact, "usr off sig off 2");
|
||||
def("fact_usr_off_sig_off_2", fact, "usr off sig off 2", args("n"));
|
||||
}
|
||||
|
||||
{
|
||||
docstring_options doc_options(true);
|
||||
doc_options.disable_cpp_signatures();
|
||||
def("fact_usr_on_psig_on_csig_off_1", fact, "usr on psig on csig off 1", args("n"));
|
||||
doc_options.enable_cpp_signatures();
|
||||
doc_options.disable_py_signatures();
|
||||
def("fact_usr_on_psig_off_csig_on_1", fact, "usr on psig off csig on 1", args("n"));
|
||||
doc_options.enable_py_signatures();
|
||||
doc_options.disable_user_defined();
|
||||
doc_options.disable_cpp_signatures();
|
||||
def("fact_usr_off_psig_on_csig_off_1", fact, "usr off psig on csig off 1", args("n"));
|
||||
doc_options.enable_cpp_signatures();
|
||||
doc_options.disable_py_signatures();
|
||||
def("fact_usr_off_psig_off_csig_on_1", fact, "usr off psig off csig on 1", args("n"));
|
||||
}
|
||||
}
|
||||
|
||||
#include "module_tail.cpp"
|
||||
|
||||
@@ -8,82 +8,114 @@
|
||||
... doc = obj.__doc__.splitlines()
|
||||
... return "\\n".join(["|"+doc[i] for i in args])
|
||||
|
||||
>>> print selected_doc(X.__init__, 0, 1, 2)
|
||||
|this is the __init__ function
|
||||
|its documentation has two lines.
|
||||
|C++ signature:
|
||||
|
||||
>>> print selected_doc(X.value, 0, 1, 3, 4, 5)
|
||||
|gets the value of the object
|
||||
|C++ signature:
|
||||
>>> print selected_doc(X.__init__, 1, 2, 3, 4, 5)
|
||||
|__init__( (object)self, (int)value) -> None :
|
||||
| this is the __init__ function
|
||||
| its documentation has two lines.
|
||||
|
|
||||
|also gets the value of the object
|
||||
|C++ signature:
|
||||
| C++ signature :
|
||||
|
||||
>>> print selected_doc(create, 0, 1)
|
||||
|creates a new X object
|
||||
|C++ signature:
|
||||
>>> print selected_doc(X.value, 1, 2, 4, 7, 8, 10)
|
||||
|value( (X)self) -> int :
|
||||
| gets the value of the object
|
||||
| C++ signature :
|
||||
|value( (X)self) -> int :
|
||||
| also gets the value of the object
|
||||
| C++ signature :
|
||||
|
||||
>>> print selected_doc(fact, 0, 1)
|
||||
|compute the factorial
|
||||
|C++ signature:
|
||||
>>> print selected_doc(create, 1, 2, 3, 4)
|
||||
|create( (int)value) -> X :
|
||||
| creates a new X object
|
||||
|
|
||||
| C++ signature :
|
||||
|
||||
>>> print selected_doc(fact, 1, 2, 3, 4)
|
||||
|fact( (int)n) -> int :
|
||||
| compute the factorial
|
||||
|
|
||||
| C++ signature :
|
||||
|
||||
>>> len(fact_usr_off_1.__doc__.splitlines())
|
||||
2
|
||||
>>> print selected_doc(fact_usr_off_1, 0)
|
||||
|C++ signature:
|
||||
5
|
||||
>>> print selected_doc(fact_usr_off_1, 1, 3)
|
||||
|fact_usr_off_1( (int)n) -> int :
|
||||
| C++ signature :
|
||||
>>> len(fact_usr_on_1.__doc__.splitlines())
|
||||
3
|
||||
>>> print selected_doc(fact_usr_on_1, 0, 1)
|
||||
|usr on 1
|
||||
|C++ signature:
|
||||
6
|
||||
>>> print selected_doc(fact_usr_on_1, 1, 2, 4)
|
||||
|fact_usr_on_1( (int)n) -> int :
|
||||
| usr on 1
|
||||
| C++ signature :
|
||||
>>> len(fact_usr_off_2.__doc__.splitlines())
|
||||
2
|
||||
>>> print selected_doc(fact_usr_off_2, 0)
|
||||
|C++ signature:
|
||||
5
|
||||
>>> print selected_doc(fact_usr_off_2, 1, 3)
|
||||
|fact_usr_off_2( (int)n) -> int :
|
||||
| C++ signature :
|
||||
>>> len(fact_usr_on_2.__doc__.splitlines())
|
||||
3
|
||||
>>> print selected_doc(fact_usr_on_2, 0, 1)
|
||||
|usr on 2
|
||||
|C++ signature:
|
||||
6
|
||||
>>> print selected_doc(fact_usr_on_2, 1, 2, 4)
|
||||
|fact_usr_on_2( (int)n) -> int :
|
||||
| usr on 2
|
||||
| C++ signature :
|
||||
|
||||
|
||||
>>> len(fact_sig_off_1.__doc__.splitlines())
|
||||
1
|
||||
>>> print selected_doc(fact_sig_off_1, 0)
|
||||
2
|
||||
>>> print selected_doc(fact_sig_off_1, 1)
|
||||
|sig off 1
|
||||
>>> len(fact_sig_on_1.__doc__.splitlines())
|
||||
3
|
||||
>>> print selected_doc(fact_sig_on_1, 0, 1)
|
||||
|sig on 1
|
||||
|C++ signature:
|
||||
6
|
||||
>>> print selected_doc(fact_sig_on_1, 1, 2, 4)
|
||||
|fact_sig_on_1( (int)n) -> int :
|
||||
| sig on 1
|
||||
| C++ signature :
|
||||
|
||||
>>> len(fact_sig_off_2.__doc__.splitlines())
|
||||
1
|
||||
>>> print selected_doc(fact_sig_off_2, 0)
|
||||
2
|
||||
>>> print selected_doc(fact_sig_off_2, 1)
|
||||
|sig off 2
|
||||
>>> len(fact_sig_on_2.__doc__.splitlines())
|
||||
3
|
||||
>>> print selected_doc(fact_sig_on_2, 0, 1)
|
||||
|sig on 2
|
||||
|C++ signature:
|
||||
6
|
||||
>>> print selected_doc(fact_sig_on_2, 1, 2, 4)
|
||||
|fact_sig_on_2( (int)n) -> int :
|
||||
| sig on 2
|
||||
| C++ signature :
|
||||
|
||||
|
||||
>>> print fact_usr_off_sig_off_1.__doc__
|
||||
None
|
||||
>>> len(fact_usr_on_sig_on_1.__doc__.splitlines())
|
||||
3
|
||||
>>> print selected_doc(fact_usr_on_sig_on_1, 0, 1)
|
||||
|usr on sig on 1
|
||||
|C++ signature:
|
||||
6
|
||||
>>> print selected_doc(fact_usr_on_sig_on_1, 1, 2, 4)
|
||||
|fact_usr_on_sig_on_1( (int)n) -> int :
|
||||
| usr on sig on 1
|
||||
| C++ signature :
|
||||
|
||||
>>> len(fact_usr_on_sig_off_1.__doc__.splitlines())
|
||||
1
|
||||
>>> print selected_doc(fact_usr_on_sig_off_1, 0)
|
||||
2
|
||||
>>> print selected_doc(fact_usr_on_sig_off_1, 1)
|
||||
|usr on sig off 1
|
||||
>>> len(fact_usr_on_sig_on_2.__doc__.splitlines())
|
||||
3
|
||||
>>> print selected_doc(fact_usr_on_sig_on_2, 0, 1)
|
||||
|usr on sig on 2
|
||||
|C++ signature:
|
||||
>>> print fact_usr_off_sig_off_2.__doc__
|
||||
None
|
||||
6
|
||||
>>> print selected_doc(fact_usr_on_sig_on_2, 1, 2, 4)
|
||||
|fact_usr_on_sig_on_2( (int)n) -> int :
|
||||
| usr on sig on 2
|
||||
| C++ signature :
|
||||
|
||||
>>> print selected_doc(fact_usr_on_psig_on_csig_off_1, 1, 2)
|
||||
|fact_usr_on_psig_on_csig_off_1( (int)n) -> int :
|
||||
| usr on psig on csig off 1
|
||||
|
||||
>>> print selected_doc(fact_usr_on_psig_off_csig_on_1, 1, 3)
|
||||
|usr on psig off csig on 1
|
||||
|C++ signature :
|
||||
|
||||
>>> print fact_usr_off_psig_on_csig_off_1.__doc__.splitlines()[1]
|
||||
fact_usr_off_psig_on_csig_off_1( (int)n) -> int
|
||||
|
||||
>>> print selected_doc(fact_usr_off_psig_off_csig_on_1,1)
|
||||
|C++ signature :
|
||||
|
||||
|
||||
'''
|
||||
|
||||
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user