mirror of
https://github.com/boostorg/python.git
synced 2026-01-20 04:42:28 +00:00
Compare commits
377 Commits
boost-1.30
...
boost-1.31
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
8e0553b310 | ||
|
|
ccc17a791a | ||
|
|
385fe03956 | ||
|
|
1727aa33b3 | ||
|
|
4c7694d81e | ||
|
|
36751a0e0a | ||
|
|
ccd909e98d | ||
|
|
01b25510ff | ||
|
|
06beca39af | ||
|
|
65c10f8f08 | ||
|
|
3c1a4b13b7 | ||
|
|
157343241c | ||
|
|
11df3bc2d3 | ||
|
|
469094ee45 | ||
|
|
ce3d43bb06 | ||
|
|
3a3f5631b9 | ||
|
|
b6707c8e61 | ||
|
|
3b25d2a78d | ||
|
|
dba4d7bf72 | ||
|
|
bf86306f8b | ||
|
|
e782dd7e02 | ||
|
|
bd4fd372a0 | ||
|
|
1102fec2a0 | ||
|
|
589fefe4b9 | ||
|
|
cfc867bd18 | ||
|
|
5bc28e3016 | ||
|
|
23b7ccca7f | ||
|
|
e9d6286a1d | ||
|
|
48321857e4 | ||
|
|
156da15715 | ||
|
|
4a0d7965cb | ||
|
|
1f522823ff | ||
|
|
6795a280fd | ||
|
|
f369e22638 | ||
|
|
a278da2eba | ||
|
|
37b2bdba79 | ||
|
|
e9519db974 | ||
|
|
dd7a24ebce | ||
|
|
bc92a7d155 | ||
|
|
a68db84df6 | ||
|
|
7b9bba3190 | ||
|
|
bcec0af232 | ||
|
|
0d437c4102 | ||
|
|
feff7bccd3 | ||
|
|
b12de3f01b | ||
|
|
0d108f12e4 | ||
|
|
4aca2ca33b | ||
|
|
9a967ae514 | ||
|
|
9481c39874 | ||
|
|
1e02065982 | ||
|
|
1fee0da689 | ||
|
|
c760cf8418 | ||
|
|
cdee5997af | ||
|
|
4289280cdc | ||
|
|
962dfa17c5 | ||
|
|
0a21aef601 | ||
|
|
8cbbd504cf | ||
|
|
91b23c8367 | ||
|
|
3729be263f | ||
|
|
ea91f4217a | ||
|
|
7fab3ce0b1 | ||
|
|
ef7d675d67 | ||
|
|
2b9d29a0fc | ||
|
|
95b95d012c | ||
|
|
4af7d5bca7 | ||
|
|
d879eb235f | ||
|
|
4f129d035b | ||
|
|
7a354c4ff4 | ||
|
|
364826b3b3 | ||
|
|
e9b308da46 | ||
|
|
94cfa2602f | ||
|
|
3533bd0504 | ||
|
|
1a51a7df9e | ||
|
|
615be89951 | ||
|
|
912ca36a1f | ||
|
|
fba93805dc | ||
|
|
96d66f4624 | ||
|
|
c3bae63e41 | ||
|
|
6c22aceabc | ||
|
|
92a77dfe7f | ||
|
|
4f2dbeda28 | ||
|
|
bec2de08fe | ||
|
|
db192e1e01 | ||
|
|
454654a9cc | ||
|
|
1018bc56eb | ||
|
|
f920dc87d0 | ||
|
|
8b97caae46 | ||
|
|
3b74aab818 | ||
|
|
e78b4939b3 | ||
|
|
621b5fc2db | ||
|
|
6ada069d5a | ||
|
|
50db384be1 | ||
|
|
ae7225ae83 | ||
|
|
911ba333a2 | ||
|
|
5cd8cce531 | ||
|
|
6a2a76cea9 | ||
|
|
7a9a3d30c9 | ||
|
|
034ca4d5eb | ||
|
|
00e3fa32fb | ||
|
|
0133bdfbe3 | ||
|
|
e563def5ba | ||
|
|
b3910f4e4d | ||
|
|
4a7b8fe839 | ||
|
|
fc56544da4 | ||
|
|
c839d25722 | ||
|
|
c6b5ecbbdb | ||
|
|
d3473afa23 | ||
|
|
379b28eb85 | ||
|
|
7f5bd33ead | ||
|
|
eef6fb9891 | ||
|
|
4a7f52ab2c | ||
|
|
10b249a162 | ||
|
|
5fc5fce663 | ||
|
|
f00fe3c0b1 | ||
|
|
3047d51613 | ||
|
|
f9f7146960 | ||
|
|
ca9dc3103a | ||
|
|
c03afa379c | ||
|
|
cbacc98e3f | ||
|
|
84daf14f1b | ||
|
|
4af28b2a46 | ||
|
|
acbc01933c | ||
|
|
7ec78eecbd | ||
|
|
87c5e37f5e | ||
|
|
d02959e3ed | ||
|
|
b844d8b750 | ||
|
|
0a3010b29f | ||
|
|
2b380d03c9 | ||
|
|
3f70253a3f | ||
|
|
165e294298 | ||
|
|
f7c9f45508 | ||
|
|
af2a924301 | ||
|
|
3981e83de5 | ||
|
|
88b9721e3f | ||
|
|
4946af1448 | ||
|
|
9959dcfa49 | ||
|
|
cfb13fad22 | ||
|
|
4e3f3a052d | ||
|
|
dc7ae9ed20 | ||
|
|
929badf4c6 | ||
|
|
c4a3f2c04f | ||
|
|
a933e458b3 | ||
|
|
06b8320815 | ||
|
|
7f3aceafd2 | ||
|
|
da5979931c | ||
|
|
d8c7e75095 | ||
|
|
187506c97f | ||
|
|
145c6d1e4f | ||
|
|
e2973f27f9 | ||
|
|
976b8180ae | ||
|
|
37acf41d43 | ||
|
|
6f26778491 | ||
|
|
834d815c87 | ||
|
|
57e58c445b | ||
|
|
8a1a8342d6 | ||
|
|
fa70ddc2c5 | ||
|
|
8ca32bb494 | ||
|
|
f6c82eba0c | ||
|
|
344044a315 | ||
|
|
b10805dc4c | ||
|
|
07f397e2ed | ||
|
|
054dc439d2 | ||
|
|
5008dcbdd4 | ||
|
|
9c6650963f | ||
|
|
d482d57689 | ||
|
|
edf6516085 | ||
|
|
957ac66e14 | ||
|
|
07ce84c4e7 | ||
|
|
918636ff03 | ||
|
|
83a6adbfa9 | ||
|
|
fcbc1d562f | ||
|
|
c3b4b58075 | ||
|
|
568b62a8a4 | ||
|
|
da34e7f507 | ||
|
|
a0c31b47e5 | ||
|
|
5fb677c0c5 | ||
|
|
168476382a | ||
|
|
7fa6a29814 | ||
|
|
f2b51da0ab | ||
|
|
53726746b8 | ||
|
|
fe0b59f559 | ||
|
|
c014dee6dc | ||
|
|
90c69d961e | ||
|
|
342f7db678 | ||
|
|
9eb704f85a | ||
|
|
7754a91929 | ||
|
|
e4dc639e54 | ||
|
|
5d90101671 | ||
|
|
437fb70852 | ||
|
|
d598404c48 | ||
|
|
32c7088600 | ||
|
|
ccede29816 | ||
|
|
b55b7e2f7b | ||
|
|
9217a6a253 | ||
|
|
07c1319b99 | ||
|
|
714b5dc26e | ||
|
|
1f715958f9 | ||
|
|
0922aca873 | ||
|
|
30ec6181b5 | ||
|
|
b28d586612 | ||
|
|
f48aacf477 | ||
|
|
bfa868a440 | ||
|
|
f01ff3a277 | ||
|
|
d88e6bf688 | ||
|
|
a3cdacd088 | ||
|
|
81d99c855f | ||
|
|
5cd110f625 | ||
|
|
416895ff30 | ||
|
|
e41abb6e92 | ||
|
|
a6440a3fa6 | ||
|
|
2dece7ecaf | ||
|
|
7aae525587 | ||
|
|
ac5314093b | ||
|
|
1524fb9fa9 | ||
|
|
957549460b | ||
|
|
3b33f54fb8 | ||
|
|
42ab6b6b66 | ||
|
|
f59a5bbabc | ||
|
|
0be371d747 | ||
|
|
2b52210291 | ||
|
|
96a7bce78e | ||
|
|
c1e1ea697c | ||
|
|
874d6ebf2c | ||
|
|
77f5eb703c | ||
|
|
af53ae8329 | ||
|
|
8f76b8880e | ||
|
|
fa398734be | ||
|
|
362d20a8c7 | ||
|
|
6a33b8aeeb | ||
|
|
d4e06ac436 | ||
|
|
817dcd37e0 | ||
|
|
25bfd3c50f | ||
|
|
b13c902fb0 | ||
|
|
c95ef44b02 | ||
|
|
162727590c | ||
|
|
7e159844fb | ||
|
|
787b79cc2c | ||
|
|
b77652b499 | ||
|
|
0c8444b8ed | ||
|
|
3e6ee799ba | ||
|
|
dd14ccb115 | ||
|
|
ba0fcd27c3 | ||
|
|
d476e67067 | ||
|
|
4588f5e9ab | ||
|
|
68f54d364b | ||
|
|
7dba18e7b9 | ||
|
|
67b265fe96 | ||
|
|
8289269a86 | ||
|
|
9f711ed821 | ||
|
|
73e2ab5125 | ||
|
|
7ea2ab1672 | ||
|
|
c821e903f8 | ||
|
|
54db04521a | ||
|
|
91fdecd76f | ||
|
|
f140a74a13 | ||
|
|
4854a2a81b | ||
|
|
d94bb65006 | ||
|
|
6ca5280b2c | ||
|
|
5da3e1deea | ||
|
|
1ae85d0e39 | ||
|
|
256e3a467c | ||
|
|
4477fe4dd6 | ||
|
|
5d1e245858 | ||
|
|
ec750a44c9 | ||
|
|
006f1d9802 | ||
|
|
638b3d4ee1 | ||
|
|
a1cc1651fa | ||
|
|
9fe141f5ad | ||
|
|
d52f0c7d40 | ||
|
|
bb55c4a855 | ||
|
|
f1a06b14de | ||
|
|
286f3dc093 | ||
|
|
a731322782 | ||
|
|
0db07ec25e | ||
|
|
bc112ba65f | ||
|
|
62ba322658 | ||
|
|
02135b550d | ||
|
|
ee4b06bb50 | ||
|
|
16c5435ca8 | ||
|
|
2595049748 | ||
|
|
5911691c0d | ||
|
|
e369bddc84 | ||
|
|
dccf2bbb4a | ||
|
|
eaab3fc038 | ||
|
|
858e1aba67 | ||
|
|
19eff7791d | ||
|
|
c81af4ffe0 | ||
|
|
9675e4233b | ||
|
|
e6a176bb1e | ||
|
|
ff0980914b | ||
|
|
43e5ccd0a7 | ||
|
|
66d6272942 | ||
|
|
2f1b828967 | ||
|
|
622636dcf1 | ||
|
|
0c22c276bf | ||
|
|
7a4a79c74e | ||
|
|
06f454e1d3 | ||
|
|
c1dbd52de1 | ||
|
|
c3f5679188 | ||
|
|
97e2628f95 | ||
|
|
6cecfcb704 | ||
|
|
022a5a16f5 | ||
|
|
a39a834e75 | ||
|
|
2a1210384a | ||
|
|
d497611069 | ||
|
|
46d8786f5a | ||
|
|
b8028729eb | ||
|
|
30e7768a87 | ||
|
|
10dc663e07 | ||
|
|
42fc57d761 | ||
|
|
74cd2f4844 | ||
|
|
a15135f1c1 | ||
|
|
ccd84c0be6 | ||
|
|
510215f284 | ||
|
|
c7ea0aacd6 | ||
|
|
f7f089d2d4 | ||
|
|
82721c77a1 | ||
|
|
1c9bf7d91c | ||
|
|
9bf78396cb | ||
|
|
d994e4719c | ||
|
|
44b886bb76 | ||
|
|
8d2f012bcf | ||
|
|
a86deed5f6 | ||
|
|
3fd9ad7a60 | ||
|
|
319a5cf97c | ||
|
|
0fd503d6af | ||
|
|
bf696026bd | ||
|
|
734657244b | ||
|
|
d2470e4f9c | ||
|
|
28a2792280 | ||
|
|
cd985a33d8 | ||
|
|
726d2beffd | ||
|
|
f04be3fc1b | ||
|
|
b6927410d9 | ||
|
|
44b2e1ef8b | ||
|
|
3d01e6af89 | ||
|
|
00387b2076 | ||
|
|
f9bf514801 | ||
|
|
fa27bddfab | ||
|
|
f27e8f8ddc | ||
|
|
5b2623ff2e | ||
|
|
a83a726b6e | ||
|
|
93df7e00a7 | ||
|
|
6b7748a88d | ||
|
|
f102c77fa2 | ||
|
|
a4fa261b77 | ||
|
|
8a15fefc6c | ||
|
|
12a4cc16be | ||
|
|
6335716342 | ||
|
|
db0602ac2a | ||
|
|
390ad530f1 | ||
|
|
6eb2e8d68a | ||
|
|
b804b3b221 | ||
|
|
936c1118bd | ||
|
|
4ba7b8a8ff | ||
|
|
70601e9da0 | ||
|
|
c32d1f9614 | ||
|
|
e031f78ad4 | ||
|
|
7d0273051a | ||
|
|
29d537571b | ||
|
|
39f243f76b | ||
|
|
0712360cc9 | ||
|
|
02c125cbb4 | ||
|
|
13256fb7e9 | ||
|
|
f11d757807 | ||
|
|
2e123849fb | ||
|
|
2f6cfaf0e9 | ||
|
|
f9b216d6f9 | ||
|
|
5fdd10d77e | ||
|
|
41de02d528 | ||
|
|
1c3d08f23a | ||
|
|
0f1dc1fd50 | ||
|
|
cd06018820 | ||
|
|
7816eb6344 | ||
|
|
9813f4b55f | ||
|
|
f81ca21b22 | ||
|
|
f1b7620c9e |
@@ -10,8 +10,7 @@
|
||||
subproject libs/python/build ;
|
||||
|
||||
# bring in the rules for python
|
||||
SEARCH on <module@>python.jam = $(BOOST_BUILD_PATH) ;
|
||||
include <module@>python.jam ;
|
||||
import python ;
|
||||
|
||||
if [ check-python-config ]
|
||||
{
|
||||
@@ -61,8 +60,14 @@ if [ check-python-config ]
|
||||
<define>BOOST_PYTHON_SOURCE
|
||||
$(bpl-linkflags)
|
||||
<msvc-stlport><release>$(msvc-stlport-workarounds)
|
||||
<darwin><*><linkflags>-bind_at_load
|
||||
;
|
||||
|
||||
template extension
|
||||
: <dll>boost_python
|
||||
: <sysinclude>../../..
|
||||
;
|
||||
|
||||
lib boost_python
|
||||
: # sources
|
||||
../src/$(sources)
|
||||
@@ -81,4 +86,8 @@ if [ check-python-config ]
|
||||
:
|
||||
debug release
|
||||
;
|
||||
}
|
||||
|
||||
install python lib
|
||||
: <dll>boost_python <lib>boost_python
|
||||
;
|
||||
}
|
||||
|
||||
@@ -1,8 +1,11 @@
|
||||
import os ;
|
||||
import modules ;
|
||||
|
||||
# Use a very crude way to sense there python is locatted
|
||||
|
||||
local PYTHON_PATH ;
|
||||
|
||||
local PYTHON_PATH = [ modules.peek : PYTHON_PATH ] ;
|
||||
ECHO "XXX" $(PYTHON_PATH) ;
|
||||
|
||||
if [ GLOB /usr/local/include/python2.2 : * ]
|
||||
{
|
||||
@@ -19,7 +22,7 @@ if [ os.name ] in CYGWIN NT
|
||||
defines = USE_DL_IMPORT ;
|
||||
|
||||
# Declare a target for the python interpreter library
|
||||
lib python : : <name>python2.2.dll ;
|
||||
lib python : : <name>python22 <search>$(PYTHON_PATH)/libs ;
|
||||
PYTHON_LIB = python ;
|
||||
}
|
||||
else
|
||||
@@ -35,12 +38,12 @@ if $(PYTHON_PATH) {
|
||||
|
||||
project boost/python
|
||||
: source-location ../src
|
||||
: requirements <include>$(PYTHON_PATH)/include/python2.2
|
||||
$(lib_condition)<library-path>$(PYTHON_PATH)/lib/python2.2/config
|
||||
: requirements <include>$(PYTHON_PATH)/include
|
||||
$(lib_condition)<library-path>$(PYTHON_PATH)/libs
|
||||
<link>shared:<library>$(PYTHON_LIB)
|
||||
<define>$(defines)
|
||||
: usage-requirements # requirement that will be propageted to *users* of this library
|
||||
<include>$(PYTHON_PATH)/include/python2.2
|
||||
<include>$(PYTHON_PATH)/include
|
||||
|
||||
# We have a bug which causes us to conclude that conditionalized
|
||||
# properties in this section are not free.
|
||||
|
||||
1127
doc/PyConDC_2003/bpl.html
Executable file
1127
doc/PyConDC_2003/bpl.html
Executable file
File diff suppressed because it is too large
Load Diff
BIN
doc/PyConDC_2003/bpl.pdf
Executable file
BIN
doc/PyConDC_2003/bpl.pdf
Executable file
Binary file not shown.
@@ -9,12 +9,10 @@
|
||||
|
||||
:Author: Ralf W. Grosse-Kunstleve
|
||||
|
||||
:status: Draft
|
||||
:copyright: Copyright David Abrahams and Ralf W. Grosse-Kunstleve 2003. All rights reserved
|
||||
|
||||
.. contents:: Table of Contents
|
||||
|
||||
|
||||
.. _`Boost Consulting`: http://www.boost-consulting.com
|
||||
|
||||
==========
|
||||
@@ -631,19 +629,22 @@ virtual functions. At least one very promising project has been
|
||||
started to write a front-end which can generate these dispatchers (and
|
||||
other wrapping code) automatically from C++ headers.
|
||||
|
||||
Pyste builds on GCC_XML_, which generates an XML version of GCC's
|
||||
internal program representation. Since GCC is a highly-conformant C++
|
||||
compiler, this ensures correct handling of the most-sophisticated
|
||||
template code and full access to the underlying type system. In
|
||||
keeping with the Boost.Python philosophy, a Pyste interface
|
||||
description is neither intrusive on the code being wrapped, nor
|
||||
expressed in some unfamiliar language: instead it is a 100% pure
|
||||
Python script. If Pyste is successful it will mark a move away from
|
||||
wrapping everything directly in C++ for many of our users. We expect
|
||||
that soon, not only our users but the Boost.Python developers
|
||||
themselves will be "thinking hybrid" about their own code.
|
||||
Pyste_ is being developed by Bruno da Silva de Oliveira. It builds on
|
||||
GCC_XML_, which generates an XML version of GCC's internal program
|
||||
representation. Since GCC is a highly-conformant C++ compiler, this
|
||||
ensures correct handling of the most-sophisticated template code and
|
||||
full access to the underlying type system. In keeping with the
|
||||
Boost.Python philosophy, a Pyste interface description is neither
|
||||
intrusive on the code being wrapped, nor expressed in some unfamiliar
|
||||
language: instead it is a 100% pure Python script. If Pyste is
|
||||
successful it will mark a move away from wrapping everything directly
|
||||
in C++ for many of our users. It will also allow us the choice to
|
||||
shift some of the metaprogram code from C++ to Python. We expect that
|
||||
soon, not only our users but the Boost.Python developers themselves
|
||||
will be "thinking hybrid" about their own code.
|
||||
|
||||
.. _`GCC_XML`: http://www.gccxml.org/HTML/Index.html
|
||||
.. _`Pyste`: http://www.boost.org/libs/python/pyste
|
||||
|
||||
---------------
|
||||
Serialization
|
||||
@@ -770,15 +771,6 @@ This almost looks and works like regular Python code, but it is pure
|
||||
C++. Of course we can wrap C++ functions which accept or return
|
||||
``object`` instances.
|
||||
|
||||
.. =====================
|
||||
Development history
|
||||
=====================
|
||||
|
||||
XXX Outline of development history to illustrate that the
|
||||
library is mature. XXX
|
||||
|
||||
This can be postponed for the PyConDC paper
|
||||
|
||||
=================
|
||||
Thinking hybrid
|
||||
=================
|
||||
@@ -816,7 +808,7 @@ mainly concentrated on the C++ parts. However, as the toolbox is
|
||||
becoming more complete, more and more newly added functionality can be
|
||||
implemented in Python.
|
||||
|
||||
.. image:: python_cpp_mix.png
|
||||
.. image:: python_cpp_mix.jpg
|
||||
|
||||
This figure shows the estimated ratio of newly added C++ and Python
|
||||
code over time as new algorithms are implemented. We expect this
|
||||
@@ -826,6 +818,87 @@ language is the return on our investment in Boost.Python. The ability
|
||||
to access all of our code from Python allows a broader group of
|
||||
developers to use it in the rapid development of new applications.
|
||||
|
||||
=====================
|
||||
Development history
|
||||
=====================
|
||||
|
||||
The first version of Boost.Python was developed in 2000 by Dave
|
||||
Abrahams at Dragon Systems, where he was privileged to have Tim Peters
|
||||
as a guide to "The Zen of Python". One of Dave's jobs was to develop
|
||||
a Python-based natural language processing system. Since it was
|
||||
eventually going to be targeting embedded hardware, it was always
|
||||
assumed that the compute-intensive core would be rewritten in C++ to
|
||||
optimize speed and memory footprint [#proto]_. The project also wanted to
|
||||
test all of its C++ code using Python test scripts [#test]_. The only
|
||||
tool we knew of for binding C++ and Python was SWIG_, and at the time
|
||||
its handling of C++ was weak. It would be false to claim any deep
|
||||
insight into the possible advantages of Boost.Python's approach at
|
||||
this point. Dave's interest and expertise in fancy C++ template
|
||||
tricks had just reached the point where he could do some real damage,
|
||||
and Boost.Python emerged as it did because it filled a need and
|
||||
because it seemed like a cool thing to try.
|
||||
|
||||
This early version was aimed at many of the same basic goals we've
|
||||
described in this paper, differing most-noticeably by having a
|
||||
slightly more cumbersome syntax and by lack of special support for
|
||||
operator overloading, pickling, and component-based development.
|
||||
These last three features were quickly added by Ullrich Koethe and
|
||||
Ralf Grosse-Kunstleve [#feature]_, and other enthusiastic contributors arrived
|
||||
on the scene to contribute enhancements like support for nested
|
||||
modules and static member functions.
|
||||
|
||||
By early 2001 development had stabilized and few new features were
|
||||
being added, however a disturbing new fact came to light: Ralf had
|
||||
begun testing Boost.Python on pre-release versions of a compiler using
|
||||
the EDG_ front-end, and the mechanism at the core of Boost.Python
|
||||
responsible for handling conversions between Python and C++ types was
|
||||
failing to compile. As it turned out, we had been exploiting a very
|
||||
common bug in the implementation of all the C++ compilers we had
|
||||
tested. We knew that as C++ compilers rapidly became more
|
||||
standards-compliant, the library would begin failing on more
|
||||
platforms. Unfortunately, because the mechanism was so central to the
|
||||
functioning of the library, fixing the problem looked very difficult.
|
||||
|
||||
Fortunately, later that year Lawrence Berkeley and later Lawrence
|
||||
Livermore National labs contracted with `Boost Consulting`_ for support
|
||||
and development of Boost.Python, and there was a new opportunity to
|
||||
address fundamental issues and ensure a future for the library. A
|
||||
redesign effort began with the low level type conversion architecture,
|
||||
building in standards-compliance and support for component-based
|
||||
development (in contrast to version 1 where conversions had to be
|
||||
explicitly imported and exported across module boundaries). A new
|
||||
analysis of the relationship between the Python and C++ objects was
|
||||
done, resulting in more intuitive handling for C++ lvalues and
|
||||
rvalues.
|
||||
|
||||
The emergence of a powerful new type system in Python 2.2 made the
|
||||
choice of whether to maintain compatibility with Python 1.5.2 easy:
|
||||
the opportunity to throw away a great deal of elaborate code for
|
||||
emulating classic Python classes alone was too good to pass up. In
|
||||
addition, Python iterators and descriptors provided crucial and
|
||||
elegant tools for representing similar C++ constructs. The
|
||||
development of the generalized ``object`` interface allowed us to
|
||||
further shield C++ programmers from the dangers and syntactic burdens
|
||||
of the Python 'C' API. A great number of other features including C++
|
||||
exception translation, improved support for overloaded functions, and
|
||||
most significantly, CallPolicies for handling pointers and
|
||||
references, were added during this period.
|
||||
|
||||
In October 2002, version 2 of Boost.Python was released. Development
|
||||
since then has concentrated on improved support for C++ runtime
|
||||
polymorphism and smart pointers. Peter Dimov's ingenious
|
||||
``boost::shared_ptr`` design in particular has allowed us to give the
|
||||
hybrid developer a consistent interface for moving objects back and
|
||||
forth across the language barrier without loss of information. At
|
||||
first, we were concerned that the sophistication and complexity of the
|
||||
Boost.Python v2 implementation might discourage contributors, but the
|
||||
emergence of Pyste_ and several other significant feature
|
||||
contributions have laid those fears to rest. Daily questions on the
|
||||
Python C++-sig and a backlog of desired improvements show that the
|
||||
library is getting used. To us, the future looks bright.
|
||||
|
||||
.. _`EDG`: http://www.edg.com
|
||||
|
||||
=============
|
||||
Conclusions
|
||||
=============
|
||||
@@ -851,3 +924,24 @@ the ground up, we can approach design with new confidence and power.
|
||||
.. [VELD1995] T. Veldhuizen, "Expression Templates," C++ Report,
|
||||
Vol. 7 No. 5 June 1995, pp. 26-31.
|
||||
http://osl.iu.edu/~tveldhui/papers/Expression-Templates/exprtmpl.html
|
||||
|
||||
===========
|
||||
Footnotes
|
||||
===========
|
||||
|
||||
.. [#proto] In retrospect, it seems that "thinking hybrid" from the
|
||||
ground up might have been better for the NLP system: the
|
||||
natural component boundaries defined by the pure python
|
||||
prototype turned out to be inappropriate for getting the
|
||||
desired performance and memory footprint out of the C++ core,
|
||||
which eventually caused some redesign overhead on the Python
|
||||
side when the core was moved to C++.
|
||||
|
||||
.. [#test] We also have some reservations about driving all C++
|
||||
testing through a Python interface, unless that's the only way
|
||||
it will be ultimately used. Any transition across language
|
||||
boundaries with such different object models can inevitably
|
||||
mask bugs.
|
||||
|
||||
.. [#feature] These features were expressed very differently in v1 of
|
||||
Boost.Python
|
||||
|
||||
BIN
doc/PyConDC_2003/python_cpp_mix.jpg
Executable file
BIN
doc/PyConDC_2003/python_cpp_mix.jpg
Executable file
Binary file not shown.
|
After Width: | Height: | Size: 22 KiB |
@@ -3,7 +3,7 @@
|
||||
<html>
|
||||
<head>
|
||||
<meta name="generator" content=
|
||||
"HTML Tidy for Windows (vers 1st August 2002), see www.w3.org">
|
||||
"HTML Tidy for Cygwin (vers 1st April 2002), see www.w3.org">
|
||||
<meta http-equiv="Content-Type" content="text/html; charset=iso-8859-1">
|
||||
<link rel="stylesheet" type="text/css" href="boost.css">
|
||||
|
||||
@@ -39,25 +39,22 @@
|
||||
<dl class="index">
|
||||
<dt><a href="#configuration">Configuration</a></dt>
|
||||
|
||||
<dt><a href="#cygwin_configuration">Configuration for Cygwin GCC
|
||||
from a Windows prompt</a></dt>
|
||||
|
||||
<dt><a href="#results">Results</a></dt>
|
||||
|
||||
<dt><a href="#cygwin">Notes for Cygwin GCC Users</a></dt>
|
||||
|
||||
<dt><a href="#mingw">Notes for MinGW (and Cygwin with -mno-cygwin)
|
||||
GCC Users</a></dt>
|
||||
|
||||
<dt><a href="#testing">Testing</a></dt>
|
||||
</dl>
|
||||
</dd>
|
||||
|
||||
<dt><a href="#building_ext">Building your Extension Module</a></dt>
|
||||
|
||||
<dd>
|
||||
<dl>
|
||||
<dt><a href="#easy">The Easy Way</a></dt>
|
||||
|
||||
<dt><a href="#outside">Building your module outside the Boost
|
||||
project tree</a></dt>
|
||||
</dl>
|
||||
</dd>
|
||||
|
||||
<dt><a href="#variants">Build Variants</a></dt>
|
||||
|
||||
<dt><a href="#VisualStudio">Building Using the Microsoft Visual Studio
|
||||
@@ -77,15 +74,15 @@
|
||||
<p>Normally, Boost.Python extension modules must be linked with the
|
||||
<code>boost_python</code> shared library. In special circumstances you
|
||||
may want to link to a static version of the <code>boost_python</code>
|
||||
library, but if multiple Boost.Pythone extension modules are used
|
||||
library, but if multiple Boost.Python extension modules are used
|
||||
together, it will prevent sharing of types across extension modules, and
|
||||
consume extra code space. To build <code>boost_python</code>, use <a
|
||||
href="../../../tools/build/index.html">Boost.Build</a> in the usual way
|
||||
href="../../../tools/build/v1/build_system.htm">Boost.Build</a> in the usual way
|
||||
from the <code>libs/python/build</code> subdirectory of your boost
|
||||
installation (if you have already built boost from the top level this may
|
||||
have no effect, since the work is already done).</p>
|
||||
|
||||
<h3><a name="configuration">Configuration</a></h3>
|
||||
<h3><a name="configuration">Basic Configuration</a></h3>
|
||||
You may need to configure the following variables to point Boost.Build at
|
||||
your Python installation:
|
||||
|
||||
@@ -128,7 +125,8 @@
|
||||
|
||||
<td>path to Python <code>#include</code> directories</td>
|
||||
|
||||
<td>Autoconfigured from <code>PYTHON_ROOT</code></td>
|
||||
<td>Autoconfigured from <code>PYTHON_ROOT</code>. Try the default
|
||||
before attempting to set it yourself.</td>
|
||||
</tr>
|
||||
|
||||
<tr>
|
||||
@@ -136,37 +134,50 @@
|
||||
|
||||
<td>path to Python library object.</td>
|
||||
|
||||
<td>Autoconfigured from <code>PYTHON_ROOT</code></td>
|
||||
<td>Autoconfigured from <code>PYTHON_ROOT</code>. Try the default
|
||||
before attempting to set it yourself.</td>
|
||||
</tr>
|
||||
</table>
|
||||
|
||||
<h3><a name="cygwin_configuration">Configuration for Cygwin GCC from a
|
||||
Windows prompt</a></h3>
|
||||
The following settings may be useful when building with <a href=
|
||||
"http://www.cygwin.com">Cygwin</a> GCC (not MinGW) from a Windows command
|
||||
shell using a Windows build of <code>bjam</code>. <b>If
|
||||
"<code>bjam -v</code>" does not report "<code>OS=NT</code>", these
|
||||
settings do not apply to you</b>; you should use the <a href=
|
||||
"#configuration">normal configuration</a> variables instead. They are
|
||||
only useful when building and testing with multiple toolsets on Windows
|
||||
using a single build command, since Cygwin GCC requires a different build
|
||||
of Python.
|
||||
|
||||
<table border="1" summary=
|
||||
"Cygwin GCC under NT build configuration variables">
|
||||
<tr>
|
||||
<th>Variable Name</th>
|
||||
|
||||
<th>Semantics</th>
|
||||
|
||||
<th>Default</th>
|
||||
</tr>
|
||||
|
||||
<tr>
|
||||
<td><code>CYGWIN_PYTHON_[DEBUG_]VERSION</code></td>
|
||||
|
||||
<td>The version of python being used under Cygwin. </td>
|
||||
<td>The version of python being used under Cygwin.</td>
|
||||
|
||||
<td>$(PYTHON_VERSION)
|
||||
|
||||
</td>
|
||||
|
||||
<td>Use only when building with <a href=
|
||||
"http://www.cygwin.com">Cygwin</a> GCC. This and the following
|
||||
settings are useful when building with multiple toolsets on
|
||||
Windows, since Cygwin GCC requires a different build of
|
||||
Python.</td> </tr>
|
||||
<td>$(PYTHON_VERSION)</td>
|
||||
</tr>
|
||||
|
||||
<tr>
|
||||
<td><code>CYGWIN_PYTHON_[DEBUG_]ROOT</code></td>
|
||||
|
||||
<td>unix-style path containing the <code>include/</code>
|
||||
directory containing
|
||||
<code>python$(CYGWIN_PYTHON_[DEBUG_]VERSION)/python.h</code>. </td>
|
||||
<td>unix-style path containing the <code>include/</code> directory
|
||||
containing
|
||||
<code>python$(CYGWIN_PYTHON_[DEBUG_]VERSION)/python.h</code>.</td>
|
||||
|
||||
<td>$(PYTHON_ROOT)
|
||||
|
||||
</td>
|
||||
|
||||
<td>Use only when building with <a href=
|
||||
"http://www.cygwin.com">Cygwin</a> GCC.</td> </tr>
|
||||
<td>$(PYTHON_ROOT)</td>
|
||||
</tr>
|
||||
|
||||
<tr>
|
||||
<td><code>CYGWIN_PYTHON_[DEBUG_]LIB_PATH</code></td>
|
||||
@@ -175,9 +186,7 @@
|
||||
<code>libpython$(CYGWIN_PYTHON_[DEBUG_]VERSION).dll.a</code></td>
|
||||
|
||||
<td>Autoconfigured from <code>CYGWIN_PYTHON_ROOT</code></td>
|
||||
|
||||
<td>Use only when building with <a href=
|
||||
"http://www.cygwin.com">Cygwin</a> GCC.</td> </tr>
|
||||
</tr>
|
||||
|
||||
<tr>
|
||||
<td><code>CYGWIN_PYTHON_[DEBUG_]DLL_PATH</code></td>
|
||||
@@ -186,10 +195,6 @@
|
||||
(<code>libpython$(CYGWIN_PYTHON_[DEBUG_]VERSION).dll</code>)</td>
|
||||
|
||||
<td><code>/bin</code></td>
|
||||
|
||||
<td>Use only when building with <a href=
|
||||
"http://www.cygwin.com">Cygwin</a> GCC.</td> </tr>
|
||||
|
||||
</tr>
|
||||
</table>
|
||||
|
||||
@@ -206,10 +211,23 @@
|
||||
"http://www.python.org/download/download_source.html">Unix installation
|
||||
process</a> to build Python from source.</p>
|
||||
|
||||
<p>The special build configuration variables listed above as "Cygwin
|
||||
only" make it possible to use a regular Win32 build of bjam to build and
|
||||
test Boost.Python and Boost.Python extensions using Cygwin GCC and
|
||||
targeting a Cygwin build of Python.</p>
|
||||
<p>The special build configuration variables listed <a href=
|
||||
"#cygwin_configuration">above</a> make it possible to use a regular Win32
|
||||
build of bjam to build and test Boost.Python and Boost.Python extensions
|
||||
using Cygwin GCC and targeting a Cygwin build of Python.</p>
|
||||
|
||||
<h3><a name="mingw">Notes for MinGW (and Cygwin with -mno-cygwin) GCC
|
||||
Users</a></h3>
|
||||
|
||||
<p>You will need to create a MinGW-compatible version of the Python
|
||||
library; the one shipped with Python will only work with a
|
||||
Microsoft-compatible linker. Follow the instructions in the
|
||||
"Non-Microsoft" section of the "Building Extensions: Tips And Tricks"
|
||||
chapter in <a href=
|
||||
"http://www.python.org/doc/current/inst/index.html">Installing Python
|
||||
Modules</a> to create <code>libpythonXX.a</code>, where <code>XX</code>
|
||||
corresponds to the major and minor version numbers of your Python
|
||||
installation.</p>
|
||||
|
||||
<h3><a name="results">Results</a></h3>
|
||||
|
||||
@@ -231,7 +249,7 @@
|
||||
<blockquote>
|
||||
<pre>
|
||||
bjam -sTOOLS=<i><a href=
|
||||
"../../../tools/build/index.html#Tools">toolset</a></i> test
|
||||
"../../../more/getting_started.html#Tools">toolset</a></i> test
|
||||
</pre>
|
||||
</blockquote>
|
||||
This will update all of the Boost.Python v1 test and example targets. The
|
||||
@@ -241,58 +259,62 @@ bjam -sTOOLS=<i><a href=
|
||||
<blockquote>
|
||||
<pre>
|
||||
bjam -sTOOLS=<i><a href=
|
||||
"../../../tools/build/index.html#Tools">toolset</a></i> -sPYTHON_TEST_ARGS=-v test
|
||||
"../../../more/getting_started.html#Tools">toolset</a></i> -sPYTHON_TEST_ARGS=-v test
|
||||
</pre>
|
||||
</blockquote>
|
||||
which will print each test's Python code with the expected output as it
|
||||
passes.
|
||||
|
||||
<h2><a name="building_ext">Building your Extension Module</a></h2>
|
||||
Though there are other approaches, the best way to build an extension
|
||||
module using Boost.Python is with Boost.Build. If you have to use another
|
||||
build system, you should use Boost.Build at least once with the
|
||||
Though there are other approaches, the smoothest and most reliable
|
||||
way to build an extension module using Boost.Python is with
|
||||
Boost.Build. If you have to use another build system, you should
|
||||
use Boost.Build at least once with the
|
||||
"<code><b>-n</b></code>" option so you can see the command-lines it uses,
|
||||
and replicate them. You are likely to run into compilation or linking
|
||||
problems otherwise.
|
||||
|
||||
<h3><a name="easy">The Easy Way</a></h3>
|
||||
Until Boost.Build v2 is released, cross-project build dependencies are
|
||||
not supported, so it works most smoothly if you add a new subproject to
|
||||
your boost installation. The <code>libs/python/example</code>
|
||||
subdirectory of your boost installation contains a minimal example (along
|
||||
with many extra sources). To copy the example subproject:
|
||||
The <code><a href="../example">libs/python/example</a></code>
|
||||
subdirectory of your boost installation contains a small example
|
||||
which builds and tests two extensions. To build your own
|
||||
extensions copy the example subproject and make the following two edits:
|
||||
|
||||
<ol>
|
||||
<li>Create a new subdirectory in, <code>libs/python</code>, say
|
||||
<code>libs/python/my_project</code>.</li>
|
||||
<ol>
|
||||
<li><code><a
|
||||
href="../example/boost-build.jam"><b>boost-build.jam</b></a></code> -
|
||||
edit the line which reads
|
||||
|
||||
<li>Copy <code><a href=
|
||||
"../example/Jamfile">libs/python/example/Jamfile</a></code> to your new
|
||||
directory.</li>
|
||||
<blockquote>
|
||||
<pre>
|
||||
boost-build ../../../tools/build/v1 ;
|
||||
</pre>
|
||||
</blockquote>
|
||||
|
||||
<li>Edit the Jamfile as appropriate for your project. You'll want to
|
||||
change the "<code>subproject</code>" rule invocation at the top, and
|
||||
the names of some of the source files and/or targets.</li>
|
||||
</ol>
|
||||
so that the path refers to the <code>tools/build/v1</code> subdirectory
|
||||
of your Boost installation.
|
||||
|
||||
|
||||
<li><code><a href="../example/Jamrules"><b>Jamrules</b></a></code> -
|
||||
edit the line which reads
|
||||
|
||||
<blockquote>
|
||||
<pre>
|
||||
path-global BOOST_ROOT : ../../.. ;
|
||||
</pre>
|
||||
</blockquote>
|
||||
so that the path refers to the root directory of your Boost installation.
|
||||
</ol>
|
||||
|
||||
<p>
|
||||
The instructions <a href="#testing">above</a> for testing Boost.Python
|
||||
apply equally to your new extension modules in this subproject.
|
||||
|
||||
<h3><a name="outside">Building your module outside the Boost project
|
||||
tree</a></h3>
|
||||
If you can't (or don't wish to) modify your boost installation, the
|
||||
alternative is to create your own Boost.Build project. A similar example
|
||||
you can use as a starting point is available in <code><a href=
|
||||
"../example/project.zip">this archive</a></code>. You'll need to edit the
|
||||
Jamfile and Jamrules files, depending on the relative location of your
|
||||
Boost installation and the new project. Note that automatic testing of
|
||||
extension modules is not available in this configuration.
|
||||
|
||||
<h2><a name="variants">Build Variants</a></h2>
|
||||
Three <a href=
|
||||
"../../../tools/build/build_system.htm#variants">variant</a>
|
||||
"../../../tools/build/v1/build_system.htm#variants">variant</a>
|
||||
configurations of all python-related targets are supported, and can be
|
||||
selected by setting the <code><a href=
|
||||
"../../../tools/build/build_system.htm#user_globals">BUILD</a></code>
|
||||
"../../../tools/build/v1/build_system.htm#user_globals">BUILD</a></code>
|
||||
variable:
|
||||
|
||||
<ul>
|
||||
@@ -357,7 +379,7 @@ bjam -sTOOLS=<i><a href=
|
||||
(i.e. <code>c:/Python/Libs</code>. Make sure it is <code>Libs</code> with
|
||||
an "<code>s</code>" and not just <code>Lib</code>).</p>
|
||||
|
||||
<h3>Using the IDE for you own projects</h3>
|
||||
<h3>Using the IDE for your own projects</h3>
|
||||
|
||||
<p>Building your own projects using the IDE is slightly more complicated.
|
||||
Firstly, you need to make sure that the project you create as the right
|
||||
|
||||
@@ -61,6 +61,7 @@
|
||||
href="http://www.llnl.gov/">Lawrence Livermore National Laboratories</a>
|
||||
and by the <a href="http://cci.lbl.gov/">Computational Crystallography
|
||||
Initiative</a> at Lawrence Berkeley National Laboratories.
|
||||
|
||||
<hr>
|
||||
|
||||
<h2>Contents</h2>
|
||||
@@ -72,6 +73,14 @@
|
||||
|
||||
<dt><a href="v2/reference.html">Reference Manual</a></dt>
|
||||
|
||||
<dt>Suites:</dt>
|
||||
<dd>
|
||||
<ul>
|
||||
<li><a href="v2/pickle.html">Pickle</a></li>
|
||||
<li><a href="v2/indexing.html">Indexing</a></li>
|
||||
</ul>
|
||||
</dd>
|
||||
|
||||
<dt><a href="v2/configuration.html">Configuration Information</a></dt>
|
||||
|
||||
<dt><a href="v2/platforms.html">Known Working Platforms and
|
||||
@@ -87,22 +96,34 @@
|
||||
|
||||
<dt><a href="../pyste/index.html">Pyste (Boost.Python code generator)</a></dt>
|
||||
|
||||
<dt><a href="news.html">News/Change Log</a></dt>
|
||||
<dt><a href="internals.html">Internals Documentation</a></dt>
|
||||
|
||||
<dt><a href="v2/progress_reports.html">LLNL Progress Reports</a></dt>
|
||||
<dt><a href="news.html">News/Change Log</a></dt>
|
||||
|
||||
<dt><a href="../todo.html">TODO list</a></dt>
|
||||
|
||||
<dt><a href="v2/progress_reports.html">LLNL Progress Reports</a></dt>
|
||||
|
||||
<dt><a href="v2/acknowledgments.html">Acknowledgments</a></dt>
|
||||
</dl>
|
||||
<hr>
|
||||
|
||||
<h2>Articles</h2>
|
||||
|
||||
"<a href="PyConDC_2003/bpl.html">Building Hybrid
|
||||
Systems With Boost Python</a>", by Dave Abrahams and Ralf
|
||||
W. Grosse-Kunstleve (<a href="PyConDC_2003/bpl.pdf">PDF</a>)
|
||||
|
||||
<hr>
|
||||
|
||||
<p>Revised
|
||||
<!--webbot bot="Timestamp" S-Type="EDITED" S-Format="%d %B, %Y" startspan -->
|
||||
17 November, 2002
|
||||
26 August, 2003
|
||||
<!--webbot bot="Timestamp" endspan i-checksum="39359" -->
|
||||
</p>
|
||||
|
||||
<p><i>© Copyright <a href="../../people/dave_abrahams.htm">Dave
|
||||
Abrahams</a> 2002. All Rights Reserved.</i></p>
|
||||
<p><i>© Copyright <a href="../../../people/dave_abrahams.htm">Dave
|
||||
Abrahams</a> 2002-2003. All Rights Reserved.</i></p>
|
||||
</body>
|
||||
</html>
|
||||
|
||||
|
||||
186
doc/internals.html
Executable file
186
doc/internals.html
Executable file
@@ -0,0 +1,186 @@
|
||||
<?xml version="1.0" encoding="utf-8" ?>
|
||||
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
|
||||
<html xmlns="http://www.w3.org/1999/xhtml" xml:lang="en" lang="en">
|
||||
<head>
|
||||
<meta http-equiv="Content-Type" content="text/html; charset=utf-8" />
|
||||
<meta name="generator" content="Docutils 0.3.0: http://docutils.sourceforge.net/" />
|
||||
<title>Boost.Python Internals Boost</title>
|
||||
<link rel="stylesheet" href="../../../rst.css" type="text/css" />
|
||||
</head>
|
||||
<body>
|
||||
<div class="document" id="boost-python-internals-logo">
|
||||
<h1 class="title"><a class="reference" href="index.html">Boost.Python</a> Internals <a class="reference" href="../../../index.htm"><img alt="Boost" src="../../../c++boost.gif" /></a></h1>
|
||||
<div class="section" id="a-conversation-between-brett-calcott-and-david-abrahams">
|
||||
<h1><a name="a-conversation-between-brett-calcott-and-david-abrahams">A conversation between Brett Calcott and David Abrahams</a></h1>
|
||||
<table class="field-list" frame="void" rules="none">
|
||||
<col class="field-name" />
|
||||
<col class="field-body" />
|
||||
<tbody valign="top">
|
||||
<tr class="field"><th class="field-name">copyright:</th><td class="field-body">Copyright David Abrahams and Brett Calcott 2003. See
|
||||
accompanying <a class="reference" href="../../../LICENSE_1_0.txt">license</a> for terms of use.</td>
|
||||
</tr>
|
||||
</tbody>
|
||||
</table>
|
||||
<p>In both of these cases, I'm quite capable of reading code - but the
|
||||
thing I don't get from scanning the source is a sense of the
|
||||
architecture, both structurally, and temporally (er, I mean in what
|
||||
order things go on).</p>
|
||||
<ol class="arabic">
|
||||
<li><p class="first">What happens when you do the following:</p>
|
||||
<pre class="literal-block">
|
||||
struct boring {};
|
||||
...etc...
|
||||
class_<boring>("boring")
|
||||
;
|
||||
</pre>
|
||||
</li>
|
||||
</ol>
|
||||
<p>There seems to be a fair bit going on.</p>
|
||||
<blockquote>
|
||||
<ul class="simple">
|
||||
<li>Python needs a new ClassType to be registered.</li>
|
||||
<li>We need to construct a new type that can hold our boring struct.</li>
|
||||
<li>Inward and outward converters need to be registered for the type.</li>
|
||||
</ul>
|
||||
</blockquote>
|
||||
<p>Can you gesture in the general direction where these things are done?</p>
|
||||
<blockquote>
|
||||
<p>I only have time for a "off-the-top-of-my-head" answer at the moment;
|
||||
I suggest you step through the code with a debugger after reading this
|
||||
to see how it works, fill in details, and make sure I didn't forget
|
||||
anything.</p>
|
||||
<blockquote>
|
||||
<p>A new (Python) subclass of Boost.Python.Instance (see
|
||||
libs/python/src/object/class.cpp) is created by invoking
|
||||
Boost.Python.class, the metatype:</p>
|
||||
<pre class="literal-block">
|
||||
>>> boring = Boost.Python.class(
|
||||
... 'boring'
|
||||
... , bases_tuple # in this case, just ()
|
||||
... , {
|
||||
... '__module__' : module_name
|
||||
... , '__doc__' : doc_string # optional
|
||||
... }
|
||||
... )
|
||||
</pre>
|
||||
<p>A handle to this object is stuck in the m_class_object field
|
||||
of the registration associated with <tt class="literal"><span class="pre">typeid(boring)</span></tt>. The
|
||||
registry will keep that object alive forever, even if you
|
||||
wipe out the 'boring' attribute of the extension module
|
||||
(probably not a good thing).</p>
|
||||
<p>Because you didn't specify <tt class="literal"><span class="pre">class<boring,</span> <span class="pre">non_copyable,</span>
|
||||
<span class="pre">...></span></tt>, a to-python converter for boring is registered which
|
||||
copies its argument into a value_holder held by the the
|
||||
Python boring object.</p>
|
||||
<p>Because you didn't specify <tt class="literal"><span class="pre">class<boring</span> <span class="pre">...>(no_init)</span></tt>,
|
||||
an <tt class="literal"><span class="pre">__init__</span></tt> function object is added to the class
|
||||
dictionary which default-constructs a boring in a
|
||||
value_holder (because you didn't specify some smart pointer
|
||||
or derived wrapper class as a holder) held by the Python
|
||||
boring object.</p>
|
||||
<p><tt class="literal"><span class="pre">register_class_from_python</span></tt> is used to register a
|
||||
from-python converter for <tt class="literal"><span class="pre">shared_ptr<boring></span></tt>.
|
||||
<tt class="literal"><span class="pre">boost::shared_ptr</span></tt>s are special among smart pointers
|
||||
because their Deleter argument can be made to manage the
|
||||
whole Python object, not just the C++ object it contains, no
|
||||
matter how the C++ object is held.</p>
|
||||
<p>If there were any <tt class="literal"><span class="pre">bases<></span></tt>, we'd also be registering the
|
||||
relationship between these base classes and boring in the
|
||||
up/down cast graph (<tt class="literal"><span class="pre">inheritance.[hpp/cpp]</span></tt>).</p>
|
||||
<p>In earlier versions of the code, we'd be registering lvalue
|
||||
from-python converters for the class here, but now
|
||||
from-python conversion for wrapped classes is handled as a
|
||||
special case, before consulting the registry, if the source
|
||||
Python object's metaclass is the Boost.Python metaclass.</p>
|
||||
<p>Hmm, that from-python converter probably ought to be handled
|
||||
the way class converters are, with no explicit conversions
|
||||
registered.</p>
|
||||
</blockquote>
|
||||
</blockquote>
|
||||
<ol class="arabic" start="2">
|
||||
<li><p class="first">Can you give a brief overview of the data structures that are
|
||||
present in the registry</p>
|
||||
<blockquote>
|
||||
<p>The registry is simple: it's just a map from typeid ->
|
||||
registration (see boost/python/converter/registrations.hpp).
|
||||
<tt class="literal"><span class="pre">lvalue_chain</span></tt> and <tt class="literal"><span class="pre">rvalue_chain</span></tt> are simple endogenous
|
||||
linked lists.</p>
|
||||
<p>If you want to know more, just ask.</p>
|
||||
<p>If you want to know about the cast graph, ask me something specific in
|
||||
a separate message.</p>
|
||||
</blockquote>
|
||||
<p>and an overview of the process that happens as a type makes its
|
||||
way from c++ to python and back again.</p>
|
||||
</li>
|
||||
</ol>
|
||||
<blockquote>
|
||||
<p>Big subject. I suggest some background reading: look for relevant
|
||||
info in the LLNL progress reports and the messages they link to.
|
||||
Also,</p>
|
||||
<blockquote>
|
||||
<p><a class="reference" href="http://mail.python.org/pipermail/c++-sig/2002-May/001023.html">http://mail.python.org/pipermail/c++-sig/2002-May/001023.html</a></p>
|
||||
<p><a class="reference" href="http://mail.python.org/pipermail/c++-sig/2002-December/003115.html">http://mail.python.org/pipermail/c++-sig/2002-December/003115.html</a></p>
|
||||
<p><a class="reference" href="http://aspn.activestate.com/ASPN/Mail/Message/1280898">http://aspn.activestate.com/ASPN/Mail/Message/1280898</a></p>
|
||||
<p><a class="reference" href="http://mail.python.org/pipermail/c++-sig/2002-July/001755.html">http://mail.python.org/pipermail/c++-sig/2002-July/001755.html</a></p>
|
||||
</blockquote>
|
||||
<p>from c++ to python:</p>
|
||||
<blockquote>
|
||||
<p>It depends on the type and the call policies in use or, for
|
||||
<tt class="literal"><span class="pre">call<>(...)</span></tt>, <tt class="literal"><span class="pre">call_method<>(...)</span></tt>, or <tt class="literal"><span class="pre">object(...)</span></tt>, if
|
||||
<tt class="literal"><span class="pre">ref</span></tt> or <tt class="literal"><span class="pre">ptr</span></tt> is used. There are also two basic
|
||||
categories to to-python conversion, "return value" conversion
|
||||
(for Python->C++ calls) and "argument" conversion (for
|
||||
C++->Python calls and explicit <tt class="literal"><span class="pre">object()</span></tt> conversions). The
|
||||
behavior of these two categories differs subtly in various ways
|
||||
whose details I forget at the moment. You can probably find
|
||||
the answers in the above references, and certainly in the code.</p>
|
||||
<p>The "default" case is by-value (copying) conversion, which uses
|
||||
to_python_value as a to-python converter.</p>
|
||||
<blockquote>
|
||||
<p>Since there can sensibly be only one way to convert any type
|
||||
to python (disregarding the idea of scoped registries for the
|
||||
moment), it makes sense that to-python conversions can be
|
||||
handled by specializing a template. If the type is one of
|
||||
the types handled by a built-in conversion
|
||||
(builtin_converters.hpp), the corresponding template
|
||||
specialization of to_python_value gets used.</p>
|
||||
<p>Otherwise, to_python_value uses the <tt class="literal"><span class="pre">m_to_python</span></tt>
|
||||
function in the registration for the C++ type.</p>
|
||||
</blockquote>
|
||||
<p>Other conversions, like by-reference conversions, are only
|
||||
available for wrapped classes, and are requested explicitly by
|
||||
using <tt class="literal"><span class="pre">ref(...)</span></tt>, <tt class="literal"><span class="pre">ptr(...)</span></tt>, or by specifying different
|
||||
CallPolicies for a call, which can cause a different to-python
|
||||
converter to be used. These conversions are never registered
|
||||
anywhere, though they do need to use the registration to find
|
||||
the Python class corresponding to the C++ type being referred
|
||||
to. They just build a new Python instance and stick the
|
||||
appropriate Holder instance in it.</p>
|
||||
</blockquote>
|
||||
<p>from python to C++:</p>
|
||||
<blockquote>
|
||||
<p>Once again I think there is a distinction between "return value"
|
||||
and "argument" conversions, and I forget exactly what that is.</p>
|
||||
<p>What happens depends on whether an lvalue conversion is needed
|
||||
(see <a class="reference" href="http://mail.python.org/pipermail/c++-sig/2002-May/001023.html">http://mail.python.org/pipermail/c++-sig/2002-May/001023.html</a>)
|
||||
All lvalue conversions are also registered in a type's rvalue
|
||||
conversion chain, since when an rvalue will do, an lvalue is
|
||||
certainly good enough.</p>
|
||||
<p>An lvalue conversion can be done in one step (just get me the
|
||||
pointer to the object - it can be <tt class="literal"><span class="pre">NULL</span></tt> if no conversion is
|
||||
possible) while an rvalue conversion requires two steps to
|
||||
support wrapped function overloading and multiple converters for
|
||||
a given C++ target type: first tell me if a conversion is
|
||||
possible, then construct the converted object as a second step.</p>
|
||||
</blockquote>
|
||||
</blockquote>
|
||||
</div>
|
||||
</div>
|
||||
<hr class="footer"/>
|
||||
<div class="footer">
|
||||
<a class="reference" href="internals.rst">View document source</a>.
|
||||
Generated on: 2003-09-12 14:51 UTC.
|
||||
Generated by <a class="reference" href="http://docutils.sourceforge.net/">Docutils</a> from <a class="reference" href="http://docutils.sourceforge.net/rst.html">reStructuredText</a> source.
|
||||
</div>
|
||||
</body>
|
||||
</html>
|
||||
181
doc/internals.rst
Executable file
181
doc/internals.rst
Executable file
@@ -0,0 +1,181 @@
|
||||
===================================
|
||||
Boost.Python_ Internals |(logo)|__
|
||||
===================================
|
||||
|
||||
.. |(logo)| image:: ../../../c++boost.gif
|
||||
:alt: Boost
|
||||
|
||||
__ ../../../index.htm
|
||||
|
||||
.. _`Boost.Python`: index.html
|
||||
|
||||
.. _license: ../../../LICENSE_1_0.txt
|
||||
|
||||
|
||||
-------------------------------------------------------
|
||||
A conversation between Brett Calcott and David Abrahams
|
||||
-------------------------------------------------------
|
||||
|
||||
:copyright: Copyright David Abrahams and Brett Calcott 2003. See
|
||||
accompanying license_ for terms of use.
|
||||
|
||||
In both of these cases, I'm quite capable of reading code - but the
|
||||
thing I don't get from scanning the source is a sense of the
|
||||
architecture, both structurally, and temporally (er, I mean in what
|
||||
order things go on).
|
||||
|
||||
1) What happens when you do the following::
|
||||
|
||||
struct boring {};
|
||||
...etc...
|
||||
class_<boring>("boring")
|
||||
;
|
||||
|
||||
There seems to be a fair bit going on.
|
||||
|
||||
- Python needs a new ClassType to be registered.
|
||||
- We need to construct a new type that can hold our boring struct.
|
||||
- Inward and outward converters need to be registered for the type.
|
||||
|
||||
Can you gesture in the general direction where these things are done?
|
||||
|
||||
I only have time for a "off-the-top-of-my-head" answer at the moment;
|
||||
I suggest you step through the code with a debugger after reading this
|
||||
to see how it works, fill in details, and make sure I didn't forget
|
||||
anything.
|
||||
|
||||
A new (Python) subclass of Boost.Python.Instance (see
|
||||
libs/python/src/object/class.cpp) is created by invoking
|
||||
Boost.Python.class, the metatype::
|
||||
|
||||
>>> boring = Boost.Python.class(
|
||||
... 'boring'
|
||||
... , bases_tuple # in this case, just ()
|
||||
... , {
|
||||
... '__module__' : module_name
|
||||
... , '__doc__' : doc_string # optional
|
||||
... }
|
||||
... )
|
||||
|
||||
A handle to this object is stuck in the m_class_object field
|
||||
of the registration associated with ``typeid(boring)``. The
|
||||
registry will keep that object alive forever, even if you
|
||||
wipe out the 'boring' attribute of the extension module
|
||||
(probably not a good thing).
|
||||
|
||||
Because you didn't specify ``class<boring, non_copyable,
|
||||
...>``, a to-python converter for boring is registered which
|
||||
copies its argument into a value_holder held by the the
|
||||
Python boring object.
|
||||
|
||||
Because you didn't specify ``class<boring ...>(no_init)``,
|
||||
an ``__init__`` function object is added to the class
|
||||
dictionary which default-constructs a boring in a
|
||||
value_holder (because you didn't specify some smart pointer
|
||||
or derived wrapper class as a holder) held by the Python
|
||||
boring object.
|
||||
|
||||
``register_class_from_python`` is used to register a
|
||||
from-python converter for ``shared_ptr<boring>``.
|
||||
``boost::shared_ptr``\ s are special among smart pointers
|
||||
because their Deleter argument can be made to manage the
|
||||
whole Python object, not just the C++ object it contains, no
|
||||
matter how the C++ object is held.
|
||||
|
||||
If there were any ``bases<>``, we'd also be registering the
|
||||
relationship between these base classes and boring in the
|
||||
up/down cast graph (``inheritance.[hpp/cpp]``).
|
||||
|
||||
In earlier versions of the code, we'd be registering lvalue
|
||||
from-python converters for the class here, but now
|
||||
from-python conversion for wrapped classes is handled as a
|
||||
special case, before consulting the registry, if the source
|
||||
Python object's metaclass is the Boost.Python metaclass.
|
||||
|
||||
Hmm, that from-python converter probably ought to be handled
|
||||
the way class converters are, with no explicit conversions
|
||||
registered.
|
||||
|
||||
2) Can you give a brief overview of the data structures that are
|
||||
present in the registry
|
||||
|
||||
The registry is simple: it's just a map from typeid ->
|
||||
registration (see boost/python/converter/registrations.hpp).
|
||||
``lvalue_chain`` and ``rvalue_chain`` are simple endogenous
|
||||
linked lists.
|
||||
|
||||
If you want to know more, just ask.
|
||||
|
||||
If you want to know about the cast graph, ask me something specific in
|
||||
a separate message.
|
||||
|
||||
and an overview of the process that happens as a type makes its
|
||||
way from c++ to python and back again.
|
||||
|
||||
Big subject. I suggest some background reading: look for relevant
|
||||
info in the LLNL progress reports and the messages they link to.
|
||||
Also,
|
||||
|
||||
http://mail.python.org/pipermail/c++-sig/2002-May/001023.html
|
||||
|
||||
http://mail.python.org/pipermail/c++-sig/2002-December/003115.html
|
||||
|
||||
http://aspn.activestate.com/ASPN/Mail/Message/1280898
|
||||
|
||||
http://mail.python.org/pipermail/c++-sig/2002-July/001755.html
|
||||
|
||||
from c++ to python:
|
||||
|
||||
It depends on the type and the call policies in use or, for
|
||||
``call<>(...)``, ``call_method<>(...)``, or ``object(...)``, if
|
||||
``ref`` or ``ptr`` is used. There are also two basic
|
||||
categories to to-python conversion, "return value" conversion
|
||||
(for Python->C++ calls) and "argument" conversion (for
|
||||
C++->Python calls and explicit ``object()`` conversions). The
|
||||
behavior of these two categories differs subtly in various ways
|
||||
whose details I forget at the moment. You can probably find
|
||||
the answers in the above references, and certainly in the code.
|
||||
|
||||
The "default" case is by-value (copying) conversion, which uses
|
||||
to_python_value as a to-python converter.
|
||||
|
||||
Since there can sensibly be only one way to convert any type
|
||||
to python (disregarding the idea of scoped registries for the
|
||||
moment), it makes sense that to-python conversions can be
|
||||
handled by specializing a template. If the type is one of
|
||||
the types handled by a built-in conversion
|
||||
(builtin_converters.hpp), the corresponding template
|
||||
specialization of to_python_value gets used.
|
||||
|
||||
Otherwise, to_python_value uses the ``m_to_python``
|
||||
function in the registration for the C++ type.
|
||||
|
||||
Other conversions, like by-reference conversions, are only
|
||||
available for wrapped classes, and are requested explicitly by
|
||||
using ``ref(...)``, ``ptr(...)``, or by specifying different
|
||||
CallPolicies for a call, which can cause a different to-python
|
||||
converter to be used. These conversions are never registered
|
||||
anywhere, though they do need to use the registration to find
|
||||
the Python class corresponding to the C++ type being referred
|
||||
to. They just build a new Python instance and stick the
|
||||
appropriate Holder instance in it.
|
||||
|
||||
|
||||
from python to C++:
|
||||
|
||||
Once again I think there is a distinction between "return value"
|
||||
and "argument" conversions, and I forget exactly what that is.
|
||||
|
||||
What happens depends on whether an lvalue conversion is needed
|
||||
(see http://mail.python.org/pipermail/c++-sig/2002-May/001023.html)
|
||||
All lvalue conversions are also registered in a type's rvalue
|
||||
conversion chain, since when an rvalue will do, an lvalue is
|
||||
certainly good enough.
|
||||
|
||||
An lvalue conversion can be done in one step (just get me the
|
||||
pointer to the object - it can be ``NULL`` if no conversion is
|
||||
possible) while an rvalue conversion requires two steps to
|
||||
support wrapped function overloading and multiple converters for
|
||||
a given C++ target type: first tell me if a conversion is
|
||||
possible, then construct the converted object as a second step.
|
||||
|
||||
108
doc/news.html
108
doc/news.html
@@ -3,7 +3,7 @@
|
||||
<html>
|
||||
<head>
|
||||
<meta name="generator" content=
|
||||
"HTML Tidy for Windows (vers 1st August 2002), see www.w3.org">
|
||||
"HTML Tidy for Cygwin (vers 1st April 2002), see www.w3.org">
|
||||
<meta http-equiv="Content-Type" content="text/html; charset=iso-8859-1">
|
||||
<link rel="stylesheet" type="text/css" href="boost.css">
|
||||
|
||||
@@ -29,18 +29,100 @@
|
||||
<hr>
|
||||
|
||||
<dl class="page-index">
|
||||
<dt>11 Sept 2003</dt>
|
||||
|
||||
<dd>
|
||||
<ul>
|
||||
<li>Changed the response to multiple to-python converters being
|
||||
registered for the same type from a hard error into warning;
|
||||
Boost.Python now reports the offending type in the message.</li>
|
||||
|
||||
<li>Added builtin <code>std::wstring</code> conversions</li>
|
||||
|
||||
<li>Added <code>std::out_of_range</code> => Python
|
||||
<code>IndexError</code> exception conversion, thanks to <a href=
|
||||
"mailto:RaoulGough-at-yahoo.co.uk">Raoul Gough</a></li>
|
||||
</ul>
|
||||
</dd>
|
||||
|
||||
<dt>9 Sept 2003</dt>
|
||||
|
||||
<dd>Added new <code><a href="v2/str.html#str-spec">str</a></code></dd>
|
||||
|
||||
<dt>constructors which take a range of characters, allowing strings
|
||||
containing nul (<code>'\0'</code>) characters.</dt>
|
||||
|
||||
<dt>8 Sept 2003</dt>
|
||||
|
||||
<dd>Added the ability to create methods from function objects (with an
|
||||
<code>operator()</code>); see the <a href=
|
||||
"v2/make_function.html#make_function-spec">make_function</a> docs for
|
||||
more info.</dd>
|
||||
|
||||
<dt>10 August 2003</dt>
|
||||
|
||||
<dd>Added the new <code>properties</code> unit tests contributed by <a
|
||||
href="mailto:romany-at-actimize.com">Roman Yakovenko</a> and documented
|
||||
<code>add_static_property</code> at his urging.</dd>
|
||||
|
||||
<dt>1 August 2003</dt>
|
||||
|
||||
<dd>
|
||||
Added the new <code>arg</code> class contributed by <a href=
|
||||
"mailto:nickm-at-sitius.com">Nikolay Mladenov</a> which supplies the
|
||||
ability to wrap functions that can be called with ommitted arguments
|
||||
in the middle:
|
||||
<pre>
|
||||
void f(int x = 0, double y = 3.14, std::string z = std::string("foo"));
|
||||
|
||||
BOOST_PYTHON_MODULE(test)
|
||||
{
|
||||
def("f", f
|
||||
, (arg("x", 0), arg("y", 3.14), arg("z", "foo")));
|
||||
}
|
||||
|
||||
</pre>
|
||||
And in Python:
|
||||
<pre>
|
||||
>>> import test
|
||||
>>> f(0, z = "bar")
|
||||
>>> f(z = "bar", y = 0.0)
|
||||
</pre>
|
||||
Thanks, Nikolay!
|
||||
</dd>
|
||||
|
||||
<dt>22 July 2003</dt>
|
||||
|
||||
<dd>Killed the dreaded "bad argument type for builtin operation" error.
|
||||
Argument errors now show the actual and expected argument types!</dd>
|
||||
|
||||
<dt>19 July 2003</dt>
|
||||
|
||||
<dd>Added the new <code><a href=
|
||||
"v2/return_arg.html">return_arg</a></code> policy from <a href=
|
||||
"mailto:nickm-at-sitius.com">Nikolay Mladenov</a>. Thanks,
|
||||
Nikolay!</dd>
|
||||
|
||||
<dt>18 March, 2003</dt>
|
||||
|
||||
<dd><a href="mailto:Gottfried.Ganssauge-at-haufe.de">Gottfried
|
||||
Ganßauge</a> has contributed <a href=
|
||||
"v2/opaque_pointer_converter.html">opaque pointer support</a>.<br>
|
||||
<a href="mailto:nicodemus-at-globalite.com.br">Bruno da Silva de Oliveira</a>
|
||||
has contributed the exciting <a href="../pyste/index.html">Pyste</a>
|
||||
("Pie-steh") package.</dd>
|
||||
|
||||
<dt>24 February 2003</dt>
|
||||
|
||||
<dd>Finished improved support
|
||||
for <code>boost::shared_ptr</code>. Now any wrapped object of
|
||||
C++ class <code>X</code> can be converted automatically
|
||||
to <code>shared_ptr<X></code>, regardless of how it was
|
||||
wrapped. The <code>shared_ptr</code> will manage the lifetime
|
||||
of the Python object which supplied the <code>X</code>, rather
|
||||
than just the <code>X</code> object itself, and when such
|
||||
a <code>shared_ptr</code> is converted back to Python, the
|
||||
original Python object will be returned.</dd>
|
||||
|
||||
<dd>Finished improved support for <code>boost::shared_ptr</code>. Now
|
||||
any wrapped object of C++ class <code>X</code> can be converted
|
||||
automatically to <code>shared_ptr<X></code>, regardless of how it
|
||||
was wrapped. The <code>shared_ptr</code> will manage the lifetime of
|
||||
the Python object which supplied the <code>X</code>, rather than just
|
||||
the <code>X</code> object itself, and when such a
|
||||
<code>shared_ptr</code> is converted back to Python, the original
|
||||
Python object will be returned.</dd>
|
||||
|
||||
<dt>19 January 2003</dt>
|
||||
|
||||
<dd>Integrated <code>staticmethod</code> support from <a href=
|
||||
@@ -98,12 +180,12 @@
|
||||
|
||||
<p>Revised
|
||||
<!--webbot bot="Timestamp" S-Type="EDITED" S-Format="%d %B, %Y" startspan -->
|
||||
20 December, 2002
|
||||
11 September 2003
|
||||
<!--webbot bot="Timestamp" endspan i-checksum="39359" -->
|
||||
</p>
|
||||
|
||||
<p><i>© Copyright <a href="../../../people/dave_abrahams.htm">Dave
|
||||
Abrahams</a> 2002. All Rights Reserved.</i></p>
|
||||
Abrahams</a> 2002-2003. All Rights Reserved.</i></p>
|
||||
</body>
|
||||
</html>
|
||||
|
||||
|
||||
@@ -3,7 +3,7 @@
|
||||
<html>
|
||||
<head>
|
||||
<meta name="generator" content=
|
||||
"HTML Tidy for Windows (vers 1st August 2002), see www.w3.org">
|
||||
"HTML Tidy for Cygwin (vers 1st April 2002), see www.w3.org">
|
||||
<meta http-equiv="Content-Type" content="text/html; charset=iso-8859-1">
|
||||
<link rel="stylesheet" type="text/css" href="boost.css">
|
||||
|
||||
@@ -38,28 +38,23 @@
|
||||
page .</p>
|
||||
<hr>
|
||||
|
||||
<h3>Enterprise Software</h3>
|
||||
<h3>Data Analysis</h3>
|
||||
|
||||
<dl class="page-index">
|
||||
<dt><b><a href="http://openwbem.sourceforge.net">OpenWBEM</a></b></dt>
|
||||
<dt><b><a href=
|
||||
"http://www.neuralynx.com/neuralab/index.htm">NeuraLab</a></b></dt>
|
||||
|
||||
<dd>
|
||||
The OpenWBEM project is an effort to develop an open-source
|
||||
implementation of Web Based Enterprise Management suitable for
|
||||
commercial and non-commercial application
|
||||
|
||||
<p><a href="mailto:dnuffer@sco.com">Dan Nuffer</a> writes:</p>
|
||||
|
||||
<blockquote>
|
||||
I'm using Boost.Python to wrap the client API of OpenWBEM.This will
|
||||
make it easier to do rapid prototyping, testing, and scripting when
|
||||
developing management solutions that use WBEM.
|
||||
</blockquote>
|
||||
</dd>
|
||||
<dd>Neuralab is a data analysis environment specifically tailored for
|
||||
neural data from <a href="http://www.neuralynx.com">Neuralynx</a>
|
||||
acquisition systems. Neuralab combines presentation quality graphics, a
|
||||
numerical analysis library, and the <a href=
|
||||
"http://www.python.org">Python</a> scripting engine in a single
|
||||
application. With Neuralab, Neuralynx users can perform common analysis
|
||||
tasks with just a few mouse clicks. More advanced users can create
|
||||
custom Python scripts, which can optionally be assigned to menus and
|
||||
mouse clicks.</dd>
|
||||
</dl>
|
||||
|
||||
<h3>Financial Analysis</h3>
|
||||
|
||||
<dl class="page-index">
|
||||
<dt><b>TSLib</b> - <a href="http://www.fortressinv.com">Fortress
|
||||
Investment Group LLC</a></dt>
|
||||
@@ -87,30 +82,85 @@
|
||||
</dd>
|
||||
</dl>
|
||||
|
||||
<h3>Educational</h3>
|
||||
|
||||
<dl class="page-index">
|
||||
<dt><a href="http://edu.kde.org/kig"><b>Kig</b></a></dt>
|
||||
|
||||
<dd>
|
||||
<p>KDE Interactive Geometry is a high-school level educational tool,
|
||||
built for the KDE desktop. It is a nice tool to let students work
|
||||
with geometrical constructions. It is meant to be the most intuitive,
|
||||
yet featureful application of its kind.</p>
|
||||
|
||||
<p>Versions after 0.6.x (will) support objects built by the user
|
||||
himself in the Python language. The exporting of the relevant
|
||||
internal API's were done using Boost.Python, which made the process
|
||||
very easy.</p>
|
||||
</dd>
|
||||
</dl>
|
||||
|
||||
<h3>Enterprise Software</h3>
|
||||
|
||||
<dl class="page-index">
|
||||
<dt><b><a href="http://openwbem.sourceforge.net">OpenWBEM</a></b></dt>
|
||||
|
||||
<dd>
|
||||
The OpenWBEM project is an effort to develop an open-source
|
||||
implementation of Web Based Enterprise Management suitable for
|
||||
commercial and non-commercial application
|
||||
|
||||
<p><a href="mailto:dnuffer@sco.com">Dan Nuffer</a> writes:</p>
|
||||
|
||||
<blockquote>
|
||||
I'm using Boost.Python to wrap the client API of OpenWBEM.This will
|
||||
make it easier to do rapid prototyping, testing, and scripting when
|
||||
developing management solutions that use WBEM.
|
||||
</blockquote>
|
||||
</dd>
|
||||
|
||||
<dt><b><a href="http://www.transversal.com">Metafaq</a></b></dt>
|
||||
|
||||
<dd>
|
||||
Metafaq, from <a href="http://www.transversal.com">Transversal,
|
||||
Inc.</a>, is an enterprise level online knowledge base management
|
||||
system.
|
||||
|
||||
<p><a href="mailto:ben.young-at-transversal.com">Ben Young</a>
|
||||
writes:</p>
|
||||
|
||||
<blockquote>
|
||||
Boost.Python is used in an automated process to generate python
|
||||
bindings to our api which is exposed though multiple backends and
|
||||
frontends. This allows us to write quick tests and bespoke scripts
|
||||
to perform one off tasks without having to go through the full
|
||||
compilation cycle.
|
||||
</blockquote>
|
||||
</dd>
|
||||
</dl>
|
||||
|
||||
<h3>Graphics</h3>
|
||||
|
||||
<dl class="page-index">
|
||||
<dt><b><a href=
|
||||
"http://www.openscenegraph.org">OpenSceneGraph</a></b></dt>
|
||||
<dt><b><a href="http://sourceforge.net/projects/pyosg">OpenSceneGraph
|
||||
Bindings</a></b></dt>
|
||||
|
||||
<dd><a href="mailto:gideon@computer.org">Gideon May</a> has created a
|
||||
set of bindings for OpenSceneGraph, a cross-platform C++/OpenGL library
|
||||
for the real-time visualization. You can read the release announcement
|
||||
at <a href="http://www.hypereyes.com">www.hypereyes.com</a>. <a href=
|
||||
"mailto:gideon@computer.org">Contact Gideon</a> for more
|
||||
information.<br>
|
||||
set of bindings for <a href=
|
||||
"http://www.openscenegraph.org">OpenSceneGraph</a>, a cross-platform
|
||||
C++/OpenGL library for the real-time visualization.<br>
|
||||
</dd>
|
||||
|
||||
<dt><a href=
|
||||
"http://pythonmagick.procoders.net/"><b>PythonMagick</b></a></dt>
|
||||
"http://www.procoders.net/pythonmagick"><b>PythonMagick</b></a></dt>
|
||||
|
||||
<dd>PythonMagick binds the <a href=
|
||||
"http://www.imagemagick.org">ImageMagick</a> image manipulation library
|
||||
to Python.<br>
|
||||
"http://www.graphicsmagick.org">GraphicsMagick</a> image manipulation
|
||||
library to Python.<br>
|
||||
</dd>
|
||||
|
||||
<dt><b>HippoDraw</b> - <a href="http://www.slac.stanford.edu">Stanford
|
||||
Linear Accelerator Center</a></dt>
|
||||
<dt><b><a href=
|
||||
"http://www.slac.stanford.edu/grp/ek/hippodraw/index.html">HippoDraw</a></b></dt>
|
||||
|
||||
<dd>
|
||||
HippoDraw is a data analysis environment consisting of a canvas upon
|
||||
@@ -120,8 +170,8 @@
|
||||
so that all the manipulation can be done from either Python or the
|
||||
GUI.
|
||||
|
||||
<p><a href="mailto:Paul_Kunz@SLAC.Stanford.EDU">Paul F. Kunz</a>
|
||||
writes:</p>
|
||||
<p>Before the web page came online, <a href=
|
||||
"mailto:Paul_Kunz@SLAC.Stanford.EDU">Paul F. Kunz</a> wrote:</p>
|
||||
|
||||
<blockquote>
|
||||
Don't have a web page for the project, but the organization's is <a
|
||||
@@ -207,17 +257,88 @@
|
||||
Boost.Python plays and essential role.</p>
|
||||
</blockquote>
|
||||
</dd>
|
||||
|
||||
<dt><b><a href="http://www.esss.com.br">ESSS</a></b></dt>
|
||||
|
||||
<dd>
|
||||
ESSS (Engineering Simulation and Scientific Software) is a company
|
||||
that provides engineering solutions and acts in the brazilian and
|
||||
south-american market providing products and services related to
|
||||
Computational Fluid Dynamics and Image Analysis.
|
||||
|
||||
<p><a href="mailto:bruno@esss.com.br">Bruno da Silva de Oliveira</a>
|
||||
writes:</p>
|
||||
|
||||
<blockquote>
|
||||
Recently we moved our work from working exclusively with C++ to an
|
||||
hybrid-language approach, using Python and C++, with Boost.Python
|
||||
providing the layer between the two. The results are great so far!
|
||||
</blockquote>
|
||||
|
||||
<p>Two projects have been developed so far with this technology:</p>
|
||||
|
||||
<p><b><a href="http://www.esss.com.br/dev_simba.phtml">Simba</a></b>
|
||||
provides 3D visualization of geological formations gattered from the
|
||||
simulation of the evolution of oil systems, allowing the user to
|
||||
analyse various aspects of the simulation, like deformation, pressure
|
||||
and fluids, along the time of the simulation.</p>
|
||||
|
||||
<p><b><a href="http://www.esss.com.br/dev_aero.phtml">Aero</a></b>
|
||||
aims to construct a CFD with brazilian technology, which involves
|
||||
various companies and universities. ESSS is responsible for various
|
||||
of the application modules, including GUI and post-processing of
|
||||
results.</p>
|
||||
</dd>
|
||||
|
||||
<dt><b><a href="http://www.rationaldiscovery.com">Rational Discovery
|
||||
LLC</a></b></dt>
|
||||
|
||||
<dd>
|
||||
Rational Discovery provides computational modeling, combinatorial
|
||||
library design and custom software development services to the
|
||||
pharmaceutical, biotech and chemical industries. We do a substantial
|
||||
amount of internal research to develop new approaches for applying
|
||||
machine-learning techniques to solve chemical problems. Because we're
|
||||
a small organization and chemistry is a large and complex field, it
|
||||
is essential that we be able to quickly and easily prototype and test
|
||||
new algorithms.
|
||||
|
||||
<p>For our internal software, we implement core data structures in C
|
||||
and expose them to Python using Boost.Python. Algorithm development
|
||||
is done in Python and then translated to C if required (often it's
|
||||
not). This hybrid development approach not only greatly increases our
|
||||
productivity, but it also allows "non-developers" (people without C
|
||||
experience) to take part in method development. Learning C is a
|
||||
daunting task, but "Python fits your brain." (Thanks to Bruce Eckel
|
||||
for the quote.)</p>
|
||||
</dd>
|
||||
</dl>
|
||||
|
||||
<h3>Tools</h3>
|
||||
|
||||
<dl>
|
||||
<dt><a href="http://www.jayacard.org"><b>Jayacard</b></a></dt>
|
||||
|
||||
<dd>
|
||||
Jayacard aims at developing a secure portable open source operating
|
||||
system for contactless smart cards and a complete suite of high
|
||||
quality development tools to ease smart card OS and application
|
||||
development.
|
||||
|
||||
<p>The core of the smart card reader management is written in C++ but
|
||||
all the development tools are written in the friendly Python
|
||||
language. Boost plays the fundamental role of binding the tools to
|
||||
our core smart card reader library.</p>
|
||||
</dd>
|
||||
</dl>
|
||||
<hr>
|
||||
|
||||
<p>Revised
|
||||
<!--webbot bot="Timestamp" S-Type="EDITED" S-Format="%d %B, %Y" startspan -->
|
||||
16 November, 2002
|
||||
<!--webbot bot="Timestamp" endspan i-checksum="39359" -->
|
||||
</p>
|
||||
15 July, 2003</p>
|
||||
|
||||
<p><i>© Copyright <a href="../../../people/dave_abrahams.htm">Dave
|
||||
Abrahams</a> 2002. All Rights Reserved.</i></p>
|
||||
Abrahams</a> 2002-2003. All Rights Reserved.</i></p>
|
||||
</body>
|
||||
</html>
|
||||
|
||||
|
||||
@@ -3,7 +3,7 @@
|
||||
<html>
|
||||
<head>
|
||||
<meta name="generator" content=
|
||||
"HTML Tidy for Windows (vers 1st August 2002), see www.w3.org">
|
||||
"HTML Tidy for Cygwin (vers 1st April 2002), see www.w3.org">
|
||||
<meta http-equiv="Content-Type" content="text/html; charset=iso-8859-1">
|
||||
<link rel="stylesheet" type="text/css" href="boost.css">
|
||||
|
||||
@@ -31,7 +31,9 @@
|
||||
<h2>Synopsis</h2>
|
||||
|
||||
<p>This is a list of available resources for support with Boost.Python
|
||||
problems and feature requests.</p>
|
||||
problems and feature requests. <b>Please try to resist emailing the
|
||||
Boost.Python developers directly for support.</b> Use the following
|
||||
resources instead; the developers are listening!</p>
|
||||
<hr>
|
||||
|
||||
<dl class="page-index">
|
||||
@@ -41,9 +43,11 @@
|
||||
you Boost.Python.<br>
|
||||
</dt>
|
||||
|
||||
<dt><b><a href="http://www.python.org/sigs/c++-sig/">The Python
|
||||
<dt><b><a href=
|
||||
"http://www.boost.org/more/mailing_lists.htm#cplussig">The Python
|
||||
C++-sig</a></b> mailing list is a forum for discussing Python/C++
|
||||
interoperability, and Boost.Python in particular.<br>
|
||||
interoperability, and Boost.Python in particular. Post your
|
||||
Boost.Python questions here.<br>
|
||||
</dt>
|
||||
|
||||
<dt>The <b>Boost.Python <a href=
|
||||
@@ -51,18 +55,17 @@
|
||||
Pages</a></b> established by Mike Rovner as part of the <a href=
|
||||
"http://www.python.org/cgi-bin/moinmoin">PythonInfo Wiki</a> serves as
|
||||
a forum to gather peoples' experience and as a cookbook.<br>
|
||||
</dt>
|
||||
</dt>
|
||||
</dl>
|
||||
<hr>
|
||||
|
||||
<p>Revised
|
||||
<!--webbot bot="Timestamp" S-Type="EDITED" S-Format="%d %B, %Y" startspan -->
|
||||
17 November, 2002
|
||||
<!--webbot bot="Timestamp" endspan i-checksum="39359" -->
|
||||
12 Sept, 2003 <!--webbot bot="Timestamp" endspan i-checksum="39359" -->
|
||||
</p>
|
||||
|
||||
<p><i>© Copyright <a href="../../../people/dave_abrahams.htm">Dave
|
||||
Abrahams</a> 2002. All Rights Reserved.</i></p>
|
||||
Abrahams</a> 2003.</i></p>
|
||||
</body>
|
||||
</html>
|
||||
|
||||
|
||||
@@ -26,7 +26,7 @@
|
||||
</table>
|
||||
<p>
|
||||
It was mentioned in passing in the previous section that
|
||||
<tt>BOOST_PYTHON_FUNCTION_OVERLOADS</tt> and <tt>BOOST_PYTHON_FUNCTION_OVERLOADS</tt>
|
||||
<tt>BOOST_PYTHON_FUNCTION_OVERLOADS</tt> and <tt>BOOST_PYTHON_MEMBER_FUNCTION_OVERLOADS</tt>
|
||||
can also be used for overloaded functions and member functions with a
|
||||
common sequence of initial arguments. Here is an example:</p>
|
||||
<code><pre>
|
||||
|
||||
@@ -37,6 +37,11 @@ with every boost distribution: <b>bjam</b>.</p>
|
||||
Besides bjam, there are of course other ways to get your module built.
|
||||
What's written here should not be taken as "the one and only way".
|
||||
There are of course other build tools apart from <tt>bjam</tt>.
|
||||
|
||||
Take note however that the preferred build tool for Boost.Python is bjam.
|
||||
There are so many ways to set up the build incorrectly. Experience shows
|
||||
that 90% of the "I can't build Boost.Python" problems come from people
|
||||
who had to use a different tool.
|
||||
</td>
|
||||
</tr>
|
||||
</table>
|
||||
|
||||
210
doc/tutorial/doc/creating_packages.html
Normal file
210
doc/tutorial/doc/creating_packages.html
Normal file
@@ -0,0 +1,210 @@
|
||||
<html>
|
||||
<head>
|
||||
<!-- Generated by the Spirit (http://spirit.sf.net) QuickDoc -->
|
||||
<title>Creating Packages</title>
|
||||
<link rel="stylesheet" href="theme/style.css" type="text/css">
|
||||
<link rel="prev" href="general_techniques.html">
|
||||
<link rel="next" href="extending_wrapped_objects_in_python.html">
|
||||
</head>
|
||||
<body>
|
||||
<table width="100%" height="48" border="0" cellspacing="2">
|
||||
<tr>
|
||||
<td><img src="theme/c%2B%2Bboost.gif">
|
||||
</td>
|
||||
<td width="85%">
|
||||
<font size="6" face="Verdana, Arial, Helvetica, sans-serif"><b>Creating Packages</b></font>
|
||||
</td>
|
||||
</tr>
|
||||
</table>
|
||||
<br>
|
||||
<table border="0">
|
||||
<tr>
|
||||
<td width="30"><a href="../index.html"><img src="theme/u_arr.gif" border="0"></a></td>
|
||||
<td width="30"><a href="general_techniques.html"><img src="theme/l_arr.gif" border="0"></a></td>
|
||||
<td width="20"><a href="extending_wrapped_objects_in_python.html"><img src="theme/r_arr.gif" border="0"></a></td>
|
||||
</tr>
|
||||
</table>
|
||||
<p>
|
||||
A Python package is a collection of modules that provide to the user a certain
|
||||
functionality. If you're not familiar on how to create packages, a good
|
||||
introduction to them is provided in the
|
||||
<a href="http://www.python.org/doc/current/tut/node8.html">
|
||||
Python Tutorial</a>.</p>
|
||||
<p>
|
||||
But we are wrapping C++ code, using Boost.Python. How can we provide a nice
|
||||
package interface to our users? To better explain some concepts, let's work
|
||||
with an example.</p>
|
||||
<p>
|
||||
We have a C++ library that works with sounds: reading and writing various
|
||||
formats, applying filters to the sound data, etc. It is named (conveniently)
|
||||
<tt>sounds</tt>. Our library already has a neat C++ namespace hierarchy, like so: </p>
|
||||
<code><pre>
|
||||
<span class=identifier>sounds</span><span class=special>::</span><span class=identifier>core
|
||||
</span><span class=identifier>sounds</span><span class=special>::</span><span class=identifier>io
|
||||
</span><span class=identifier>sounds</span><span class=special>::</span><span class=identifier>filters
|
||||
</span></pre></code>
|
||||
<p>
|
||||
We would like to present this same hierarchy to the Python user, allowing him
|
||||
to write code like this:</p>
|
||||
<code><pre>
|
||||
<span class=identifier>import </span><span class=identifier>sounds</span><span class=special>.</span><span class=identifier>filters
|
||||
</span><span class=identifier>sounds</span><span class=special>.</span><span class=identifier>filters</span><span class=special>.</span><span class=identifier>echo</span><span class=special>(...) </span>##<span class=identifier>echo </span><span class=identifier>is </span><span class=identifier>a </span><span class=identifier>C</span><span class=special>++ </span><span class=identifier>function
|
||||
</span></pre></code>
|
||||
<p>
|
||||
The first step is to write the wrapping code. We have to export each module
|
||||
separately with Boost.Python, like this:</p>
|
||||
<code><pre>
|
||||
<span class=comment>/* file core.cpp */
|
||||
</span><span class=identifier>BOOST_PYTHON_MODULE</span><span class=special>(</span><span class=identifier>core</span><span class=special>)
|
||||
{
|
||||
/* </span><span class=keyword>export </span><span class=identifier>everything </span><span class=identifier>in </span><span class=identifier>the </span><span class=identifier>sounds</span><span class=special>::</span><span class=identifier>core </span><span class=keyword>namespace </span><span class=special>*/
|
||||
...
|
||||
}
|
||||
|
||||
/* </span><span class=identifier>file </span><span class=identifier>io</span><span class=special>.</span><span class=identifier>cpp </span><span class=special>*/
|
||||
</span><span class=identifier>BOOST_PYTHON_MODULE</span><span class=special>(</span><span class=identifier>io</span><span class=special>)
|
||||
{
|
||||
/* </span><span class=keyword>export </span><span class=identifier>everything </span><span class=identifier>in </span><span class=identifier>the </span><span class=identifier>sounds</span><span class=special>::</span><span class=identifier>io </span><span class=keyword>namespace </span><span class=special>*/
|
||||
...
|
||||
}
|
||||
|
||||
/* </span><span class=identifier>file </span><span class=identifier>filters</span><span class=special>.</span><span class=identifier>cpp </span><span class=special>*/
|
||||
</span><span class=identifier>BOOST_PYTHON_MODULE</span><span class=special>(</span><span class=identifier>filters</span><span class=special>)
|
||||
{
|
||||
/* </span><span class=keyword>export </span><span class=identifier>everything </span><span class=identifier>in </span><span class=identifier>the </span><span class=identifier>sounds</span><span class=special>::</span><span class=identifier>filters </span><span class=keyword>namespace </span><span class=special>*/
|
||||
...
|
||||
}
|
||||
</span></pre></code>
|
||||
<p>
|
||||
Compiling these files will generate the following Python extensions:
|
||||
<tt>core.pyd</tt>, <tt>io.pyd</tt> and <tt>filters.pyd</tt>.</p>
|
||||
<table width="80%" border="0" align="center">
|
||||
<tr>
|
||||
<td class="note_box">
|
||||
<img src="theme/note.gif"></img> The extension <tt>.pyd</tt> is used for python extension modules, which
|
||||
are just shared libraries. Using the default for your system, like <tt>.so</tt> for
|
||||
Unix and <tt>.dll</tt> for Windows, works just as well. </td>
|
||||
</tr>
|
||||
</table>
|
||||
<p>
|
||||
Now, we create this directory structure for our Python package:</p>
|
||||
<code><pre>
|
||||
sounds/
|
||||
__init__.py
|
||||
core.pyd
|
||||
filters.pyd
|
||||
io.pyd
|
||||
</pre></code><p>
|
||||
The file <tt>__init__.py</tt> is what tells Python that the directory <tt>sounds/</tt> is
|
||||
actually a Python package. It can be a empty file, but can also perform some
|
||||
magic, that will be shown later. </p>
|
||||
<p>
|
||||
Now our package is ready. All the user has to do is put <tt>sounds</tt> into his
|
||||
<a href="http://www.python.org/doc/current/tut/node8.html#SECTION008110000000000000000">
|
||||
PYTHONPATH</a> and fire up the interpreter:</p>
|
||||
<code><pre>
|
||||
<span class=special>>>> </span><span class=identifier>import </span><span class=identifier>sounds</span><span class=special>.</span><span class=identifier>io
|
||||
</span><span class=special>>>> </span><span class=identifier>import </span><span class=identifier>sounds</span><span class=special>.</span><span class=identifier>filters
|
||||
</span><span class=special>>>> </span><span class=identifier>sound </span><span class=special>= </span><span class=identifier>sounds</span><span class=special>.</span><span class=identifier>io</span><span class=special>.</span><span class=identifier>open</span><span class=special>(</span><span class=literal>'file.mp3'</span><span class=special>)
|
||||
>>> </span><span class=identifier>new_sound </span><span class=special>= </span><span class=identifier>sounds</span><span class=special>.</span><span class=identifier>filters</span><span class=special>.</span><span class=identifier>echo</span><span class=special>(</span><span class=identifier>sound</span><span class=special>, </span><span class=number>1.0</span><span class=special>)
|
||||
</span></pre></code>
|
||||
<p>
|
||||
Nice heh? </p>
|
||||
<p>
|
||||
This is the simplest way to create hierarchies of packages, but it is not very
|
||||
flexible. What if we want to add a <i>pure</i> Python function to the filters
|
||||
package, for instance, one that applies 3 filters in a sound object at once?
|
||||
Sure, you can do this in C++ and export it, but why not do so in Python? You
|
||||
don't have to recompile the extension modules, plus it will be easier to write
|
||||
it.</p>
|
||||
<p>
|
||||
If we want this flexibility, we will have to complicate our package hierarchy a
|
||||
little. First, we will have to change the name of the extension modules:</p>
|
||||
<code><pre>
|
||||
<span class=comment>/* file core.cpp */
|
||||
</span><span class=identifier>BOOST_PYTHON_MODULE</span><span class=special>(</span><span class=identifier>_core</span><span class=special>)
|
||||
{
|
||||
...
|
||||
/* </span><span class=keyword>export </span><span class=identifier>everything </span><span class=identifier>in </span><span class=identifier>the </span><span class=identifier>sounds</span><span class=special>::</span><span class=identifier>core </span><span class=keyword>namespace </span><span class=special>*/
|
||||
}
|
||||
</span></pre></code>
|
||||
<p>
|
||||
Note that we added an underscore to the module name. The filename will have to
|
||||
be changed to <tt>_core.pyd</tt> as well, and we do the same to the other extension modules.
|
||||
Now, we change our package hierarchy like so:</p>
|
||||
<code><pre>
|
||||
sounds/
|
||||
__init__.py
|
||||
core/
|
||||
__init__.py
|
||||
_core.pyd
|
||||
filters/
|
||||
__init__.py
|
||||
_filters.pyd
|
||||
io/
|
||||
__init__.py
|
||||
_io.pyd
|
||||
</pre></code><p>
|
||||
Note that we created a directory for each extension module, and added a
|
||||
__init__.py to each one. But if we leave it that way, the user will have to
|
||||
access the functions in the core module with this syntax: </p>
|
||||
<code><pre>
|
||||
<span class=special>>>> </span><span class=identifier>import </span><span class=identifier>sounds</span><span class=special>.</span><span class=identifier>core</span><span class=special>.</span><span class=identifier>_core
|
||||
</span><span class=special>>>> </span><span class=identifier>sounds</span><span class=special>.</span><span class=identifier>core</span><span class=special>.</span><span class=identifier>_core</span><span class=special>.</span><span class=identifier>foo</span><span class=special>(...)
|
||||
</span></pre></code>
|
||||
<p>
|
||||
which is not what we want. But here enters the <tt>__init__.py</tt> magic: everything
|
||||
that is brought to the <tt>__init__.py</tt> namespace can be accessed directly by the
|
||||
user. So, all we have to do is bring the entire namespace from <tt>_core.pyd</tt>
|
||||
to <tt>core/__init__.py</tt>. So add this line of code to <tt>sounds/core/__init__.py</tt>:</p>
|
||||
<code><pre>
|
||||
<span class=identifier>from </span><span class=identifier>_core </span><span class=identifier>import </span><span class=special>*
|
||||
</span></pre></code>
|
||||
<p>
|
||||
We do the same for the other packages. Now the user accesses the functions and
|
||||
classes in the extension modules like before:</p>
|
||||
<code><pre>
|
||||
<span class=special>>>> </span><span class=identifier>import </span><span class=identifier>sounds</span><span class=special>.</span><span class=identifier>filters
|
||||
</span><span class=special>>>> </span><span class=identifier>sounds</span><span class=special>.</span><span class=identifier>filters</span><span class=special>.</span><span class=identifier>echo</span><span class=special>(...)
|
||||
</span></pre></code>
|
||||
<p>
|
||||
with the additional benefit that we can easily add pure Python functions to
|
||||
any module, in a way that the user can't tell the difference between a C++
|
||||
function and a Python function. Let's add a <i>pure</i> Python function,
|
||||
<tt>echo_noise</tt>, to the <tt>filters</tt> package. This function applies both the
|
||||
<tt>echo</tt> and <tt>noise</tt> filters in sequence in the given <tt>sound</tt> object. We
|
||||
create a file named <tt>sounds/filters/echo_noise.py</tt> and code our function:</p>
|
||||
<code><pre>
|
||||
<span class=identifier>import </span><span class=identifier>_filters
|
||||
</span><span class=identifier>def </span><span class=identifier>echo_noise</span><span class=special>(</span><span class=identifier>sound</span><span class=special>):
|
||||
</span><span class=identifier>s </span><span class=special>= </span><span class=identifier>_filters</span><span class=special>.</span><span class=identifier>echo</span><span class=special>(</span><span class=identifier>sound</span><span class=special>)
|
||||
</span><span class=identifier>s </span><span class=special>= </span><span class=identifier>_filters</span><span class=special>.</span><span class=identifier>noise</span><span class=special>(</span><span class=identifier>sound</span><span class=special>)
|
||||
</span><span class=keyword>return </span><span class=identifier>s
|
||||
</span></pre></code>
|
||||
<p>
|
||||
Next, we add this line to <tt>sounds/filters/__init__.py</tt>:</p>
|
||||
<code><pre>
|
||||
<span class=identifier>from </span><span class=identifier>echo_noise </span><span class=identifier>import </span><span class=identifier>echo_noise
|
||||
</span></pre></code>
|
||||
<p>
|
||||
And that's it. The user now accesses this function like any other function
|
||||
from the <tt>filters</tt> package:</p>
|
||||
<code><pre>
|
||||
<span class=special>>>> </span><span class=identifier>import </span><span class=identifier>sounds</span><span class=special>.</span><span class=identifier>filters
|
||||
</span><span class=special>>>> </span><span class=identifier>sounds</span><span class=special>.</span><span class=identifier>filters</span><span class=special>.</span><span class=identifier>echo_noise</span><span class=special>(...)
|
||||
</span></pre></code>
|
||||
<table border="0">
|
||||
<tr>
|
||||
<td width="30"><a href="../index.html"><img src="theme/u_arr.gif" border="0"></a></td>
|
||||
<td width="30"><a href="general_techniques.html"><img src="theme/l_arr.gif" border="0"></a></td>
|
||||
<td width="20"><a href="extending_wrapped_objects_in_python.html"><img src="theme/r_arr.gif" border="0"></a></td>
|
||||
</tr>
|
||||
</table>
|
||||
<br>
|
||||
<hr size="1"><p class="copyright">Copyright © 2002-2003 David Abrahams<br>Copyright © 2002-2003 Joel de Guzman<br><br>
|
||||
<font size="2">Permission to copy, use, modify, sell and distribute this document
|
||||
is granted provided this copyright notice appears in all copies. This document
|
||||
is provided "as is" without express or implied warranty, and with
|
||||
no claim as to its suitability for any purpose. </font> </p>
|
||||
</body>
|
||||
</html>
|
||||
@@ -83,7 +83,7 @@ respectively. In our <tt>foo</tt> function the minimum number of arguments is 1
|
||||
and the maximum number of arguments is 4. The <tt>def(...)</tt> function will
|
||||
automatically add all the foo variants for us:</p>
|
||||
<code><pre>
|
||||
<span class=special>.</span><span class=identifier>def</span><span class=special>(</span><span class=string>"foo"</span><span class=special>, </span><span class=identifier>foo</span><span class=special>, </span><span class=identifier>foo_overloads</span><span class=special>());
|
||||
<span 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></code>
|
||||
<a name="boost_python_member_function_overloads"></a><h2>BOOST_PYTHON_MEMBER_FUNCTION_OVERLOADS</h2><p>
|
||||
Objects here, objects there, objects here there everywhere. More frequently
|
||||
@@ -93,7 +93,7 @@ arguments or overloads with a common sequence of initial arguments come
|
||||
into play. Another macro is provided to make this a breeze.</p>
|
||||
<p>
|
||||
Like <tt>BOOST_PYTHON_FUNCTION_OVERLOADS</tt>,
|
||||
<tt>BOOST_PYTHON_FUNCTION_OVERLOADS</tt> may be used to automatically create
|
||||
<tt>BOOST_PYTHON_MEMBER_FUNCTION_OVERLOADS</tt> may be used to automatically create
|
||||
the thin wrappers for wrapping member functions. Let's have an example:</p>
|
||||
<code><pre>
|
||||
<span class=keyword>struct </span><span class=identifier>george
|
||||
|
||||
@@ -44,10 +44,9 @@ both Boost.Python's and Python's static link library.</p>
|
||||
Boost.Python's static link library comes in two variants. Both are located
|
||||
in Boost's <tt>/libs/python/build/bin-stage</tt> subdirectory. On Windows, the
|
||||
variants are called <tt>boost_python.lib</tt> (for release builds) and
|
||||
<tt>boost_python_debug.lib</tt> (for debugging). If you can't find the
|
||||
libraries, you probably haven't built Boost.Python yet. See <a
|
||||
href="../../building.html">Building and Testing</a> on how to do
|
||||
this.</p>
|
||||
<tt>boost_python_debug.lib</tt> (for debugging). If you can't find the libraries,
|
||||
you probably haven't built Boost.Python yet. See <a href="../../building.html">
|
||||
Building and Testing</a> on how to do this.</p>
|
||||
<p>
|
||||
Python's static link library can be found in the <tt>/libs</tt> subdirectory of
|
||||
your Python directory. On Windows it is called pythonXY.lib where X.Y is
|
||||
@@ -88,7 +87,7 @@ Py_Finalize</a>() to stop the interpreter and release its resources.</li></ol><p
|
||||
</tr>
|
||||
</table>
|
||||
<br>
|
||||
<hr size="1"><p class="copyright">Copyright © 2002-2003 Dirk Gerrits<br><br>
|
||||
<hr size="1"><p class="copyright">Copyright © 2002-2003 David Abrahams<br>Copyright © 2002-2003 Joel de Guzman<br><br>
|
||||
<font size="2">Permission to copy, use, modify, sell and distribute this document
|
||||
is granted provided this copyright notice appears in all copies. This document
|
||||
is provided "as is" without express or implied warranty, and with
|
||||
|
||||
@@ -4,6 +4,7 @@
|
||||
<title>Exception Translation</title>
|
||||
<link rel="stylesheet" href="theme/style.css" type="text/css">
|
||||
<link rel="prev" href="iterators.html">
|
||||
<link rel="next" href="general_techniques.html">
|
||||
</head>
|
||||
<body>
|
||||
<table width="100%" height="48" border="0" cellspacing="2">
|
||||
@@ -20,7 +21,7 @@
|
||||
<tr>
|
||||
<td width="30"><a href="../index.html"><img src="theme/u_arr.gif" border="0"></a></td>
|
||||
<td width="30"><a href="iterators.html"><img src="theme/l_arr.gif" border="0"></a></td>
|
||||
<td width="20"><img src="theme/r_arr_disabled.gif" border="0"></td>
|
||||
<td width="20"><a href="general_techniques.html"><img src="theme/r_arr.gif" border="0"></a></td>
|
||||
</tr>
|
||||
</table>
|
||||
<p>
|
||||
@@ -47,7 +48,7 @@ Users may provide custom translation. Here's an example:</p>
|
||||
<tr>
|
||||
<td width="30"><a href="../index.html"><img src="theme/u_arr.gif" border="0"></a></td>
|
||||
<td width="30"><a href="iterators.html"><img src="theme/l_arr.gif" border="0"></a></td>
|
||||
<td width="20"><img src="theme/r_arr_disabled.gif" border="0"></td>
|
||||
<td width="20"><a href="general_techniques.html"><img src="theme/r_arr.gif" border="0"></a></td>
|
||||
</tr>
|
||||
</table>
|
||||
<br>
|
||||
|
||||
134
doc/tutorial/doc/extending_wrapped_objects_in_python.html
Normal file
134
doc/tutorial/doc/extending_wrapped_objects_in_python.html
Normal file
@@ -0,0 +1,134 @@
|
||||
<html>
|
||||
<head>
|
||||
<!-- Generated by the Spirit (http://spirit.sf.net) QuickDoc -->
|
||||
<title>Extending Wrapped Objects in Python</title>
|
||||
<link rel="stylesheet" href="theme/style.css" type="text/css">
|
||||
<link rel="prev" href="creating_packages.html">
|
||||
<link rel="next" href="reducing_compiling_time.html">
|
||||
</head>
|
||||
<body>
|
||||
<table width="100%" height="48" border="0" cellspacing="2">
|
||||
<tr>
|
||||
<td><img src="theme/c%2B%2Bboost.gif">
|
||||
</td>
|
||||
<td width="85%">
|
||||
<font size="6" face="Verdana, Arial, Helvetica, sans-serif"><b>Extending Wrapped Objects in Python</b></font>
|
||||
</td>
|
||||
</tr>
|
||||
</table>
|
||||
<br>
|
||||
<table border="0">
|
||||
<tr>
|
||||
<td width="30"><a href="../index.html"><img src="theme/u_arr.gif" border="0"></a></td>
|
||||
<td width="30"><a href="creating_packages.html"><img src="theme/l_arr.gif" border="0"></a></td>
|
||||
<td width="20"><a href="reducing_compiling_time.html"><img src="theme/r_arr.gif" border="0"></a></td>
|
||||
</tr>
|
||||
</table>
|
||||
<p>
|
||||
Thanks to Python's flexibility, you can easily add new methods to a class,
|
||||
even after it was already created:</p>
|
||||
<code><pre>
|
||||
<span class=special>>>> </span><span class=keyword>class </span><span class=identifier>C</span><span class=special>(</span><span class=identifier>object</span><span class=special>): </span><span class=identifier>pass
|
||||
</span><span class=special>>>>
|
||||
>>> </span>##<span class=identifier>a </span><span class=identifier>regular </span><span class=identifier>function
|
||||
</span><span class=special>>>> </span><span class=identifier>def </span><span class=identifier>C_str</span><span class=special>(</span><span class=identifier>self</span><span class=special>): </span><span class=keyword>return </span><span class=literal>'A C instance!'
|
||||
</span><span class=special>>>>
|
||||
>>> </span>##<span class=identifier>now </span><span class=identifier>we </span><span class=identifier>turn </span><span class=identifier>it </span><span class=identifier>in </span><span class=identifier>a </span><span class=identifier>member </span><span class=identifier>function
|
||||
</span><span class=special>>>> </span><span class=identifier>C</span><span class=special>.</span><span class=identifier>__str__ </span><span class=special>= </span><span class=identifier>C_str
|
||||
</span><span class=special>>>>
|
||||
>>> </span><span class=identifier>c </span><span class=special>= </span><span class=identifier>C</span><span class=special>()
|
||||
>>> </span><span class=identifier>print </span><span class=identifier>c
|
||||
</span><span class=identifier>A </span><span class=identifier>C </span><span class=identifier>instance</span><span class=special>!
|
||||
>>> </span><span class=identifier>C_str</span><span class=special>(</span><span class=identifier>c</span><span class=special>)
|
||||
</span><span class=identifier>A </span><span class=identifier>C </span><span class=identifier>instance</span><span class=special>!
|
||||
</span></pre></code>
|
||||
<p>
|
||||
Yes, Python rox. <img src="theme/smiley.gif"></img></p>
|
||||
<p>
|
||||
We can do the same with classes that were wrapped with Boost.Python. Suppose
|
||||
we have a class <tt>point</tt> in C++:</p>
|
||||
<code><pre>
|
||||
<span class=keyword>class </span><span class=identifier>point </span><span class=special>{...};
|
||||
|
||||
</span><span class=identifier>BOOST_PYTHON_MODULE</span><span class=special>(</span><span class=identifier>_geom</span><span class=special>)
|
||||
{
|
||||
</span><span class=identifier>class_</span><span class=special><</span><span class=identifier>point</span><span class=special>>(</span><span class=string>"point"</span><span class=special>)...;
|
||||
}
|
||||
</span></pre></code>
|
||||
<p>
|
||||
If we are using the technique from the previous session, <a href="creating_packages.html">
|
||||
|
||||
Creating Packages</a>, we can code directly into <tt>geom/__init__.py</tt>:</p>
|
||||
<code><pre>
|
||||
<span class=identifier>from </span><span class=identifier>_geom </span><span class=identifier>import </span><span class=special>*
|
||||
|
||||
</span>##<span class=identifier>a </span><span class=identifier>regular </span><span class=identifier>function
|
||||
</span><span class=identifier>def </span><span class=identifier>point_str</span><span class=special>(</span><span class=identifier>self</span><span class=special>):
|
||||
</span><span class=keyword>return </span><span class=identifier>str</span><span class=special>((</span><span class=identifier>self</span><span class=special>.</span><span class=identifier>x</span><span class=special>, </span><span class=identifier>self</span><span class=special>.</span><span class=identifier>y</span><span class=special>))
|
||||
|
||||
</span>##<span class=identifier>now </span><span class=identifier>we </span><span class=identifier>turn </span><span class=identifier>it </span><span class=identifier>into </span><span class=identifier>a </span><span class=identifier>member </span><span class=identifier>function
|
||||
</span><span class=identifier>point</span><span class=special>.</span><span class=identifier>__str__ </span><span class=special>= </span><span class=identifier>point_str
|
||||
</span></pre></code>
|
||||
<p>
|
||||
<b>All</b> point instances created from C++ will also have this member function!
|
||||
This technique has several advantages:</p>
|
||||
<ul><li>Cut down compile times to zero for these additional functions</li><li>Reduce the memory footprint to virtually zero</li><li>Minimize the need to recompile</li><li>Rapid prototyping (you can move the code to C++ if required without changing the interface)</li></ul><p>
|
||||
You can even add a little syntactic sugar with the use of metaclasses. Let's
|
||||
create a special metaclass that "injects" methods in other classes.</p>
|
||||
<code><pre>
|
||||
##<span class=identifier>The </span><span class=identifier>one </span><span class=identifier>Boost</span><span class=special>.</span><span class=identifier>Python </span><span class=identifier>uses </span><span class=keyword>for </span><span class=identifier>all </span><span class=identifier>wrapped </span><span class=identifier>classes</span><span class=special>.
|
||||
</span>##<span class=identifier>You </span><span class=identifier>can </span><span class=identifier>use </span><span class=identifier>here </span><span class=identifier>any </span><span class=keyword>class </span><span class=identifier>exported </span><span class=identifier>by </span><span class=identifier>Boost </span><span class=identifier>instead </span><span class=identifier>of </span><span class=string>"point"
|
||||
</span><span class=identifier>BoostPythonMetaclass </span><span class=special>= </span><span class=identifier>point</span><span class=special>.</span><span class=identifier>__class__
|
||||
|
||||
</span><span class=keyword>class </span><span class=identifier>injector</span><span class=special>(</span><span class=identifier>object</span><span class=special>):
|
||||
</span><span class=keyword>class </span><span class=identifier>__metaclass__</span><span class=special>(</span><span class=identifier>BoostPythonMetaclass</span><span class=special>):
|
||||
</span><span class=identifier>def </span><span class=identifier>__init__</span><span class=special>(</span><span class=identifier>self</span><span class=special>, </span><span class=identifier>name</span><span class=special>, </span><span class=identifier>bases</span><span class=special>, </span><span class=identifier>dict</span><span class=special>):
|
||||
</span><span class=keyword>for </span><span class=identifier>b </span><span class=identifier>in </span><span class=identifier>bases</span><span class=special>:
|
||||
</span><span class=keyword>if </span><span class=identifier>type</span><span class=special>(</span><span class=identifier>b</span><span class=special>) </span><span class=keyword>not </span><span class=identifier>in </span><span class=special>(</span><span class=identifier>self</span><span class=special>, </span><span class=identifier>type</span><span class=special>):
|
||||
</span><span class=keyword>for </span><span class=identifier>k</span><span class=special>,</span><span class=identifier>v </span><span class=identifier>in </span><span class=identifier>dict</span><span class=special>.</span><span class=identifier>items</span><span class=special>():
|
||||
</span><span class=identifier>setattr</span><span class=special>(</span><span class=identifier>b</span><span class=special>,</span><span class=identifier>k</span><span class=special>,</span><span class=identifier>v</span><span class=special>)
|
||||
</span><span class=keyword>return </span><span class=identifier>type</span><span class=special>.</span><span class=identifier>__init__</span><span class=special>(</span><span class=identifier>self</span><span class=special>, </span><span class=identifier>name</span><span class=special>, </span><span class=identifier>bases</span><span class=special>, </span><span class=identifier>dict</span><span class=special>)
|
||||
|
||||
</span>##<span class=identifier>inject </span><span class=identifier>some </span><span class=identifier>methods </span><span class=identifier>in </span><span class=identifier>the </span><span class=identifier>point </span><span class=identifier>foo
|
||||
</span><span class=keyword>class </span><span class=identifier>more_point</span><span class=special>(</span><span class=identifier>injector</span><span class=special>, </span><span class=identifier>point</span><span class=special>):
|
||||
</span><span class=identifier>def </span><span class=identifier>__repr__</span><span class=special>(</span><span class=identifier>self</span><span class=special>):
|
||||
</span><span class=keyword>return </span><span class=literal>'Point(x=%s, y=%s)' </span><span class=special>% (</span><span class=identifier>self</span><span class=special>.</span><span class=identifier>x</span><span class=special>, </span><span class=identifier>self</span><span class=special>.</span><span class=identifier>y</span><span class=special>)
|
||||
</span><span class=identifier>def </span><span class=identifier>foo</span><span class=special>(</span><span class=identifier>self</span><span class=special>):
|
||||
</span><span class=identifier>print </span><span class=literal>'foo!'
|
||||
</span></pre></code>
|
||||
<p>
|
||||
Now let's see how it got:</p>
|
||||
<code><pre>
|
||||
<span class=special>>>> </span><span class=identifier>print </span><span class=identifier>point</span><span class=special>()
|
||||
</span><span class=identifier>Point</span><span class=special>(</span><span class=identifier>x</span><span class=special>=</span><span class=number>10</span><span class=special>, </span><span class=identifier>y</span><span class=special>=</span><span class=number>10</span><span class=special>)
|
||||
>>> </span><span class=identifier>point</span><span class=special>().</span><span class=identifier>foo</span><span class=special>()
|
||||
</span><span class=identifier>foo</span><span class=special>!
|
||||
</span></pre></code>
|
||||
<p>
|
||||
Another useful idea is to replace constructors with factory functions:</p>
|
||||
<code><pre>
|
||||
<span class=identifier>_point </span><span class=special>= </span><span class=identifier>point
|
||||
|
||||
</span><span class=identifier>def </span><span class=identifier>point</span><span class=special>(</span><span class=identifier>x</span><span class=special>=</span><span class=number>0</span><span class=special>, </span><span class=identifier>y</span><span class=special>=</span><span class=number>0</span><span class=special>):
|
||||
</span><span class=keyword>return </span><span class=identifier>_point</span><span class=special>(</span><span class=identifier>x</span><span class=special>, </span><span class=identifier>y</span><span class=special>)
|
||||
</span></pre></code>
|
||||
<p>
|
||||
In this simple case there is not much gained, but for constructurs with
|
||||
many overloads and/or arguments this is often a great simplification, again
|
||||
with virtually zero memory footprint and zero compile-time overhead for
|
||||
the keyword support.</p>
|
||||
<table border="0">
|
||||
<tr>
|
||||
<td width="30"><a href="../index.html"><img src="theme/u_arr.gif" border="0"></a></td>
|
||||
<td width="30"><a href="creating_packages.html"><img src="theme/l_arr.gif" border="0"></a></td>
|
||||
<td width="20"><a href="reducing_compiling_time.html"><img src="theme/r_arr.gif" border="0"></a></td>
|
||||
</tr>
|
||||
</table>
|
||||
<br>
|
||||
<hr size="1"><p class="copyright">Copyright © 2002-2003 David Abrahams<br>Copyright © 2002-2003 Joel de Guzman<br><br>
|
||||
<font size="2">Permission to copy, use, modify, sell and distribute this document
|
||||
is granted provided this copyright notice appears in all copies. This document
|
||||
is provided "as is" without express or implied warranty, and with
|
||||
no claim as to its suitability for any purpose. </font> </p>
|
||||
</body>
|
||||
</html>
|
||||
43
doc/tutorial/doc/general_techniques.html
Normal file
43
doc/tutorial/doc/general_techniques.html
Normal file
@@ -0,0 +1,43 @@
|
||||
<html>
|
||||
<head>
|
||||
<!-- Generated by the Spirit (http://spirit.sf.net) QuickDoc -->
|
||||
<title>General Techniques</title>
|
||||
<link rel="stylesheet" href="theme/style.css" type="text/css">
|
||||
<link rel="prev" href="exception_translation.html">
|
||||
<link rel="next" href="creating_packages.html">
|
||||
</head>
|
||||
<body>
|
||||
<table width="100%" height="48" border="0" cellspacing="2">
|
||||
<tr>
|
||||
<td><img src="theme/c%2B%2Bboost.gif">
|
||||
</td>
|
||||
<td width="85%">
|
||||
<font size="6" face="Verdana, Arial, Helvetica, sans-serif"><b>General Techniques</b></font>
|
||||
</td>
|
||||
</tr>
|
||||
</table>
|
||||
<br>
|
||||
<table border="0">
|
||||
<tr>
|
||||
<td width="30"><a href="../index.html"><img src="theme/u_arr.gif" border="0"></a></td>
|
||||
<td width="30"><a href="exception_translation.html"><img src="theme/l_arr.gif" border="0"></a></td>
|
||||
<td width="20"><a href="creating_packages.html"><img src="theme/r_arr.gif" border="0"></a></td>
|
||||
</tr>
|
||||
</table>
|
||||
<p>
|
||||
Here are presented some useful techniques that you can use while wrapping code with Boost.Python.</p>
|
||||
<table border="0">
|
||||
<tr>
|
||||
<td width="30"><a href="../index.html"><img src="theme/u_arr.gif" border="0"></a></td>
|
||||
<td width="30"><a href="exception_translation.html"><img src="theme/l_arr.gif" border="0"></a></td>
|
||||
<td width="20"><a href="creating_packages.html"><img src="theme/r_arr.gif" border="0"></a></td>
|
||||
</tr>
|
||||
</table>
|
||||
<br>
|
||||
<hr size="1"><p class="copyright">Copyright © 2002-2003 David Abrahams<br>Copyright © 2002-2003 Joel de Guzman<br><br>
|
||||
<font size="2">Permission to copy, use, modify, sell and distribute this document
|
||||
is granted provided this copyright notice appears in all copies. This document
|
||||
is provided "as is" without express or implied warranty, and with
|
||||
no claim as to its suitability for any purpose. </font> </p>
|
||||
</body>
|
||||
</html>
|
||||
@@ -62,6 +62,11 @@ with every boost distribution: [*bjam].
|
||||
Besides bjam, there are of course other ways to get your module built.
|
||||
What's written here should not be taken as "the one and only way".
|
||||
There are of course other build tools apart from [^bjam].
|
||||
|
||||
Take note however that the preferred build tool for Boost.Python is bjam.
|
||||
There are so many ways to set up the build incorrectly. Experience shows
|
||||
that 90% of the "I can't build Boost.Python" problems come from people
|
||||
who had to use a different tool.
|
||||
]
|
||||
|
||||
We shall skip over the details. Our objective will be to simply create the
|
||||
@@ -994,7 +999,7 @@ respectively. In our [^foo] function the minimum number of arguments is 1
|
||||
and the maximum number of arguments is 4. The [^def(...)] function will
|
||||
automatically add all the foo variants for us:
|
||||
|
||||
.def("foo", foo, foo_overloads());
|
||||
def("foo", foo, foo_overloads());
|
||||
|
||||
[h2 BOOST_PYTHON_MEMBER_FUNCTION_OVERLOADS]
|
||||
|
||||
@@ -1005,7 +1010,7 @@ arguments or overloads with a common sequence of initial arguments come
|
||||
into play. Another macro is provided to make this a breeze.
|
||||
|
||||
Like [^BOOST_PYTHON_FUNCTION_OVERLOADS],
|
||||
[^BOOST_PYTHON_FUNCTION_OVERLOADS] may be used to automatically create
|
||||
[^BOOST_PYTHON_MEMBER_FUNCTION_OVERLOADS] may be used to automatically create
|
||||
the thin wrappers for wrapping member functions. Let's have an example:
|
||||
|
||||
struct george
|
||||
@@ -1053,7 +1058,7 @@ Notice the use of [^init<...>] and [^optional<...>] to signify the default
|
||||
[page:1 Auto-Overloading]
|
||||
|
||||
It was mentioned in passing in the previous section that
|
||||
[^BOOST_PYTHON_FUNCTION_OVERLOADS] and [^BOOST_PYTHON_FUNCTION_OVERLOADS]
|
||||
[^BOOST_PYTHON_FUNCTION_OVERLOADS] and [^BOOST_PYTHON_MEMBER_FUNCTION_OVERLOADS]
|
||||
can also be used for overloaded functions and member functions with a
|
||||
common sequence of initial arguments. Here is an example:
|
||||
|
||||
@@ -1330,6 +1335,258 @@ create a new scope around a class:
|
||||
.value("blue", blue)
|
||||
;
|
||||
|
||||
[def Py_Initialize [@http://www.python.org/doc/current/api/initialization.html#l2h-652 Py_Initialize]]
|
||||
[def Py_Finalize [@http://www.python.org/doc/current/api/initialization.html#l2h-656 Py_Finalize]]
|
||||
[def PyRun_String [@http://www.python.org/doc/current/api/veryhigh.html#l2h-55 PyRun_String]]
|
||||
[def PyRun_File [@http://www.python.org/doc/current/api/veryhigh.html#l2h-56 PyRun_File]]
|
||||
[def Py_eval_input [@http://www.python.org/doc/current/api/veryhigh.html#l2h-58 Py_eval_input]]
|
||||
[def Py_file_input [@http://www.python.org/doc/current/api/veryhigh.html#l2h-59 Py_file_input]]
|
||||
[def Py_single_input [@http://www.python.org/doc/current/api/veryhigh.html#l2h-60 Py_single_input]]
|
||||
[def Py_XINCREF [@http://www.python.org/doc/current/api/countingRefs.html#l2h-65 Py_XINCREF]]
|
||||
[def Py_XDECREF [@http://www.python.org/doc/current/api/countingRefs.html#l2h-67 Py_XDECREF]]
|
||||
[def PyImport_AppendInittab [@http://www.python.org/doc/current/api/importing.html#l2h-137 PyImport_AppendInittab]]
|
||||
[def PyImport_AddModule [@http://www.python.org/doc/current/api/importing.html#l2h-125 PyImport_AddModule]]
|
||||
[def PyModule_New [@http://www.python.org/doc/current/api/moduleObjects.html#l2h-591 PyModule_New]]
|
||||
[def PyModule_GetDict [@http://www.python.org/doc/current/api/moduleObjects.html#l2h-594 PyModule_GetDict]]
|
||||
|
||||
[page:0 Embedding]
|
||||
|
||||
By now you should know how to use Boost.Python to call your C++ code from
|
||||
Python. However, sometimes you may need to do the reverse: call Python code
|
||||
from the C++-side. This requires you to ['embed] the Python interpreter
|
||||
into your C++ program.
|
||||
|
||||
Currently, Boost.Python does not directly support everything you'll need
|
||||
when embedding. Therefore you'll need to use the
|
||||
[@http://www.python.org/doc/current/api/api.html Python/C API] to fill in
|
||||
the gaps. However, Boost.Python already makes embedding a lot easier and,
|
||||
in a future version, it may become unnecessary to touch the Python/C API at
|
||||
all. So stay tuned... :-)
|
||||
|
||||
[h2 Building embedded programs]
|
||||
|
||||
To be able to use embedding in your programs, they have to be linked to
|
||||
both Boost.Python's and Python's static link library.
|
||||
|
||||
Boost.Python's static link library comes in two variants. Both are located
|
||||
in Boost's [^/libs/python/build/bin-stage] subdirectory. On Windows, the
|
||||
variants are called [^boost_python.lib] (for release builds) and
|
||||
[^boost_python_debug.lib] (for debugging). If you can't find the libraries,
|
||||
you probably haven't built Boost.Python yet. See [@../../building.html
|
||||
Building and Testing] on how to do this.
|
||||
|
||||
Python's static link library can be found in the [^/libs] subdirectory of
|
||||
your Python directory. On Windows it is called pythonXY.lib where X.Y is
|
||||
your major Python version number.
|
||||
|
||||
Additionally, Python's [^/include] subdirectory has to be added to your
|
||||
include path.
|
||||
|
||||
In a Jamfile, all the above boils down to:
|
||||
|
||||
[pre
|
||||
projectroot c:\projects\embedded_program ; # location of the program
|
||||
|
||||
# bring in the rules for python
|
||||
SEARCH on python.jam = $(BOOST_BUILD_PATH) ;
|
||||
include python.jam ;
|
||||
|
||||
exe embedded_program # name of the executable
|
||||
: #sources
|
||||
embedded_program.cpp
|
||||
: # requirements
|
||||
<find-library>boost_python <library-path>c:\boost\libs\python
|
||||
$(PYTHON_PROPERTIES)
|
||||
<library-path>$(PYTHON_LIB_PATH)
|
||||
<find-library>$(PYTHON_EMBEDDED_LIBRARY) ;
|
||||
]
|
||||
|
||||
[h2 Getting started]
|
||||
|
||||
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>][br][br]
|
||||
|
||||
# Call Py_Initialize() to start the interpreter and create the [^__main__] module.[br][br]
|
||||
|
||||
# Call other Python C API routines to use the interpreter.[br][br]
|
||||
|
||||
# Call Py_Finalize() to stop the interpreter and release its resources.
|
||||
|
||||
(Of course, there can be other C++ code between all of these steps.)
|
||||
|
||||
[:['[*Now that we can embed the interpreter in our programs, lets see how to put it to use...]]]
|
||||
|
||||
[page:1 Using the interpreter]
|
||||
|
||||
As you probably already know, objects in Python are reference-counted.
|
||||
Naturally, the [^PyObject]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
|
||||
[@http://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 [@../../v2/handle.html handle] class
|
||||
template to automate the process.
|
||||
|
||||
[h2 Reference-counting handles]
|
||||
|
||||
There are two ways in which a function in the Python/C API can return a
|
||||
[^PyObject*]: as a ['borrowed reference] or as a ['new reference]. Which of
|
||||
these a function uses, is listed in that function's documentation. The two
|
||||
require slightely different approaches to reference-counting but both can
|
||||
be 'handled' by Boost.Python.
|
||||
|
||||
For a function returning a ['borrowed reference] we'll have to tell the
|
||||
[^handle] that the [^PyObject*] is borrowed with the aptly named
|
||||
[@../../v2/handle.html#borrowed-spec borrowed] function. Two functions
|
||||
returning borrowed references are PyImport_AddModule and PyModule_GetDict.
|
||||
The former returns a reference to an already imported module, the latter
|
||||
retrieves a module's namespace dictionary. Let's use them to retrieve the
|
||||
namespace of the [^__main__] module:
|
||||
|
||||
handle<> main_module(borrowed( PyImport_AddModule("__main__") ));
|
||||
handle<> main_namespace(borrowed( PyModule_GetDict(main_module.get()) ));
|
||||
|
||||
Because the Python/C API doesn't know anything about [^handle]s, we used
|
||||
the [@../../v2/handle.html#handle-spec-observers get] member function to
|
||||
retrieve the [^PyObject*] from which the [^handle] was constructed.
|
||||
|
||||
For a function returning a ['new reference] we can just create a [^handle]
|
||||
out of the raw [^PyObject*] without wrapping it in a call to borrowed. One
|
||||
such function that returns a new reference is PyRun_String which we'll
|
||||
discuss in the next section.
|
||||
|
||||
[blurb __detail__ [*Handle is a class ['template], so why haven't we been using any template parameters?][br]
|
||||
[br]
|
||||
[^handle] has a single template parameter specifying the type of the managed object. This type is [^PyObject] 99% of the time, so the parameter was defaulted to [^PyObject] for convenience. Therefore we can use the shorthand [^handle<>] instead of the longer, but equivalent, [^handle<PyObject>].
|
||||
]
|
||||
|
||||
[h2 Running Python code]
|
||||
|
||||
To run Python code from C++ there is a family of functions in the API
|
||||
starting with the PyRun prefix. You can find the full list of these
|
||||
functions [@http://www.python.org/doc/current/api/veryhigh.html here]. They
|
||||
all work similarly so we will look at only one of them, namely:
|
||||
|
||||
PyObject* PyRun_String(char *str, int start, PyObject *globals, PyObject *locals)
|
||||
|
||||
PyRun_String takes the code to execute as a null-terminated (C-style)
|
||||
string in its [^str] parameter. The function returns a new reference to a
|
||||
Python object. Which object is returned depends on the [^start] paramater.
|
||||
|
||||
The [^start] parameter is the start symbol from the Python grammar to use
|
||||
for interpreting the code. The possible values are:
|
||||
|
||||
[table Start symbols
|
||||
|
||||
[Py_eval_input] [for interpreting isolated expressions]
|
||||
[Py_file_input] [for interpreting sequences of statements]
|
||||
[Py_single_input] [for interpreting a single statement]
|
||||
]
|
||||
|
||||
When using Py_eval_input, the input string must contain a single expression
|
||||
and its result is returned. When using Py_file_input, the string can
|
||||
contain an abitrary number of statements and None is returned.
|
||||
Py_single_input works in the same way as Py_file_input but only accepts a
|
||||
single statement.
|
||||
|
||||
Lastly, the [^globals] and [^locals] 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
|
||||
[^__main__] module for both parameters.
|
||||
|
||||
We have already seen how to get the [^__main__] module's namespace so let's
|
||||
run some Python code in it:
|
||||
|
||||
handle<> main_module(borrowed( PyImport_AddModule("__main__") ));
|
||||
handle<> main_namespace(borrowed( PyModule_GetDict(main_module.get()) ));
|
||||
handle<>( PyRun_String("hello = file('hello.txt', 'w')\n"
|
||||
"hello.write('Hello world!')\n"
|
||||
"hello.close()", Py_file_input,
|
||||
main_namespace.get(), main_namespace.get()) );
|
||||
|
||||
This should create a file called 'hello.txt' in the current directory
|
||||
containing a phrase that is well-known in programming circles.
|
||||
|
||||
__note__ [*Note] that we wrap the return value of PyRun_String in a
|
||||
(nameless) [^handle] even though we are not interested in it. If we didn't
|
||||
do this, the the returned object would be kept alive unnecessarily. Unless
|
||||
you want to be a Dr. Frankenstein, always wrap [^PyObject*]s in [^handle]s.
|
||||
|
||||
[h2 Beyond handles]
|
||||
|
||||
It's nice that [^handle] manages the reference counting details for us, but
|
||||
other than that it doesn't do much. Often we'd like to have a more useful
|
||||
class to manipulate Python objects. But we have already seen such a class
|
||||
in the [@object_interface.html previous section]: the aptly named [^object]
|
||||
class and it's derivatives. What we haven't seen, is that they can be
|
||||
constructed from a [^handle]. The following examples should illustrate this
|
||||
fact:
|
||||
|
||||
handle<> main_module(borrowed( PyImport_AddModule("__main__") ));
|
||||
dict main_namespace(handle<>(borrowed( PyModule_GetDict(main_module.get()) )));
|
||||
handle<>( PyRun_String("result = 5 ** 2", Py_file_input,
|
||||
main_namespace.ptr(), main_namespace.ptr()) );
|
||||
int five_squared = extract<int>( main_namespace["result"] );
|
||||
|
||||
Here we create a dictionary object for the [^__main__] 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 let
|
||||
PyRun_String return the result directly with Py_eval_input:
|
||||
|
||||
object result(handle<>( PyRun_String("5 ** 2", Py_eval_input,
|
||||
main_namespace.ptr(), main_namespace.ptr()) ));
|
||||
int five_squared = extract<int>(result);
|
||||
|
||||
__note__ [*Note] that [^object]'s member function to return the wrapped
|
||||
[^PyObject*] is called [^ptr] instead of [^get]. This makes sense if you
|
||||
take into account the different functions that [^object] and [^handle]
|
||||
perform.
|
||||
|
||||
[h2 Exception handling]
|
||||
|
||||
If an exception occurs in the execution of some Python code, the PyRun_String function returns a null pointer. Constructing a [^handle] out of this null pointer throws [@../../v2/errors.html#error_already_set-spec error_already_set], so basically, the Python exception is automatically translated into a C++ exception when using [^handle]:
|
||||
|
||||
try
|
||||
{
|
||||
object result(handle<>( PyRun_String("5/0", Py_eval_input,
|
||||
main_namespace.ptr(), main_namespace.ptr()) ));
|
||||
// execution will never get here:
|
||||
int five_divided_by_zero = extract<int>(result);
|
||||
}
|
||||
catch(error_already_set)
|
||||
{
|
||||
// handle the exception in some way
|
||||
}
|
||||
|
||||
The [^error_already_set] exception class doesn't carry any information in itself. To find out more about the Python exception that occurred, you need to use the [@http://www.python.org/doc/api/exceptionHandling.html exception handling functions] of the Python/C API in your catch-statement. This can be as simple as calling [@http://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 [@http://www.python.org/doc/api/standardExceptions.html standard exceptions]:
|
||||
|
||||
catch(error_already_set)
|
||||
{
|
||||
if (PyErr_ExceptionMatches(PyExc_ZeroDivisionError))
|
||||
{
|
||||
// handle ZeroDivisionError specially
|
||||
}
|
||||
else
|
||||
{
|
||||
// print all other errors to stderr
|
||||
PyErr_Print();
|
||||
}
|
||||
}
|
||||
|
||||
(To retrieve even more information from the exception you can use some of the other exception handling functions listed [@http://www.python.org/doc/api/exceptionHandling.html here].)
|
||||
|
||||
If you'd rather not have [^handle] throw a C++ exception when it is constructed, you can use the [@../../v2/handle.html#allow_null-spec allow_null] function in the same way you'd use borrowed:
|
||||
|
||||
handle<> result(allow_null( PyRun_String("5/0", Py_eval_input,
|
||||
main_namespace.ptr(), main_namespace.ptr()) ));
|
||||
if (!result)
|
||||
// Python exception occurred
|
||||
else
|
||||
// everything went okay, it's safe to use the result
|
||||
|
||||
[page Iterators]
|
||||
|
||||
In C++, and STL in particular, we see iterators everywhere. Python also has
|
||||
@@ -1424,3 +1681,321 @@ Users may provide custom translation. Here's an example:
|
||||
PodBayDoorException>(translator);
|
||||
...
|
||||
|
||||
[page General Techniques]
|
||||
|
||||
Here are presented some useful techniques that you can use while wrapping code with Boost.Python.
|
||||
|
||||
[page:1 Creating Packages]
|
||||
|
||||
A Python package is a collection of modules that provide to the user a certain
|
||||
functionality. If you're not familiar on how to create packages, a good
|
||||
introduction to them is provided in the
|
||||
[@http://www.python.org/doc/current/tut/node8.html Python Tutorial].
|
||||
|
||||
But we are wrapping C++ code, using Boost.Python. How can we provide a nice
|
||||
package interface to our users? To better explain some concepts, let's work
|
||||
with an example.
|
||||
|
||||
We have a C++ library that works with sounds: reading and writing various
|
||||
formats, applying filters to the sound data, etc. It is named (conveniently)
|
||||
[^sounds]. Our library already has a neat C++ namespace hierarchy, like so:
|
||||
|
||||
sounds::core
|
||||
sounds::io
|
||||
sounds::filters
|
||||
|
||||
We would like to present this same hierarchy to the Python user, allowing him
|
||||
to write code like this:
|
||||
|
||||
import sounds.filters
|
||||
sounds.filters.echo(...) # echo is a C++ function
|
||||
|
||||
The first step is to write the wrapping code. We have to export each module
|
||||
separately with Boost.Python, like this:
|
||||
|
||||
/* file core.cpp */
|
||||
BOOST_PYTHON_MODULE(core)
|
||||
{
|
||||
/* export everything in the sounds::core namespace */
|
||||
...
|
||||
}
|
||||
|
||||
/* file io.cpp */
|
||||
BOOST_PYTHON_MODULE(io)
|
||||
{
|
||||
/* export everything in the sounds::io namespace */
|
||||
...
|
||||
}
|
||||
|
||||
/* file filters.cpp */
|
||||
BOOST_PYTHON_MODULE(filters)
|
||||
{
|
||||
/* export everything in the sounds::filters namespace */
|
||||
...
|
||||
}
|
||||
|
||||
Compiling these files will generate the following Python extensions:
|
||||
[^core.pyd], [^io.pyd] and [^filters.pyd].
|
||||
|
||||
[blurb __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.]
|
||||
|
||||
Now, we create this directory structure for our Python package:
|
||||
|
||||
[pre
|
||||
sounds/
|
||||
__init__.py
|
||||
core.pyd
|
||||
filters.pyd
|
||||
io.pyd
|
||||
]
|
||||
|
||||
The file [^__init__.py] is what tells Python that the directory [^sounds/] is
|
||||
actually a Python package. It can be a empty file, but can also perform some
|
||||
magic, that will be shown later.
|
||||
|
||||
Now our package is ready. All the user has to do is put [^sounds] into his
|
||||
[@http://www.python.org/doc/current/tut/node8.html#SECTION008110000000000000000 PYTHONPATH] and fire up the interpreter:
|
||||
|
||||
>>> import sounds.io
|
||||
>>> import sounds.filters
|
||||
>>> sound = sounds.io.open('file.mp3')
|
||||
>>> new_sound = sounds.filters.echo(sound, 1.0)
|
||||
|
||||
Nice heh?
|
||||
|
||||
This is the simplest way to create hierarchies of packages, but it is not very
|
||||
flexible. What if we want to add a ['pure] Python function to the filters
|
||||
package, for instance, one that applies 3 filters in a sound object at once?
|
||||
Sure, you can do this in C++ and export it, but why not do so in Python? You
|
||||
don't have to recompile the extension modules, plus it will be easier to write
|
||||
it.
|
||||
|
||||
If we want this flexibility, we will have to complicate our package hierarchy a
|
||||
little. First, we will have to change the name of the extension modules:
|
||||
|
||||
/* file core.cpp */
|
||||
BOOST_PYTHON_MODULE(_core)
|
||||
{
|
||||
...
|
||||
/* export everything in the sounds::core namespace */
|
||||
}
|
||||
|
||||
Note that we added an underscore to the module name. The filename will have to
|
||||
be changed to [^_core.pyd] as well, and we do the same to the other extension modules.
|
||||
Now, we change our package hierarchy like so:
|
||||
|
||||
[pre
|
||||
sounds/
|
||||
__init__.py
|
||||
core/
|
||||
__init__.py
|
||||
_core.pyd
|
||||
filters/
|
||||
__init__.py
|
||||
_filters.pyd
|
||||
io/
|
||||
__init__.py
|
||||
_io.pyd
|
||||
]
|
||||
|
||||
Note that we created a directory for each extension module, and added a
|
||||
__init__.py to each one. But if we leave it that way, the user will have to
|
||||
access the functions in the core module with this syntax:
|
||||
|
||||
>>> import sounds.core._core
|
||||
>>> sounds.core._core.foo(...)
|
||||
|
||||
which is not what we want. But here enters the [^__init__.py] magic: everything
|
||||
that is brought to the [^__init__.py] namespace can be accessed directly by the
|
||||
user. So, all we have to do is bring the entire namespace from [^_core.pyd]
|
||||
to [^core/__init__.py]. So add this line of code to [^sounds/core/__init__.py]:
|
||||
|
||||
from _core import *
|
||||
|
||||
We do the same for the other packages. Now the user accesses the functions and
|
||||
classes in the extension modules like before:
|
||||
|
||||
>>> import sounds.filters
|
||||
>>> sounds.filters.echo(...)
|
||||
|
||||
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 ['pure] Python function,
|
||||
[^echo_noise], to the [^filters] package. This function applies both the
|
||||
[^echo] and [^noise] filters in sequence in the given [^sound] object. We
|
||||
create a file named [^sounds/filters/echo_noise.py] and code our function:
|
||||
|
||||
import _filters
|
||||
def echo_noise(sound):
|
||||
s = _filters.echo(sound)
|
||||
s = _filters.noise(sound)
|
||||
return s
|
||||
|
||||
Next, we add this line to [^sounds/filters/__init__.py]:
|
||||
|
||||
from echo_noise import echo_noise
|
||||
|
||||
And that's it. The user now accesses this function like any other function
|
||||
from the [^filters] package:
|
||||
|
||||
>>> import sounds.filters
|
||||
>>> sounds.filters.echo_noise(...)
|
||||
|
||||
[page:1 Extending Wrapped Objects in Python]
|
||||
|
||||
Thanks to Python's flexibility, you can easily add new methods to a class,
|
||||
even after it was already created:
|
||||
|
||||
>>> class C(object): pass
|
||||
>>>
|
||||
>>> # a regular function
|
||||
>>> def C_str(self): return 'A C instance!'
|
||||
>>>
|
||||
>>> # now we turn it in a member function
|
||||
>>> C.__str__ = C_str
|
||||
>>>
|
||||
>>> c = C()
|
||||
>>> print c
|
||||
A C instance!
|
||||
>>> C_str(c)
|
||||
A C instance!
|
||||
|
||||
Yes, Python rox. :-)
|
||||
|
||||
We can do the same with classes that were wrapped with Boost.Python. Suppose
|
||||
we have a class [^point] in C++:
|
||||
|
||||
class point {...};
|
||||
|
||||
BOOST_PYTHON_MODULE(_geom)
|
||||
{
|
||||
class_<point>("point")...;
|
||||
}
|
||||
|
||||
If we are using the technique from the previous session, [@creating_packages.html
|
||||
Creating Packages], we can code directly into [^geom/__init__.py]:
|
||||
|
||||
from _geom import *
|
||||
|
||||
# a regular function
|
||||
def point_str(self):
|
||||
return str((self.x, self.y))
|
||||
|
||||
# now we turn it into a member function
|
||||
point.__str__ = point_str
|
||||
|
||||
[*All] point instances created from C++ will also have this member function!
|
||||
This technique has several advantages:
|
||||
|
||||
* Cut down compile times to zero for these additional functions
|
||||
* Reduce the memory footprint to virtually zero
|
||||
* Minimize the need to recompile
|
||||
* Rapid prototyping (you can move the code to C++ if required without changing the interface)
|
||||
|
||||
You can even add a little syntactic sugar with the use of metaclasses. Let's
|
||||
create a special metaclass that "injects" methods in other classes.
|
||||
|
||||
# The one Boost.Python uses for all wrapped classes.
|
||||
# You can use here any class exported by Boost instead of "point"
|
||||
BoostPythonMetaclass = point.__class__
|
||||
|
||||
class injector(object):
|
||||
class __metaclass__(BoostPythonMetaclass):
|
||||
def __init__(self, name, bases, dict):
|
||||
for b in bases:
|
||||
if type(b) not in (self, type):
|
||||
for k,v in dict.items():
|
||||
setattr(b,k,v)
|
||||
return type.__init__(self, name, bases, dict)
|
||||
|
||||
# inject some methods in the point foo
|
||||
class more_point(injector, point):
|
||||
def __repr__(self):
|
||||
return 'Point(x=%s, y=%s)' % (self.x, self.y)
|
||||
def foo(self):
|
||||
print 'foo!'
|
||||
|
||||
Now let's see how it got:
|
||||
|
||||
>>> print point()
|
||||
Point(x=10, y=10)
|
||||
>>> point().foo()
|
||||
foo!
|
||||
|
||||
Another useful idea is to replace constructors with factory functions:
|
||||
|
||||
_point = point
|
||||
|
||||
def point(x=0, y=0):
|
||||
return _point(x, y)
|
||||
|
||||
In this simple case there is not much gained, but for constructurs with
|
||||
many overloads and/or arguments this is often a great simplification, again
|
||||
with virtually zero memory footprint and zero compile-time overhead for
|
||||
the keyword support.
|
||||
|
||||
[page:1 Reducing Compiling Time]
|
||||
|
||||
If you have ever exported a lot of classes, you know that it takes quite a good
|
||||
time to compile the Boost.Python wrappers. Plus the memory consumption can
|
||||
easily become too high. If this is causing you problems, you can split the
|
||||
class_ definitions in multiple files:
|
||||
|
||||
/* file point.cpp */
|
||||
#include <point.h>
|
||||
#include <boost/python.hpp>
|
||||
|
||||
void export_point()
|
||||
{
|
||||
class_<point>("point")...;
|
||||
}
|
||||
|
||||
/* file triangle.cpp */
|
||||
#include <triangle.h>
|
||||
#include <boost/python.hpp>
|
||||
|
||||
void export_triangle()
|
||||
{
|
||||
class_<triangle>("triangle")...;
|
||||
}
|
||||
|
||||
Now you create a file [^main.cpp], which contains the [^BOOST_PYTHON_MODULE]
|
||||
macro, and call the various export functions inside it.
|
||||
|
||||
void export_point();
|
||||
void export_triangle();
|
||||
|
||||
BOOST_PYTHON_MODULE(_geom)
|
||||
{
|
||||
export_point();
|
||||
export_triangle();
|
||||
}
|
||||
|
||||
Compiling and linking together all this files produces the same result as the
|
||||
usual approach:
|
||||
|
||||
#include <boost/python.hpp>
|
||||
#include <point.h>
|
||||
#include <triangle.h>
|
||||
|
||||
BOOST_PYTHON_MODULE(_geom)
|
||||
{
|
||||
class_<point>("point")...;
|
||||
class_<triangle>("triangle")...;
|
||||
}
|
||||
|
||||
but the memory is kept under control.
|
||||
|
||||
This method is recommended too if you are developing the C++ library and
|
||||
exporting it to Python at the same time: changes in a class will only demand
|
||||
the compilation of a single cpp, instead of the entire wrapper code.
|
||||
|
||||
[blurb __note__ If you're exporting your classes with [@../../../pyste/index.html Pyste],
|
||||
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
|
||||
['"fatal error C1204:Compiler limit:internal structure overflow"] when compiling
|
||||
a large source file, as explained in the [@../../v2/faq.html#c1204 FAQ].]
|
||||
|
||||
115
doc/tutorial/doc/reducing_compiling_time.html
Normal file
115
doc/tutorial/doc/reducing_compiling_time.html
Normal file
@@ -0,0 +1,115 @@
|
||||
<html>
|
||||
<head>
|
||||
<!-- Generated by the Spirit (http://spirit.sf.net) QuickDoc -->
|
||||
<title>Reducing Compiling Time</title>
|
||||
<link rel="stylesheet" href="theme/style.css" type="text/css">
|
||||
<link rel="prev" href="extending_wrapped_objects_in_python.html">
|
||||
</head>
|
||||
<body>
|
||||
<table width="100%" height="48" border="0" cellspacing="2">
|
||||
<tr>
|
||||
<td><img src="theme/c%2B%2Bboost.gif">
|
||||
</td>
|
||||
<td width="85%">
|
||||
<font size="6" face="Verdana, Arial, Helvetica, sans-serif"><b>Reducing Compiling Time</b></font>
|
||||
</td>
|
||||
</tr>
|
||||
</table>
|
||||
<br>
|
||||
<table border="0">
|
||||
<tr>
|
||||
<td width="30"><a href="../index.html"><img src="theme/u_arr.gif" border="0"></a></td>
|
||||
<td width="30"><a href="extending_wrapped_objects_in_python.html"><img src="theme/l_arr.gif" border="0"></a></td>
|
||||
<td width="20"><img src="theme/r_arr_disabled.gif" border="0"></td>
|
||||
</tr>
|
||||
</table>
|
||||
<p>
|
||||
If you have ever exported a lot of classes, you know that it takes quite a good
|
||||
time to compile the Boost.Python wrappers. Plus the memory consumption can
|
||||
easily become too high. If this is causing you problems, you can split the
|
||||
class_ definitions in multiple files:</p>
|
||||
<code><pre>
|
||||
<span class=comment>/* file point.cpp */
|
||||
</span><span class=preprocessor>#include </span><span class=special><</span><span class=identifier>point</span><span class=special>.</span><span class=identifier>h</span><span class=special>>
|
||||
</span><span class=preprocessor>#include </span><span class=special><</span><span class=identifier>boost</span><span class=special>/</span><span class=identifier>python</span><span class=special>.</span><span class=identifier>hpp</span><span class=special>>
|
||||
|
||||
</span><span class=keyword>void </span><span class=identifier>export_point</span><span class=special>()
|
||||
{
|
||||
</span><span class=identifier>class_</span><span class=special><</span><span class=identifier>point</span><span class=special>>(</span><span class=string>"point"</span><span class=special>)...;
|
||||
}
|
||||
|
||||
/* </span><span class=identifier>file </span><span class=identifier>triangle</span><span class=special>.</span><span class=identifier>cpp </span><span class=special>*/
|
||||
</span><span class=preprocessor>#include </span><span class=special><</span><span class=identifier>triangle</span><span class=special>.</span><span class=identifier>h</span><span class=special>>
|
||||
</span><span class=preprocessor>#include </span><span class=special><</span><span class=identifier>boost</span><span class=special>/</span><span class=identifier>python</span><span class=special>.</span><span class=identifier>hpp</span><span class=special>>
|
||||
|
||||
</span><span class=keyword>void </span><span class=identifier>export_triangle</span><span class=special>()
|
||||
{
|
||||
</span><span class=identifier>class_</span><span class=special><</span><span class=identifier>triangle</span><span class=special>>(</span><span class=string>"triangle"</span><span class=special>)...;
|
||||
}
|
||||
</span></pre></code>
|
||||
<p>
|
||||
Now you create a file <tt>main.cpp</tt>, which contains the <tt>BOOST_PYTHON_MODULE</tt>
|
||||
macro, and call the various export functions inside it. </p>
|
||||
<code><pre>
|
||||
<span class=keyword>void </span><span class=identifier>export_point</span><span class=special>();
|
||||
</span><span class=keyword>void </span><span class=identifier>export_triangle</span><span class=special>();
|
||||
|
||||
</span><span class=identifier>BOOST_PYTHON_MODULE</span><span class=special>(</span><span class=identifier>_geom</span><span class=special>)
|
||||
{
|
||||
</span><span class=identifier>export_point</span><span class=special>();
|
||||
</span><span class=identifier>export_triangle</span><span class=special>();
|
||||
}
|
||||
</span></pre></code>
|
||||
<p>
|
||||
Compiling and linking together all this files produces the same result as the
|
||||
usual approach:</p>
|
||||
<code><pre>
|
||||
<span class=preprocessor>#include </span><span class=special><</span><span class=identifier>boost</span><span class=special>/</span><span class=identifier>python</span><span class=special>.</span><span class=identifier>hpp</span><span class=special>>
|
||||
</span><span class=preprocessor>#include </span><span class=special><</span><span class=identifier>point</span><span class=special>.</span><span class=identifier>h</span><span class=special>>
|
||||
</span><span class=preprocessor>#include </span><span class=special><</span><span class=identifier>triangle</span><span class=special>.</span><span class=identifier>h</span><span class=special>>
|
||||
|
||||
</span><span class=identifier>BOOST_PYTHON_MODULE</span><span class=special>(</span><span class=identifier>_geom</span><span class=special>)
|
||||
{
|
||||
</span><span class=identifier>class_</span><span class=special><</span><span class=identifier>point</span><span class=special>>(</span><span class=string>"point"</span><span class=special>)...;
|
||||
</span><span class=identifier>class_</span><span class=special><</span><span class=identifier>triangle</span><span class=special>>(</span><span class=string>"triangle"</span><span class=special>)...;
|
||||
}
|
||||
</span></pre></code>
|
||||
<p>
|
||||
but the memory is kept under control. </p>
|
||||
<p>
|
||||
This method is recommended too if you are developing the C++ library and
|
||||
exporting it to Python at the same time: changes in a class will only demand
|
||||
the compilation of a single cpp, instead of the entire wrapper code.</p>
|
||||
<table width="80%" border="0" align="center">
|
||||
<tr>
|
||||
<td class="note_box">
|
||||
<img src="theme/note.gif"></img> If you're exporting your classes with <a href="../../../pyste/index.html">
|
||||
Pyste</a>,
|
||||
take a look at the <tt>--multiple</tt> option, that generates the wrappers in
|
||||
various files as demonstrated here. </td>
|
||||
</tr>
|
||||
</table>
|
||||
<table width="80%" border="0" align="center">
|
||||
<tr>
|
||||
<td class="note_box">
|
||||
<img src="theme/note.gif"></img> This method is useful too if you are getting the error message
|
||||
<i>"fatal error C1204:Compiler limit:internal structure overflow"</i> when compiling
|
||||
a large source file, as explained in the <a href="../../v2/faq.html#c1204">
|
||||
FAQ</a>. </td>
|
||||
</tr>
|
||||
</table>
|
||||
<table border="0">
|
||||
<tr>
|
||||
<td width="30"><a href="../index.html"><img src="theme/u_arr.gif" border="0"></a></td>
|
||||
<td width="30"><a href="extending_wrapped_objects_in_python.html"><img src="theme/l_arr.gif" border="0"></a></td>
|
||||
<td width="20"><img src="theme/r_arr_disabled.gif" border="0"></td>
|
||||
</tr>
|
||||
</table>
|
||||
<br>
|
||||
<hr size="1"><p class="copyright">Copyright © 2002-2003 David Abrahams<br>Copyright © 2002-2003 Joel de Guzman<br><br>
|
||||
<font size="2">Permission to copy, use, modify, sell and distribute this document
|
||||
is granted provided this copyright notice appears in all copies. This document
|
||||
is provided "as is" without express or implied warranty, and with
|
||||
no claim as to its suitability for any purpose. </font> </p>
|
||||
</body>
|
||||
</html>
|
||||
@@ -147,7 +147,7 @@ constructed from a <tt>handle</tt>. The following examples should illustrate thi
|
||||
fact:</p>
|
||||
<code><pre>
|
||||
<span class=identifier>handle</span><span class=special><> </span><span class=identifier>main_module</span><span class=special>(</span><span class=identifier>borrowed</span><span class=special>( </span><span class=identifier>PyImport_AddModule</span><span class=special>(</span><span class=string>"__main__"</span><span class=special>) ));
|
||||
</span><span class=identifier>main_namespace </span><span class=identifier>dict</span><span class=special>(</span><span class=identifier>handle</span><span class=special><>(</span><span class=identifier>borrowed</span><span class=special>( </span><span class=identifier>PyModule_GetDict</span><span class=special>(</span><span class=identifier>main_module</span><span class=special>.</span><span class=identifier>get</span><span class=special>()) )));
|
||||
</span><span class=identifier>dict </span><span class=identifier>main_namespace</span><span class=special>(</span><span class=identifier>handle</span><span class=special><>(</span><span class=identifier>borrowed</span><span class=special>( </span><span class=identifier>PyModule_GetDict</span><span class=special>(</span><span class=identifier>main_module</span><span class=special>.</span><span class=identifier>get</span><span class=special>()) )));
|
||||
</span><span class=identifier>handle</span><span class=special><>( </span><span class=identifier>PyRun_String</span><span class=special>(</span><span class=string>"result = 5 ** 2"</span><span class=special>, </span><span class=identifier>Py_file_input</span><span class=special>,
|
||||
</span><span class=identifier>main_namespace</span><span class=special>.</span><span class=identifier>ptr</span><span class=special>(), </span><span class=identifier>main_namespace</span><span class=special>.</span><span class=identifier>ptr</span><span class=special>()) );
|
||||
</span><span class=keyword>int </span><span class=identifier>five_squared </span><span class=special>= </span><span class=identifier>extract</span><span class=special><</span><span class=keyword>int</span><span class=special>>( </span><span class=identifier>main_namespace</span><span class=special>[</span><span class=string>"result"</span><span class=special>] );
|
||||
@@ -227,7 +227,7 @@ allow_null</a> function in the same way you'd use borrowed:</p>
|
||||
</tr>
|
||||
</table>
|
||||
<br>
|
||||
<hr size="1"><p class="copyright">Copyright © 2002-2003 Dirk Gerrits<br><br>
|
||||
<hr size="1"><p class="copyright">Copyright © 2002-2003 David Abrahams<br>Copyright © 2002-2003 Joel de Guzman<br><br>
|
||||
<font size="2">Permission to copy, use, modify, sell and distribute this document
|
||||
is granted provided this copyright notice appears in all copies. This document
|
||||
is provided "as is" without express or implied warranty, and with
|
||||
|
||||
@@ -145,6 +145,26 @@
|
||||
<a href="doc/exception_translation.html">Exception Translation</a>
|
||||
</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td class="toc_cells_L0">
|
||||
<a href="doc/general_techniques.html">General Techniques</a>
|
||||
</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td class="toc_cells_L1">
|
||||
<a href="doc/creating_packages.html">Creating Packages</a>
|
||||
</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td class="toc_cells_L1">
|
||||
<a href="doc/extending_wrapped_objects_in_python.html">Extending Wrapped Objects in Python</a>
|
||||
</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td class="toc_cells_L1">
|
||||
<a href="doc/reducing_compiling_time.html">Reducing Compiling Time</a>
|
||||
</td>
|
||||
</tr>
|
||||
</table>
|
||||
<br>
|
||||
<hr size="1"><p class="copyright">Copyright © 2002-2003 David Abrahams<br>Copyright © 2002-2003 Joel de Guzman<br><br>
|
||||
|
||||
@@ -45,7 +45,7 @@ of work got done...
|
||||
<h3><a name="arity">Arbitrary Arity Support</a></h3>
|
||||
|
||||
I began using the <a
|
||||
href="../../../preprocessor/doc/index.htm">Boost.Preprocessor</a>
|
||||
href="../../../preprocessor/doc/index.html">Boost.Preprocessor</a>
|
||||
metaprogramming library to generate support for functions and member
|
||||
functions of arbitrary arity, which was, to say the least, quite an
|
||||
adventure. The feedback cycle resulting from my foray into
|
||||
|
||||
@@ -28,50 +28,40 @@
|
||||
|
||||
<h2><a name="introduction"></a>Introduction</h2>
|
||||
|
||||
<p>Instances of a dereferenceable type can be used like a pointer to access an lvalue.
|
||||
<p>Instances of a Dereferenceable type can be used like a pointer to access an lvalue.
|
||||
|
||||
<h2><a name="concept-requirements"></a>Concept Requirements</h2>
|
||||
<h3><a name="Dereferenceable-concept"></a>Dereferenceable Concept</h3>
|
||||
|
||||
<p>In the table below, <code><b>x</b></code> denotes an object whose
|
||||
type is a model of Dereferenceable.
|
||||
|
||||
<table summary="Dereferenceable expressions" border="1" cellpadding="5">
|
||||
|
||||
<tr>
|
||||
<td><b>Expression</b></td>
|
||||
<td><b>Requirements</b></td>
|
||||
</tr>
|
||||
|
||||
<tr>
|
||||
<td valign="top"><code>*x</code></td>
|
||||
<td>An lvalue
|
||||
</tr>
|
||||
</table>
|
||||
|
||||
If <code><b>x</b></code> is not a pointer type, it also must satsify the following expression:
|
||||
<p>In the table below, <code><b>T</b></code> is a model of
|
||||
Dereferenceable, and <code><b>x</b></code> denotes an object of
|
||||
type <code>T</code>. In addition, all pointers are Dereferenceable.
|
||||
|
||||
<table summary="Dereferenceable expressions" border="1" cellpadding="5">
|
||||
|
||||
<tr>
|
||||
<td><b>Expression</b></td>
|
||||
<td><b>Result</b></td>
|
||||
<td><b>Operational Semantics</b></td>
|
||||
</tr>
|
||||
|
||||
<tr>
|
||||
<td valign="top"><code>x.get()</code></td>
|
||||
<td><code>get_pointer(x)</code></td>
|
||||
<td>convertible to <code><a href="pointee.html#pointee-spec">pointee</a><T>::type*</code>
|
||||
<td><code>&*x</code>, or a null pointer
|
||||
</tr>
|
||||
<tr>
|
||||
|
||||
</table>
|
||||
|
||||
<hr>
|
||||
<p>Revised
|
||||
<!--webbot bot="Timestamp" S-Type="EDITED" S-Format="%d %B, %Y" startspan -->
|
||||
29 November, 2002
|
||||
18 December, 2003
|
||||
<!--webbot bot="Timestamp" endspan i-checksum="39359" -->
|
||||
</p>
|
||||
<p><i>© Copyright <a href="../../../../people/dave_abrahams.htm">Dave
|
||||
Abrahams</a> 2002. All Rights Reserved.</i>
|
||||
Abrahams</a> 2002-2003. All Rights Reserved.</i>
|
||||
|
||||
<p>Permission to copy, use, modify, sell
|
||||
and distribute this software is granted provided this copyright notice appears
|
||||
|
||||
@@ -54,7 +54,7 @@ focused on reducing the support burden. In recent weeks, responding to
|
||||
requests for support, espcially surrounding building the library, had
|
||||
begun to impede progress on development. There was a major push to
|
||||
release a stable 1.28.0 of Boost, including documentation of <a
|
||||
href="../../../../tools/build/index.html">Boost.Build</a> and specific
|
||||
href="../../../../tools/build/v1/build_system.htm">Boost.Build</a> and specific
|
||||
<a href="../building.html">instructions</a> for building Boost.Python
|
||||
v1. The documentation for Boost.Python v2 was also updated as
|
||||
described <a href="#documentation">here</a>.
|
||||
@@ -70,7 +70,7 @@ described <a href="#documentation">here</a>.
|
||||
Martin Casado which uncovered the key mechanism required to allow
|
||||
shared libraries to use functions from the Python executable. The
|
||||
current solution used in Boost.Build relies on a <a
|
||||
href="../../../../tools/build/gen_aix_import_file.py">Python
|
||||
href="../../../../tools/build/v1/gen_aix_import_file.py">Python
|
||||
Script</a> as part of the build process. This is not a problem for
|
||||
Boost.Python, as Python will be available. However, the commands
|
||||
issued by the script are so simple that a 100%-pure-Boost.Jam
|
||||
@@ -84,8 +84,7 @@ described <a href="#documentation">here</a>.
|
||||
|
||||
Support for exposing C++ operators and functions as the corresponding
|
||||
Python special methods was added. Thinking that the Boost.Python
|
||||
<a href="../special.html#numeric">v1 interface</a> was a little too
|
||||
esoteric (especially the use of
|
||||
v1 interface was a little too esoteric (especially the use of
|
||||
<code>left_operand<...>/right_operand<...></code> for
|
||||
asymmetric operands), I introduced a simple form of <a
|
||||
href="http://osl.iu.edu/~tveldhui/papers/Expression-Templates/exprtmpl.html">expression
|
||||
@@ -155,7 +154,7 @@ This forced the exposure of the <a
|
||||
href="http://www.python.org/2.2/descrintro.html#property"><code>property</code></a>
|
||||
interface used internally to implement the data member exposure
|
||||
facility described in <a
|
||||
href="Mar2002#data_members">March</a>. Properties are an
|
||||
href="Mar2002.html#data_members">March</a>. Properties are an
|
||||
incredibly useful idiom, so it's good to be able to provide them
|
||||
at little new development cost.
|
||||
|
||||
@@ -212,7 +211,7 @@ Major updates were made to the following pages:
|
||||
|
||||
<blockquote>
|
||||
<dl>
|
||||
<dt><a href="call.html">call.html</a><dd> <dt><a href="updated">updated</a><dd>
|
||||
<dt><a href="call.html">call.html</a><dd> <dt>updated<dd>
|
||||
<dt><a href="class.html">class.html</a><dd>
|
||||
<dt><a href="reference.html">reference.html</a><dd>
|
||||
</dl>
|
||||
|
||||
@@ -31,6 +31,15 @@
|
||||
<p><a href="../../../../people/dave_abrahams.htm">Dave Abrahams</a> is
|
||||
the architect, designer, and implementor of <b>Boost.Python</b>.</p>
|
||||
|
||||
<p><a href="mailto:brett.calcott@paradise.net.nz">Brett Calcott</a>
|
||||
contributed and maintains the Visual Studio project files and
|
||||
documentation.</p>
|
||||
|
||||
<p><a href="mailto:Gottfried.Ganssauge-at-haufe.de">Gottfried
|
||||
Ganßauge</a> supplied support for opaque pointer conversions,
|
||||
complete with documentation and a regression test (and I didn't
|
||||
even have to ask him for those)!
|
||||
|
||||
<p>Joel de Guzman implemented the <a href="overloads.html">default
|
||||
argument support</a> and wrote the excellent <a href=
|
||||
"../tutorial/index.html">tutorial documentation</a>.</p>
|
||||
@@ -63,6 +72,17 @@
|
||||
use the new preproccessor metaprogramming constructs and helping us to
|
||||
work around buggy and slow C++ preprocessors.</p>
|
||||
|
||||
<p><a href="mailto:nicodemus-at-globalite.com.br">Bruno da Silva de
|
||||
Oliveira</a> contributed the ingenious <a
|
||||
href="../../pyste/index.html">Pyste</a> ("Pie-Steh")
|
||||
code generator.
|
||||
|
||||
<p><a href="mailto:nickm@sitius.com">Nikolay Mladenov</a> contributed
|
||||
<code>staticmethod</code> support.</p>
|
||||
|
||||
<p>Martin Casado solved some sticky problems which allow us to build the
|
||||
Boost.Python shared library for AIX's crazy dynamic linking model.</p>
|
||||
|
||||
<p><a href="mailto:achim@procoders.net">Achim Domma</a> contributed some
|
||||
of the <a href="reference.html#object_wrappers">Object Wrappers</a> and
|
||||
HTML templates for this documentation. Dave Hawkes contributed
|
||||
@@ -71,16 +91,6 @@
|
||||
definition syntax. Pearu Pearson wrote some of the test cases that are in
|
||||
the current test suite.</p>
|
||||
|
||||
<p><a href="mailto:brett.calcott@paradise.net.nz">Brett Calcott</a>
|
||||
contributed and maintains the Visual Studio project files and
|
||||
documentation.</p>
|
||||
|
||||
<p><a href="mailto:nickm@sitius.com">Nikolay Mladenov</a> contributed
|
||||
<code>staticmethod</code> support.</p>
|
||||
|
||||
<p>Martin Casado solved some sticky problems which allow us to build the
|
||||
Boost.Python shared library for AIX's crazy dynamic linking model.</p>
|
||||
|
||||
<p>The development of this version of Boost.Python was funded in part by
|
||||
the <a href="http://www.llnl.gov/">Lawrence Livermore National
|
||||
Laboratories</a> and by the <a href="http://cci.lbl.gov/">Computational
|
||||
|
||||
134
doc/v2/args.html
134
doc/v2/args.html
@@ -3,7 +3,7 @@
|
||||
<html>
|
||||
<head>
|
||||
<meta name="generator" content=
|
||||
"HTML Tidy for Windows (vers 1st August 2002), see www.w3.org">
|
||||
"HTML Tidy for Cygwin (vers 1st April 2002), see www.w3.org">
|
||||
<meta http-equiv="Content-Type" content="text/html; charset=iso-8859-1">
|
||||
<link rel="stylesheet" type="text/css" href="../boost.css">
|
||||
|
||||
@@ -35,7 +35,31 @@
|
||||
|
||||
<dt><a href="#keyword-expression"><i>keyword-expressions</i></a></dt>
|
||||
|
||||
<dt><a href="#functions">Functions</a></dt>
|
||||
<dt><a href="#classes">Classes</a></dt>
|
||||
|
||||
<dd>
|
||||
<dl class="page-index">
|
||||
<dt><a href="#arg-spec">class <code>arg</code></a></dt>
|
||||
|
||||
<dd>
|
||||
<dl class="page-index">
|
||||
<dt><a href="#arg-synopsis">class <code>arg</code>
|
||||
synopsis</a></dt>
|
||||
|
||||
<dt><a href="#arg-ctor">class <code>arg</code>
|
||||
constructor</a></dt>
|
||||
|
||||
<dt><a href="#arg-operator">class <code>arg</code> template
|
||||
<code>operator =</code></a></dt>
|
||||
</dl>
|
||||
</dd>
|
||||
</dl>
|
||||
</dd>
|
||||
|
||||
<dt><a href="#keyword-expression-operators"><i>Keyword-expression</i>
|
||||
operator <code>,</code></a></dt>
|
||||
|
||||
<dt><a href="#functions">Functions (deprecated)</a></dt>
|
||||
|
||||
<dd>
|
||||
<dl class="page-index">
|
||||
@@ -57,27 +81,95 @@
|
||||
|
||||
<p>A <b>keyword-expression</b> results in an object which holds a
|
||||
sequence of <a href="definitions.html#ntbs">ntbs</a>es, and whose type
|
||||
encodes the number of keywords specified.</p>
|
||||
encodes the number of keywords specified. The <b>keyword-expression</b>
|
||||
may contain default values for some or all of the keywords it holds</p>
|
||||
|
||||
<h2><a name="functions"></a>Functions</h2>
|
||||
<h2><a name="classes"></a>Classes</h2>
|
||||
|
||||
<h3><a name="args-spec"></a><code>args(</code>...<code>)</code></h3>
|
||||
<h3><a name="arg-spec"></a><code>class arg;</code></h3>
|
||||
|
||||
<p>The objects of class arg are keyword-expressions holding one keyword (
|
||||
size one )</p>
|
||||
|
||||
<h4><a name="arg-synopsis"></a>Class <code>arg</code> synopsis</h4>
|
||||
<pre>
|
||||
<i>unspecified1</i> args(char const*);
|
||||
<i>unspecified2</i> args(char const*, char const*);
|
||||
.
|
||||
.
|
||||
.
|
||||
<i>unspecifiedN</i> args(char const*, char const*, ... char const*);
|
||||
namespace boost { namespace python
|
||||
{
|
||||
struct arg
|
||||
{
|
||||
template <class T>
|
||||
arg &perator = (T const &value);
|
||||
explicit arg (char const *name){elements[0].name = name;}
|
||||
};
|
||||
|
||||
}}
|
||||
</pre>
|
||||
|
||||
<h4><a name="arg-ctor"></a>Class <code>arg</code> constructor</h4>
|
||||
<pre>
|
||||
arg(char const* name);
|
||||
</pre>
|
||||
|
||||
<dl class="function-semantics">
|
||||
<dt><b>Requires:</b> Every argument must be a <a href=
|
||||
<dt><b>Requires:</b> The argument must be a <a href=
|
||||
"definitions.html#ntbs">ntbs</a>.</dt>
|
||||
|
||||
<dt><b>Returns:</b> an object representing a <a href=
|
||||
"#keyword-expression"><i>keyword-expression</i></a> encapsulating the
|
||||
arguments passed.</dt>
|
||||
<dt><b>Effects:</b> Constructs an <code>arg</code> object holding a
|
||||
keyword with name <code>name</code>.</dt>
|
||||
</dl>
|
||||
|
||||
<h4><a name="arg-operator"></a>Class <code>arg</code> operator =</h4>
|
||||
<pre>
|
||||
template <class T> arg &operator = (T const &value);
|
||||
</pre>
|
||||
|
||||
<dl class="function-semantics">
|
||||
<dt><b>Requires:</b> The argument must convertible to python.</dt>
|
||||
|
||||
<dt><b>Effects:</b> Assigns default value for the keyword.</dt>
|
||||
|
||||
<dt><b>Returns:</b> Reference to <code>this</code>.</dt>
|
||||
</dl>
|
||||
|
||||
<h2><a name="keyword-expression-operators"><i>Keyword-expression</i>
|
||||
operator <code>,</code></a></h2>
|
||||
<pre>
|
||||
<i>keyword-expression</i> operator , (<i>keyword-expression</i>, const arg &kw) const
|
||||
<i>keyword-expression</i> operator , (<i>keyword-expression</i>, const char *name) const;
|
||||
</pre>
|
||||
|
||||
<dl class="function-semantics">
|
||||
<dt><b>Requires:</b> The argument <code>name</code> must be a <a href=
|
||||
"definitions.html#ntbs">ntbs</a>.</dt>
|
||||
|
||||
<dt><b>Effects:</b> Extends the <i>keyword-expression</i> argument with
|
||||
one more keyword.</dt>
|
||||
|
||||
<dt><b>Returns:</b> The extended <i>keyword-expression</i>.</dt>
|
||||
</dl>
|
||||
|
||||
<h2><font color="#7F7F7F"><a name="functions"></a>Functions
|
||||
(deprecated)</font></h2>
|
||||
|
||||
<h3><a name="args-spec"></a><code><font color=
|
||||
"#7F7F7F">args</font>(</code>...<code>)</code></h3>
|
||||
<pre>
|
||||
<font color="#7F7F7F"> <i>unspecified1</i> args(char const*);
|
||||
<i>unspecified2</i> args(char const*, char const*);
|
||||
.
|
||||
.
|
||||
.
|
||||
<i>unspecifiedN</i> args(char const*, char const*, ... char const*);
|
||||
</font>
|
||||
</pre>
|
||||
|
||||
<dl class="function-semantics">
|
||||
<dt><font color="#7F7F7F"><b>Requires:</b> Every argument must be a <a
|
||||
href="definitions.html#ntbs">ntbs</a>.</font></dt>
|
||||
|
||||
<dt><font color="#7F7F7F"><b>Returns:</b> an object representing a <a
|
||||
href="#keyword-expression"><i>keyword-expression</i></a> encapsulating
|
||||
the arguments passed.</font></dt>
|
||||
</dl>
|
||||
|
||||
<h2><a name="examples"></a>Example</h2>
|
||||
@@ -85,19 +177,21 @@
|
||||
#include <boost/python/def.hpp>
|
||||
using namespace boost::python;
|
||||
|
||||
int f(int x, int y, int z);
|
||||
int f(double x, double y, double z=0.0, double w=1.0);
|
||||
|
||||
BOOST_PYTHON_MODULE(xxx)
|
||||
{
|
||||
def("f", f, args("x", "y", "z"));
|
||||
def("f", f
|
||||
, ( arg("x"), "y", arg("z")=0.0, arg("w")=1.0 )
|
||||
);
|
||||
}
|
||||
</pre>
|
||||
|
||||
<p>Revised 05 November, 2001</p>
|
||||
<p>Revised 01 August, 2003</p>
|
||||
|
||||
<p><i>© Copyright <a href=
|
||||
"../../../../people/dave_abrahams.htm">Dave Abrahams</a> 2002. All Rights
|
||||
Reserved.</i></p>
|
||||
"../../../../people/dave_abrahams.htm">Dave Abrahams</a> 2002-2003. All
|
||||
Rights Reserved.</i></p>
|
||||
</body>
|
||||
</html>
|
||||
|
||||
|
||||
@@ -3,7 +3,7 @@
|
||||
<html>
|
||||
<head>
|
||||
<meta name="generator" content=
|
||||
"HTML Tidy for Windows (vers 1st August 2002), see www.w3.org">
|
||||
"HTML Tidy for Cygwin (vers 1st April 2002), see www.w3.org">
|
||||
<meta http-equiv="Content-Type" content="text/html; charset=iso-8859-1">
|
||||
<link rel="stylesheet" type="text/css" href="../boost.css">
|
||||
|
||||
@@ -212,7 +212,7 @@
|
||||
namespace boost { namespace python
|
||||
{
|
||||
template <class T
|
||||
<font color="#007F00"> , class Bases = bases<>
|
||||
<font color="#007F00"> , class Bases = bases<>
|
||||
, class HeldType = T
|
||||
, class NonCopyable = <i>unspecified</i>
|
||||
>
|
||||
@@ -261,12 +261,23 @@ namespace boost { namespace python
|
||||
template <class D>
|
||||
class_& def_readwrite(char const* name, D T::*pm);
|
||||
|
||||
// exposing static data members
|
||||
template <class D>
|
||||
class_& def_readonly(char const* name, D const& d);
|
||||
template <class D>
|
||||
class_& def_readwrite(char const* name, D& d);
|
||||
|
||||
// property creation
|
||||
template <class Get>
|
||||
void add_property(char const* name, Get const& fget);
|
||||
template <class Get, class Set>
|
||||
void add_property(char const* name, Get const& fget, Set const& fset);
|
||||
|
||||
template <class Get>
|
||||
void add_static_property(char const* name, Get const& fget);
|
||||
template <class Get, class Set>
|
||||
void add_static_property(char const* name, Get const& fget, Set const& fset);
|
||||
|
||||
// pickle support
|
||||
template <typename PickleSuite>
|
||||
self& def_pickle(PickleSuite const&);
|
||||
@@ -579,8 +590,40 @@ void add_property(char const* name, Get const& fget, Set const& fset);
|
||||
</dl>
|
||||
<br>
|
||||
<pre>
|
||||
template <class Get>
|
||||
void add_static_property(char const* name, Get const& fget);
|
||||
template <class Get, class Set>
|
||||
void add_static_property(char const* name, Get const& fget, Set const& fset);
|
||||
</pre>
|
||||
|
||||
<dl class="function-semantics">
|
||||
<dt><b>Requires:</b> <code>name</code> is an <a href=
|
||||
"definitions.html#ntbs">ntbs</a> which conforms to Python's <a href=
|
||||
"http://www.python.org/doc/current/ref/identifiers.html">identifier
|
||||
naming rules</a>.</dt>
|
||||
|
||||
<dt><b>Effects:</b> Creates a Boost.Python.StaticProperty object,
|
||||
passing <code><a href=
|
||||
"object.html#object-spec-ctors">object</a>(fget)</code> (and <code><a
|
||||
href="object.html#object-spec-ctors">object</a>(fset)</code> in the
|
||||
second form) to its constructor, then adds that property to the Python
|
||||
class under construction with the given attribute <code>name</code>.
|
||||
StaticProperty is a special subclass of Python's <a href=
|
||||
"http://www.python.org/2.2.2/descrintro.html#property"><code>property</code></a>
|
||||
class which can be called without an initial <code>self</code>
|
||||
argument.</dt>
|
||||
|
||||
<dt><b>Returns:</b> <code>*this</code></dt>
|
||||
|
||||
<dt><b>Rationale:</b> Allows users to easily expose functions that can
|
||||
be invoked from Python with static attribute access syntax.</dt>
|
||||
</dl>
|
||||
<br>
|
||||
<pre>
|
||||
template <class D>
|
||||
class_& def_readonly(char const* name, D T::*pm);
|
||||
template <class D>
|
||||
class_& def_readonly(char const* name, D const& d);
|
||||
</pre>
|
||||
|
||||
<dl class="function-semantics">
|
||||
@@ -596,17 +639,26 @@ class_& def_readonly(char const* name, D T::*pm);
|
||||
this->add_property(name, <a href=
|
||||
"data_members.html#make_getter-spec">make_getter</a>(pm));
|
||||
</pre>
|
||||
and
|
||||
<pre>
|
||||
this->add_static_property(name, <a href=
|
||||
"data_members.html#make_getter-spec">make_getter</a>(pm));
|
||||
</pre>
|
||||
respectively.<br>
|
||||
<br>
|
||||
</dd>
|
||||
|
||||
<dt><b>Returns:</b> <code>*this</code></dt>
|
||||
|
||||
<dt><b>Rationale:</b> Allows users to easily expose a class' data
|
||||
member such that it can be inspected from Python with a natural
|
||||
syntax.</dt>
|
||||
member or free variable such that it can be inspected from Python with
|
||||
a natural syntax.</dt>
|
||||
</dl>
|
||||
<pre>
|
||||
template <class D>
|
||||
class_& def_readwrite(char const* name, D T::*pm);
|
||||
template <class D>
|
||||
class_& def_readwrite(char const* name, D& d);
|
||||
</pre>
|
||||
|
||||
<dl class="function-semantics">
|
||||
@@ -618,13 +670,21 @@ this->add_property(name, <a href=
|
||||
"data_members.html#make_getter-spec">make_getter</a>(pm), <a href=
|
||||
"data_members.html#make_setter-spec">make_setter</a>(pm));
|
||||
</pre>
|
||||
and
|
||||
<pre>
|
||||
this->add_static_property(name, <a href=
|
||||
"data_members.html#make_getter-spec">make_getter</a>(pm), <a href=
|
||||
"data_members.html#make_setter-spec">make_setter</a>(pm));
|
||||
</pre>
|
||||
respectively.<br>
|
||||
<br>
|
||||
</dd>
|
||||
|
||||
<dt><b>Returns:</b> <code>*this</code></dt>
|
||||
|
||||
<dt><b>Rationale:</b> Allows users to easily expose a class' data
|
||||
member such that it can be inspected and set from Python with a natural
|
||||
syntax.</dt>
|
||||
<dt><b>Rationale:</b> Allows users to easily expose a class' data or
|
||||
free variable member such that it can be inspected and set from Python
|
||||
with a natural syntax.</dt>
|
||||
</dl>
|
||||
<pre>
|
||||
template <typename PickleSuite>
|
||||
@@ -714,8 +774,7 @@ class_<Derived, bases<Base> >("Derived");
|
||||
</pre>
|
||||
Revised
|
||||
<!--webbot bot="Timestamp" S-Type="EDITED" S-Format="%d %B, %Y" startspan -->
|
||||
13 November, 2002
|
||||
<!--webbot bot="Timestamp" endspan i-checksum="39359" -->
|
||||
5 August, 2002 <!--webbot bot="Timestamp" endspan i-checksum="39359" -->
|
||||
|
||||
|
||||
<p><i>© Copyright <a href=
|
||||
|
||||
@@ -3,7 +3,7 @@
|
||||
<html>
|
||||
<head>
|
||||
<meta name="generator" content=
|
||||
"HTML Tidy for Windows (vers 1st August 2002), see www.w3.org">
|
||||
"HTML Tidy for Cygwin (vers 1st April 2002), see www.w3.org">
|
||||
<meta http-equiv="Content-Type" content="text/html; charset=iso-8859-1">
|
||||
<link rel="stylesheet" type="text/css" href="../boost.css">
|
||||
|
||||
@@ -92,6 +92,39 @@ template <class C, class D, class Policies>
|
||||
callable object.</dt>
|
||||
</dl>
|
||||
<pre>
|
||||
template <class D>
|
||||
<a href="object.html#object-spec">object</a> make_getter(D const& d);
|
||||
template <class D, class Policies>
|
||||
<a href=
|
||||
"object.html#object-spec">object</a> make_getter(D const& d, Policies const& policies);
|
||||
|
||||
template <class D>
|
||||
<a href="object.html#object-spec">object</a> make_getter(D const* p);
|
||||
template <class D, class Policies>
|
||||
<a href=
|
||||
"object.html#object-spec">object</a> make_getter(D const* p, Policies const& policies);
|
||||
</pre>
|
||||
|
||||
<dl class="function-semantics">
|
||||
<dt><b>Requires:</b> <code>Policies</code> is a model of <a href=
|
||||
"CallPolicies.html">CallPolicies</a>.</dt>
|
||||
|
||||
<dt><b>Effects:</b> Creates a Python callable object which accepts no
|
||||
arguments and returns <code>d</code> or <code>*p</code>, converted
|
||||
<code>to_python</code> on demand. If <code>policies</code> is supplied,
|
||||
it will be applied to the function as described <a href=
|
||||
"CallPolicies.html">here</a>. Otherwise, the library attempts to
|
||||
determine whether <code>D</code> is a user-defined class type, and if
|
||||
so uses <code><a href=
|
||||
"reference_existing_object.html#reference_existing_object-spec">reference_existing_object</a></code></dt>
|
||||
|
||||
<dt>for <code>Policies</code>.</dt>
|
||||
|
||||
<dt><b>Returns:</b> An instance of <a href=
|
||||
"object.html#object-spec">object</a> which holds the new Python
|
||||
callable object.</dt>
|
||||
</dl>
|
||||
<pre>
|
||||
<a name="make_setter-spec">template <class C, class D></a>
|
||||
<a href="object.html#object-spec">object</a> make_setter(D C::*pm);
|
||||
|
||||
@@ -116,6 +149,34 @@ template <class C, class D, class Policies>
|
||||
"object.html#object-spec">object</a> which holds the new Python
|
||||
callable object.</dt>
|
||||
</dl>
|
||||
<pre>
|
||||
template <class D>
|
||||
<a href="object.html#object-spec">object</a> make_setter(D& d);
|
||||
template <class D, class Policies>
|
||||
<a href=
|
||||
"object.html#object-spec">object</a> make_setter(D& d, Policies const& policies);
|
||||
|
||||
template <class D>
|
||||
<a href="object.html#object-spec">object</a> make_setter(D* p);
|
||||
template <class D, class Policies>
|
||||
<a href=
|
||||
"object.html#object-spec">object</a> make_setter(D* p, Policies const& policies);
|
||||
</pre>
|
||||
|
||||
<dl class="function-semantics">
|
||||
<dt><b>Requires:</b> <code>Policies</code> is a model of <a href=
|
||||
"CallPolicies.html">CallPolicies</a>.</dt>
|
||||
|
||||
<dt><b>Effects:</b> Creates a Python callable object which accepts one
|
||||
argument, which is converted from Python to <code>D const&</code>
|
||||
and written into <code>d</code> or <code>*p</code>, respectively. If
|
||||
<code>policies</code> is supplied, it will be applied to the function
|
||||
as described <a href="CallPolicies.html">here</a>.</dt>
|
||||
|
||||
<dt><b>Returns:</b> An instance of <a href=
|
||||
"object.html#object-spec">object</a> which holds the new Python
|
||||
callable object.</dt>
|
||||
</dl>
|
||||
|
||||
<h2><a name="examples"></a>Example</h2>
|
||||
|
||||
@@ -155,8 +216,7 @@ BOOST_PYTHON_MODULE_INIT(data_members_example)
|
||||
|
||||
<p>
|
||||
<!--webbot bot="Timestamp" S-Type="EDITED" S-Format="%d %B, %Y" startspan -->
|
||||
13 November, 2002
|
||||
<!--webbot bot="Timestamp" endspan i-checksum="39359" -->
|
||||
5 August, 2003 <!--webbot bot="Timestamp" endspan i-checksum="39359" -->
|
||||
</p>
|
||||
|
||||
<p><i>© Copyright <a href=
|
||||
|
||||
135
doc/v2/def_visitor.html
Normal file
135
doc/v2/def_visitor.html
Normal file
@@ -0,0 +1,135 @@
|
||||
<!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN">
|
||||
<meta name="generator" content="Microsoft FrontPage 5.0">
|
||||
<meta http-equiv="Content-Type" content="text/html; charset=iso-8859-1">
|
||||
<link rel="stylesheet" type="text/css" href="../boost.css">
|
||||
|
||||
<title>Boost.Python - <boost/python/def_visitor.hpp></title>
|
||||
|
||||
<table border="0" cellpadding="7" cellspacing="0" width="100%" summary=
|
||||
"header">
|
||||
<tr>
|
||||
<td valign="top" width="300">
|
||||
<h3><a href="../../../../index.htm"><img height="86" width="277" alt=
|
||||
"C++ Boost" src="../../../../c++boost.gif" border="0"></a></h3>
|
||||
|
||||
<td valign="top">
|
||||
<h1 align="center"><a href="../index.html"><font size="7">Boost.Python</font></a></h1>
|
||||
|
||||
<h2 align="center">Header <boost/python/def_visitor.hpp></h2>
|
||||
</table>
|
||||
<hr>
|
||||
|
||||
<h2>Contents</h2>
|
||||
|
||||
|
||||
<dl class="page-index">
|
||||
<dt><a href="#introduction">Introduction</a>
|
||||
<dt><a href="#classes">Classes</a>
|
||||
<dd>
|
||||
<dl class="page-index">
|
||||
<dt><a href="#def_visitor-spec">Class <code>def_visitor</code></a>
|
||||
<dd> <a href="#def_visitor-synopsis">Class <code>def_visitor</code>
|
||||
synopsis</a></dd>
|
||||
<dd> <a href="#def_visitor-requirements">Class <code>def_visitor</code>
|
||||
requirements</a></dd>
|
||||
</dl>
|
||||
<dt><a href="#examples">Example</a>
|
||||
</dl>
|
||||
<hr>
|
||||
|
||||
<h2><a name="introduction"></a>Introduction</h2>
|
||||
|
||||
|
||||
<p><code><boost/python/def_visitor.hpp></code> provides a generic visitation
|
||||
interface through which the <a href="class.html">class_</a> <b>def</b> member
|
||||
functionality can be extended non-intrusively to avoid cluttering the <a href="class.html">class_</a>
|
||||
interface. It declares the <code>def_visitor<T> </code>class template,
|
||||
which is parameterized on the derived type <tt>DerivedVisitor</tt>, which provides
|
||||
the actual <b>def</b> functionality through its <b>visit</b> member functions.
|
||||
<h2><a name="classes"></a>Classes</h2>
|
||||
|
||||
<h3><a name="def_visitor-spec"></a>Class template <code>def_visitor<DerivedVisitor></code></h3>
|
||||
|
||||
|
||||
<p>The class def_visitor is a base class paramaterized by its derived class. The
|
||||
def_visitor class is a protocol class. Its derived class, DerivedVisitor, is
|
||||
expected to have a member function visit. The def_visitor class is never instantiated
|
||||
directly. Instead, an instance of its subclass, DerivedVisitor, is passed
|
||||
on as an argument to the <a href="class.html">class_</a> def member function.
|
||||
<h4>
|
||||
<a name="def_visitor-synopsis" id="def_visitor-synopsis"></a>Class <code>def_visitor </code>synopsis</h4>
|
||||
<pre>namespace boost { namespace python {
|
||||
|
||||
template <class DerivedVisitor>
|
||||
class def_visitor {};
|
||||
}</pre>
|
||||
<h3><a name="def_visitor-requirements"></a><code>def_visitor </code>requirements</h3>
|
||||
|
||||
|
||||
<p>The <span class="pre">client supplied class </span><span class="pre"></span><tt class="literal"><span class="pre">DerivedVisitor</span></tt>
|
||||
template parameter is expected to:
|
||||
<ul>
|
||||
<li>be privately derived from def_visitor</li>
|
||||
<li>grant friend access to class def_visitor_access</li>
|
||||
<li>define either or both visit member functions listed in the table below:</li>
|
||||
</ul>
|
||||
|
||||
|
||||
<table border class="table">
|
||||
<tr>
|
||||
<td width="181" nowrap><b>Expression</b></td>
|
||||
<td width="85"><b>Return Type</b></td>
|
||||
<td width="330"><b>Requirements</b></td>
|
||||
<td width="259"><b>Effects</b></td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td nowrap>visitor.visit(cls)</td>
|
||||
<td>void</td>
|
||||
<td>cls is an instance of a <a href="class.html">class_</a> being wrapped
|
||||
to Python. visitor is a def_visitor derived class.</td>
|
||||
<td>A call to cls.def(visitor) forwards to this member function.</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td nowrap>visitor.visit(cls, name, options)</td>
|
||||
<td>void</td>
|
||||
<td>cls is a class_ instance, name is a C string. visitor is a def_visitor
|
||||
derived class. options is a context specific optional argument.</td>
|
||||
<td>A call to cls.def(name, visitor) or cls.def(name, visitor, options) forwards
|
||||
to this member function. </td>
|
||||
</tr>
|
||||
</table>
|
||||
|
||||
<h2><a name="examples"></a>Example</h2>
|
||||
|
||||
|
||||
<pre>class X {/*...*/};<br>
|
||||
class my_def_visitor : boost::python::def_visitor<my_def_visitor>
|
||||
{
|
||||
friend class def_visitor_access;
|
||||
|
||||
template <class classT>
|
||||
void visit(classT& c) const
|
||||
{
|
||||
c
|
||||
.def("foo", &my_def_visitor::foo)
|
||||
.def("bar", &my_def_visitor::bar)
|
||||
;
|
||||
}
|
||||
|
||||
static void foo(X& self);
|
||||
static void bar(X& self);
|
||||
};
|
||||
|
||||
BOOST_PYTHON_MODULE(my_ext)
|
||||
{
|
||||
class_<X>("X")
|
||||
.def(my_def_visitor())
|
||||
;
|
||||
}
|
||||
</pre>
|
||||
<p>Revised
|
||||
<!--webbot bot="Timestamp" S-Type="EDITED" S-Format="%d %B, %Y" startspan -->27 August, 2003<!--webbot bot="Timestamp" endspan i-checksum="34484" -->
|
||||
</p>
|
||||
|
||||
|
||||
<p><i>© Copyright Joel de Guzman 2003. All Rights Reserved.</i>
|
||||
488
doc/v2/faq.html
488
doc/v2/faq.html
@@ -29,6 +29,10 @@
|
||||
<hr>
|
||||
|
||||
<dl class="page-index">
|
||||
|
||||
<dt><a href="#funcptr">How can I wrap a function which takes a
|
||||
function pointer as an argument?</a><dd>
|
||||
|
||||
<dt><a href="#dangling">I'm getting the "attempt to return dangling
|
||||
reference" error. What am I doing wrong?</a></dt>
|
||||
|
||||
@@ -53,13 +57,84 @@
|
||||
|
||||
<dt><a href="#ownership">How can I wrap a function which needs to take
|
||||
ownership of a raw pointer?</a></dt>
|
||||
|
||||
<dt><a href="#slow_compilation">Compilation takes too much time and eats too much memory!
|
||||
What can I do to make it faster?</a></dt>
|
||||
|
||||
<dt><a href="#packages">How do I create sub-packages using Boost.Python?</a></dt>
|
||||
|
||||
<dt><a href="#msvcthrowbug"
|
||||
>error C2064: term does not evaluate to a function taking 2 arguments</a>
|
||||
</dt>
|
||||
|
||||
<dt><a href="#voidptr">How do I handle <tt>void *</tt> conversion?</a></dt>
|
||||
|
||||
<dt><a href="#custom_string"
|
||||
>How can I automatically convert my custom string type to
|
||||
and from a Python string?</a></dt>
|
||||
|
||||
<dt><a href="#topythonconversionfailed">Why is my automatic to-python conversion not being
|
||||
found?</a></dt>
|
||||
|
||||
<dt><a href="#threadsupport">Is Boost.Python thread-aware/compatible with multiple interpreters?</a></dt>
|
||||
</dl>
|
||||
<hr>
|
||||
|
||||
<h2><a name="funcptr">How can I wrap a function which takes a
|
||||
function pointer as an argument?</a></h2>
|
||||
|
||||
If what you're trying to do is something like this:
|
||||
<pre>
|
||||
typedef boost::function<void (string s) > funcptr;
|
||||
|
||||
void foo(funcptr fp)
|
||||
{
|
||||
fp("hello,world!");
|
||||
}
|
||||
|
||||
BOOST_PYTHON_MODULE(test)
|
||||
{
|
||||
def("foo",foo) ;
|
||||
}
|
||||
</pre>
|
||||
|
||||
And then:
|
||||
|
||||
<pre>
|
||||
>>> def hello(s):
|
||||
... print s
|
||||
...
|
||||
>>> foo(hello)
|
||||
hello, world!
|
||||
</pre>
|
||||
|
||||
The short answer is: "you can't". This is not a
|
||||
Boost.Python limitation so much as a limitation of C++. The
|
||||
problem is that a Python function is actually data, and the only
|
||||
way of associating data with a C++ function pointer is to store it
|
||||
in a static variable of the function. The problem with that is
|
||||
that you can only associate one piece of data with every C++
|
||||
function, and we have no way of compiling a new C++ function
|
||||
on-the-fly for every Python function you decide to pass
|
||||
to <code>foo</code>. In other words, this could work if the C++
|
||||
function is always going to invoke the <em>same</em> Python
|
||||
function, but you probably don't want that.
|
||||
|
||||
<p>If you have the luxury of changing the C++ code you're
|
||||
wrapping, pass it an <code>object</code> instead and call that;
|
||||
the overloaded function call operator will invoke the Python
|
||||
function you pass it behind the <code>object</code>.
|
||||
|
||||
<p>For more perspective on the issue, see <a
|
||||
href="http://aspn.activestate.com/ASPN/Mail/Message/1554837">this
|
||||
posting</a>.
|
||||
|
||||
<hr>
|
||||
|
||||
<h2><a name="dangling">I'm getting the "attempt to return dangling
|
||||
reference" error. What am I doing wrong?</a></h2>
|
||||
That exception is protecting you from causing a nasty crash. It usually
|
||||
happens in response to some code like this:
|
||||
happens in response to some code like this:
|
||||
<pre>
|
||||
period const& get_floating_frequency() const
|
||||
{
|
||||
@@ -67,7 +142,7 @@ period const& get_floating_frequency() const
|
||||
m_self,"get_floating_frequency");
|
||||
}
|
||||
</pre>
|
||||
And you get:
|
||||
And you get:
|
||||
<pre>
|
||||
ReferenceError: Attempt to return dangling reference to object of type:
|
||||
class period
|
||||
@@ -98,7 +173,7 @@ class period
|
||||
I have the choice of using copy_const_reference or
|
||||
return_internal_reference. Are there considerations that would lead me
|
||||
to prefer one over the other, such as size of generated code or memory
|
||||
overhead?</i>
|
||||
overhead?</i>
|
||||
|
||||
<p><b>A:</b> copy_const_reference will make an instance with storage
|
||||
for one of your objects, size = base_size + 12 * sizeof(double).
|
||||
@@ -120,7 +195,7 @@ class period
|
||||
|
||||
<ol>
|
||||
<li>
|
||||
Using the regular <code>class_<></code> wrapper:
|
||||
Using the regular <code>class_<></code> wrapper:
|
||||
<pre>
|
||||
class_<std::vector<double> >("std_vector_double")
|
||||
.def(...)
|
||||
@@ -129,13 +204,13 @@ class_<std::vector<double> >("std_vector_double")
|
||||
</pre>
|
||||
This can be moved to a template so that several types (double, int,
|
||||
long, etc.) can be wrapped with the same code. This technique is used
|
||||
in the file
|
||||
in the file
|
||||
|
||||
<blockquote>
|
||||
scitbx/include/scitbx/array_family/boost_python/flex_wrapper.h
|
||||
</blockquote>
|
||||
in the "scitbx" package. The file could easily be modified for
|
||||
wrapping std::vector<> instantiations.
|
||||
wrapping std::vector<> instantiations.
|
||||
|
||||
<p>This type of C++/Python binding is most suitable for containers
|
||||
that may contain a large number of elements (>10000).</p>
|
||||
@@ -143,19 +218,19 @@ class_<std::vector<double> >("std_vector_double")
|
||||
|
||||
<li>
|
||||
Using custom rvalue converters. Boost.Python "rvalue converters"
|
||||
match function signatures such as:
|
||||
match function signatures such as:
|
||||
<pre>
|
||||
void foo(std::vector<double> const& array); // pass by const-reference
|
||||
void foo(std::vector<double> array); // pass by value
|
||||
</pre>
|
||||
Some custom rvalue converters are implemented in the file
|
||||
Some custom rvalue converters are implemented in the file
|
||||
|
||||
<blockquote>
|
||||
scitbx/include/scitbx/boost_python/container_conversions.h
|
||||
</blockquote>
|
||||
This code can be used to convert from C++ container types such as
|
||||
std::vector<> or std::list<> to Python tuples and vice
|
||||
versa. A few simple examples can be found in the file
|
||||
versa. A few simple examples can be found in the file
|
||||
|
||||
<blockquote>
|
||||
scitbx/array_family/boost_python/regression_test_module.cpp
|
||||
@@ -170,7 +245,7 @@ void foo(std::vector<double> array); // pass by value
|
||||
rvalue converters that convert to a "math_array" type instead of tuples.
|
||||
This is currently not implemented but is possible within the framework of
|
||||
Boost.Python V2 as it will be released in the next couple of weeks. [ed.:
|
||||
this was posted on 2002/03/10]
|
||||
this was posted on 2002/03/10]
|
||||
|
||||
<p>It would also be useful to also have "custom lvalue converters" such
|
||||
as std::vector<> <-> Python list. These converters would
|
||||
@@ -185,7 +260,7 @@ void foo(std::vector<double>& array)
|
||||
}
|
||||
}
|
||||
</pre>
|
||||
Python:
|
||||
Python:
|
||||
<pre>
|
||||
>>> l = [1, 2, 3]
|
||||
>>> foo(l)
|
||||
@@ -193,7 +268,7 @@ void foo(std::vector<double>& array)
|
||||
[2, 4, 6]
|
||||
</pre>
|
||||
Custom lvalue converters require changes to the Boost.Python core library
|
||||
and are currently not available.
|
||||
and are currently not available.
|
||||
|
||||
<p>P.S.:</p>
|
||||
|
||||
@@ -210,7 +285,7 @@ cvs -d:pserver:anonymous@cvs.cctbx.sourceforge.net:/cvsroot/cctbx co scitbx
|
||||
|
||||
<blockquote>
|
||||
<b>Q:</b> <i>I get this error message when compiling a large source
|
||||
file. What can I do?</i>
|
||||
file. What can I do?</i>
|
||||
|
||||
<p><b>A:</b> You have two choices:</p>
|
||||
|
||||
@@ -218,7 +293,7 @@ cvs -d:pserver:anonymous@cvs.cctbx.sourceforge.net:/cvsroot/cctbx co scitbx
|
||||
<li>Upgrade your compiler (preferred)</li>
|
||||
|
||||
<li>
|
||||
Break your source file up into multiple translation units.
|
||||
Break your source file up into multiple translation units.
|
||||
|
||||
<p><code><b>my_module.cpp</b></code>:</p>
|
||||
<pre>
|
||||
@@ -232,7 +307,7 @@ BOOST_PYTHON_MODULE(my_module)
|
||||
more_of_my_module();
|
||||
}
|
||||
</pre>
|
||||
<code><b>more_of_my_module.cpp</b></code>:
|
||||
<code><b>more_of_my_module.cpp</b></code>:
|
||||
<pre>
|
||||
void more_of_my_module()
|
||||
{
|
||||
@@ -246,7 +321,7 @@ void more_of_my_module()
|
||||
can always pass a reference to the <code>class_</code> object to a
|
||||
function in another source file, and call some of its member
|
||||
functions (e.g. <code>.def(...)</code>) in the auxilliary source
|
||||
file:
|
||||
file:
|
||||
|
||||
<p><code><b>more_of_my_class.cpp</b></code>:</p>
|
||||
<pre>
|
||||
@@ -277,7 +352,7 @@ void more_of_my_class(class<my_class>& x)
|
||||
library that is under test, given that python code is minimal and
|
||||
boost::python either works or it doesn't. (ie. While errors can occur
|
||||
when the wrapping method is invalid, most errors are caught by the
|
||||
compiler ;-).
|
||||
compiler ;-).
|
||||
|
||||
<p>The basic steps required to initiate a gdb session to debug a c++
|
||||
library via python are shown here. Note, however that you should start
|
||||
@@ -308,20 +383,69 @@ Current language: auto; currently c++
|
||||
solid and "just works" without requiring any special tricks from the
|
||||
user.</p>
|
||||
|
||||
<p>Unfortunately for Cygwin and MinGW users, as of this writing gdb on
|
||||
Windows has a very hard time dealing with shared libraries, which could
|
||||
make Greg's approach next to useless for you. My best advice for you is
|
||||
to use Metrowerks C++ for compiler conformance and Microsoft Visual
|
||||
Studio as a debugger when you need one.</p>
|
||||
<p>Raoul Gough has provided the following for gdb on Windows:</p>
|
||||
|
||||
<blockquote>
|
||||
|
||||
<p>gdb support for Windows DLLs has improved lately, so it is
|
||||
now possible to debug Python extensions using a few
|
||||
tricks. Firstly, you will need an up-to-date gdb with support
|
||||
for minimal symbol extraction from a DLL. Any gdb from version 6
|
||||
onwards, or Cygwin gdb-20030214-1 and onwards should do. A
|
||||
suitable release will have a section in the gdb.info file under
|
||||
Configuration – Native – Cygwin Native –
|
||||
Non-debug DLL symbols. Refer to that info section for more
|
||||
details of the procedures outlined here.</p>
|
||||
|
||||
<p>Secondly, it seems necessary to set a breakpoint in the
|
||||
Python interpreter, rather than using ^C to break execution. A
|
||||
good place to set this breakpoint is PyOS_Readline, which will
|
||||
stop execution immediately before reading each interactive
|
||||
Python command. You have to let Python start once under the
|
||||
debugger, so that it loads its own DLL, before you can set the
|
||||
breakpoint:</p>
|
||||
|
||||
<p>
|
||||
<pre>
|
||||
$ gdb python
|
||||
GNU gdb 2003-09-02-cvs (cygwin-special)
|
||||
[...]
|
||||
|
||||
(gdb) run
|
||||
Starting program: /cygdrive/c/Python22/python.exe
|
||||
Python 2.2.2 (#37, Oct 14 2002, 17:02:34) [MSC 32 bit (Intel)] on win32
|
||||
Type "help", "copyright", "credits" or "license" for more information.
|
||||
>>> ^Z
|
||||
|
||||
|
||||
Program exited normally.
|
||||
(gdb) break *&PyOS_Readline
|
||||
Breakpoint 1 at 0x1e04eff0
|
||||
(gdb) run
|
||||
Starting program: /cygdrive/c/Python22/python.exe
|
||||
Python 2.2.2 (#37, Oct 14 2002, 17:02:34) [MSC 32 bit (Intel)] on win32
|
||||
Type "help", "copyright", "credits" or "license" for more information.
|
||||
|
||||
Breakpoint 1, 0x1e04eff0 in python22!PyOS_Readline ()
|
||||
from /cygdrive/c/WINNT/system32/python22.dll
|
||||
(gdb) cont
|
||||
Continuing.
|
||||
>>> from my_ext import *
|
||||
|
||||
Breakpoint 1, 0x1e04eff0 in python22!PyOS_Readline ()
|
||||
from /cygdrive/c/WINNT/system32/python22.dll
|
||||
(gdb) # my_ext now loaded (with any debugging symbols it contains)
|
||||
</pre>
|
||||
</blockquote>
|
||||
|
||||
<h3>Debugging extensions through Boost.Build</h3>
|
||||
If you are launching your extension module tests with <a href=
|
||||
"../../../tools/build">Boost.Build</a> using the
|
||||
"../../../../tools/build/v1/build_system.htm">Boost.Build</a> using the
|
||||
<code>boost-python-runtest</code> rule, you can ask it to launch your
|
||||
debugger for you by adding "-sPYTHON_LAUNCH=<i>debugger</i>" to your bjam
|
||||
command-line:
|
||||
debugger for you by adding "--debugger=<i>debugger</i>" to your bjam
|
||||
command-line:
|
||||
<pre>
|
||||
bjam -sTOOLS=metrowerks "-sPYTHON_LAUNCH=devenv /debugexe" test
|
||||
bjam -sTOOLS=vc7.1 "--debugger=devenv /debugexe" test
|
||||
bjam -sTOOLS=gcc -sPYTHON_LAUNCH=gdb test
|
||||
</pre>
|
||||
It can also be extremely useful to add the <code>-d+2</code> option when
|
||||
@@ -329,7 +453,7 @@ bjam -sTOOLS=gcc -sPYTHON_LAUNCH=gdb test
|
||||
commands it uses to invoke it. This will invariably involve setting up
|
||||
PYTHONPATH and other important environment variables such as
|
||||
LD_LIBRARY_PATH which may be needed by your debugger in order to get
|
||||
things to work right.
|
||||
things to work right.
|
||||
<hr>
|
||||
|
||||
<h2><a name="imul"></a>Why doesn't my <code>*=</code> operator work?</h2>
|
||||
@@ -340,7 +464,7 @@ bjam -sTOOLS=gcc -sPYTHON_LAUNCH=gdb test
|
||||
<i>operator. It always tells me "can't multiply sequence with non int
|
||||
type". If I use</i> <code>p1.__imul__(p2)</code> <i>instead of</i>
|
||||
<code>p1 *= p2</code><i>, it successfully executes my code. What's
|
||||
wrong with me?</i>
|
||||
wrong with me?</i>
|
||||
|
||||
<p><b>A:</b> There's nothing wrong with you. This is a bug in Python
|
||||
2.2. You can see the same effect in Pure Python (you can learn a lot
|
||||
@@ -361,24 +485,54 @@ bjam -sTOOLS=gcc -sPYTHON_LAUNCH=gdb test
|
||||
|
||||
<h2><a name="macosx"></a>Does Boost.Python work with Mac OS X?</h2>
|
||||
|
||||
<blockquote>
|
||||
<p>The short answer: as of January 2003, unfortunately not.</p>
|
||||
It is known to work under 10.2.8 and 10.3 using
|
||||
Apple's gcc 3.3 compiler:
|
||||
<pre>gcc (GCC) 3.3 20030304 (Apple Computer, Inc. build 1493)</pre>
|
||||
Under 10.2.8 get the August 2003 gcc update (free at
|
||||
<a href="http://connect.apple.com/">http://connect.apple.com/</a>).
|
||||
Under 10.3 get the Xcode Tools v1.0 (also free).
|
||||
<p>
|
||||
Python 2.3 is required. The Python that ships with 10.3 is
|
||||
fine. Under 10.2.8 use these commands to install Python
|
||||
as a framework:
|
||||
<pre>./configure --enable-framework
|
||||
make
|
||||
make frameworkinstall</pre>
|
||||
The last command requires root privileges because the target
|
||||
directory is
|
||||
<tt>/Library/Frameworks/Python.framework/Versions/2.3</tt>.
|
||||
However, the installation does not interfere with the Python
|
||||
version that ships with 10.2.8.
|
||||
<p>
|
||||
It is also crucial to increase the <tt>stacksize</tt> before
|
||||
starting compilations, e.g.:
|
||||
<pre>limit stacksize 8192k</pre>
|
||||
If the <tt>stacksize</tt> is too small the build might crash with
|
||||
internal compiler errors.
|
||||
<p>
|
||||
Sometimes Apple's compiler exhibits a bug by printing an error
|
||||
like the following while compiling a
|
||||
<tt>boost::python::class_<your_type></tt>
|
||||
template instantiation:
|
||||
<pre>.../inheritance.hpp:44: error: cannot
|
||||
dynamic_cast `p' (of type `struct cctbx::boost_python::<unnamed>::add_pair*
|
||||
') to type `void*' (source type is not polymorphic)</pre>
|
||||
|
||||
<p>The longer answer: using Mac OS 10.2.3 with the December Developer's
|
||||
Kit, Python 2.3a1, and bjam's darwin-tools.jam, Boost.Python compiles
|
||||
fine, including the examples. However, there are problems at runtime
|
||||
(see <a href=
|
||||
"http://mail.python.org/pipermail/c++-sig/2003-January/003267.html">http://mail.python.org/pipermail/c++-sig/2003-January/003267.html</a>).
|
||||
Solutions are currently unknown.</p>
|
||||
We do not know a general workaround, but if the definition of
|
||||
<tt>your_type</tt> can be modified the following was found
|
||||
to work in all cases encountered so far:<pre>struct your_type
|
||||
{
|
||||
// before defining any member data
|
||||
#if defined(__MACH__) && defined(__APPLE_CC__) && __APPLE_CC__ == 1493
|
||||
bool dummy_;
|
||||
#endif
|
||||
// now your member data, e.g.
|
||||
double x;
|
||||
int j;
|
||||
// etc.
|
||||
};</pre>
|
||||
|
||||
<p>It is known that under certain circumstances objects are
|
||||
double-destructed. See <a href=
|
||||
"http://mail.python.org/pipermail/c++-sig/2003-January/003278.html">http://mail.python.org/pipermail/c++-sig/2003-January/003278.html</a>
|
||||
for details. It is not clear however if this problem is related to the
|
||||
Boost.Python runtime issues.</p>
|
||||
</blockquote>
|
||||
<hr>
|
||||
|
||||
<h2><a name="xref">How can I find the existing PyObject that holds a C++
|
||||
object?</a></h2>
|
||||
|
||||
@@ -390,7 +544,7 @@ bjam -sTOOLS=gcc -sPYTHON_LAUNCH=gdb test
|
||||
with virtual functions. If you make a wrapper class with an initial
|
||||
PyObject* constructor argument and store that PyObject* as "self", you
|
||||
can get back to it by casting down to that wrapper type in a thin wrapper
|
||||
function. For example:
|
||||
function. For example:
|
||||
<pre>
|
||||
class X { X(int); virtual ~X(); ... };
|
||||
X* f(); // known to return Xs that are managed by Python objects
|
||||
@@ -423,7 +577,7 @@ class_<X,X_wrap>("X", init<int>())
|
||||
runtime check that it's valid. This approach also only works if the
|
||||
<code>X</code> object was constructed from Python, because
|
||||
<code>X</code>s constructed from C++ are of course never
|
||||
<code>X_wrap</code> objects.
|
||||
<code>X_wrap</code> objects.
|
||||
|
||||
<p>Another approach to this requires you to change your C++ code a bit;
|
||||
if that's an option for you it might be a better way to go. work we've
|
||||
@@ -442,11 +596,13 @@ class_<X,X_wrap>("X", init<int>())
|
||||
its containing Python object, and you could have your f_wrap function
|
||||
look in that mapping to get the Python object out.</p>
|
||||
|
||||
<hr>
|
||||
|
||||
<h2><a name="ownership">How can I wrap a function which needs to take
|
||||
ownership of a raw pointer?</a></h2>
|
||||
|
||||
<blockquote>
|
||||
<i>Part of an API that I'm wrapping goes something like this:</i>
|
||||
<i>Part of an API that I'm wrapping goes something like this:</i>
|
||||
<pre>
|
||||
struct A {}; struct B { void add( A* ); }
|
||||
where B::add() takes ownership of the pointer passed to it.
|
||||
@@ -457,9 +613,9 @@ where B::add() takes ownership of the pointer passed to it.
|
||||
a = mod.A()
|
||||
b = mod.B()
|
||||
b.add( a )
|
||||
del a
|
||||
del a
|
||||
del b
|
||||
# python interpreter crashes
|
||||
# python interpreter crashes
|
||||
# later due to memory corruption.
|
||||
</pre>
|
||||
|
||||
@@ -470,13 +626,13 @@ del b
|
||||
|
||||
<p><i>--Bruce Lowery</i></p>
|
||||
</blockquote>
|
||||
Yes: Make sure the C++ object is held by auto_ptr:
|
||||
Yes: Make sure the C++ object is held by auto_ptr:
|
||||
<pre>
|
||||
class_<A, std::auto_ptr<A> >("A")
|
||||
...
|
||||
;
|
||||
</pre>
|
||||
Then make a thin wrapper function which takes an auto_ptr parameter:
|
||||
Then make a thin wrapper function which takes an auto_ptr parameter:
|
||||
<pre>
|
||||
void b_insert(B& b, std::auto_ptr<A> a)
|
||||
{
|
||||
@@ -487,12 +643,237 @@ void b_insert(B& b, std::auto_ptr<A> a)
|
||||
Wrap that as B.add. Note that pointers returned via <code><a href=
|
||||
"manage_new_object.html#manage_new_object-spec">manage_new_object</a></code>
|
||||
will also be held by <code>auto_ptr</code>, so this transfer-of-ownership
|
||||
will also work correctly.
|
||||
will also work correctly.
|
||||
|
||||
<hr>
|
||||
<h2><a name="slow_compilation">Compilation takes too much time and eats too
|
||||
much memory! What can I do to make it faster?</a></h2>
|
||||
<p>
|
||||
Please refer to the <a href="../tutorial/doc/reducing_compiling_time.html"
|
||||
>Reducing Compiling Time</a> section in the tutorial.
|
||||
</p>
|
||||
|
||||
<hr>
|
||||
<h2><a name="packages">How do I create sub-packages using Boost.Python?</a></h2>
|
||||
<p>
|
||||
Please refer to the <a href="../tutorial/doc/creating_packages.html"
|
||||
>Creating Packages</a> section in the tutorial.
|
||||
</p>
|
||||
|
||||
<hr>
|
||||
<h2><a name="msvcthrowbug"></a>error C2064: term does
|
||||
not evaluate to a function taking 2 arguments</h2>
|
||||
<font size="-1"><i>Niall Douglas provides these notes:</i></font><p>
|
||||
If you see Microsoft Visual C++ 7.1 (MS Visual Studio .NET 2003) issue
|
||||
an error message like the following it is most likely due to a bug
|
||||
in the compiler:
|
||||
<pre>boost\boost\python\detail\invoke.hpp(76):
|
||||
error C2064: term does not evaluate to a function taking 2 arguments"</pre>
|
||||
This message is triggered by code like the following:
|
||||
<pre>#include <boost/python.hpp>
|
||||
|
||||
using namespace boost::python;
|
||||
|
||||
class FXThread
|
||||
{
|
||||
public:
|
||||
bool setAutoDelete(bool doso) throw();
|
||||
};
|
||||
|
||||
void Export_FXThread()
|
||||
{
|
||||
class_< FXThread >("FXThread")
|
||||
.def("setAutoDelete", &FXThread::setAutoDelete)
|
||||
;
|
||||
}
|
||||
</pre>
|
||||
The bug is related to the <code>throw()</code> modifier.
|
||||
As a workaround cast off the modifier. E.g.:
|
||||
<pre>
|
||||
.def("setAutoDelete", (bool (FXThread::*)(bool)) &FXThread::setAutoDelete)</pre>
|
||||
<p>(The bug has been reported to Microsoft.)</p>
|
||||
|
||||
<hr>
|
||||
<h2><a name="voidptr"></a>How do I handle <tt>void *</tt> conversion?</h2>
|
||||
<font size="-1"><i>Niall Douglas provides these notes:</i></font><p>
|
||||
For several reasons Boost.Python does not support <tt>void *</tt> as
|
||||
an argument or as a return value. However, it is possible to wrap
|
||||
functions with <tt>void *</tt> arguments or return values using
|
||||
thin wrappers and the <i>opaque pointer</i> facility. E.g.:
|
||||
<pre>// Declare the following in each translation unit
|
||||
struct void_; // Deliberately do not define
|
||||
BOOST_PYTHON_OPAQUE_SPECIALIZED_TYPE_ID(void_);
|
||||
|
||||
void *foo(int par1, void *par2);
|
||||
|
||||
void_ *foo_wrapper(int par1, void_ *par2)
|
||||
{
|
||||
return (void_ *) foo(par1, par2);
|
||||
}
|
||||
...
|
||||
BOOST_PYTHON_MODULE(bar)
|
||||
{
|
||||
def("foo", &foo_wrapper);
|
||||
}</pre>
|
||||
|
||||
<hr>
|
||||
<h2><a name="custom_string"></a>How can I automatically
|
||||
convert my custom string type to and from a Python string?</h2>
|
||||
<font size="-1"><i>Ralf W. Grosse-Kunstleve provides these
|
||||
notes:</i></font><p>
|
||||
Below is a small, self-contained demo extension module that shows
|
||||
how to do this. Here is the corresponding trivial test:
|
||||
<pre>import custom_string
|
||||
assert custom_string.hello() == "Hello world."
|
||||
assert custom_string.size("california") == 10</pre>
|
||||
|
||||
If you look at the code you will find:
|
||||
|
||||
<ul>
|
||||
<li>A custom <tt>to_python</tt> converter (easy):
|
||||
<tt>custom_string_to_python_str</tt>
|
||||
|
||||
<li>A custom lvalue converter (needs more code):
|
||||
<tt>custom_string_from_python_str</tt>
|
||||
</ul>
|
||||
|
||||
The custom converters are registered in the global Boost.Python
|
||||
registry near the top of the module initialization function. Once
|
||||
flow control has passed through the registration code the automatic
|
||||
conversions from and to Python strings will work in any module
|
||||
imported in the same process.
|
||||
|
||||
<pre>#include <boost/python/module.hpp>
|
||||
#include <boost/python/def.hpp>
|
||||
#include <boost/python/to_python_converter.hpp>
|
||||
|
||||
namespace sandbox { namespace {
|
||||
|
||||
class custom_string
|
||||
{
|
||||
public:
|
||||
custom_string() {}
|
||||
custom_string(std::string const& value) : value_(value) {}
|
||||
std::string const& value() const { return value_; }
|
||||
private:
|
||||
std::string value_;
|
||||
};
|
||||
|
||||
struct custom_string_to_python_str
|
||||
{
|
||||
static PyObject* convert(custom_string const& s)
|
||||
{
|
||||
return boost::python::incref(boost::python::object(s.value()).ptr());
|
||||
}
|
||||
};
|
||||
|
||||
struct custom_string_from_python_str
|
||||
{
|
||||
custom_string_from_python_str()
|
||||
{
|
||||
boost::python::converter::registry::push_back(
|
||||
&convertible,
|
||||
&construct,
|
||||
boost::python::type_id<custom_string>());
|
||||
}
|
||||
|
||||
static void* convertible(PyObject* obj_ptr)
|
||||
{
|
||||
if (!PyString_Check(obj_ptr)) return 0;
|
||||
return obj_ptr;
|
||||
}
|
||||
|
||||
static void construct(
|
||||
PyObject* obj_ptr,
|
||||
boost::python::converter::rvalue_from_python_stage1_data* data)
|
||||
{
|
||||
const char* value = PyString_AsString(obj_ptr);
|
||||
if (value == 0) boost::python::throw_error_already_set();
|
||||
void* storage = (
|
||||
(boost::python::converter::rvalue_from_python_storage<custom_string>*)
|
||||
data)->storage.bytes;
|
||||
new (storage) custom_string(value);
|
||||
data->convertible = storage;
|
||||
}
|
||||
};
|
||||
|
||||
custom_string hello() { return custom_string("Hello world."); }
|
||||
|
||||
std::size_t size(custom_string const& s) { return s.value().size(); }
|
||||
|
||||
void init_module()
|
||||
{
|
||||
using namespace boost::python;
|
||||
|
||||
boost::python::to_python_converter<
|
||||
custom_string,
|
||||
custom_string_to_python_str>();
|
||||
|
||||
custom_string_from_python_str();
|
||||
|
||||
def("hello", hello);
|
||||
def("size", size);
|
||||
}
|
||||
|
||||
}} // namespace sandbox::<anonymous>
|
||||
|
||||
BOOST_PYTHON_MODULE(custom_string)
|
||||
{
|
||||
sandbox::init_module();
|
||||
}</pre>
|
||||
|
||||
<hr>
|
||||
<h2><a name="topythonconversionfailed"></a
|
||||
>Why is my automatic to-python conversion not being found?</h2>
|
||||
<font size="-1"><i>Niall Douglas provides these notes:</i></font><p>
|
||||
If you define custom converters similar to the ones
|
||||
shown above the <tt>def_readonly()</tt> and <tt>def_readwrite()</tt>
|
||||
member functions provided by <tt>boost::python::class_</tt> for
|
||||
direct access to your member data will not work as expected.
|
||||
This is because <tt>def_readonly("bar", &foo::bar)</tt> is
|
||||
equivalent to:
|
||||
|
||||
<pre>.add_property("bar", make_getter(&foo::bar, return_internal_reference()))</pre>
|
||||
|
||||
Similarly, <tt>def_readwrite("bar", &foo::bar)</tt> is
|
||||
equivalent to:
|
||||
|
||||
<pre>.add_property("bar", make_getter(&foo::bar, return_internal_reference()),
|
||||
make_setter(&foo::bar, return_internal_reference())</pre>
|
||||
|
||||
In order to define return value policies compatible with the
|
||||
custom conversions replace <tt>def_readonly()</tt> and
|
||||
<tt>def_readwrite()</tt> by <tt>add_property()</tt>. E.g.:
|
||||
|
||||
<pre>.add_property("bar", make_getter(&foo::bar, return_value_policy<return_by_value>()),
|
||||
make_setter(&foo::bar, return_value_policy<return_by_value>()))</pre>
|
||||
|
||||
<hr>
|
||||
<h2><a name="threadsupport"></a
|
||||
>Is Boost.Python thread-aware/compatible with multiple interpreters?</h2>
|
||||
<font size="-1"><i>Niall Douglas provides these notes:</i></font><p>
|
||||
The quick answer to this is: no.</p>
|
||||
<p>
|
||||
The longer answer is that it can be patched to be so, but it's
|
||||
complex. You will need to add custom lock/unlock wrapping of every
|
||||
time your code enters Boost.Python (particularly every virtual
|
||||
function override) plus heavily modify
|
||||
<tt>boost/python/detail/invoke.hpp</tt> with custom unlock/lock
|
||||
wrapping of every time Boost.Python enters your code. You must
|
||||
furthermore take care to <i>not</i> unlock/lock when Boost.Python
|
||||
is invoking iterator changes via <tt>invoke.hpp</tt>.</p>
|
||||
<p>
|
||||
There is a patched <tt>invoke.hpp</tt> posted on the C++-SIG
|
||||
mailing list archives and you can find a real implementation of all
|
||||
the machinery necessary to fully implement this in the TnFOX
|
||||
project at <a href="http://sourceforge.net/projects/tnfox/"> this
|
||||
SourceForge project location</a>.</p>
|
||||
|
||||
<hr>
|
||||
|
||||
<p>Revised
|
||||
<p>Revised
|
||||
<!--webbot bot="Timestamp" S-Type="EDITED" S-Format="%d %B, %Y" startspan -->
|
||||
23 January, 2003
|
||||
28 January, 2004
|
||||
<!--webbot bot="Timestamp" endspan i-checksum="39359" -->
|
||||
</p>
|
||||
|
||||
@@ -501,4 +882,3 @@ void b_insert(B& b, std::auto_ptr<A> a)
|
||||
Rights Reserved.</i></p>
|
||||
</body>
|
||||
</html>
|
||||
|
||||
|
||||
@@ -71,9 +71,8 @@ namespace boost { namespace python
|
||||
{
|
||||
template <class T>
|
||||
struct from_python : private <a href=
|
||||
"../../../utility/utility.htm#Class noncopyable">boost::noncopyable</a> // Exposition only.
|
||||
// from_python<T> meets the <a href=
|
||||
"NonCopyable.html">NonCopyable</a> requirements
|
||||
"../../../utility/utility.htm#Class_noncopyable">boost::noncopyable</a> // Exposition only.
|
||||
// from_python<T> meets the NonCopyable requirements
|
||||
{
|
||||
from_python(PyObject*);
|
||||
bool convertible() const;
|
||||
|
||||
@@ -10,7 +10,7 @@
|
||||
</head>
|
||||
|
||||
<body>
|
||||
Automatic redirection failed, please go to <a href=
|
||||
Loading index page; if nothing happens, please go to <a href=
|
||||
"../index.html">../index.html</a>.
|
||||
</body>
|
||||
</html>
|
||||
|
||||
636
doc/v2/indexing.html
Normal file
636
doc/v2/indexing.html
Normal file
@@ -0,0 +1,636 @@
|
||||
<!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN">
|
||||
<html>
|
||||
<head>
|
||||
<meta name="generator" content=
|
||||
"HTML Tidy for Windows (vers 1st February 2003), see www.w3.org">
|
||||
<meta http-equiv="Content-Type" content="text/html; charset=us-ascii">
|
||||
<link rel="stylesheet" type="text/css" href="../boost.css">
|
||||
<title>
|
||||
Indexing Support
|
||||
</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="../../../../c++boost.gif" border=
|
||||
"0"></a>
|
||||
</h3>
|
||||
</td>
|
||||
<td valign="top">
|
||||
<h1 align="center">
|
||||
<a href="../index.html">Boost.Python</a>
|
||||
</h1>
|
||||
|
||||
<h2> Headers <boost/python/indexing/indexing_suite.hpp><br>
|
||||
<boost/python/indexing/vector_indexing_suite.hpp></h2>
|
||||
</td>
|
||||
</tr>
|
||||
</table>
|
||||
<hr>
|
||||
<h2>
|
||||
Contents
|
||||
</h2>
|
||||
<dl class="page-index">
|
||||
<dt>
|
||||
<a href="#introduction">Introduction</a>
|
||||
</dt>
|
||||
<dt>
|
||||
<a href="#interface">Interface</a>
|
||||
</dt>
|
||||
<dd>
|
||||
<dl class="page-index">
|
||||
<dt>
|
||||
<a href="#indexing_suite">indexing_suite</a>
|
||||
</dt>
|
||||
<dt>
|
||||
<a href="#indexing_suite_subclasses">indexing_suite
|
||||
sub-classes</a>
|
||||
</dt>
|
||||
<dd>
|
||||
<dl class="page-index">
|
||||
<dt>
|
||||
<a href="#vector_indexing_suite">vector_indexing_suite</a>
|
||||
</dt>
|
||||
</dl>
|
||||
</dd>
|
||||
</dl>
|
||||
</dd>
|
||||
</dl>
|
||||
<dl>
|
||||
<dt>
|
||||
<a href="#indexing_suite_class">indexing_suite class</a>
|
||||
</dt>
|
||||
<dt>
|
||||
<a href="#vector_indexing_suite_class">vector_indexing_suite
|
||||
class</a>
|
||||
</dt>
|
||||
</dl>
|
||||
<hr>
|
||||
<h2>
|
||||
<a name="introduction" id="introduction"></a>Introduction
|
||||
</h2>
|
||||
<p>
|
||||
Indexing is a Boost Python facility for easy exportation of indexable
|
||||
C++ containers to Python. Indexable containers are containers that
|
||||
allow random access through the operator[] (e.g. std::vector).
|
||||
</p>
|
||||
<p>
|
||||
While Boost Python has all the facilities needed to expose indexable
|
||||
C++ containers such as the ubiquitous std::vector to Python, the
|
||||
procedure is not as straightforward as we'd like it to be. Python
|
||||
containers do not map easily to C++ containers. Emulating Python
|
||||
containers in C++ (see Python Reference Manual, <a href=
|
||||
"http://www.python.org/doc/current/ref/sequence-types.html">Emulating
|
||||
container types</a>) using Boost Python is non trivial. There are a lot
|
||||
of issues to consider before we can map a C++ container to Python.
|
||||
These involve implementing wrapper functions for the methods
|
||||
<strong>__len__</strong>, <strong>__getitem__</strong>,
|
||||
<strong>__setitem__</strong>, <strong>__delitem__,</strong>
|
||||
<strong>__iter__</strong> and <strong>__contains</strong>.
|
||||
</p>
|
||||
<p>
|
||||
The goals:
|
||||
</p>
|
||||
<ul>
|
||||
<li>
|
||||
<div>
|
||||
Make indexable C++ containers behave exactly as one would expect a
|
||||
Python container to behave.
|
||||
</div>
|
||||
</li>
|
||||
<li>
|
||||
Provide default reference semantics for container element indexing
|
||||
(<tt>__getitem__</tt>) such that <tt>c[i]</tt> can be mutable.
|
||||
Require:
|
||||
<div>
|
||||
<pre>
|
||||
val = c[i]
|
||||
c[i].m()
|
||||
val == c[i]
|
||||
</pre>
|
||||
</div>where <tt>m</tt> is a non-const (mutating) member function
|
||||
(method).
|
||||
</li>
|
||||
<li>
|
||||
Return safe references from <tt>__getitem__</tt> such that subsequent
|
||||
adds and deletes to and from the container will not result in
|
||||
dangling references (will not crash Python).
|
||||
</li>
|
||||
<li>
|
||||
Support slice indexes.
|
||||
</li>
|
||||
<li>
|
||||
Accept Python container arguments (e.g. lists, tuples) wherever
|
||||
appropriate.
|
||||
</li>
|
||||
<li>
|
||||
Allow for extensibility through re-definable policy classes.
|
||||
</li>
|
||||
<li>
|
||||
Provide predefined support for the most common STL and STL like
|
||||
indexable containers.
|
||||
</li>
|
||||
</ul>
|
||||
<hr>
|
||||
|
||||
<h2> <a name="interface"></a>The Boost.Python Indexing Interface</h2>
|
||||
<h3> <a name="indexing_suite"></a>indexing_suite [ Header <boost/python/indexing/indexing_suite.hpp>
|
||||
]</h3>
|
||||
<p>
|
||||
The <tt>indexing_suite</tt> class is the base protocol 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. The class automatically wraps these
|
||||
special Python methods (taken from the Python reference: <a href=
|
||||
"http://www.python.org/doc/current/ref/sequence-types.html">Emulating
|
||||
container types</a>):
|
||||
</p>
|
||||
<dl>
|
||||
<dd>
|
||||
<dl>
|
||||
<dt>
|
||||
<b><a name="l2h-126"><tt class=
|
||||
"method">__len__</tt></a></b>(<var>self</var>)
|
||||
</dt>
|
||||
<dd>
|
||||
Called to implement the built-in function <tt class=
|
||||
"function">len()</tt><a name="l2h-134"> </a> Should return
|
||||
the length of the object, an integer <code>>=</code> 0. Also,
|
||||
an object that doesn't define a <tt class=
|
||||
"method">__nonzero__()</tt> method and whose <tt class=
|
||||
"method">__len__()</tt> method returns zero is considered to be
|
||||
false in a Boolean context. <a name="l2h-128"> </a>
|
||||
</dd>
|
||||
</dl>
|
||||
<dl>
|
||||
<dt>
|
||||
<b><a name="l2h-129"><tt class=
|
||||
"method">__getitem__</tt></a></b>(<var>self, key</var>)
|
||||
</dt>
|
||||
<dd>
|
||||
Called to implement evaluation of
|
||||
<code><var>self</var>[<var>key</var>]</code>. For sequence types,
|
||||
the accepted keys should be integers and slice
|
||||
objects.<a name="l2h-135"> </a> Note that the special
|
||||
interpretation of negative indexes (if the class wishes to
|
||||
emulate a sequence type) is up to the <tt class=
|
||||
"method">__getitem__()</tt> method. If <var>key</var> is of
|
||||
an inappropriate type, <tt class="exception">TypeError</tt>
|
||||
may be raised; if of a value outside the set of indexes for
|
||||
the sequence (after any special interpretation of negative
|
||||
values), <tt class="exception">IndexError</tt> should be
|
||||
raised. <span class="note"><b class="label">Note:</b>
|
||||
<tt class="keyword">for</tt> loops expect that an <tt class=
|
||||
"exception">IndexError</tt> will be raised for illegal
|
||||
indexes to allow proper detection of the end of the
|
||||
sequence.</span>
|
||||
</dd>
|
||||
</dl>
|
||||
<dl>
|
||||
<dt>
|
||||
<b><a name="l2h-130"><tt class=
|
||||
"method">__setitem__</tt></a></b>(<var>self, key, value</var>)
|
||||
</dt>
|
||||
<dd>
|
||||
Called to implement assignment to
|
||||
<code><var>self</var>[<var>key</var>]</code>. Same note as for
|
||||
<tt class="method">__getitem__()</tt>. This should only be
|
||||
implemented for mappings if the objects support changes to the
|
||||
values for keys, or if new keys can be added, or for sequences if
|
||||
elements can be replaced. The same exceptions should be raised
|
||||
for improper <var>key</var> values as for the <tt class=
|
||||
"method">__getitem__()</tt> method.
|
||||
</dd>
|
||||
</dl>
|
||||
<dl>
|
||||
<dt>
|
||||
<b><a name="l2h-131"><tt class=
|
||||
"method">__delitem__</tt></a></b>(<var>self, key</var>)
|
||||
</dt>
|
||||
<dd>
|
||||
Called to implement deletion of
|
||||
<code><var>self</var>[<var>key</var>]</code>. Same note as for
|
||||
<tt class="method">__getitem__()</tt>. This should only be
|
||||
implemented for mappings if the objects support removal of keys,
|
||||
or for sequences if elements can be removed from the sequence.
|
||||
The same exceptions should be raised for improper <var>key</var>
|
||||
values as for the <tt class="method">__getitem__()</tt> method.
|
||||
</dd>
|
||||
</dl>
|
||||
<dl>
|
||||
<dt>
|
||||
<b><a name="l2h-132"><tt class=
|
||||
"method">__iter__</tt></a></b>(<var>self</var>)
|
||||
</dt>
|
||||
<dd>
|
||||
This method is called when an iterator is required for a
|
||||
container. This method should return a new iterator object that
|
||||
can iterate over all the objects in the container. For mappings,
|
||||
it should iterate over the keys of the container, and should also
|
||||
be made available as the method <tt class=
|
||||
"method">iterkeys()</tt>.
|
||||
<p>
|
||||
Iterator objects also need to implement this method; they are
|
||||
required to return themselves. For more information on iterator
|
||||
objects, see ``<a class="ulink" href=
|
||||
"http://www.python.org/doc/current/lib/typeiter.html">Iterator
|
||||
Types</a>'' in the <em class="citetitle"><a href=
|
||||
"http://www.python.org/doc/current/lib/lib.html" title=
|
||||
"Python Library Reference">Python Library Reference</a></em>.
|
||||
</p>
|
||||
</dd>
|
||||
</dl>
|
||||
<dl>
|
||||
<dt>
|
||||
<b><a name="l2h-133"><tt class=
|
||||
"method">__contains__</tt></a></b>(<var>self, item</var>)
|
||||
</dt>
|
||||
<dd>
|
||||
Called to implement membership test operators. Should return true
|
||||
if <var>item</var> is in <var>self</var>, false otherwise. For
|
||||
mapping objects, this should consider the keys of the mapping
|
||||
rather than the values or the key-item pairs.
|
||||
</dd>
|
||||
</dl>
|
||||
</dd>
|
||||
</dl>
|
||||
|
||||
<h3> <a name="indexing_suite_subclasses"></a>indexing_suite sub-classes</h3>
|
||||
<p>
|
||||
The <tt>indexing_suite</tt> is not meant to be used as is. A couple of
|
||||
policy functions must be supplied by subclasses of
|
||||
<tt>indexing_suite</tt>. However, a set of <tt>indexing_suite</tt>
|
||||
subclasses for the standard indexable STL containers will be provided,
|
||||
In most cases, we can simply use the available predefined suites. In
|
||||
some cases, we can refine the predefined suites to suit our needs.
|
||||
</p>
|
||||
|
||||
<h3> <a name="vector_indexing_suite"></a>vector_indexing_suite [ Header <boost/python/indexing/vector_indexing_suite.hpp>
|
||||
] </h3>
|
||||
<p>
|
||||
The <tt>vector_indexing_suite</tt> class is a predefined
|
||||
<tt>indexing_suite</tt> derived class designed to wrap
|
||||
<tt>std::vector</tt> (and <tt>std::vector</tt> like [i.e. a class with
|
||||
std::vector interface]) classes (currently, this is the only predefined
|
||||
suite available). It provides all the policies required by the
|
||||
<tt>indexing_suite</tt>.
|
||||
</p>
|
||||
<p>
|
||||
Example usage:
|
||||
</p>
|
||||
<pre>
|
||||
class X {...};
|
||||
...
|
||||
|
||||
class_<std::vector<X> >("XVec")
|
||||
.def(vector_indexing_suite<std::vector<X> >())
|
||||
;
|
||||
</pre>
|
||||
<p>
|
||||
<tt>XVec</tt> is now a full-fledged Python container (see the
|
||||
<a href="../../test/vector_indexing_suite.cpp">example in full</a>,
|
||||
along with its <a href="../../test/vector_indexing_suite.py">python
|
||||
test</a>).
|
||||
</p>
|
||||
<hr>
|
||||
<h2>
|
||||
<a name="indexing_suite_class"></a>indexing_suite class
|
||||
</h2>
|
||||
<h3>
|
||||
<br>
|
||||
<tt>indexing_suite<<br>
|
||||
class Container<br>
|
||||
, class DerivedPolicies<font color="#007F00"><br>
|
||||
</font></tt> <tt>,
|
||||
bool NoProxy<br>
|
||||
, class Element<br>
|
||||
, class Key<br>
|
||||
, class Index</tt>
|
||||
</h3>
|
||||
<table width="100%" border="1">
|
||||
<tr>
|
||||
<td>
|
||||
<strong>Template Parameter</strong><br>
|
||||
</td>
|
||||
<td>
|
||||
<strong>Requirements</strong>
|
||||
</td>
|
||||
<td>
|
||||
<strong>Semantics</strong>
|
||||
</td>
|
||||
<td>
|
||||
<strong>Default</strong>
|
||||
</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>
|
||||
<font color="#007F00"><tt>Container</tt></font>
|
||||
</td>
|
||||
<td>
|
||||
A class type
|
||||
</td>
|
||||
<td>
|
||||
The container type to be wrapped to Python.
|
||||
</td>
|
||||
<td>
|
||||
|
||||
</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>
|
||||
<font color="#007F00"><tt>DerivedPolicies</tt></font>
|
||||
</td>
|
||||
<td>
|
||||
A subclass of indexing_suite
|
||||
</td>
|
||||
<td>
|
||||
Derived classes provide the policy hooks. See <a href=
|
||||
"#DerivedPolicies">DerivedPolicies</a> below.
|
||||
</td>
|
||||
<td>
|
||||
|
||||
</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>
|
||||
<font color="#007F00"><tt>NoProxy</tt></font>
|
||||
</td>
|
||||
<td>
|
||||
A boolean
|
||||
</td>
|
||||
<td>
|
||||
By default indexed elements have Python reference semantics and are
|
||||
returned by proxy. This can be disabled by supplying
|
||||
<strong>true</strong> in the <tt>NoProxy</tt> template parameter.
|
||||
</td>
|
||||
<td>
|
||||
false
|
||||
</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>
|
||||
<font color="#007F00"><tt>Element</tt></font>
|
||||
</td>
|
||||
<td>
|
||||
|
||||
</td>
|
||||
<td>
|
||||
The container's element type.
|
||||
</td>
|
||||
<td>
|
||||
<tt>Container::value_type</tt>
|
||||
</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>
|
||||
<font color="#007F00"><tt>Key</tt></font>
|
||||
</td>
|
||||
<td>
|
||||
|
||||
</td>
|
||||
<td>
|
||||
The container's key type.
|
||||
</td>
|
||||
<td>
|
||||
<tt>Container::value_type</tt>
|
||||
</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>
|
||||
<font color="#007F00"><tt>Index</tt></font>
|
||||
</td>
|
||||
<td>
|
||||
|
||||
</td>
|
||||
<td>
|
||||
The container's index type.
|
||||
</td>
|
||||
<td>
|
||||
<tt>Container::size_type</tt>
|
||||
</td>
|
||||
</tr>
|
||||
</table>
|
||||
<pre>
|
||||
template <<br> class Container
|
||||
, class DerivedPolicies
|
||||
, bool NoProxy = false
|
||||
, class Element = typename Container::value_type
|
||||
, class Key = typename Container::value_type
|
||||
, class Index = typename Container::size_type
|
||||
><br> class indexing_suite
|
||||
: unspecified
|
||||
{
|
||||
public:
|
||||
|
||||
indexing_suite(); // default constructor
|
||||
}
|
||||
</pre>
|
||||
<h2>
|
||||
<tt><a name="DerivedPolicies"></a>DerivedPolicies</tt>
|
||||
</h2>
|
||||
<dl>
|
||||
<dd>
|
||||
Derived classes provide the hooks needed by
|
||||
the<tt>indexing_suite:</tt>
|
||||
</dd>
|
||||
</dl>
|
||||
<pre>
|
||||
static element_type&
|
||||
get_item(Container& container, index_type i);
|
||||
|
||||
static object
|
||||
get_slice(Container& container, index_type from, index_type to);
|
||||
|
||||
static void
|
||||
set_item(Container& container, index_type i, element_type const& v);
|
||||
|
||||
static void
|
||||
set_slice(
|
||||
Container& container, index_type from,
|
||||
index_type to, element_type const& v
|
||||
);
|
||||
|
||||
template <class Iter>
|
||||
static void<br> set_slice(Container& container, index_type from,
|
||||
index_type to, Iter first, Iter last
|
||||
);
|
||||
|
||||
static void
|
||||
delete_item(Container& container, index_type i);
|
||||
|
||||
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,
|
||||
index_type to, size_type len
|
||||
);
|
||||
</pre>
|
||||
<blockquote>
|
||||
<p>
|
||||
Most of these policies are self explanatory. <tt>However,
|
||||
<strong>convert_index</strong></tt> and
|
||||
<tt><strong>adjust_index</strong></tt> deserve some explanation.
|
||||
</p>
|
||||
<p>
|
||||
<strong><tt>convert_index</tt></strong> converts a Python index into
|
||||
a C++ index that the container can handle. For instance, negative
|
||||
indexes in Python, by convention, start counting from the right(e.g.
|
||||
<tt>C[-1]</tt> indexes the rightmost element in <tt>C</tt>).
|
||||
<strong><tt>convert_index</tt></strong> should handle the necessary
|
||||
conversion for the C++ container (e.g. convert <tt>-1</tt> to
|
||||
<tt>C.size()-1</tt>). <tt><strong>convert_index</strong></tt> should
|
||||
also be able to convert the type of the index (A dynamic Python type)
|
||||
to the actual type that the C++ container expects.
|
||||
</p>
|
||||
<p>
|
||||
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, what
|
||||
used to be at index 4 will now be at index 1:
|
||||
</p>
|
||||
<pre>
|
||||
[a][b][c][d][e] ---> [d][e]
|
||||
^ ^
|
||||
4 1
|
||||
</pre>
|
||||
<p>
|
||||
<strong><tt>adjust_index</tt></strong> takes care of the adjustment.
|
||||
Given a current index, the function should return the adjusted index
|
||||
when data in the container at index <tt>from</tt>..<tt>to</tt> is
|
||||
replaced by <tt>len</tt> elements.
|
||||
</p>
|
||||
</blockquote>
|
||||
<div>
|
||||
<hr>
|
||||
<h2>
|
||||
<a name="vector_indexing_suite_class"></a>vector_indexing_suite class
|
||||
</h2>
|
||||
<h3>
|
||||
Class template <tt><br>
|
||||
vector_indexing_suite<<br>
|
||||
class <font color="#007F00">Container</font><br>
|
||||
, bool <font color="#007F00">NoProxy</font><br>
|
||||
, class <font color="#007F00">DerivedPolicies</font>></tt>
|
||||
</h3>
|
||||
<table width="100%" border="1">
|
||||
<tr>
|
||||
<td>
|
||||
<strong>Template Parameter</strong><br>
|
||||
</td>
|
||||
<td>
|
||||
<strong>Requirements</strong>
|
||||
</td>
|
||||
<td>
|
||||
<strong>Semantics</strong>
|
||||
</td>
|
||||
<td>
|
||||
<strong>Default</strong>
|
||||
</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>
|
||||
<font color="#007F00"><tt>Container</tt></font>
|
||||
</td>
|
||||
<td>
|
||||
A class type
|
||||
</td>
|
||||
<td>
|
||||
The container type to be wrapped to Python.
|
||||
</td>
|
||||
<td>
|
||||
|
||||
</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>
|
||||
<font color="#007F00"><tt>NoProxy</tt></font>
|
||||
</td>
|
||||
<td>
|
||||
A boolean
|
||||
</td>
|
||||
<td>
|
||||
By default indexed elements have Python reference semantics and
|
||||
are returned by proxy. This can be disabled by supplying
|
||||
<strong>true</strong> in the <tt>NoProxy</tt> template parameter.
|
||||
</td>
|
||||
<td>
|
||||
false
|
||||
</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>
|
||||
<font color="#007F00"><tt>DerivedPolicies</tt></font>
|
||||
</td>
|
||||
<td>
|
||||
A subclass of indexing_suite
|
||||
</td>
|
||||
<td>
|
||||
The <tt>vector_indexing_suite</tt> may still be derived to
|
||||
further tweak any of the predefined policies. Static polymorphism
|
||||
through CRTP (James Coplien. "Curiously Recurring Template
|
||||
Pattern". C++ Report, Feb. 1995) enables the base
|
||||
<tt>indexing_suite</tt> class to call policy function of the most
|
||||
derived class
|
||||
</td>
|
||||
<td>
|
||||
|
||||
</td>
|
||||
</tr>
|
||||
</table>
|
||||
<pre>
|
||||
template <<br> class Container,<br> bool NoProxy = false,<br> class DerivedPolicies = unspecified_default<br> class vector_indexing_suite<br> : public indexing_suite<Container, DerivedPolicies, NoProxy><br> {<br> public:<br><br> typedef typename Container::value_type element_type;<br> typedef typename Container::value_type key_type;<br> typedef typename Container::size_type index_type;<br> typedef typename Container::size_type size_type;<br> typedef typename Container::difference_type difference_type;<br> <br> static element_type&<br> get_item(Container& container, index_type i);
|
||||
|
||||
static object
|
||||
get_slice(Container& container, index_type from, index_type to);
|
||||
|
||||
static void<br> set_item(Container& container, index_type i, element_type const& v);
|
||||
|
||||
static void
|
||||
set_slice(Container& container, index_type from,
|
||||
index_type to, element_type const& v);
|
||||
|
||||
template <class Iter><br> static void<br> set_slice(Container& container, index_type from,<br> index_type to, Iter first, Iter last);
|
||||
|
||||
static void
|
||||
delete_item(Container& container, index_type i);
|
||||
|
||||
static void
|
||||
delete_slice(Container& container, index_type from, index_type to);<br>
|
||||
static size_t
|
||||
size(Container& container);
|
||||
|
||||
static bool
|
||||
contains(Container& container, key_type const& key);
|
||||
|
||||
static index_type
|
||||
convert_index(Container& container, PyObject* i);
|
||||
|
||||
static index_type
|
||||
adjust_index(index_type current, index_type from,
|
||||
index_type to, size_type len);
|
||||
};
|
||||
</pre>
|
||||
<hr>
|
||||
© Copyright Joel de Guzman 2003. Permission to copy, use, modify,
|
||||
sell and distribute this document is granted provided this copyright
|
||||
notice appears in all copies. This document is provided "as is" without
|
||||
express or implied warranty, and with no claim as to its suitability
|
||||
for any purpose.
|
||||
</div>
|
||||
</body>
|
||||
</html>
|
||||
@@ -97,7 +97,7 @@
|
||||
<pre>
|
||||
namespace boost { namespace python
|
||||
{
|
||||
class instance_holder : <a href="../../../utility/utility.htm#Class noncopyable">noncopyable</a>
|
||||
class instance_holder : <a href="../../../utility/utility.htm#Class_noncopyable">noncopyable</a>
|
||||
{
|
||||
public:
|
||||
// destructor
|
||||
|
||||
@@ -66,9 +66,13 @@ template <class F, class Policies>
|
||||
<a href=
|
||||
"object.html#object-spec">object</a> make_function(F f, Policies const& policies)
|
||||
|
||||
template <class F, class Policies, class Keywords>
|
||||
template <class F, class Policies, class KeywordsOrSignature>
|
||||
<a href=
|
||||
"object.html#object-spec">object</a> make_function(F f, Policies const& policies, Keywords const& keywords)
|
||||
"object.html#object-spec">object</a> make_function(F f, Policies const& policies, KeywordsOrSignature const& ks)
|
||||
|
||||
template <class F, class Policies, class Keywords, class Signature>
|
||||
<a href=
|
||||
"object.html#object-spec">object</a> make_function(F f, Policies const& policies, Keywords const& kw, Signature const& sig)
|
||||
</pre>
|
||||
|
||||
<dl class="function-semantics">
|
||||
@@ -82,19 +86,41 @@ template <class F, class Policies, class Keywords>
|
||||
|
||||
<dt><b>Effects:</b> Creates a Python callable object which, when called
|
||||
from Python, converts its arguments to C++ and calls <code>f</code>. If
|
||||
<code>F</code> is a pointer-to-member-function type, the target object
|
||||
of the function call (<code>*this</code>) will be taken from the first
|
||||
Python argument, and subsequent Python arguments will be used as the
|
||||
arguments to <code>f</code>. If <code>policies</code> are supplied, it
|
||||
<code>F</code> is a pointer-to-member-function type, the target
|
||||
object of the function call (<code>*this</code>) will be taken
|
||||
from the first Python argument, and subsequent Python arguments
|
||||
will be used as the arguments
|
||||
to <code>f</code>. <ul>
|
||||
<li> If <code>policies</code> are supplied, it
|
||||
will be applied to the function as described <a href=
|
||||
"CallPolicies.html">here</a>. If <code>keywords</code> are
|
||||
"CallPolicies.html">here</a>.
|
||||
<li>If <code>keywords</code> are
|
||||
supplied, the keywords will be applied in order to the final
|
||||
arguments of the resulting function.</dt>
|
||||
arguments of the resulting function.
|
||||
<li>If <code>Signature</code>
|
||||
is supplied, it should be an instance of an <a
|
||||
href="../../../mpl/doc/ref/Sequence.html">MPL front-extensible
|
||||
sequence</a> representing the function's return type followed by
|
||||
its argument types. Pass a <code>Signature</code> when wrapping
|
||||
function object types whose signatures can't be deduced, or when
|
||||
you wish to override the types which will be passed to the
|
||||
wrapped function.
|
||||
</ul></dt>
|
||||
|
||||
<dt><b>Returns:</b> An instance of <a href=
|
||||
"object.html#object-spec">object</a> which holds the new Python
|
||||
callable object.</dt>
|
||||
|
||||
<dt><b>Caveats:</b> An argument of pointer type may
|
||||
be <code>0</code> if <code>None</code> is passed from Python.
|
||||
An argument type which is a constant reference may refer to a
|
||||
temporary which was created from the Python object for just the
|
||||
duration of the call to the wrapped function, for example
|
||||
a <code>std::vector</code> conjured up by the conversion process
|
||||
from a Python list. Use a non-<code>const</code> reference
|
||||
argument when a persistent lvalue is required.
|
||||
</dl>
|
||||
|
||||
<pre>
|
||||
<a name=
|
||||
"make_constructor-spec"></a>template <class T, class ArgList, class Generator>
|
||||
@@ -109,7 +135,7 @@ template <class ArgList, class Generator, class Policies>
|
||||
<dt><b>Requires:</b> <code>T</code> is a class type.
|
||||
<code>Policies</code> is a model of <a href=
|
||||
"CallPolicies.html">CallPolicies</a>. <code>ArgList</code> is an <a
|
||||
href="../../../mpl/doc/Sequences.html">MPL sequence</a> of C++ argument
|
||||
href="../../../mpl/doc/ref/Sequences.html">MPL sequence</a> of C++ argument
|
||||
types (<i>A1, A2,... AN</i>) such that if
|
||||
<code>a1, a2</code>... <code>aN</code> are objects of type
|
||||
<i>A1, A2,... AN</i> respectively, the expression <code>new
|
||||
|
||||
142
doc/v2/opaque_pointer_converter.html
Normal file
142
doc/v2/opaque_pointer_converter.html
Normal file
@@ -0,0 +1,142 @@
|
||||
<!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN">
|
||||
|
||||
<html>
|
||||
<head>
|
||||
<meta http-equiv="Content-Type" content="text/html; charset=iso-8859-1">
|
||||
<link rel="stylesheet" type="text/css" href="../boost.css">
|
||||
|
||||
<title>Boost.Python - <boost/python/opaque_pointer_converter.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="../../../../c++boost.gif" border="0"></a></h3>
|
||||
</td>
|
||||
|
||||
<td valign="top">
|
||||
<h1 align="center"><a href="../index.html">Boost.Python</a></h1>
|
||||
|
||||
<h2 align="center">Header
|
||||
<boost/python/opaque_pointer_converter.hpp></h2>
|
||||
</td>
|
||||
</tr>
|
||||
</table>
|
||||
<hr>
|
||||
|
||||
<h2>Contents</h2>
|
||||
|
||||
<dl class="page-index">
|
||||
<dt><a href="#classes">Classes</a></dt>
|
||||
|
||||
<dd>
|
||||
<dl class="page-index">
|
||||
<dt><a href="#opaque_pointer_converter-spec">Class template
|
||||
<code>opaque_pointer_converter<P></code></a></dt>
|
||||
|
||||
<dd>
|
||||
<dl class="page-index">
|
||||
<dt><a href="#opaque_pointer_converter-spec-synopsis">Class template
|
||||
<code>opaque_pointer_converter</code> synopsis</a></dt>
|
||||
</dl>
|
||||
</dd>
|
||||
</dl>
|
||||
</dd>
|
||||
|
||||
<dt><a href="#macros">Macros</a></dt>
|
||||
<dd>
|
||||
<dl class="page-index">
|
||||
<dt><a href="#BOOST_PYTHON_OPAQUE_SPECIALIZED_TYPE_ID-spec">Macro
|
||||
<code>BOOST_PYTHON_OPAQUE_SPECIALIZED_TYPE_ID</code></a></dt>
|
||||
</dl>
|
||||
</dd>
|
||||
|
||||
<dt><a href="#examples">Example</a></dt>
|
||||
|
||||
<dt><a href="#see-also">See Also</a></dt>
|
||||
</dl>
|
||||
<hr>
|
||||
|
||||
<h2><a name="classes"></a>Classes</h2>
|
||||
|
||||
<h3><a name="opaque_pointer_converter-spec"></a>Class template
|
||||
<code>opaque_pointer_converter<P></code></h3>
|
||||
|
||||
<p><code>opaque_pointer_converter<></code> is derived from
|
||||
<a href="to_python_converter.html#to_python_converter-spec">
|
||||
<code>to_python_converter</code></a>
|
||||
and registers itself as an
|
||||
<a href="lvalue_from_pytype.html#lvalue_from_pytype-spec">
|
||||
<code>lvalue_from_pytype</code></a> converter from Python objects
|
||||
into pointers to undefined types.
|
||||
Thus it may be used as a converter from opaque pointers into
|
||||
Python objects and vice versa.</p>
|
||||
|
||||
<h4><a name="opaque_pointer_converter-spec-synopsis"></a>Class template
|
||||
<code>opaque_pointer_converter</code> synopsis</h4>
|
||||
<pre>
|
||||
namespace boost { namespace python
|
||||
{
|
||||
template<class Pointer>
|
||||
struct opaque_pointer_converter
|
||||
: to_python_converter<
|
||||
Pointer, opaque_pointer_converter<Pointer> >
|
||||
{
|
||||
explicit opaque_pointer_converter(char const* name);
|
||||
};
|
||||
}}
|
||||
</pre>
|
||||
|
||||
<h4><a name="opaque_pointer_converter-spec-constructor"></a>Class template
|
||||
<code>opaque_pointer_converter</code> constructor</h4>
|
||||
<pre>
|
||||
explicit opaque_pointer_converter(char const* name);
|
||||
</pre>
|
||||
|
||||
<dl class="function-semantics">
|
||||
<dt><b>Effects:</b>
|
||||
<p>Registers the instance as a
|
||||
<a href="lvalue_from_pytype.html#lvalue_from_pytype-spec">
|
||||
<code>lvalue_from_pytype</code></a> converter from Python objects
|
||||
into opaque pointers.</p>
|
||||
<p>The name is used for the type of the Python Objects created;
|
||||
it should be printable but needn't be an
|
||||
<a href="definitions.html#ntbs">ntbs</a> because the object type is
|
||||
not supposed to be user constructible within python scripts.</p>
|
||||
</dt>
|
||||
</dl>
|
||||
|
||||
<h2><a name="macros"></a>Macros</h2>
|
||||
|
||||
<h3><a name="BOOST_PYTHON_OPAQUE_SPECIALIZED_TYPE_ID-spec"></a>
|
||||
Macro BOOST_PYTHON_OPAQUE_SPECIALIZED_TYPE_ID(Pointee)</h3>
|
||||
<p>This macro must be used to define specializations of the
|
||||
<a href="type_id.html#type_id-spec">type_id</a> function
|
||||
which can't be instantiated for incomplete types.</p>
|
||||
<h4>Note</h4>
|
||||
<p>In order for this to work in a cross-module environment the macro must
|
||||
be invoked in every translation unit which uses the
|
||||
opaque_pointer_converter.</p>
|
||||
|
||||
<h2><a name="examples"></a>Example</h2>
|
||||
|
||||
please see example for <a href="return_opaque_pointer.html#example">
|
||||
return_opaque_pointer</a>.
|
||||
|
||||
<h2><a name="see-also"></a>See Also</h2>
|
||||
<p>
|
||||
<a href="return_opaque_pointer.html">return_opaque_pointer</a>
|
||||
</p>
|
||||
|
||||
<p>Revised
|
||||
10 March, 2003
|
||||
</p>
|
||||
|
||||
<p><i>© Copyright 2003 Haufe Mediengruppe. All Rights
|
||||
Reserved.</i></p>
|
||||
</body>
|
||||
</html>
|
||||
|
||||
@@ -196,6 +196,8 @@ namespace boost { namespace python { namespace self_ns {
|
||||
"#operator_-spec">operator_</a><<i>unspecified</i>> operator+(self_t);
|
||||
<a href=
|
||||
"#operator_-spec">operator_</a><<i>unspecified</i>> operator~(self_t);
|
||||
<a href=
|
||||
"#operator_-spec">operator_</a><<i>unspecified</i>> operator!(self_t);
|
||||
|
||||
// value operations
|
||||
<a href=
|
||||
@@ -349,123 +351,123 @@ namespace boost { namespace python { namespace self_ns {
|
||||
</tr>
|
||||
|
||||
<tr>
|
||||
<td>self == r</td>
|
||||
<td><code>self == r</code></td>
|
||||
|
||||
<td>__eq__</td>
|
||||
<td><code>__eq__</code></td>
|
||||
|
||||
<td>x == y</td>
|
||||
<td><code>x == y</code></td>
|
||||
|
||||
<td>x == y, y == x</td>
|
||||
<td><code>x == y, y == x</code></td>
|
||||
</tr>
|
||||
|
||||
<tr>
|
||||
<td>l == self</td>
|
||||
<td><code>l == self</code></td>
|
||||
|
||||
<td>__eq__</td>
|
||||
<td><code>__eq__</code></td>
|
||||
|
||||
<td>y == x</td>
|
||||
<td><code>y == x</code></td>
|
||||
|
||||
<td>y == x, x == y</td>
|
||||
<td><code>y == x, x == y</code></td>
|
||||
</tr>
|
||||
|
||||
<tr>
|
||||
<td>self != r</td>
|
||||
<td><code>self != r</code></td>
|
||||
|
||||
<td>__ne__</td>
|
||||
<td><code>__ne__</code></td>
|
||||
|
||||
<td>x != y</td>
|
||||
<td><code>x != y</code></td>
|
||||
|
||||
<td>x != y, y != x</td>
|
||||
<td><code>x != y, y != x</code></td>
|
||||
</tr>
|
||||
|
||||
<tr>
|
||||
<td>l != self</td>
|
||||
<td><code>l != self</code></td>
|
||||
|
||||
<td>__ne__</td>
|
||||
<td><code>__ne__</code></td>
|
||||
|
||||
<td>y != x</td>
|
||||
<td><code>y != x</code></td>
|
||||
|
||||
<td>y != x, x != y</td>
|
||||
<td><code>y != x, x != y</code></td>
|
||||
</tr>
|
||||
|
||||
<tr>
|
||||
<td>self < r</td>
|
||||
<td><code>self < r</code></td>
|
||||
|
||||
<td>__lt__</td>
|
||||
<td><code>__lt__</code></td>
|
||||
|
||||
<td>x < y</td>
|
||||
<td><code>x < y</code></td>
|
||||
|
||||
<td>x < y, y > x</td>
|
||||
<td><code>x < y, y > x</code></td>
|
||||
</tr>
|
||||
|
||||
<tr>
|
||||
<td>l < self</td>
|
||||
<td><code>l < self</code></td>
|
||||
|
||||
<td>__gt__</td>
|
||||
<td><code>__gt__</code></td>
|
||||
|
||||
<td>y < x</td>
|
||||
<td><code>y < x</code></td>
|
||||
|
||||
<td>y > x, x < y</td>
|
||||
<td><code>y > x, x < y</code></td>
|
||||
</tr>
|
||||
|
||||
<tr>
|
||||
<td>self > r</td>
|
||||
<td><code>self > r</code></td>
|
||||
|
||||
<td>__gt__</td>
|
||||
<td><code>__gt__</code></td>
|
||||
|
||||
<td>x > y</td>
|
||||
<td><code>x > y</code></td>
|
||||
|
||||
<td>x > y, y < x</td>
|
||||
<td><code>x > y, y < x</code></td>
|
||||
</tr>
|
||||
|
||||
<tr>
|
||||
<td>l > self</td>
|
||||
<td><code>l > self</code></td>
|
||||
|
||||
<td>__lt__</td>
|
||||
<td><code>__lt__</code></td>
|
||||
|
||||
<td>y > x</td>
|
||||
<td><code>y > x</code></td>
|
||||
|
||||
<td>y < x, x > y</td>
|
||||
<td><code>y < x, x > y</code></td>
|
||||
</tr>
|
||||
|
||||
<tr>
|
||||
<td>self <= r</td>
|
||||
<td><code>self <= r</code></td>
|
||||
|
||||
<td>__le__</td>
|
||||
<td><code>__le__</code></td>
|
||||
|
||||
<td>x <= y</td>
|
||||
<td><code>x <= y</code></td>
|
||||
|
||||
<td>x <= y, y >= x</td>
|
||||
<td><code>x <= y, y >= x</code></td>
|
||||
</tr>
|
||||
|
||||
<tr>
|
||||
<td>l <= self</td>
|
||||
<td><code>l <= self</code></td>
|
||||
|
||||
<td>__ge__</td>
|
||||
<td><code>__ge__</code></td>
|
||||
|
||||
<td>y <= x</td>
|
||||
<td><code>y <= x</code></td>
|
||||
|
||||
<td>y >= x, x <= y</td>
|
||||
<td><code>y >= x, x <= y</code></td>
|
||||
</tr>
|
||||
|
||||
<tr>
|
||||
<td>self >= r</td>
|
||||
<td><code>self >= r</code></td>
|
||||
|
||||
<td>__ge__</td>
|
||||
<td><code>__ge__</code></td>
|
||||
|
||||
<td>x >= y</td>
|
||||
<td><code>x >= y</code></td>
|
||||
|
||||
<td>x >= y, y <= x</td>
|
||||
<td><code>x >= y, y <= x</code></td>
|
||||
</tr>
|
||||
|
||||
<tr>
|
||||
<td>l >= self</td>
|
||||
<td><code>l >= self</code></td>
|
||||
|
||||
<td>__le__</td>
|
||||
<td><code>__le__</code></td>
|
||||
|
||||
<td>y >= x</td>
|
||||
<td><code>y >= x</code></td>
|
||||
|
||||
<td>y <= x, x >= y</td>
|
||||
<td><code>y <= x, x >= y</code></td>
|
||||
</tr>
|
||||
</table>
|
||||
|
||||
@@ -487,183 +489,183 @@ namespace boost { namespace python { namespace self_ns {
|
||||
</tr>
|
||||
|
||||
<tr>
|
||||
<td>self + r</td>
|
||||
<td><code>self + r</code></td>
|
||||
|
||||
<td>__add__</td>
|
||||
<td><code>__add__</code></td>
|
||||
|
||||
<td>x + y</td>
|
||||
<td><code>x + y</code></td>
|
||||
</tr>
|
||||
|
||||
<tr>
|
||||
<td>l + self</td>
|
||||
<td><code>l + self</code></td>
|
||||
|
||||
<td>__radd__</td>
|
||||
<td><code>__radd__</code></td>
|
||||
|
||||
<td>y + x</td>
|
||||
<td><code>y + x</code></td>
|
||||
</tr>
|
||||
|
||||
<tr>
|
||||
<td>self - r</td>
|
||||
<td><code>self - r</code></td>
|
||||
|
||||
<td>__sub__</td>
|
||||
<td><code>__sub__</code></td>
|
||||
|
||||
<td>x - y</td>
|
||||
<td><code>x - y</code></td>
|
||||
</tr>
|
||||
|
||||
<tr>
|
||||
<td>l - self</td>
|
||||
<td><code>l - self</code></td>
|
||||
|
||||
<td>__rsub__</td>
|
||||
<td><code>__rsub__</code></td>
|
||||
|
||||
<td>y - x</td>
|
||||
<td><code>y - x</code></td>
|
||||
</tr>
|
||||
|
||||
<tr>
|
||||
<td>self * r</td>
|
||||
<td><code>self * r</code></td>
|
||||
|
||||
<td>__mul__</td>
|
||||
<td><code>__mul__</code></td>
|
||||
|
||||
<td>x * y</td>
|
||||
<td><code>x * y</code></td>
|
||||
</tr>
|
||||
|
||||
<tr>
|
||||
<td>l * self</td>
|
||||
<td><code>l * self</code></td>
|
||||
|
||||
<td>__rmul__</td>
|
||||
<td><code>__rmul__</code></td>
|
||||
|
||||
<td>y * x</td>
|
||||
<td><code>y * x</code></td>
|
||||
</tr>
|
||||
|
||||
<tr>
|
||||
<td>self / r</td>
|
||||
<td><code>self / r</code></td>
|
||||
|
||||
<td>__div__</td>
|
||||
<td><code>__div__</code></td>
|
||||
|
||||
<td>x / y</td>
|
||||
<td><code>x / y</code></td>
|
||||
</tr>
|
||||
|
||||
<tr>
|
||||
<td>l / self</td>
|
||||
<td><code>l / self</code></td>
|
||||
|
||||
<td>__rdiv__</td>
|
||||
<td><code>__rdiv__</code></td>
|
||||
|
||||
<td>y / x</td>
|
||||
<td><code>y / x</code></td>
|
||||
</tr>
|
||||
|
||||
<tr>
|
||||
<td>self % r</td>
|
||||
<td><code>self % r</code></td>
|
||||
|
||||
<td>__mod__</td>
|
||||
<td><code>__mod__</code></td>
|
||||
|
||||
<td>x % y</td>
|
||||
<td><code>x % y</code></td>
|
||||
</tr>
|
||||
|
||||
<tr>
|
||||
<td>l % self</td>
|
||||
<td><code>l % self</code></td>
|
||||
|
||||
<td>__rmod__</td>
|
||||
<td><code>__rmod__</code></td>
|
||||
|
||||
<td>y % x</td>
|
||||
<td><code>y % x</code></td>
|
||||
</tr>
|
||||
|
||||
<tr>
|
||||
<td>self >> r</td>
|
||||
<td><code>self >> r</code></td>
|
||||
|
||||
<td>__rshift__</td>
|
||||
<td><code>__rshift__</code></td>
|
||||
|
||||
<td>x >> y</td>
|
||||
<td><code>x >> y</code></td>
|
||||
</tr>
|
||||
|
||||
<tr>
|
||||
<td>l >> self</td>
|
||||
<td><code>l >> self</code></td>
|
||||
|
||||
<td>__rrshift__</td>
|
||||
<td><code>__rrshift__</code></td>
|
||||
|
||||
<td>y >> x</td>
|
||||
<td><code>y >> x</code></td>
|
||||
</tr>
|
||||
|
||||
<tr>
|
||||
<td>self << r</td>
|
||||
<td><code>self << r</code></td>
|
||||
|
||||
<td>__lshift__</td>
|
||||
<td><code>__lshift__</code></td>
|
||||
|
||||
<td>x << y</td>
|
||||
<td><code>x << y</code></td>
|
||||
</tr>
|
||||
|
||||
<tr>
|
||||
<td>l << self</td>
|
||||
<td><code>l << self</code></td>
|
||||
|
||||
<td>__rlshift__</td>
|
||||
<td><code>__rlshift__</code></td>
|
||||
|
||||
<td>y << x</td>
|
||||
<td><code>y << x</code></td>
|
||||
</tr>
|
||||
|
||||
<tr>
|
||||
<td>self & r</td>
|
||||
<td><code>self & r</code></td>
|
||||
|
||||
<td>__and__</td>
|
||||
<td><code>__and__</code></td>
|
||||
|
||||
<td>x & y</td>
|
||||
<td><code>x & y</code></td>
|
||||
</tr>
|
||||
|
||||
<tr>
|
||||
<td>l & self</td>
|
||||
<td><code>l & self</code></td>
|
||||
|
||||
<td>__rand__</td>
|
||||
<td><code>__rand__</code></td>
|
||||
|
||||
<td>y & x</td>
|
||||
<td><code>y & x</code></td>
|
||||
</tr>
|
||||
|
||||
<tr>
|
||||
<td>self ^ r</td>
|
||||
<td><code>self ^ r</code></td>
|
||||
|
||||
<td>__xor__</td>
|
||||
<td><code>__xor__</code></td>
|
||||
|
||||
<td>x ^ y</td>
|
||||
<td><code>x ^ y</code></td>
|
||||
</tr>
|
||||
|
||||
<tr>
|
||||
<td>l ^ self</td>
|
||||
<td><code>l ^ self</code></td>
|
||||
|
||||
<td>__rxor__</td>
|
||||
<td><code>__rxor__</code></td>
|
||||
|
||||
<td>y ^ x</td>
|
||||
<td><code>y ^ x</code></td>
|
||||
</tr>
|
||||
|
||||
<tr>
|
||||
<td>self | r</td>
|
||||
<td><code>self | r</code></td>
|
||||
|
||||
<td>__or__</td>
|
||||
<td><code>__or__</code></td>
|
||||
|
||||
<td>x | y</td>
|
||||
<td><code>x | y</code></td>
|
||||
</tr>
|
||||
|
||||
<tr>
|
||||
<td>l | self</td>
|
||||
<td><code>l | self</code></td>
|
||||
|
||||
<td>__ror__</td>
|
||||
<td><code>__ror__</code></td>
|
||||
|
||||
<td>y | x</td>
|
||||
<td><code>y | x</code></td>
|
||||
</tr>
|
||||
|
||||
<tr>
|
||||
<td>pow(self, r)</td>
|
||||
<td><code>pow(self, r)</code></td>
|
||||
|
||||
<td>__pow__</td>
|
||||
<td><code>__pow__</code></td>
|
||||
|
||||
<td>pow(x, y)</td>
|
||||
<td><code>pow(x, y)</code></td>
|
||||
</tr>
|
||||
|
||||
<tr>
|
||||
<td>pow(l, self)</td>
|
||||
<td><code>pow(l, self)</code></td>
|
||||
|
||||
<td>__rpow__</td>
|
||||
<td><code>__rpow__</code></td>
|
||||
|
||||
<td>pow(y, x)</td>
|
||||
<td><code>pow(y, x)</code></td>
|
||||
</tr>
|
||||
</table>
|
||||
|
||||
<h4><a name="self_t-spec-unary-ops"></a>Class <code>self_t</code> unary
|
||||
<h4><a name="self_t-spec-value-unary-ops"></a>Class <code>self_t</code> unary
|
||||
operations</h4>
|
||||
|
||||
<table border="1" summary="self_t unary operations">
|
||||
@@ -676,27 +678,35 @@ namespace boost { namespace python { namespace self_ns {
|
||||
</tr>
|
||||
|
||||
<tr>
|
||||
<td>-self</td>
|
||||
<td><code>-self</code></td>
|
||||
|
||||
<td>__neg__</td>
|
||||
<td><code>__neg__</code></td>
|
||||
|
||||
<td>-x</td>
|
||||
<td><code>-x</code></td>
|
||||
</tr>
|
||||
|
||||
<tr>
|
||||
<td>+self</td>
|
||||
<td><code>+self</code></td>
|
||||
|
||||
<td>__pos__</td>
|
||||
<td><code>__pos__</code></td>
|
||||
|
||||
<td>+x</td>
|
||||
<td><code>+x</code></td>
|
||||
</tr>
|
||||
|
||||
<tr>
|
||||
<td>~self</td>
|
||||
<td><code>~self</code></td>
|
||||
|
||||
<td>__invert__</td>
|
||||
<td><code>__invert__</code></td>
|
||||
|
||||
<td>~x</td>
|
||||
<td><code>~x</code></td>
|
||||
</tr>
|
||||
|
||||
<tr>
|
||||
<td><code>not self</code><br><i>or</i><br><code>!self</code></td>
|
||||
|
||||
<td><code>__nonzero__</code></td>
|
||||
|
||||
<td><code>!!x</code></td>
|
||||
</tr>
|
||||
</table>
|
||||
|
||||
@@ -713,44 +723,44 @@ namespace boost { namespace python { namespace self_ns {
|
||||
</tr>
|
||||
|
||||
<tr>
|
||||
<td>int_(self)</td>
|
||||
<td><code>int_(self)</code></td>
|
||||
|
||||
<td>__int__</td>
|
||||
<td><code>__int__</code></td>
|
||||
|
||||
<td>long(x)</td>
|
||||
<td><code>long(x)</code></td>
|
||||
</tr>
|
||||
|
||||
<tr>
|
||||
<td>long_</td>
|
||||
<td><code>long_</code></td>
|
||||
|
||||
<td>__long__</td>
|
||||
<td><code>__long__</code></td>
|
||||
|
||||
<td>PyLong_FromLong(x)</td>
|
||||
<td><code>PyLong_FromLong(x)</code></td>
|
||||
</tr>
|
||||
|
||||
<tr>
|
||||
<td>float_</td>
|
||||
<td><code>float_</code></td>
|
||||
|
||||
<td>__float__</td>
|
||||
<td><code>__float__</code></td>
|
||||
|
||||
<td>double(x)</td>
|
||||
<td><code>double(x)</code></td>
|
||||
</tr>
|
||||
|
||||
<tr>
|
||||
<td>complex_</td>
|
||||
<td><code>complex_</code></td>
|
||||
|
||||
<td>__complex__</td>
|
||||
<td><code>__complex__</code></td>
|
||||
|
||||
<td>std::complex<double>(x)</td>
|
||||
<td><code>std::complex<double>(x)</code></td>
|
||||
</tr>
|
||||
|
||||
<tr>
|
||||
<td>str</td>
|
||||
<td><code>str</code></td>
|
||||
|
||||
<td>__str__</td>
|
||||
<td><code>__str__</code></td>
|
||||
|
||||
<td><a href=
|
||||
"../../../conversion/lexical_cast.htm#lexical_cast">lexical_cast</a><std::string>(x)</td>
|
||||
<td><code><a href=
|
||||
"../../../conversion/lexical_cast.htm#lexical_cast">lexical_cast</a><std::string>(x)</code></td>
|
||||
</tr>
|
||||
</table>
|
||||
|
||||
@@ -876,7 +886,7 @@ BOOST_PYTHON_MODULE(demo)
|
||||
|
||||
<p>Revised
|
||||
<!--webbot bot="Timestamp" S-Type="EDITED" S-Format="%d %B, %Y" startspan -->
|
||||
13 November, 2002
|
||||
3 October, 2003
|
||||
<!--webbot bot="Timestamp" endspan i-checksum="39359" -->
|
||||
</p>
|
||||
|
||||
|
||||
@@ -194,9 +194,10 @@ BOOST_PYTHON_MEMBER_FUNCTION_OVERLOADS(X_f_overloads, X::f, 1, 3)
|
||||
|
||||
BOOST_PYTHON_MODULE(args_ext)
|
||||
{
|
||||
def("f", f, args("x", "y", "z")
|
||||
, "This is f's docstring"
|
||||
);
|
||||
def("f", f,
|
||||
f_overloads(
|
||||
args("x", "y", "z"), "This is f's docstring"
|
||||
));
|
||||
|
||||
|
||||
class_<Y>("Y")
|
||||
@@ -204,16 +205,17 @@ BOOST_PYTHON_MODULE(args_ext)
|
||||
|
||||
class_<X>("X", "This is X's docstring")
|
||||
.def("f1", &X::f,
|
||||
X_f_overloads(args("x", "y", "z"),
|
||||
"f's docstring"
|
||||
)[return_internal_reference<>()])
|
||||
X_f_overloads(
|
||||
args("x", "y", "z"), "f's docstring"
|
||||
)[return_internal_reference<>()]
|
||||
)
|
||||
;
|
||||
}
|
||||
</pre>
|
||||
|
||||
<p>Revised
|
||||
<!--webbot bot="Timestamp" S-Type="EDITED" S-Format="%d %B, %Y" startspan -->
|
||||
15 December, 2002
|
||||
15 April, 2003
|
||||
<!--webbot bot="Timestamp" endspan i-checksum="39359" -->
|
||||
</p>
|
||||
|
||||
|
||||
@@ -27,8 +27,15 @@
|
||||
</tr>
|
||||
</table>
|
||||
<hr>
|
||||
<b>Boost.Python</b> has been successfully tested on the following
|
||||
platforms and compilers:
|
||||
Please see
|
||||
our <a
|
||||
href="http://boost.sourceforge.net/regression-logs">regression
|
||||
logs</a> for up-to-date information. Note that logs not marked
|
||||
otherwise reflect the CVS state, not the condition of the release.
|
||||
|
||||
<p>
|
||||
Earlier versions of <b>Boost.Python</b> have been successfully
|
||||
tested on the following platforms and compilers.
|
||||
|
||||
<dl class="page-index">
|
||||
<dt>Unix Platforms:</dt>
|
||||
|
||||
@@ -13,7 +13,7 @@
|
||||
p.c3 {font-style: italic}
|
||||
h2.c2 {text-align: center}
|
||||
h1.c1 {text-align: center}
|
||||
</style>
|
||||
</style>
|
||||
</head>
|
||||
|
||||
<body>
|
||||
@@ -96,193 +96,158 @@
|
||||
|
||||
<h2><a name="high_level">High Level Components</a></h2>
|
||||
|
||||
<dl>
|
||||
<dt><a href="class.html">class.hpp/class_fwd.hpp</a></dt>
|
||||
|
||||
<dd>
|
||||
|
||||
<dl>
|
||||
<dt><a href="class.html">class.hpp/class_fwd.hpp</a></dt>
|
||||
<dd>
|
||||
<dl class="index">
|
||||
<dt><a href="class.html#classes">Classes</a></dt>
|
||||
<dd>
|
||||
<dl class="index">
|
||||
<dt><a href="class.html#classes">Classes</a></dt>
|
||||
|
||||
<dd>
|
||||
<dl class="index">
|
||||
<dt><a href="class.html#class_-spec">class_</a></dt>
|
||||
|
||||
<dt><a href="class.html#bases-spec">bases</a></dt>
|
||||
</dl>
|
||||
</dd>
|
||||
</dl>
|
||||
</dd>
|
||||
|
||||
<dt><a href="def.html">def.hpp</a></dt>
|
||||
|
||||
<dd>
|
||||
<dl class="index">
|
||||
<dt><a href="def.html#functions">Functions</a></dt>
|
||||
|
||||
<dd>
|
||||
<dl class="page-index">
|
||||
<dt><a href="def.html#def-spec">def</a></dt>
|
||||
</dl>
|
||||
</dd>
|
||||
</dl>
|
||||
</dd>
|
||||
|
||||
<dt><a href="enum.html">enum.hpp</a></dt>
|
||||
|
||||
<dd>
|
||||
<dl class="index">
|
||||
<dt><a href="enum.html#classes">Classes</a></dt>
|
||||
|
||||
<dd>
|
||||
<dl class="index">
|
||||
<dt><a href="enum.html#enum_-spec">enum_</a></dt>
|
||||
</dl>
|
||||
</dd>
|
||||
</dl>
|
||||
</dd>
|
||||
|
||||
<dt><a href="errors.html">errors.hpp</a></dt>
|
||||
|
||||
<dd>
|
||||
<dl class="index">
|
||||
<dt><a href="errors.html#classes">Classes</a></dt>
|
||||
|
||||
<dd>
|
||||
<dl class="index">
|
||||
<dt><a href=
|
||||
"errors.html#error_already_set-spec">error_already_set</a></dt>
|
||||
</dl>
|
||||
</dd>
|
||||
|
||||
<dt><a href="errors.html#functions">Functions</a></dt>
|
||||
|
||||
<dd>
|
||||
<dl class="index">
|
||||
<dt><a href=
|
||||
"errors.html#handle_exception-spec">handle_exception</a></dt>
|
||||
|
||||
<dt><a href=
|
||||
"errors.html#expect_non_null-spec">expect_non_null</a></dt>
|
||||
|
||||
<dt><a href=
|
||||
"errors.html#throw_error_already_set-spec">throw_error_already_set</a></dt>
|
||||
</dl>
|
||||
</dd>
|
||||
</dl>
|
||||
</dd>
|
||||
|
||||
<dt><a href=
|
||||
"exception_translator.html">exception_translator.hpp</a></dt>
|
||||
|
||||
<dd>
|
||||
<dl class="index">
|
||||
<dt><a href=
|
||||
"exception_translator.html#functions">Functions</a></dt>
|
||||
|
||||
<dd>
|
||||
<dl class="index">
|
||||
<dt><a href=
|
||||
"exception_translator.html#register_exception_translator-spec">register_exception_translator</a></dt>
|
||||
</dl>
|
||||
</dd>
|
||||
</dl>
|
||||
</dd>
|
||||
|
||||
<dt><a href="init.html">init.hpp</a></dt>
|
||||
|
||||
<dd>
|
||||
<dl class="index">
|
||||
<dt><a href="init.html#classes">Classes</a></dt>
|
||||
|
||||
<dd>
|
||||
<dl class="index">
|
||||
<dt><a href="init.html#init-spec">init</a></dt>
|
||||
|
||||
<dt><a href="init.html#optional-spec">optional</a></dt>
|
||||
</dl>
|
||||
</dd>
|
||||
</dl>
|
||||
</dd>
|
||||
|
||||
<dt><a href="iterator.html">iterator.hpp</a></dt>
|
||||
|
||||
<dd>
|
||||
<dl class="index">
|
||||
<dt><a href="iterator.html#classes">Classes</a></dt>
|
||||
|
||||
<dd>
|
||||
<dl class="index">
|
||||
<dt><a href="iterator.html#iterator-spec">iterator</a></dt>
|
||||
|
||||
<dt><a href="iterator.html#iterators-spec">iterators</a></dt>
|
||||
</dl>
|
||||
</dd>
|
||||
|
||||
<dt><a href="iterator.html#functions">Functions</a></dt>
|
||||
|
||||
<dd>
|
||||
<dl class="index">
|
||||
<dt><a href="iterator.html#range-spec">range</a></dt>
|
||||
</dl>
|
||||
</dd>
|
||||
</dl>
|
||||
</dd>
|
||||
|
||||
<dt><a href="module.html">module.hpp</a></dt>
|
||||
|
||||
<dd>
|
||||
<dl class="index">
|
||||
<dt><a href="module.html#macros">Macros</a></dt>
|
||||
|
||||
<dd>
|
||||
<dl class="index">
|
||||
<dt><a href=
|
||||
"module.html#BOOST_PYTHON_MODULE-spec">BOOST_PYTHON_MODULE</a></dt>
|
||||
</dl>
|
||||
</dd>
|
||||
</dl>
|
||||
</dd>
|
||||
|
||||
<dt><a href="operators.html">operators.hpp</a></dt>
|
||||
|
||||
<dd>
|
||||
<dl class="index">
|
||||
<dt><a href="operators.html#classes">Classes</a></dt>
|
||||
|
||||
<dd>
|
||||
<dl class="index">
|
||||
<dt><a href="operators.html#self_t-spec">self_t</a></dt>
|
||||
|
||||
<dt><a href="operators.html#other-spec">other</a></dt>
|
||||
|
||||
<dt><a href="operators.html#operator_-spec">operator_</a></dt>
|
||||
</dl>
|
||||
</dd>
|
||||
|
||||
<dt><a href="operators.html#objects">Objects</a></dt>
|
||||
|
||||
<dd>
|
||||
<dl class="index">
|
||||
<dt><a href="operators.html#self-spec">self</a></dt>
|
||||
</dl>
|
||||
</dd>
|
||||
</dl>
|
||||
</dd>
|
||||
|
||||
<dt><a href="scope.html">scope.hpp</a></dt>
|
||||
|
||||
<dd>
|
||||
<dl class="index">
|
||||
<dt><a href="scope.html#classes">Classes</a></dt>
|
||||
|
||||
<dd>
|
||||
<dl class="index">
|
||||
<dt><a href="scope.html#scope-spec">scope</a></dt>
|
||||
</dl>
|
||||
</dd>
|
||||
<dt><a href="class.html#class_-spec">class_</a></dt>
|
||||
<dt><a href="class.html#bases-spec">bases</a></dt>
|
||||
</dl>
|
||||
</dd>
|
||||
</dl>
|
||||
</dd>
|
||||
<dt><a href="def.html">def.hpp</a></dt>
|
||||
<dd>
|
||||
<dl class="index">
|
||||
<dt><a href="def.html#functions">Functions</a></dt>
|
||||
<dd>
|
||||
<dl class="page-index">
|
||||
<dt><a href="def.html#def-spec">def</a></dt>
|
||||
</dl>
|
||||
</dd>
|
||||
</dl>
|
||||
</dd>
|
||||
<dt><a href="def_visitor.html">def_visitor.hpp</a></dt>
|
||||
<dd>
|
||||
<dl class="index">
|
||||
<dt><a href="def_visitor.html#classes">Classes</a></dt>
|
||||
</dl>
|
||||
</dd>
|
||||
<dt><a href="enum.html">enum.hpp</a></dt>
|
||||
<dd>
|
||||
<dl class="index">
|
||||
<dt><a href="enum.html#classes">Classes</a></dt>
|
||||
<dd>
|
||||
<dl class="index">
|
||||
<dt><a href="enum.html#enum_-spec">enum_</a></dt>
|
||||
</dl>
|
||||
</dd>
|
||||
</dl>
|
||||
</dd>
|
||||
<dt><a href="errors.html">errors.hpp</a></dt>
|
||||
<dd>
|
||||
<dl class="index">
|
||||
<dt><a href="errors.html#classes">Classes</a></dt>
|
||||
<dd>
|
||||
<dl class="index">
|
||||
<dt><a href=
|
||||
"errors.html#error_already_set-spec">error_already_set</a></dt>
|
||||
</dl>
|
||||
</dd>
|
||||
<dt><a href="errors.html#functions">Functions</a></dt>
|
||||
<dd>
|
||||
<dl class="index">
|
||||
<dt><a href=
|
||||
"errors.html#handle_exception-spec">handle_exception</a></dt>
|
||||
<dt><a href=
|
||||
"errors.html#expect_non_null-spec">expect_non_null</a></dt>
|
||||
<dt><a href=
|
||||
"errors.html#throw_error_already_set-spec">throw_error_already_set</a></dt>
|
||||
</dl>
|
||||
</dd>
|
||||
</dl>
|
||||
</dd>
|
||||
<dt><a href=
|
||||
"exception_translator.html">exception_translator.hpp</a></dt>
|
||||
<dd>
|
||||
<dl class="index">
|
||||
<dt><a href=
|
||||
"exception_translator.html#functions">Functions</a></dt>
|
||||
<dd>
|
||||
<dl class="index">
|
||||
<dt><a href=
|
||||
"exception_translator.html#register_exception_translator-spec">register_exception_translator</a></dt>
|
||||
</dl>
|
||||
</dd>
|
||||
</dl>
|
||||
</dd>
|
||||
<dt><a href="init.html">init.hpp</a></dt>
|
||||
<dd>
|
||||
<dl class="index">
|
||||
<dt><a href="init.html#classes">Classes</a></dt>
|
||||
<dd>
|
||||
<dl class="index">
|
||||
<dt><a href="init.html#init-spec">init</a></dt>
|
||||
<dt><a href="init.html#optional-spec">optional</a></dt>
|
||||
</dl>
|
||||
</dd>
|
||||
</dl>
|
||||
</dd>
|
||||
<dt><a href="iterator.html">iterator.hpp</a></dt>
|
||||
<dd>
|
||||
<dl class="index">
|
||||
<dt><a href="iterator.html#classes">Classes</a></dt>
|
||||
<dd>
|
||||
<dl class="index">
|
||||
<dt><a href="iterator.html#iterator-spec">iterator</a></dt>
|
||||
<dt><a href="iterator.html#iterators-spec">iterators</a></dt>
|
||||
</dl>
|
||||
</dd>
|
||||
<dt><a href="iterator.html#functions">Functions</a></dt>
|
||||
<dd>
|
||||
<dl class="index">
|
||||
<dt><a href="iterator.html#range-spec">range</a></dt>
|
||||
</dl>
|
||||
</dd>
|
||||
</dl>
|
||||
</dd>
|
||||
<dt><a href="module.html">module.hpp</a></dt>
|
||||
<dd>
|
||||
<dl class="index">
|
||||
<dt><a href="module.html#macros">Macros</a></dt>
|
||||
<dd>
|
||||
<dl class="index">
|
||||
<dt><a href=
|
||||
"module.html#BOOST_PYTHON_MODULE-spec">BOOST_PYTHON_MODULE</a></dt>
|
||||
</dl>
|
||||
</dd>
|
||||
</dl>
|
||||
</dd>
|
||||
<dt><a href="operators.html">operators.hpp</a></dt>
|
||||
<dd>
|
||||
<dl class="index">
|
||||
<dt><a href="operators.html#classes">Classes</a></dt>
|
||||
<dd>
|
||||
<dl class="index">
|
||||
<dt><a href="operators.html#self_t-spec">self_t</a></dt>
|
||||
<dt><a href="operators.html#other-spec">other</a></dt>
|
||||
<dt><a href="operators.html#operator_-spec">operator_</a></dt>
|
||||
</dl>
|
||||
</dd>
|
||||
<dt><a href="operators.html#objects">Objects</a></dt>
|
||||
<dd>
|
||||
<dl class="index">
|
||||
<dt><a href="operators.html#self-spec">self</a></dt>
|
||||
</dl>
|
||||
</dd>
|
||||
</dl>
|
||||
</dd>
|
||||
<dt><a href="scope.html">scope.hpp</a></dt>
|
||||
<dd>
|
||||
<dl class="index">
|
||||
<dt><a href="scope.html#classes">Classes</a></dt>
|
||||
<dd>
|
||||
<dl class="index">
|
||||
<dt><a href="scope.html#scope-spec">scope</a></dt>
|
||||
</dl>
|
||||
</dd>
|
||||
</dl>
|
||||
</dd>
|
||||
</dl>
|
||||
|
||||
<h2><a name="object_wrappers">Object Wrappers</a></h2>
|
||||
|
||||
@@ -371,7 +336,7 @@
|
||||
</dl>
|
||||
</dd>
|
||||
|
||||
<dt><a href="str.html">tuple.hpp</a></dt>
|
||||
<dt><a href="tuple.html">tuple.hpp</a></dt>
|
||||
|
||||
<dd>
|
||||
<dl class="index">
|
||||
@@ -570,6 +535,24 @@
|
||||
</dl>
|
||||
</dd>
|
||||
|
||||
<dt><a href="return_arg.html">return_arg.hpp</a></dt>
|
||||
|
||||
<dd>
|
||||
<dl class="index">
|
||||
<dt><a href="return_arg.html#classes">Classes</a></dt>
|
||||
|
||||
<dd>
|
||||
<dl class="index">
|
||||
<dt><a href=
|
||||
"return_arg.html#return_arg-spec">return_arg</a></dt>
|
||||
|
||||
<dt><a href=
|
||||
"return_arg.html#return_self-spec">return_self</a></dt>
|
||||
</dl>
|
||||
</dd>
|
||||
</dl>
|
||||
</dd>
|
||||
|
||||
<dt><a href=
|
||||
"return_internal_reference.html">return_internal_reference.hpp</a></dt>
|
||||
|
||||
@@ -749,6 +732,23 @@
|
||||
</dd>
|
||||
</dl>
|
||||
</dd>
|
||||
|
||||
<dt><a href=
|
||||
"return_opaque_pointer.html">return_opaque_pointer.hpp</a></dt>
|
||||
|
||||
<dd>
|
||||
<dl class="index">
|
||||
<dt><a href=
|
||||
"return_opaque_pointer.html#classes">Classes</a></dt>
|
||||
|
||||
<dd>
|
||||
<dl class="index">
|
||||
<dt><a href=
|
||||
"return_opaque_pointer.html#return_opaque_pointer-spec">return_opaque_pointer</a></dt>
|
||||
</dl>
|
||||
</dd>
|
||||
</dl>
|
||||
</dd>
|
||||
</dl>
|
||||
</dd>
|
||||
</dl>
|
||||
@@ -806,6 +806,33 @@
|
||||
</dl>
|
||||
</dd>
|
||||
|
||||
<dt><a href=
|
||||
"opaque_pointer_converter.html">opaque_pointer_converter.hpp</a></dt>
|
||||
|
||||
<dd>
|
||||
<dl class="index">
|
||||
<dt><a href=
|
||||
"opaque_pointer_converter.html#classes">Classes</a></dt>
|
||||
|
||||
<dd>
|
||||
<dl class="index">
|
||||
<dt><a href=
|
||||
"opaque_pointer_converter.html#opaque_pointer_converter-spec">opaque_pointer_converter</a></dt>
|
||||
</dl>
|
||||
</dd>
|
||||
|
||||
<dt><a href="opaque_pointer_converter.html#macros">Macros</a></dt>
|
||||
|
||||
<dd>
|
||||
<dl class="index">
|
||||
<dt><a href=
|
||||
"opaque_pointer_converter.html#BOOST_PYTHON_OPAQUE_SPECIALIZED_TYPE_ID-spec">
|
||||
BOOST_PYTHON_OPAQUE_SPECIALIZED_TYPE_ID</a></dt>
|
||||
</dl>
|
||||
</dd>
|
||||
</dl>
|
||||
</dd>
|
||||
|
||||
<dt><a href="to_python_converter.html">to_python_converter.hpp</a></dt>
|
||||
|
||||
<dd>
|
||||
@@ -820,6 +847,23 @@
|
||||
</dd>
|
||||
</dl>
|
||||
</dd>
|
||||
|
||||
<dt><a href=
|
||||
"register_ptr_to_python.html">register_ptr_to_python.hpp</a></dt>
|
||||
|
||||
<dd>
|
||||
<dl class="index">
|
||||
<dt><a href=
|
||||
"register_ptr_to_python.html#functions">Functions</a></dt>
|
||||
|
||||
<dd>
|
||||
<dl class="index">
|
||||
<dt><a href=
|
||||
"register_ptr_to_python.html#register_ptr_to_python-spec">register_ptr_to_python</a></dt>
|
||||
</dl>
|
||||
</dd>
|
||||
</dl>
|
||||
</dd>
|
||||
</dl>
|
||||
|
||||
<h2><a name="utility">Utility and Infrastructure</a></h2>
|
||||
@@ -921,18 +965,17 @@
|
||||
|
||||
<h2><a name="topics">Topics</a></h2>
|
||||
|
||||
<dl>
|
||||
<dt><a href="callbacks.html">Calling Python Functions and
|
||||
Methods</a></dt>
|
||||
|
||||
<dt><a href="pickle.html">Pickle Support</a></dt>
|
||||
</dl>
|
||||
|
||||
<dl>
|
||||
<dt><a href="callbacks.html">Calling Python Functions and Methods</a></dt>
|
||||
<dt><a href="pickle.html">Pickle Support</a><br>
|
||||
<a href="indexing.html">Indexing Support</a></dt>
|
||||
</dl>
|
||||
<hr>
|
||||
|
||||
<p>Revised
|
||||
<!--webbot bot="Timestamp" S-Type="EDITED" S-Format="%d %B, %Y" startspan -->
|
||||
7 March, 2003
|
||||
<!--webbot bot="Timestamp" endspan i-checksum="39359" -->
|
||||
19 July, 2003 <!--webbot bot="Timestamp" endspan i-checksum="39359" -->
|
||||
</p>
|
||||
|
||||
<p class="c3">© Copyright <a href=
|
||||
|
||||
159
doc/v2/register_ptr_to_python.html
Normal file
159
doc/v2/register_ptr_to_python.html
Normal file
@@ -0,0 +1,159 @@
|
||||
<html>
|
||||
<head>
|
||||
<meta http-equiv="Content-Type" content="text/html; charset=iso-8859-1">
|
||||
<link rel="stylesheet" type="text/css" href="../boost.css">
|
||||
<title>Boost.Python - <register_ptr_to_python.hpp></title>
|
||||
</head>
|
||||
<body link="#0000ff" vlink="#800080">
|
||||
<table border="0" cellpadding="7" cellspacing="0" width="100%" summary=
|
||||
"header">
|
||||
<tr>
|
||||
<td valign="top" width="300">
|
||||
<h3><a href="../../../../index.htm"><img height="86" width="277" alt=
|
||||
"C++ Boost" src="../../../../c++boost.gif" border="0"></a></h3>
|
||||
</td>
|
||||
<td valign="top">
|
||||
<h1 align="center"><a href="../index.html">Boost.Python</a></h1>
|
||||
<h2 align="center">Header <register_ptr_to_python.hpp></h2>
|
||||
</td>
|
||||
</tr>
|
||||
</table>
|
||||
<hr>
|
||||
<h2>Contents</h2>
|
||||
<dl class="page-index">
|
||||
<dt><a href="#introduction">Introduction</a></dt>
|
||||
<dt><a href="#functions">Functions</a></dt>
|
||||
<dl class="page-index">
|
||||
<dt><a href="#register_ptr_to_python-spec">register_ptr_to_python</a></dt>
|
||||
</dl>
|
||||
|
||||
<dt><a href="#examples">Example(s)</a></dt>
|
||||
|
||||
</dl>
|
||||
<hr>
|
||||
<h2><a name="introduction"></a>Introduction</h2>
|
||||
<p>
|
||||
<code><boost/python/register_ptr_to_python.hpp></code>
|
||||
supplies <code>register_ptr_to_python</code>, a function template
|
||||
which registers a conversion for smart pointers to Python. The
|
||||
resulting Python object holds a copy of the converted smart pointer,
|
||||
but behaves as though it were a wrapped copy of the pointee. If
|
||||
the pointee type has virtual functions and the class representing
|
||||
its dynamic (most-derived) type has been wrapped, the Python object
|
||||
will be an instance of the wrapper for the most-derived type. More than
|
||||
one smart pointer type for a pointee's class can be registered.
|
||||
</p>
|
||||
<p>
|
||||
Note that in order to convert a Python <code>X</code> object to a
|
||||
<code>smart_ptr<X>&</code> (non-const reference), the embedded C++
|
||||
object must be held by <code>smart_ptr<X></code>, and that when wrapped
|
||||
objects are created by calling the constructor from Python, how they are held
|
||||
is determined by the <code>HeldType</code> parameter to
|
||||
<code>class_<...></code> instances.
|
||||
</p>
|
||||
|
||||
<h2><a name="functions"></a>Functions</h2>
|
||||
<pre>
|
||||
<a name="register_ptr_to_python-spec">template <class P>
|
||||
void register_ptr_to_python()
|
||||
</pre>
|
||||
<dl class="function-semantics">
|
||||
<dt><b>Requires:</b> <code>P</code> is <a href="Dereferenceable.html#Dereferenceable-concept">Dereferenceable</a>.
|
||||
</dt>
|
||||
<dt><b>Effects:</b> Allows conversions to-python of <code>P</code>
|
||||
instances.
|
||||
</dt>
|
||||
</dl>
|
||||
|
||||
<h2><a name="examples"></a>Example(s)</h2>
|
||||
|
||||
<h3>C++ Wrapper Code</h3>
|
||||
|
||||
Here is an example of a module that contains a class <code>A</code> with
|
||||
virtual functions and some functions that work with
|
||||
<code>boost::shared_ptr<A></code>.
|
||||
|
||||
<pre>
|
||||
struct A
|
||||
{
|
||||
virtual int f() { return 0; }
|
||||
};
|
||||
|
||||
shared_ptr<A> New() { return shared_ptr<A>( new A() ); }
|
||||
|
||||
int Ok( const shared_ptr<A>& a ) { return a->f(); }
|
||||
|
||||
int Fail( shared_ptr<A>& a ) { return a->f(); }
|
||||
|
||||
struct A_Wrapper: A
|
||||
{
|
||||
A_Wrapper(PyObject* self_): self(self_) {}
|
||||
int f() { return call_method<int>(self, "f"); }
|
||||
int default_f() { return A::f(); }
|
||||
PyObject* self;
|
||||
};
|
||||
|
||||
BOOST_PYTHON_MODULE(register_ptr)
|
||||
{
|
||||
class_<A, A_Wrapper>("A")
|
||||
.def("f", &A::f, &A_Wrapper::default_f)
|
||||
;
|
||||
|
||||
def("New", &New);
|
||||
def("Ok", &Call);
|
||||
def("Fail", &Fail);
|
||||
|
||||
register_ptr_to_python< shared_ptr<A> >();
|
||||
}
|
||||
</pre>
|
||||
|
||||
<h3>Python Code</h3>
|
||||
|
||||
<pre>
|
||||
>>> from register_ptr import *
|
||||
>>> a = A()
|
||||
>>> Ok(a) # ok, passed as shared_ptr<A>
|
||||
0
|
||||
>>> Fail(a) # passed as shared_ptr<A>&, and was created in Python!
|
||||
Traceback (most recent call last):
|
||||
File "<stdin>", line 1, in ?
|
||||
TypeError: bad argument type for built-in operation
|
||||
>>>
|
||||
>>> na = New() # now "na" is actually a shared_ptr<A>
|
||||
>>> Ok(a)
|
||||
0
|
||||
>>> Fail(a)
|
||||
0
|
||||
>>>
|
||||
</pre>
|
||||
|
||||
If <code>shared_ptr<A></code> is registered as follows:
|
||||
|
||||
<pre>
|
||||
class_<A, A_Wrapper, shared_ptr<A> >("A")
|
||||
.def("f", &A::f, &A_Wrapper::default_f)
|
||||
;
|
||||
</pre>
|
||||
|
||||
There will be an error when trying to convert <code>shared_ptr<A></code> to
|
||||
<code>shared_ptr<A_Wrapper></code>:
|
||||
|
||||
<pre>
|
||||
>>> a = New()
|
||||
Traceback (most recent call last):
|
||||
File "<stdin>", line 1, in ?
|
||||
TypeError: No to_python (by-value) converter found for C++ type: class boost::shared_ptr<struct A>
|
||||
>>>
|
||||
</pre>
|
||||
|
||||
<p>Revised
|
||||
<!--webbot bot="Timestamp" S-Type="EDITED" S-Format="%d %B, %Y" startspan -->
|
||||
24 Jun, 2003
|
||||
<!--webbot bot="Timestamp" endspan i-checksum="39359" -->
|
||||
</p>
|
||||
<p><i>© Copyright <a href="../../../../people/dave_abrahams.htm">Dave Abrahams</a>
|
||||
2002. All Rights Reserved.</i></p>
|
||||
</body>
|
||||
</html>
|
||||
|
||||
|
||||
219
doc/v2/return_arg.html
Executable file
219
doc/v2/return_arg.html
Executable file
@@ -0,0 +1,219 @@
|
||||
<!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN">
|
||||
|
||||
<html>
|
||||
<head>
|
||||
<meta name="generator" content=
|
||||
"HTML Tidy for Cygwin (vers 1st April 2002), see www.w3.org">
|
||||
<meta http-equiv="Content-Type" content="text/html; charset=iso-8859-1">
|
||||
<link rel="stylesheet" type="text/css" href="../boost.css">
|
||||
|
||||
<title>Boost.Python - <boost/python/return_arg.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="../../../../c++boost.gif" border="0"></a></h3>
|
||||
</td>
|
||||
|
||||
<td valign="top">
|
||||
<h1 align="center"><a href="../index.html">Boost.Python</a></h1>
|
||||
|
||||
<h2 align="center">Header <boost/python/return_arg.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="#return_arg-spec">Class Template
|
||||
<code>return_arg</code></a></dt>
|
||||
|
||||
<dd>
|
||||
<dl class="page-index">
|
||||
<dt><a href="#return_arg-spec-synopsis">Class Template
|
||||
<code>return_arg</code> synopsis</a></dt>
|
||||
|
||||
<dt><a href="#return_arg-spec-statics">Class
|
||||
<code>return_arg</code> static functions</a></dt>
|
||||
</dl>
|
||||
</dd>
|
||||
|
||||
<dt><a href="#return_self-spec">Class Template
|
||||
<code>return_self</code></a></dt>
|
||||
</dl>
|
||||
</dd>
|
||||
|
||||
<dt><a href="#examples">Example</a></dt>
|
||||
</dl>
|
||||
<hr>
|
||||
|
||||
<h2><a name="introduction"></a>Introduction</h2>
|
||||
<code>return_arg</code> and <code>return_self</code> instantiations are
|
||||
models of <a href="CallPolicies.html">CallPolicies</a> which return the
|
||||
specified argument parameter (usually <code>*this</code>) of a wrapped
|
||||
(member) function.
|
||||
|
||||
<h2><a name="classes"></a>Classes</h2>
|
||||
|
||||
<h3><a name="return_arg-spec"></a>Class template
|
||||
<code>return_arg</code></h3>
|
||||
|
||||
<table border="1" summary="return_arg template parameters">
|
||||
<caption>
|
||||
<b><code>return_arg</code> template parameters</b>
|
||||
</caption>
|
||||
|
||||
<tr>
|
||||
<th>Parameter</th>
|
||||
|
||||
<th>Requirements</th>
|
||||
|
||||
<th>Description</th>
|
||||
|
||||
<th>Default</th>
|
||||
</tr>
|
||||
|
||||
<tr>
|
||||
<td><code>arg_pos</code></td>
|
||||
|
||||
<td>A positive compile-time constant of type
|
||||
<code>std::size_t</code>.</td>
|
||||
|
||||
<td>the position of the argument to be returned.</td>
|
||||
|
||||
<td>1</td>
|
||||
</tr>
|
||||
|
||||
<tr>
|
||||
<td><code>Base</code></td>
|
||||
|
||||
<td>A model of <a href="CallPolicies.html">CallPolicies</a></td>
|
||||
|
||||
<td>Used for policy composition. Any <code>result_converter</code> it
|
||||
supplies will be overridden by <code>return_arg</code>, but its
|
||||
<code>precall</code> and <code>postcall</code> policies are composed
|
||||
as described here <a href=
|
||||
"CallPolicies.html#composition">CallPolicies</a>.</td>
|
||||
|
||||
<td><code><a href=
|
||||
"default_call_policies.html#default_call_policies-spec">default_call_policies</a></code></td>
|
||||
</tr>
|
||||
</table>
|
||||
|
||||
<h4><a name="return_arg-spec-synopsis"></a>Class template
|
||||
<code>return_arg</code> synopsis</h4>
|
||||
<pre>
|
||||
namespace boost { namespace python
|
||||
{
|
||||
template <size_t arg_pos=1, class Base = default_call_policies>
|
||||
struct return_arg : Base
|
||||
{
|
||||
static PyObject* postcall(PyObject*, PyObject* result);
|
||||
struct result_converter{ template <class T> struct apply; };
|
||||
};
|
||||
}}
|
||||
</pre>
|
||||
|
||||
<h4><a name="return_arg-spec-statics"></a>Class <code>return_arg</code>
|
||||
static functions</h4>
|
||||
<pre>
|
||||
PyObject* postcall(PyObject* args, PyObject* result);
|
||||
</pre>
|
||||
|
||||
<dl class="function-semantics">
|
||||
<dt><b>Requires:</b> <code><a href=
|
||||
"http://www.python.org/doc/2.2/api/tupleObjects.html#l2h-476">PyTuple_Check</a>(args)
|
||||
!= 0</code> and <code>PyTuple_Size(args) != 0</code></dt>
|
||||
|
||||
<dt><b>Returns:</b> <code>PyTuple_GetItem(args,arg_pos-1)</code></dt>
|
||||
</dl>
|
||||
|
||||
<h3><a name="return_self-spec"></a>Class template
|
||||
<code>return_self</code></h3>
|
||||
|
||||
<h4>Class template <code>return_self</code> synopsis:</h4>
|
||||
<pre>
|
||||
namespace boost { namespace python
|
||||
{
|
||||
template <class Base = default_call_policies>
|
||||
struct return_self
|
||||
: return_arg<1,Base>
|
||||
{};
|
||||
}}
|
||||
</pre>
|
||||
|
||||
<h2><a name="examples"></a>Example</h2>
|
||||
|
||||
<h3>C++ module definition</h3>
|
||||
<pre>
|
||||
#include <boost/python/module.hpp>
|
||||
#include <boost/python/class.hpp>
|
||||
#include <boost/python/return_arg.hpp>
|
||||
|
||||
struct Widget
|
||||
{
|
||||
Widget() :sensitive_(true){}
|
||||
bool get_sensitive() const { return sensitive_; }
|
||||
void set_sensitive(bool s) { this->sensitive_ = s; }
|
||||
private:
|
||||
bool sensitive_;
|
||||
};
|
||||
|
||||
struct Label : Widget
|
||||
{
|
||||
Label() {}
|
||||
|
||||
std::string get_label() const { return label_; }
|
||||
void set_label(const std::string &l){ label_ = l; }
|
||||
|
||||
private:
|
||||
std::string label_;
|
||||
};
|
||||
|
||||
using namespace boost::python;
|
||||
BOOST_PYTHON_MODULE(return_self_ext)
|
||||
{
|
||||
class_<widget>("Widget")
|
||||
.def("sensitive", &Widget::get_sensitive)
|
||||
.def("sensitive", &Widget::set_sensitive, return_self<>())
|
||||
;
|
||||
|
||||
class_<Label, bases<Widget> >("Label")
|
||||
.def("label", &Label::get_label)
|
||||
.def("label", &Label::set_label, return_self<>())
|
||||
;
|
||||
}
|
||||
|
||||
|
||||
</pre>
|
||||
|
||||
<h3>Python code</h3>
|
||||
<pre>
|
||||
>>> from return_self_ext import *
|
||||
>>> l1 = Label().label("foo").sensitive(false)
|
||||
>>> l2 = Label().sensitive(false).label("foo")
|
||||
</pre>
|
||||
|
||||
<p>Revised
|
||||
<!--webbot bot="Timestamp" S-Type="EDITED" S-Format="%d %B, %Y" startspan -->
|
||||
19 July, 2003 <!--webbot bot="Timestamp" endspan i-checksum="39359" -->
|
||||
</p>
|
||||
|
||||
<p><i>© Copyright <a href=
|
||||
"../../../../people/dave_abrahams.htm">Dave Abrahams</a> and Nikolay
|
||||
Mladenov 2003. All Rights Reserved.</i></p>
|
||||
</body>
|
||||
</html>
|
||||
|
||||
189
doc/v2/return_opaque_pointer.html
Normal file
189
doc/v2/return_opaque_pointer.html
Normal file
@@ -0,0 +1,189 @@
|
||||
<!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN">
|
||||
|
||||
<html>
|
||||
<head>
|
||||
<meta http-equiv="Content-Type" content="text/html; charset=iso-8859-1">
|
||||
<link rel="stylesheet" type="text/css" href="../boost.css">
|
||||
|
||||
<title>Boost.Python - <boost/python/return_opaque_pointer.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="../../../../c++boost.gif" border="0"></a></h3>
|
||||
</td>
|
||||
|
||||
<td valign="top">
|
||||
<h1 align="center"><a href="../index.html">Boost.Python</a></h1>
|
||||
|
||||
<h2 align="center">Header
|
||||
<boost/python/return_opaque_pointer.hpp></h2>
|
||||
</td>
|
||||
</tr>
|
||||
</table>
|
||||
<hr>
|
||||
|
||||
<h2>Contents</h2>
|
||||
|
||||
<dl class="page-index">
|
||||
<dt><a href="#classes">Classes</a></dt>
|
||||
|
||||
<dd>
|
||||
<dl class="page-index">
|
||||
<dt><a href="#return_opaque_pointer-spec">Class
|
||||
<code>return_opaque_pointer</code></a></dt>
|
||||
|
||||
<dd>
|
||||
<dl class="page-index">
|
||||
<dt><a href="#return_opaque_pointer-spec-synopsis">Class
|
||||
<code>return_opaque_pointer</code> synopsis</a></dt>
|
||||
|
||||
<dt><a href="#return_opaque_pointer-spec-metafunctions">Class
|
||||
<code>return_opaque_pointer</code> metafunctions</a></dt>
|
||||
</dl>
|
||||
</dd>
|
||||
</dl>
|
||||
</dd>
|
||||
|
||||
<dt><a href="#examples">Example</a></dt>
|
||||
|
||||
<dt><a href="#see-also">See Also</a></dt>
|
||||
</dl>
|
||||
<hr>
|
||||
|
||||
<h2><a name="classes"></a>Classes</h2>
|
||||
|
||||
<h3><a name="return_opaque_pointer-spec"></a>Class
|
||||
<code>return_opaque_pointer</code></h3>
|
||||
|
||||
<p><code>return_opaque_pointer</code> is a model of
|
||||
<a href="ResultConverter.html#ResultConverterGenerator-concept">
|
||||
ResultConverterGenerator</a>
|
||||
which can be used to wrap C++ functions returning pointers to
|
||||
undefined types such that the return value is copied into a
|
||||
new Python object.</p>
|
||||
<p>In addition to specifying the <code>return_opaque_pointer</code>
|
||||
policy the <a href="opaque_pointer_converter.html#BOOST_PYTHON_OPAQUE_SPECIALIZED_TYPE_ID-spec">
|
||||
<code>BOOST_PYTHON_OPAQUE_SPECIALIZED_TYPE_ID</code></a> macro must be
|
||||
used to define specializations for the
|
||||
<a href="type_id.html#type_id-spec">type_id</a> function
|
||||
on the type pointed to by returned pointer.</p>
|
||||
|
||||
<h4><a name="return_opaque_pointer-spec-synopsis"></a>Class
|
||||
<code>return_opaque_pointer</code> synopsis</h4>
|
||||
<pre>
|
||||
namespace boost { namespace python
|
||||
{
|
||||
struct return_opaque_pointer
|
||||
{
|
||||
template <class R> struct apply;
|
||||
};
|
||||
}}
|
||||
</pre>
|
||||
|
||||
<h4><a name="return_opaque_pointer-spec-metafunctions"></a>Class
|
||||
<code>return_opaque_pointer</code> metafunctions</h4>
|
||||
<pre>
|
||||
template <class R> struct apply
|
||||
</pre>
|
||||
|
||||
<dl class="metafunction-semantics">
|
||||
<dt><b>Returns:</b> <code>typedef
|
||||
detail::opaque_conversion_holder<R>
|
||||
type;</code></dt>
|
||||
</dl>
|
||||
|
||||
<h2><a name="examples"></a>Example</h2>
|
||||
|
||||
<h3>C++ Module Definition</h3>
|
||||
<pre>
|
||||
# include <boost/python/return_opaque_pointer.hpp>
|
||||
# include <boost/python/def.hpp>
|
||||
# include <boost/python/module.hpp>
|
||||
# include <boost/python/return_value_policy.hpp>
|
||||
|
||||
typedef struct opaque_ *opaque;
|
||||
|
||||
opaque the_op = ((opaque) 0x47110815);
|
||||
|
||||
opaque get () { return the_op; }
|
||||
void use (opaque op) {
|
||||
if (op != the_op)
|
||||
throw std::runtime_error (std::string ("failed"));
|
||||
}
|
||||
|
||||
void failuse (opaque op) {
|
||||
if (op == the_op)
|
||||
throw std::runtime_error (std::string ("success"));
|
||||
}
|
||||
|
||||
BOOST_PYTHON_OPAQUE_SPECIALIZED_TYPE_ID(opaque_)
|
||||
|
||||
namespace bpl = boost::python;
|
||||
|
||||
BOOST_PYTHON_MODULE(opaque_ext)
|
||||
{
|
||||
bpl::def (
|
||||
"get", &::get, bpl::return_value_policy<bpl::return_opaque_pointer>());
|
||||
bpl::def ("use", &::use);
|
||||
bpl::def ("failuse", &::failuse);
|
||||
}
|
||||
</pre>
|
||||
|
||||
<h3>Python Code</h3>
|
||||
<pre>
|
||||
"""
|
||||
>>> from opaque_ext import *
|
||||
>>> #
|
||||
>>> # Check for correct conversion
|
||||
>>> use(get())
|
||||
>>> failuse(get())
|
||||
Traceback (most recent call last):
|
||||
...
|
||||
RuntimeError: success
|
||||
>>> #
|
||||
>>> # Check that there is no conversion from integers ...
|
||||
>>> use(0)
|
||||
Traceback (most recent call last):
|
||||
...
|
||||
TypeError: bad argument type for built-in operation
|
||||
>>> #
|
||||
>>> # ... and from strings to opaque objects
|
||||
>>> use("")
|
||||
Traceback (most recent call last):
|
||||
...
|
||||
TypeError: bad argument type for built-in operation
|
||||
"""
|
||||
def run(args = None):
|
||||
import sys
|
||||
import doctest
|
||||
|
||||
if args is not None:
|
||||
sys.argv = args
|
||||
return doctest.testmod(sys.modules.get(__name__))
|
||||
|
||||
if __name__ == '__main__':
|
||||
print "running..."
|
||||
import sys
|
||||
sys.exit(run()[0])
|
||||
</pre>
|
||||
|
||||
<h2><a name="see-also"></a>See Also</h2>
|
||||
<p>
|
||||
<a href="opaque_pointer_converter.html">
|
||||
opaque_pointer_converter</a>
|
||||
</p>
|
||||
|
||||
<p>Revised
|
||||
28 January, 2003
|
||||
</p>
|
||||
|
||||
<p><i>© Copyright 2003 Haufe Mediengruppe. All Rights
|
||||
Reserved.</i></p>
|
||||
</body>
|
||||
</html>
|
||||
|
||||
@@ -86,7 +86,7 @@
|
||||
"ResultConverter.html#ResultConverterGenerator-concept">ResultConverterGenerator</a></td>
|
||||
|
||||
<td>A model of <a href=
|
||||
"ResultConverterGenerator.html">ResultConverterGenerator</a>.</td>
|
||||
"ResultConverter.html#ResultConverterGenerator-concept">ResultConverterGenerator</a>.</td>
|
||||
</tr>
|
||||
|
||||
<tr>
|
||||
|
||||
@@ -67,8 +67,10 @@
|
||||
<p>Exposes the <a href=
|
||||
"http://www.python.org/dev/doc/devel/lib/string-methods.html">string
|
||||
methods</a> of Python's built-in <code>str</code> type. The
|
||||
semantics of the constructors and member functions defined below
|
||||
can be fully understood by reading the <a href=
|
||||
semantics of the constructors and member functions defined below,
|
||||
except for the two-argument constructors which construct str
|
||||
objects from a range of characters, can be fully understood by
|
||||
reading the <a href=
|
||||
"ObjectWrapper.html#TypeWrapper-concept">TypeWrapper</a> concept
|
||||
definition. Since <code>str</code> is publicly derived from
|
||||
<code><a href="object.html#object-spec">object</a></code>, the
|
||||
@@ -85,7 +87,10 @@ namespace boost { namespace python
|
||||
public:
|
||||
str(); // new str
|
||||
|
||||
str(const char* s); // new str
|
||||
str(char const* s); // new str
|
||||
|
||||
str(char const* start, char const* finish); // new str
|
||||
str(char const* start, std::size_t length); // new str
|
||||
|
||||
template <class T>
|
||||
explicit str(T const& other);
|
||||
|
||||
@@ -60,8 +60,8 @@ namespace boost { namespace python
|
||||
template <class T>
|
||||
struct to_python_value
|
||||
{
|
||||
typedef typename <a href="../../../type_traits/index.htm#transformations">add_reference</a><
|
||||
typename <a href="../../../type_traits/index.htm#transformations">add_const</a><T>::type
|
||||
typedef typename <a href="../../../type_traits/index.html#transformations">add_reference</a><
|
||||
typename <a href="../../../type_traits/index.html#transformations">add_const</a><T>::type
|
||||
>::type argument_type;
|
||||
|
||||
static bool convertible();
|
||||
|
||||
@@ -1,5 +1,8 @@
|
||||
# Specify our location in the boost project hierarchy
|
||||
subproject libs/python/example ;
|
||||
# Copyright David Abrahams 2003. See accompanying LICENSE for terms
|
||||
# and conditions of use.
|
||||
|
||||
# This is the top of our own project tree
|
||||
project-root ;
|
||||
|
||||
# Declares the following targets:
|
||||
#
|
||||
@@ -19,18 +22,17 @@ subproject libs/python/example ;
|
||||
#
|
||||
|
||||
# Include definitions needed for Python modules
|
||||
SEARCH on python.jam = $(BOOST_BUILD_PATH) ;
|
||||
include python.jam ;
|
||||
import python ;
|
||||
|
||||
# ----- getting_started1 -------
|
||||
|
||||
# Declare a Python extension called getting_started1
|
||||
extension getting_started1
|
||||
: # sources
|
||||
getting_started1.cpp
|
||||
: # sources
|
||||
getting_started1.cpp
|
||||
|
||||
# dependencies
|
||||
<dll>../build/boost_python
|
||||
# requirements and dependencies for Boost.Python extensions
|
||||
<template>@boost/libs/python/build/extension
|
||||
;
|
||||
|
||||
# Declare a test for the extension module
|
||||
@@ -49,8 +51,8 @@ extension getting_started2
|
||||
: # sources
|
||||
getting_started2.cpp
|
||||
|
||||
# dependencies
|
||||
<dll>../build/boost_python
|
||||
# requirements and dependencies for Boost.Python extensions
|
||||
<template>@boost/libs/python/build/extension
|
||||
;
|
||||
|
||||
# Declare a test for the extension module
|
||||
|
||||
@@ -2,11 +2,9 @@
|
||||
use-project /boost/python : ../build ;
|
||||
|
||||
project
|
||||
: requirements <library>@/boost/python/boost_python
|
||||
: requirements <library>/boost/python//boost_python
|
||||
;
|
||||
|
||||
python-extension getting_started1 : getting_started1.cpp : <shared>true ;
|
||||
python-extension getting_started2 : getting_started2.cpp : <shared>true ;
|
||||
python-extension getting_started1 : getting_started1.cpp : <link>shared ;
|
||||
python-extension getting_started2 : getting_started2.cpp : <link>shared ;
|
||||
|
||||
exe embedding_test : embedding_test.cpp : <define>BOOST_PYTHON_DYNAMIC_LIB <shared>true ;
|
||||
|
||||
|
||||
7
example/Jamrules
Executable file
7
example/Jamrules
Executable file
@@ -0,0 +1,7 @@
|
||||
# Copyright David Abrahams 2003. See accompanying LICENSE for terms
|
||||
# and conditions of use.
|
||||
|
||||
# Edit this path to point at the root directory of your Boost
|
||||
# installation. Absolute paths work, too.
|
||||
path-global BOOST_ROOT : ../../.. ;
|
||||
project boost : $(BOOST_ROOT) ;
|
||||
6
example/boost-build.jam
Executable file
6
example/boost-build.jam
Executable file
@@ -0,0 +1,6 @@
|
||||
# Copyright David Abrahams 2003. See accompanying LICENSE for terms
|
||||
# and conditions of use.
|
||||
|
||||
# Edit this path to point at the tools/build/v1 subdirectory of your
|
||||
# Boost installation. Absolute paths work, too.
|
||||
boost-build ../../../tools/build/v1 ;
|
||||
18
example/test_getting_started1.py
Normal file
18
example/test_getting_started1.py
Normal file
@@ -0,0 +1,18 @@
|
||||
r'''>>> import getting_started1
|
||||
>>> print getting_started1.greet()
|
||||
hello, world
|
||||
>>> number = 11
|
||||
>>> print number, '*', number, '=', getting_started1.square(number)
|
||||
11 * 11 = 121
|
||||
'''
|
||||
|
||||
def run(args = None):
|
||||
if args is not None:
|
||||
import sys
|
||||
sys.argv = args
|
||||
import doctest, test_getting_started1
|
||||
return doctest.testmod(test_getting_started1)
|
||||
|
||||
if __name__ == '__main__':
|
||||
import sys
|
||||
sys.exit(run()[0])
|
||||
31
example/test_getting_started2.py
Normal file
31
example/test_getting_started2.py
Normal file
@@ -0,0 +1,31 @@
|
||||
r'''>>> from getting_started2 import *
|
||||
>>> hi = hello('California')
|
||||
>>> hi.greet()
|
||||
'Hello from California'
|
||||
>>> invite(hi)
|
||||
'Hello from California! Please come soon!'
|
||||
>>> hi.invite()
|
||||
'Hello from California! Please come soon!'
|
||||
|
||||
>>> class wordy(hello):
|
||||
... def greet(self):
|
||||
... return hello.greet(self) + ', where the weather is fine'
|
||||
...
|
||||
>>> hi2 = wordy('Florida')
|
||||
>>> hi2.greet()
|
||||
'Hello from Florida, where the weather is fine'
|
||||
>>> invite(hi2)
|
||||
'Hello from Florida! Please come soon!'
|
||||
'''
|
||||
|
||||
def run(args = None):
|
||||
if args is not None:
|
||||
import sys
|
||||
sys.argv = args
|
||||
import doctest, test_getting_started2
|
||||
return doctest.testmod(test_getting_started2)
|
||||
|
||||
if __name__ == '__main__':
|
||||
import sys
|
||||
sys.exit(run()[0])
|
||||
|
||||
@@ -5,8 +5,7 @@
|
||||
subproject libs/python/example/tutorial ;
|
||||
|
||||
# Include definitions needed for Python modules
|
||||
SEARCH on python.jam = $(BOOST_BUILD_PATH) ;
|
||||
include python.jam ;
|
||||
import python ;
|
||||
|
||||
extension hello # Declare a Python extension called hello
|
||||
: hello.cpp # source
|
||||
|
||||
@@ -43,13 +43,18 @@
|
||||
# include <boost/python/object.hpp>
|
||||
# include <boost/python/object_protocol.hpp>
|
||||
# include <boost/python/object_protocol_core.hpp>
|
||||
# include <boost/python/opaque_pointer_converter.hpp>
|
||||
# include <boost/python/operators.hpp>
|
||||
# include <boost/python/other.hpp>
|
||||
# include <boost/python/overloads.hpp>
|
||||
# include <boost/python/pointee.hpp>
|
||||
# include <boost/python/pure_virtual.hpp>
|
||||
# include <boost/python/ptr.hpp>
|
||||
# include <boost/python/reference_existing_object.hpp>
|
||||
# include <boost/python/register_ptr_to_python.hpp>
|
||||
# include <boost/python/return_arg.hpp>
|
||||
# include <boost/python/return_internal_reference.hpp>
|
||||
# include <boost/python/return_opaque_pointer.hpp>
|
||||
# include <boost/python/return_value_policy.hpp>
|
||||
# include <boost/python/scope.hpp>
|
||||
# include <boost/python/self.hpp>
|
||||
|
||||
@@ -6,6 +6,7 @@
|
||||
#ifndef ARG_FROM_PYTHON_DWA2002128_HPP
|
||||
# define ARG_FROM_PYTHON_DWA2002128_HPP
|
||||
|
||||
# include <boost/python/detail/prefix.hpp>
|
||||
# include <boost/python/converter/arg_from_python.hpp>
|
||||
# include <boost/python/detail/indirect_traits.hpp>
|
||||
|
||||
@@ -25,51 +26,25 @@ struct arg_from_python<PyObject*>
|
||||
{
|
||||
typedef PyObject* result_type;
|
||||
|
||||
arg_from_python(PyObject*) {}
|
||||
arg_from_python(PyObject* p) : m_source(p) {}
|
||||
bool convertible() const { return true; }
|
||||
PyObject* operator()(PyObject* source) const { return source; }
|
||||
PyObject* operator()() const { return m_source; }
|
||||
private:
|
||||
PyObject* m_source;
|
||||
};
|
||||
|
||||
template <>
|
||||
struct arg_from_python<PyObject* const&>
|
||||
{
|
||||
typedef PyObject* const& result_type;
|
||||
arg_from_python(PyObject*) {}
|
||||
|
||||
arg_from_python(PyObject* p) : m_source(p) {}
|
||||
bool convertible() const { return true; }
|
||||
PyObject*const& operator()(PyObject*const& source) const { return source; }
|
||||
PyObject*const& operator()() const { return m_source; }
|
||||
private:
|
||||
PyObject* m_source;
|
||||
};
|
||||
|
||||
namespace detail
|
||||
{
|
||||
//
|
||||
// Meta-iterators for use with caller<>
|
||||
//
|
||||
|
||||
// temporary hack
|
||||
template <class T> struct nullary : T
|
||||
{
|
||||
nullary(PyObject* x) : T(x), m_p(x) {}
|
||||
typename T::result_type operator()() { return this->T::operator()(m_p); }
|
||||
PyObject* m_p;
|
||||
};
|
||||
|
||||
// An MPL metafunction class which returns arg_from_python<ArgType>
|
||||
struct gen_arg_from_python
|
||||
{
|
||||
template <class ArgType> struct apply
|
||||
{
|
||||
typedef nullary<arg_from_python<ArgType> > type;
|
||||
};
|
||||
};
|
||||
|
||||
// An MPL iterator over an endless sequence of gen_arg_from_python
|
||||
struct args_from_python
|
||||
{
|
||||
typedef gen_arg_from_python type;
|
||||
typedef args_from_python next;
|
||||
};
|
||||
}
|
||||
|
||||
//
|
||||
// implementations
|
||||
//
|
||||
|
||||
@@ -6,6 +6,8 @@
|
||||
#ifndef KEYWORDS_DWA2002323_HPP
|
||||
# define KEYWORDS_DWA2002323_HPP
|
||||
|
||||
# include <boost/python/detail/prefix.hpp>
|
||||
|
||||
# include <boost/python/args_fwd.hpp>
|
||||
# include <boost/config.hpp>
|
||||
# include <boost/python/detail/preprocessor.hpp>
|
||||
@@ -21,18 +23,21 @@
|
||||
# include <boost/preprocessor/iteration/local.hpp>
|
||||
|
||||
# include <boost/python/detail/mpl_lambda.hpp>
|
||||
# include <boost/python/object_core.hpp>
|
||||
|
||||
# include <boost/mpl/bool.hpp>
|
||||
|
||||
# include <boost/type.hpp>
|
||||
# include <cstddef>
|
||||
|
||||
# include <algorithm>
|
||||
|
||||
namespace boost { namespace python {
|
||||
|
||||
typedef detail::keywords<1> arg;
|
||||
|
||||
namespace detail
|
||||
{
|
||||
template <std::size_t nkeywords>
|
||||
struct keywords
|
||||
struct keywords_base
|
||||
{
|
||||
BOOST_STATIC_CONSTANT(std::size_t, size = nkeywords);
|
||||
|
||||
@@ -40,9 +45,62 @@ namespace detail
|
||||
{
|
||||
return keyword_range(elements, elements + nkeywords);
|
||||
}
|
||||
|
||||
|
||||
keyword elements[nkeywords];
|
||||
|
||||
keywords<nkeywords+1>
|
||||
operator,(arg const &k) const;
|
||||
|
||||
keywords<nkeywords + 1>
|
||||
operator,(char const *name) const;
|
||||
};
|
||||
|
||||
template <std::size_t nkeywords>
|
||||
struct keywords : keywords_base<nkeywords>
|
||||
{
|
||||
};
|
||||
|
||||
template <>
|
||||
struct keywords<1> : keywords_base<1>
|
||||
{
|
||||
explicit keywords(char const *name)
|
||||
{
|
||||
elements[0].name = name;
|
||||
}
|
||||
|
||||
template <class T>
|
||||
arg& operator=(T const& value)
|
||||
{
|
||||
object z(value);
|
||||
elements[0].default_value = handle<>(python::borrowed(object(value).ptr()));
|
||||
return *this;
|
||||
}
|
||||
|
||||
operator detail::keyword const&() const
|
||||
{
|
||||
return elements[0];
|
||||
}
|
||||
};
|
||||
|
||||
template <std::size_t nkeywords>
|
||||
inline
|
||||
keywords<nkeywords+1>
|
||||
keywords_base<nkeywords>::operator,(arg const &k) const
|
||||
{
|
||||
keywords<nkeywords> const& l = *static_cast<keywords<nkeywords> const*>(this);
|
||||
python::detail::keywords<nkeywords+1> res;
|
||||
std::copy(l.elements, l.elements+nkeywords, res.elements);
|
||||
res.elements[nkeywords] = k.elements[0];
|
||||
return res;
|
||||
}
|
||||
|
||||
template <std::size_t nkeywords>
|
||||
inline
|
||||
keywords<nkeywords + 1>
|
||||
keywords_base<nkeywords>::operator,(char const *name) const
|
||||
{
|
||||
return this->operator,(python::arg(name));
|
||||
}
|
||||
|
||||
# ifndef BOOST_NO_TEMPLATE_PARTIAL_SPECIALIZATION
|
||||
template<typename T>
|
||||
@@ -95,6 +153,11 @@ namespace detail
|
||||
# endif
|
||||
}
|
||||
|
||||
inline detail::keywords<1> args(char const* name)
|
||||
{
|
||||
return detail::keywords<1>(name);
|
||||
}
|
||||
|
||||
# define BOOST_PYTHON_ASSIGN_NAME(z, n, _) result.elements[n].name = name##n;
|
||||
# define BOOST_PP_LOCAL_MACRO(n) \
|
||||
inline detail::keywords<n> args(BOOST_PP_ENUM_PARAMS_Z(1, n, char const* name)) \
|
||||
@@ -103,7 +166,7 @@ inline detail::keywords<n> args(BOOST_PP_ENUM_PARAMS_Z(1, n, char const* name))
|
||||
BOOST_PP_REPEAT_1(n, BOOST_PYTHON_ASSIGN_NAME, _) \
|
||||
return result; \
|
||||
}
|
||||
# define BOOST_PP_LOCAL_LIMITS (1, BOOST_PYTHON_MAX_ARITY)
|
||||
# define BOOST_PP_LOCAL_LIMITS (2, BOOST_PYTHON_MAX_ARITY)
|
||||
# include BOOST_PP_LOCAL_ITERATE()
|
||||
|
||||
}} // namespace boost::python
|
||||
|
||||
@@ -6,6 +6,8 @@
|
||||
#ifndef ARGS_FWD_DWA2002927_HPP
|
||||
# define ARGS_FWD_DWA2002927_HPP
|
||||
|
||||
# include <boost/python/detail/prefix.hpp>
|
||||
|
||||
# include <boost/python/handle.hpp>
|
||||
# include <boost/config.hpp>
|
||||
# include <cstddef>
|
||||
@@ -17,6 +19,10 @@ namespace detail
|
||||
{
|
||||
struct keyword
|
||||
{
|
||||
keyword(char const* name_=0)
|
||||
: name(name_)
|
||||
{}
|
||||
|
||||
char const* name;
|
||||
handle<> default_value;
|
||||
};
|
||||
|
||||
@@ -6,6 +6,8 @@
|
||||
#ifndef BACK_REFERENCE_DWA2002510_HPP
|
||||
# define BACK_REFERENCE_DWA2002510_HPP
|
||||
|
||||
# include <boost/python/detail/prefix.hpp>
|
||||
|
||||
# include <boost/python/object_fwd.hpp>
|
||||
# include <boost/python/detail/dependent.hpp>
|
||||
# include <boost/python/detail/raw_pyobject.hpp>
|
||||
|
||||
@@ -6,6 +6,8 @@
|
||||
#ifndef BASE_TYPE_TRAITS_DWA2002614_HPP
|
||||
# define BASE_TYPE_TRAITS_DWA2002614_HPP
|
||||
|
||||
# include <boost/python/detail/prefix.hpp>
|
||||
|
||||
namespace boost { namespace python {
|
||||
|
||||
namespace detail
|
||||
|
||||
@@ -5,6 +5,8 @@
|
||||
// to its suitability for any purpose.
|
||||
#ifndef BASES_DWA2002321_HPP
|
||||
# define BASES_DWA2002321_HPP
|
||||
|
||||
# include <boost/python/detail/prefix.hpp>
|
||||
# include <boost/type_traits/object_traits.hpp>
|
||||
# include <boost/python/detail/type_list.hpp>
|
||||
# include <boost/mpl/if.hpp>
|
||||
|
||||
@@ -5,6 +5,8 @@
|
||||
// to its suitability for any purpose.
|
||||
#ifndef BORROWED_DWA2002614_HPP
|
||||
# define BORROWED_DWA2002614_HPP
|
||||
|
||||
# include <boost/python/detail/prefix.hpp>
|
||||
# include <boost/python/detail/borrowed_ptr.hpp>
|
||||
|
||||
namespace boost { namespace python {
|
||||
|
||||
@@ -9,6 +9,8 @@
|
||||
# ifndef CALL_DWA2002411_HPP
|
||||
# define CALL_DWA2002411_HPP
|
||||
|
||||
# include <boost/python/detail/prefix.hpp>
|
||||
|
||||
# include <boost/type.hpp>
|
||||
|
||||
# include <boost/python/converter/arg_to_python.hpp>
|
||||
@@ -38,7 +40,10 @@ namespace boost { namespace python {
|
||||
# endif // CALL_DWA2002411_HPP
|
||||
|
||||
#elif BOOST_PP_ITERATION_DEPTH() == 1
|
||||
# line BOOST_PP_LINE(__LINE__, call.hpp)
|
||||
# if !(BOOST_WORKAROUND(__MWERKS__, > 0x3100) \
|
||||
&& BOOST_WORKAROUND(__MWERKS__, BOOST_TESTED_AT(0x3201)))
|
||||
# line BOOST_PP_LINE(__LINE__, call.hpp)
|
||||
# endif
|
||||
|
||||
# define N BOOST_PP_ITERATION()
|
||||
|
||||
@@ -52,13 +57,22 @@ call(PyObject* callable
|
||||
, boost::type<R>* = 0
|
||||
)
|
||||
{
|
||||
converter::return_from_python<R> converter;
|
||||
return converter(
|
||||
PyObject* const result =
|
||||
PyEval_CallFunction(
|
||||
callable
|
||||
, const_cast<char*>("(" BOOST_PP_REPEAT_1ST(N, BOOST_PYTHON_FIXED, "O") ")")
|
||||
BOOST_PP_REPEAT_1ST(N, BOOST_PYTHON_FAST_ARG_TO_PYTHON_GET, nil)
|
||||
));
|
||||
);
|
||||
|
||||
// This conversion *must not* be done in the same expression as
|
||||
// the call, because, in the special case where the result is a
|
||||
// reference a Python object which was created by converting a C++
|
||||
// argument for passing to PyEval_CallFunction, its reference
|
||||
// count will be 2 until the end of the full expression containing
|
||||
// the conversion, and that interferes with dangling
|
||||
// pointer/reference detection.
|
||||
converter::return_from_python<R> converter;
|
||||
return converter(result);
|
||||
}
|
||||
|
||||
# undef N
|
||||
|
||||
@@ -8,6 +8,8 @@
|
||||
# ifndef CALL_METHOD_DWA2002411_HPP
|
||||
# define CALL_METHOD_DWA2002411_HPP
|
||||
|
||||
# include <boost/python/detail/prefix.hpp>
|
||||
|
||||
# include <boost/type.hpp>
|
||||
|
||||
# include <boost/python/converter/arg_to_python.hpp>
|
||||
@@ -37,7 +39,10 @@ namespace boost { namespace python {
|
||||
# endif // CALL_METHOD_DWA2002411_HPP
|
||||
|
||||
#elif BOOST_PP_ITERATION_DEPTH() == 1
|
||||
# line BOOST_PP_LINE(__LINE__, call_method.hpp)
|
||||
# if !(BOOST_WORKAROUND(__MWERKS__, > 0x3100) \
|
||||
&& BOOST_WORKAROUND(__MWERKS__, BOOST_TESTED_AT(0x3201)))
|
||||
# line BOOST_PP_LINE(__LINE__, call_method.hpp)
|
||||
# endif
|
||||
|
||||
# define N BOOST_PP_ITERATION()
|
||||
|
||||
@@ -51,14 +56,23 @@ call_method(PyObject* self, char const* name
|
||||
, boost::type<R>* = 0
|
||||
)
|
||||
{
|
||||
converter::return_from_python<R> converter;
|
||||
return converter(
|
||||
PyObject* const result =
|
||||
PyEval_CallMethod(
|
||||
self
|
||||
, const_cast<char*>(name)
|
||||
, const_cast<char*>("(" BOOST_PP_REPEAT_1ST(N, BOOST_PYTHON_FIXED, "O") ")")
|
||||
BOOST_PP_REPEAT_1ST(N, BOOST_PYTHON_FAST_ARG_TO_PYTHON_GET, nil)
|
||||
));
|
||||
);
|
||||
|
||||
// This conversion *must not* be done in the same expression as
|
||||
// the call, because, in the special case where the result is a
|
||||
// reference a Python object which was created by converting a C++
|
||||
// argument for passing to PyEval_CallFunction, its reference
|
||||
// count will be 2 until the end of the full expression containing
|
||||
// the conversion, and that interferes with dangling
|
||||
// pointer/reference detection.
|
||||
converter::return_from_python<R> converter;
|
||||
return converter(result);
|
||||
}
|
||||
|
||||
# undef N
|
||||
|
||||
@@ -6,7 +6,8 @@
|
||||
#ifndef CAST_DWA200269_HPP
|
||||
# define CAST_DWA200269_HPP
|
||||
|
||||
# include <boost/python/detail/wrap_python.hpp>
|
||||
# include <boost/python/detail/prefix.hpp>
|
||||
|
||||
# include <boost/type_traits/same_traits.hpp>
|
||||
# include <boost/type_traits/cv_traits.hpp>
|
||||
# include <boost/type.hpp>
|
||||
@@ -78,7 +79,7 @@ namespace detail
|
||||
{
|
||||
typedef typename add_cv<Source>::type src_t;
|
||||
typedef typename add_cv<Target>::type target_t;
|
||||
static bool const same = is_same<src_t,target_t>::value;
|
||||
bool const same = is_same<src_t,target_t>::value;
|
||||
|
||||
return detail::upcaster<same>::execute(x, (Target*)0);
|
||||
}
|
||||
|
||||
@@ -6,6 +6,8 @@
|
||||
#ifndef CLASS_DWA200216_HPP
|
||||
# define CLASS_DWA200216_HPP
|
||||
|
||||
# include <boost/python/detail/prefix.hpp>
|
||||
|
||||
# include <boost/python/class_fwd.hpp>
|
||||
# include <boost/python/object/class.hpp>
|
||||
|
||||
@@ -18,6 +20,18 @@
|
||||
# include <boost/python/init.hpp>
|
||||
# include <boost/python/args_fwd.hpp>
|
||||
|
||||
# include <boost/python/object/select_holder.hpp>
|
||||
# include <boost/python/object/class_wrapper.hpp>
|
||||
# include <boost/python/object/make_instance.hpp>
|
||||
# include <boost/python/object/pickle_support.hpp>
|
||||
# include <boost/python/object/add_to_namespace.hpp>
|
||||
# include <boost/python/object/class_converters.hpp>
|
||||
|
||||
# include <boost/python/detail/overloads_fwd.hpp>
|
||||
# include <boost/python/detail/operator_id.hpp>
|
||||
# include <boost/python/detail/def_helper.hpp>
|
||||
# include <boost/python/detail/force_instantiate.hpp>
|
||||
|
||||
# include <boost/type_traits/is_same.hpp>
|
||||
# include <boost/type_traits/is_convertible.hpp>
|
||||
# include <boost/type_traits/is_member_function_pointer.hpp>
|
||||
@@ -28,26 +42,30 @@
|
||||
# include <boost/mpl/bool.hpp>
|
||||
# include <boost/mpl/not.hpp>
|
||||
# include <boost/mpl/or.hpp>
|
||||
|
||||
# include <boost/python/object/select_holder.hpp>
|
||||
# include <boost/python/object/class_wrapper.hpp>
|
||||
# include <boost/python/object/make_instance.hpp>
|
||||
# include <boost/python/object/pickle_support.hpp>
|
||||
# include <boost/python/object/add_to_namespace.hpp>
|
||||
# include <boost/python/object/class_converters.hpp>
|
||||
|
||||
# include <boost/python/detail/string_literal.hpp>
|
||||
# include <boost/python/detail/overloads_fwd.hpp>
|
||||
# include <boost/python/detail/operator_id.hpp>
|
||||
# include <boost/python/detail/member_function_cast.hpp>
|
||||
# include <boost/python/detail/def_helper.hpp>
|
||||
# include <boost/python/detail/force_instantiate.hpp>
|
||||
# include <boost/mpl/vector/vector10.hpp>
|
||||
|
||||
# include <boost/utility.hpp>
|
||||
# include <boost/detail/workaround.hpp>
|
||||
|
||||
# if BOOST_WORKAROUND(__MWERKS__, <= 0x3004) \
|
||||
/* pro9 reintroduced the bug */ \
|
||||
|| (BOOST_WORKAROUND(__MWERKS__, > 0x3100) \
|
||||
&& BOOST_WORKAROUND(__MWERKS__, BOOST_TESTED_AT(0x3201))) \
|
||||
|| BOOST_WORKAROUND(__GNUC__, < 3)
|
||||
|
||||
# define BOOST_PYTHON_NO_MEMBER_POINTER_ORDERING 1
|
||||
|
||||
# endif
|
||||
|
||||
# ifdef BOOST_PYTHON_NO_MEMBER_POINTER_ORDERING
|
||||
# include <boost/mpl/and.hpp>
|
||||
# include <boost/type_traits/is_member_pointer.hpp>
|
||||
# endif
|
||||
|
||||
namespace boost { namespace python {
|
||||
|
||||
template <class DerivedVisitor> class def_visitor;
|
||||
|
||||
enum no_init_t { no_init };
|
||||
|
||||
namespace detail
|
||||
@@ -75,16 +93,13 @@ namespace detail
|
||||
template <class T1, class T2, class T3>
|
||||
struct has_noncopyable;
|
||||
|
||||
template <detail::operator_id, class L, class R>
|
||||
struct operator_;
|
||||
|
||||
// Register to_python converters for a class T. The first argument
|
||||
// will be mpl::true_ unless noncopyable was specified as a
|
||||
// class_<...> template parameter. The 2nd argument is a pointer to
|
||||
// the type of holder that must be created. The 3rd argument is a
|
||||
// reference to the Python type object to be created.
|
||||
template <class T, class SelectHolder>
|
||||
inline void register_class_to_python(mpl::true_ copyable, SelectHolder selector, T* = 0)
|
||||
inline void register_class_to_python(mpl::true_, SelectHolder, T* = 0)
|
||||
{
|
||||
typedef typename SelectHolder::type holder;
|
||||
force_instantiate(objects::class_cref_wrapper<T, objects::make_instance<T,holder> >());
|
||||
@@ -92,11 +107,54 @@ namespace detail
|
||||
}
|
||||
|
||||
template <class T, class SelectHolder>
|
||||
inline void register_class_to_python(mpl::false_ copyable, SelectHolder selector, T* = 0)
|
||||
inline void register_class_to_python(mpl::false_, SelectHolder, T* = 0)
|
||||
{
|
||||
SelectHolder::register_();
|
||||
}
|
||||
|
||||
//
|
||||
// register_wrapper_class -- register the relationship between a
|
||||
// virtual function callback wrapper class and the class being
|
||||
// wrapped.
|
||||
//
|
||||
template <class T>
|
||||
inline void register_wrapper_class_impl(T*, T*, int) {}
|
||||
|
||||
template <class Wrapper, class T>
|
||||
inline void register_wrapper_class_impl(Wrapper*, T*, ...)
|
||||
{
|
||||
objects::register_class_from_python<Wrapper, mpl::vector1<T> >();
|
||||
objects::copy_class_object(type_id<T>(), type_id<Wrapper>());
|
||||
}
|
||||
|
||||
template <class Held, class T>
|
||||
inline void register_wrapper_class(Held* = 0, T* = 0)
|
||||
{
|
||||
register_wrapper_class_impl((Held*)0, (T*)0, 0);
|
||||
}
|
||||
|
||||
template <class T>
|
||||
struct is_data_member_pointer
|
||||
: mpl::and_<
|
||||
is_member_pointer<T>
|
||||
, mpl::not_<is_member_function_pointer<T> >
|
||||
>
|
||||
{};
|
||||
|
||||
# ifdef BOOST_PYTHON_NO_MEMBER_POINTER_ORDERING
|
||||
# define BOOST_PYTHON_DATA_MEMBER_HELPER(D) , detail::is_data_member_pointer<D>()
|
||||
# define BOOST_PYTHON_YES_DATA_MEMBER , mpl::true_
|
||||
# define BOOST_PYTHON_NO_DATA_MEMBER , mpl::false_
|
||||
# elif defined(BOOST_NO_FUNCTION_TEMPLATE_ORDERING)
|
||||
# define BOOST_PYTHON_DATA_MEMBER_HELPER(D) , 0
|
||||
# define BOOST_PYTHON_YES_DATA_MEMBER , int
|
||||
# define BOOST_PYTHON_NO_DATA_MEMBER , ...
|
||||
# else
|
||||
# define BOOST_PYTHON_DATA_MEMBER_HELPER(D)
|
||||
# define BOOST_PYTHON_YES_DATA_MEMBER
|
||||
# define BOOST_PYTHON_NO_DATA_MEMBER
|
||||
# endif
|
||||
|
||||
namespace error
|
||||
{
|
||||
//
|
||||
@@ -159,14 +217,16 @@ class class_ : public objects::class_base
|
||||
typedef class_<T,X1,X2,X3> self;
|
||||
BOOST_STATIC_CONSTANT(bool, is_copyable = (!detail::has_noncopyable<X1,X2,X3>::value));
|
||||
|
||||
// held_type - either T, a class derived from T or a smart pointer
|
||||
// to a (class derived from) T.
|
||||
typedef typename detail::select_held_type<
|
||||
X1, typename detail::select_held_type<
|
||||
X2, typename detail::select_held_type<
|
||||
X3
|
||||
>::type>::type>::type held_type;
|
||||
|
||||
typedef objects::select_holder<T,held_type> holder_selector;
|
||||
|
||||
typedef objects::select_holder<T,held_type> select_holder;
|
||||
|
||||
private: // types
|
||||
|
||||
typedef typename detail::select_bases<X1
|
||||
@@ -212,9 +272,8 @@ class class_ : public objects::class_base
|
||||
inline class_(char const* name, init_base<DerivedT> const& i)
|
||||
: base(name, id_vector::size, id_vector().ids)
|
||||
{
|
||||
this->register_();
|
||||
define_init(*this, i.derived());
|
||||
this->set_instance_size(holder_selector::additional_size());
|
||||
this->register_holder();
|
||||
this->def(i);
|
||||
}
|
||||
|
||||
// Construct with class name, docstring and init<> function
|
||||
@@ -222,24 +281,23 @@ class class_ : public objects::class_base
|
||||
inline class_(char const* name, char const* doc, init_base<DerivedT> const& i)
|
||||
: base(name, id_vector::size, id_vector().ids, doc)
|
||||
{
|
||||
this->register_();
|
||||
define_init(*this, i.derived());
|
||||
this->set_instance_size(holder_selector::additional_size());
|
||||
this->register_holder();
|
||||
this->def(i);
|
||||
}
|
||||
|
||||
public: // member functions
|
||||
|
||||
// Define additional constructors
|
||||
template <class DerivedT>
|
||||
self& def(init_base<DerivedT> const& i)
|
||||
// Generic visitation
|
||||
template <class Derived>
|
||||
self& def(def_visitor<Derived> const& visitor)
|
||||
{
|
||||
define_init(*this, i.derived());
|
||||
visitor.visit(*this);
|
||||
return *this;
|
||||
}
|
||||
|
||||
// Wrap a member function or a non-member function which can take
|
||||
// a T, T cv&, or T cv* as its first parameter, or a callable
|
||||
// python object.
|
||||
// a T, T cv&, or T cv* as its first parameter, a callable
|
||||
// python object, or a generic visitor.
|
||||
template <class F>
|
||||
self& def(char const* name, F f)
|
||||
{
|
||||
@@ -280,57 +338,59 @@ class class_ : public objects::class_base
|
||||
return *this;
|
||||
}
|
||||
|
||||
template <detail::operator_id id, class L, class R>
|
||||
self& def(detail::operator_<id,L,R> const& op)
|
||||
{
|
||||
typedef detail::operator_<id,L,R> op_t;
|
||||
return this->def(op.name(), &op_t::template apply<T>::execute);
|
||||
}
|
||||
|
||||
//
|
||||
// Data member access
|
||||
//
|
||||
template <class D, class B>
|
||||
self& def_readonly(char const* name, D B::*pm_)
|
||||
template <class D>
|
||||
self& def_readonly(char const* name, D const& d)
|
||||
{
|
||||
D T::*pm = pm_;
|
||||
this->add_property(name, make_getter(pm));
|
||||
return *this;
|
||||
return this->def_readonly_impl(name, d BOOST_PYTHON_DATA_MEMBER_HELPER(D));
|
||||
}
|
||||
|
||||
template <class D, class B>
|
||||
self& def_readwrite(char const* name, D B::*pm_)
|
||||
template <class D>
|
||||
self& def_readwrite(char const* name, D const& d)
|
||||
{
|
||||
D T::*pm = pm_;
|
||||
return this->add_property(name, make_getter(pm), make_setter(pm));
|
||||
return this->def_readwrite_impl(name, d BOOST_PYTHON_DATA_MEMBER_HELPER(D));
|
||||
}
|
||||
|
||||
template <class D>
|
||||
self& def_readonly(char const* name, D& d)
|
||||
{
|
||||
return this->def_readonly_impl(name, d BOOST_PYTHON_DATA_MEMBER_HELPER(D));
|
||||
}
|
||||
|
||||
template <class D>
|
||||
self& def_readwrite(char const* name, D& d)
|
||||
{
|
||||
return this->def_readwrite_impl(name, d BOOST_PYTHON_DATA_MEMBER_HELPER(D));
|
||||
}
|
||||
|
||||
// Property creation
|
||||
template <class Get>
|
||||
self& add_property(char const* name, Get fget)
|
||||
{
|
||||
base::add_property(
|
||||
name
|
||||
, object(
|
||||
detail::member_function_cast<T,Get>::stage1(fget).stage2((T*)0).stage3(fget)
|
||||
)
|
||||
);
|
||||
|
||||
base::add_property(name, this->make_getter(fget));
|
||||
return *this;
|
||||
}
|
||||
|
||||
template <class Get, class Set>
|
||||
self& add_property(char const* name, Get fget, Set fset)
|
||||
{
|
||||
base::add_property(
|
||||
name
|
||||
, object(
|
||||
detail::member_function_cast<T,Get>::stage1(fget).stage2((T*)0).stage3(fget)
|
||||
)
|
||||
, object(
|
||||
detail::member_function_cast<T,Set>::stage1(fset).stage2((T*)0).stage3(fset)
|
||||
)
|
||||
);
|
||||
base::add_property(name, this->make_getter(fget), this->make_setter(fset));
|
||||
return *this;
|
||||
}
|
||||
|
||||
template <class Get>
|
||||
self& add_static_property(char const* name, Get fget)
|
||||
{
|
||||
base::add_static_property(name, object(fget));
|
||||
return *this;
|
||||
}
|
||||
|
||||
template <class Get, class Set>
|
||||
self& add_static_property(char const* name, Get fget, Set fset)
|
||||
{
|
||||
base::add_static_property(name, object(fget), object(fset));
|
||||
return *this;
|
||||
}
|
||||
|
||||
@@ -362,52 +422,137 @@ class class_ : public objects::class_base
|
||||
}
|
||||
private: // helper functions
|
||||
|
||||
inline void register_() const;
|
||||
// Builds a method for this class around the given [member]
|
||||
// function pointer or object, appropriately adjusting the type of
|
||||
// the first signature argument so that if f is a member of a
|
||||
// (possibly not wrapped) base class of T, an lvalue argument of
|
||||
// type T will be required.
|
||||
//
|
||||
// @group PropertyHelpers {
|
||||
template <class F>
|
||||
object make_getter(F f)
|
||||
{
|
||||
typedef typename api::is_object_operators<F>::type is_obj_or_proxy;
|
||||
|
||||
return this->make_fn_impl(
|
||||
f, is_obj_or_proxy(), (char*)0, detail::is_data_member_pointer<F>()
|
||||
);
|
||||
}
|
||||
|
||||
template <class F>
|
||||
object make_setter(F f)
|
||||
{
|
||||
typedef typename api::is_object_operators<F>::type is_obj_or_proxy;
|
||||
|
||||
return this->make_fn_impl(
|
||||
f, is_obj_or_proxy(), (int*)0, detail::is_data_member_pointer<F>()
|
||||
);
|
||||
}
|
||||
|
||||
template <class F>
|
||||
object make_fn_impl(F const& f, mpl::false_, void*, mpl::false_)
|
||||
{
|
||||
return python::make_function(f, default_call_policies(), detail::get_signature(f, (T*)0));
|
||||
}
|
||||
|
||||
template <class D, class B>
|
||||
object make_fn_impl(D B::*pm_, mpl::false_, char*, mpl::true_)
|
||||
{
|
||||
D T::*pm = pm_;
|
||||
return python::make_getter(pm);
|
||||
}
|
||||
|
||||
template <class D, class B>
|
||||
object make_fn_impl(D B::*pm_, mpl::false_, int*, mpl::true_)
|
||||
{
|
||||
D T::*pm = pm_;
|
||||
return python::make_setter(pm);
|
||||
}
|
||||
|
||||
template <class F>
|
||||
object make_fn_impl(F const& x, mpl::true_, void*, mpl::false_)
|
||||
{
|
||||
return x;
|
||||
}
|
||||
// }
|
||||
|
||||
template <class D, class B>
|
||||
self& def_readonly_impl(
|
||||
char const* name, D B::*pm_ BOOST_PYTHON_YES_DATA_MEMBER)
|
||||
{
|
||||
return this->add_property(name, pm_);
|
||||
}
|
||||
|
||||
template <class D, class B>
|
||||
self& def_readwrite_impl(
|
||||
char const* name, D B::*pm_ BOOST_PYTHON_YES_DATA_MEMBER)
|
||||
{
|
||||
return this->add_property(name, pm_, pm_);
|
||||
}
|
||||
|
||||
template <class D>
|
||||
self& def_readonly_impl(
|
||||
char const* name, D& d BOOST_PYTHON_NO_DATA_MEMBER)
|
||||
{
|
||||
return this->add_static_property(name, python::make_getter(d));
|
||||
}
|
||||
|
||||
template <class D>
|
||||
self& def_readwrite_impl(
|
||||
char const* name, D& d BOOST_PYTHON_NO_DATA_MEMBER)
|
||||
{
|
||||
return this->add_static_property(name, python::make_getter(d), python::make_setter(d));
|
||||
}
|
||||
|
||||
inline void register_() const;
|
||||
inline void register_holder();
|
||||
|
||||
//
|
||||
// These two overloads discriminate between def() as applied to
|
||||
// things which are already wrapped into callable python::object
|
||||
// instances and everything else.
|
||||
// These two overloads discriminate between def() as applied to a
|
||||
// generic visitor and everything else.
|
||||
//
|
||||
template <class F, class A1>
|
||||
// @group def_impl {
|
||||
template <class Helper, class LeafVisitor, class Visitor>
|
||||
inline void def_impl(
|
||||
char const* name
|
||||
, F f
|
||||
, detail::def_helper<A1> const& helper
|
||||
, object const*)
|
||||
, LeafVisitor
|
||||
, Helper const& helper
|
||||
, def_visitor<Visitor> const* v
|
||||
)
|
||||
{
|
||||
// It's too late to specify anything other than docstrings, if
|
||||
// the callable object is already wrapped.
|
||||
BOOST_STATIC_ASSERT(
|
||||
(is_same<char const*,A1>::value
|
||||
|| detail::is_string_literal<A1>::value));
|
||||
|
||||
objects::add_to_namespace(*this, name, f, helper.doc());
|
||||
v->visit(*this, name, helper);
|
||||
}
|
||||
|
||||
template <class Fn, class Helper>
|
||||
inline void def_impl(
|
||||
char const* name
|
||||
, Fn fn
|
||||
, Helper const& helper
|
||||
, ...)
|
||||
, Fn fn
|
||||
, Helper const& helper
|
||||
, ...
|
||||
)
|
||||
{
|
||||
objects::add_to_namespace(
|
||||
*this, name,
|
||||
make_function(
|
||||
// This bit of nastiness casts F to a member function of T if possible.
|
||||
detail::member_function_cast<T,Fn>::stage1(fn).stage2((T*)0).stage3(fn)
|
||||
, helper.policies(), helper.keywords())
|
||||
, helper.doc());
|
||||
*this
|
||||
, name
|
||||
, make_function(
|
||||
fn
|
||||
, helper.policies()
|
||||
, helper.keywords()
|
||||
, detail::get_signature(fn, (T*)0)
|
||||
)
|
||||
, helper.doc()
|
||||
);
|
||||
|
||||
this->def_default(name, fn, helper, mpl::bool_<Helper::has_default_implementation>());
|
||||
}
|
||||
// }
|
||||
|
||||
//
|
||||
// These two overloads handle the definition of default
|
||||
// implementation overloads for virtual functions. The second one
|
||||
// handles the case where no default implementation was specified.
|
||||
//
|
||||
// @group def_default {
|
||||
template <class Fn, class Helper>
|
||||
inline void def_default(
|
||||
char const* name
|
||||
@@ -428,6 +573,7 @@ class class_ : public objects::class_base
|
||||
template <class Fn, class Helper>
|
||||
inline void def_default(char const*, Fn, Helper const&, mpl::bool_<false>)
|
||||
{ }
|
||||
// }
|
||||
|
||||
//
|
||||
// These two overloads discriminate between def() as applied to
|
||||
@@ -435,6 +581,7 @@ class class_ : public objects::class_base
|
||||
// BOOST_PYTHON_FUNCTION_OVERLOADS(). The final argument is used to
|
||||
// discriminate.
|
||||
//
|
||||
// @group def_maybe_overloads {
|
||||
template <class OverloadsT, class SigT>
|
||||
void def_maybe_overloads(
|
||||
char const* name
|
||||
@@ -457,11 +604,14 @@ class class_ : public objects::class_base
|
||||
, ...)
|
||||
{
|
||||
this->def_impl(
|
||||
name, fn
|
||||
, detail::def_helper<A1>(a1)
|
||||
, &fn);
|
||||
name
|
||||
, fn
|
||||
, detail::def_helper<A1>(a1)
|
||||
, &fn
|
||||
);
|
||||
|
||||
}
|
||||
// }
|
||||
};
|
||||
|
||||
|
||||
@@ -475,29 +625,31 @@ inline void class_<T,X1,X2,X3>::register_() const
|
||||
{
|
||||
objects::register_class_from_python<T,bases>();
|
||||
|
||||
typedef BOOST_DEDUCED_TYPENAME select_holder::held_type held_t;
|
||||
detail::register_wrapper_class<held_t,T>();
|
||||
|
||||
detail::register_class_to_python<T>(
|
||||
mpl::bool_<is_copyable>()
|
||||
# if BOOST_WORKAROUND(__MWERKS__, <= 0x2407)
|
||||
, holder_selector::execute((held_type*)0)
|
||||
# elif BOOST_WORKAROUND(BOOST_MSVC, <= 1300)
|
||||
, holder_selector::type()
|
||||
# else
|
||||
, typename holder_selector::type()
|
||||
# endif
|
||||
);
|
||||
, select_holder()
|
||||
);
|
||||
}
|
||||
|
||||
template <class T, class X1, class X2, class X3>
|
||||
inline void class_<T,X1,X2,X3>::register_holder()
|
||||
{
|
||||
this->register_();
|
||||
typedef typename select_holder::type holder;
|
||||
this->set_instance_size(
|
||||
objects::additional_instance_size<holder>::value
|
||||
);
|
||||
}
|
||||
|
||||
template <class T, class X1, class X2, class X3>
|
||||
inline class_<T,X1,X2,X3>::class_(char const* name, char const* doc)
|
||||
: base(name, id_vector::size, id_vector().ids, doc)
|
||||
{
|
||||
this->register_();
|
||||
this->set_instance_size(holder_selector::additional_size());
|
||||
# if BOOST_WORKAROUND(__MWERKS__, <= 0x2407)
|
||||
holder_selector::execute((held_type*)0).assert_default_constructible();
|
||||
# else
|
||||
holder_selector::type::assert_default_constructible();
|
||||
# endif
|
||||
this->register_holder();
|
||||
select_holder::assert_default_constructible();
|
||||
this->def(init<>());
|
||||
}
|
||||
|
||||
@@ -529,20 +681,25 @@ namespace detail
|
||||
{};
|
||||
|
||||
|
||||
template <class T, class Prev>
|
||||
struct select_held_type
|
||||
: mpl::if_<
|
||||
mpl::or_<
|
||||
specifies_bases<T>
|
||||
, is_same<T,noncopyable>
|
||||
>
|
||||
, Prev
|
||||
, T
|
||||
>
|
||||
{
|
||||
};
|
||||
template <class T, class Prev>
|
||||
struct select_held_type
|
||||
: mpl::if_<
|
||||
mpl::or_<
|
||||
specifies_bases<T>
|
||||
, is_same<T,noncopyable>
|
||||
>
|
||||
, Prev
|
||||
, T
|
||||
>
|
||||
{
|
||||
};
|
||||
}
|
||||
|
||||
}} // namespace boost::python
|
||||
|
||||
# undef BOOST_PYTHON_DATA_MEMBER_HELPER
|
||||
# undef BOOST_PYTHON_YES_DATA_MEMBER
|
||||
# undef BOOST_PYTHON_NO_DATA_MEMBER
|
||||
# undef BOOST_PYTHON_NO_MEMBER_POINTER_ORDERING
|
||||
|
||||
#endif // CLASS_DWA200216_HPP
|
||||
|
||||
@@ -5,6 +5,8 @@
|
||||
// to its suitability for any purpose.
|
||||
#ifndef CLASS_FWD_DWA200222_HPP
|
||||
# define CLASS_FWD_DWA200222_HPP
|
||||
|
||||
# include <boost/python/detail/prefix.hpp>
|
||||
# include <boost/python/detail/not_specified.hpp>
|
||||
|
||||
namespace boost { namespace python {
|
||||
|
||||
@@ -6,8 +6,8 @@
|
||||
#ifndef ARG_FROM_PYTHON_DWA2002127_HPP
|
||||
# define ARG_FROM_PYTHON_DWA2002127_HPP
|
||||
|
||||
# include <boost/python/detail/prefix.hpp>
|
||||
# include <boost/python/converter/from_python.hpp>
|
||||
# include <boost/python/detail/wrap_python.hpp>
|
||||
# include <boost/python/detail/indirect_traits.hpp>
|
||||
# include <boost/type_traits/transform_traits.hpp>
|
||||
# include <boost/type_traits/cv_traits.hpp>
|
||||
@@ -44,7 +44,7 @@ struct pointer_cref_arg_from_python
|
||||
typedef T result_type;
|
||||
|
||||
pointer_cref_arg_from_python(PyObject*);
|
||||
T operator()(PyObject*) const;
|
||||
T operator()() const;
|
||||
bool convertible() const;
|
||||
|
||||
private: // storage for a U*
|
||||
@@ -74,7 +74,7 @@ struct pointer_arg_from_python : arg_lvalue_from_python_base
|
||||
typedef T result_type;
|
||||
|
||||
pointer_arg_from_python(PyObject*);
|
||||
T operator()(PyObject*) const;
|
||||
T operator()() const;
|
||||
};
|
||||
|
||||
// Used when T == U& and (T != V const& or T == W volatile&)
|
||||
@@ -84,7 +84,7 @@ struct reference_arg_from_python : arg_lvalue_from_python_base
|
||||
typedef T result_type;
|
||||
|
||||
reference_arg_from_python(PyObject*);
|
||||
T operator()(PyObject*) const;
|
||||
T operator()() const;
|
||||
};
|
||||
|
||||
// ===================
|
||||
@@ -114,10 +114,11 @@ struct arg_rvalue_from_python
|
||||
# if BOOST_MSVC < 1301 || _MSC_FULL_VER > 13102196
|
||||
typename arg_rvalue_from_python<T>::
|
||||
# endif
|
||||
result_type operator()(PyObject*);
|
||||
result_type operator()();
|
||||
|
||||
private:
|
||||
rvalue_from_python_data<result_type> m_data;
|
||||
PyObject* m_source;
|
||||
};
|
||||
|
||||
|
||||
@@ -132,9 +133,10 @@ struct back_reference_arg_from_python
|
||||
typedef T result_type;
|
||||
|
||||
back_reference_arg_from_python(PyObject*);
|
||||
T operator()(PyObject*);
|
||||
T operator()();
|
||||
private:
|
||||
typedef boost::python::arg_from_python<typename T::type> base;
|
||||
PyObject* m_source;
|
||||
};
|
||||
|
||||
|
||||
@@ -259,9 +261,9 @@ inline bool pointer_cref_arg_from_python<T>::convertible() const
|
||||
return python::detail::void_ptr_to_reference(m_result.bytes, (T(*)())0) != 0;
|
||||
}
|
||||
template <class T>
|
||||
inline T pointer_cref_arg_from_python<T>::operator()(PyObject* p) const
|
||||
inline T pointer_cref_arg_from_python<T>::operator()() const
|
||||
{
|
||||
return (p == Py_None) // None ==> 0
|
||||
return (*(void**)m_result.bytes == Py_None) // None ==> 0
|
||||
? detail::null_ptr_reference((T(*)())0)
|
||||
// Otherwise, return a U*const& to the m_result storage.
|
||||
: python::detail::void_ptr_to_reference(m_result.bytes, (T(*)())0);
|
||||
@@ -277,9 +279,9 @@ inline pointer_arg_from_python<T>::pointer_arg_from_python(PyObject* p)
|
||||
}
|
||||
|
||||
template <class T>
|
||||
inline T pointer_arg_from_python<T>::operator()(PyObject* p) const
|
||||
inline T pointer_arg_from_python<T>::operator()() const
|
||||
{
|
||||
return (p == Py_None) ? 0 : T(result());
|
||||
return (result() == Py_None) ? 0 : T(result());
|
||||
}
|
||||
|
||||
// reference_arg_from_python
|
||||
@@ -291,7 +293,7 @@ inline reference_arg_from_python<T>::reference_arg_from_python(PyObject* p)
|
||||
}
|
||||
|
||||
template <class T>
|
||||
inline T reference_arg_from_python<T>::operator()(PyObject*) const
|
||||
inline T reference_arg_from_python<T>::operator()() const
|
||||
{
|
||||
return python::detail::void_ptr_to_reference(result(), (T(*)())0);
|
||||
}
|
||||
@@ -302,6 +304,7 @@ inline T reference_arg_from_python<T>::operator()(PyObject*) const
|
||||
template <class T>
|
||||
inline arg_rvalue_from_python<T>::arg_rvalue_from_python(PyObject* obj)
|
||||
: m_data(converter::rvalue_from_python_stage1(obj, registered<T>::converters))
|
||||
, m_source(obj)
|
||||
{
|
||||
}
|
||||
|
||||
@@ -313,10 +316,10 @@ inline bool arg_rvalue_from_python<T>::convertible() const
|
||||
|
||||
template <class T>
|
||||
inline typename arg_rvalue_from_python<T>::result_type
|
||||
arg_rvalue_from_python<T>::operator()(PyObject* p)
|
||||
arg_rvalue_from_python<T>::operator()()
|
||||
{
|
||||
if (m_data.stage1.construct != 0)
|
||||
m_data.stage1.construct(p, &m_data.stage1);
|
||||
m_data.stage1.construct(m_source, &m_data.stage1);
|
||||
|
||||
return python::detail::void_ptr_to_reference(m_data.stage1.convertible, (result_type(*)())0);
|
||||
}
|
||||
@@ -325,15 +328,15 @@ arg_rvalue_from_python<T>::operator()(PyObject* p)
|
||||
//
|
||||
template <class T>
|
||||
back_reference_arg_from_python<T>::back_reference_arg_from_python(PyObject* x)
|
||||
: base(x)
|
||||
: base(x), m_source(x)
|
||||
{
|
||||
}
|
||||
|
||||
template <class T>
|
||||
inline T
|
||||
back_reference_arg_from_python<T>::operator()(PyObject* x)
|
||||
back_reference_arg_from_python<T>::operator()()
|
||||
{
|
||||
return T(x, base::operator()(x));
|
||||
return T(m_source, base::operator()());
|
||||
}
|
||||
|
||||
}}} // namespace boost::python::converter
|
||||
|
||||
@@ -5,7 +5,6 @@
|
||||
// to its suitability for any purpose.
|
||||
#ifndef ARG_TO_PYTHON_BASE_DWA200237_HPP
|
||||
# define ARG_TO_PYTHON_BASE_DWA200237_HPP
|
||||
# include <boost/python/detail/wrap_python.hpp>
|
||||
# include <boost/python/handle.hpp>
|
||||
|
||||
namespace boost { namespace python { namespace converter {
|
||||
|
||||
@@ -19,16 +19,13 @@ struct as_to_python_function
|
||||
// the first overload ensures it isn't used in case T is a
|
||||
// reference.
|
||||
template <class U>
|
||||
static int convert_function_must_take_value_or_const_reference(U(*)(T), int, T* = 0);
|
||||
static void convert_function_must_take_value_or_const_reference(U(*)(T), int, T* = 0) {}
|
||||
template <class U>
|
||||
static int convert_function_must_take_value_or_const_reference(U(*)(T const&), long ...);
|
||||
static void convert_function_must_take_value_or_const_reference(U(*)(T const&), long ...) {}
|
||||
|
||||
static PyObject* convert(void const* x)
|
||||
{
|
||||
BOOST_STATIC_ASSERT(
|
||||
sizeof(
|
||||
convert_function_must_take_value_or_const_reference(&ToPython::convert, 1L))
|
||||
== sizeof(int));
|
||||
convert_function_must_take_value_or_const_reference(&ToPython::convert, 1L);
|
||||
|
||||
// Yes, the const_cast below opens a hole in const-correctness,
|
||||
// but it's needed to convert auto_ptr<U> to python.
|
||||
|
||||
@@ -5,9 +5,10 @@
|
||||
// to its suitability for any purpose.
|
||||
#ifndef BUILTIN_CONVERTERS_DWA2002124_HPP
|
||||
# define BUILTIN_CONVERTERS_DWA2002124_HPP
|
||||
# include <boost/python/detail/wrap_python.hpp>
|
||||
# include <boost/python/detail/prefix.hpp>
|
||||
# include <boost/python/detail/none.hpp>
|
||||
# include <boost/python/handle.hpp>
|
||||
# include <boost/implicit_cast.hpp>
|
||||
# include <string>
|
||||
# include <complex>
|
||||
# include <boost/limits.hpp>
|
||||
@@ -82,16 +83,16 @@ namespace detail
|
||||
|
||||
// Specialize converters for signed and unsigned T to Python Int
|
||||
# define BOOST_PYTHON_TO_INT(T) \
|
||||
BOOST_PYTHON_TO_PYTHON_BY_VALUE(signed T, PyInt_FromLong(x)) \
|
||||
BOOST_PYTHON_TO_PYTHON_BY_VALUE(signed T, ::PyInt_FromLong(x)) \
|
||||
BOOST_PYTHON_TO_PYTHON_BY_VALUE( \
|
||||
unsigned T \
|
||||
, static_cast<unsigned long>(x) > static_cast<unsigned long>( \
|
||||
std::numeric_limits<long>::max()) \
|
||||
? PyLong_FromUnsignedLong(x) \
|
||||
: PyInt_FromLong(x))
|
||||
? ::PyLong_FromUnsignedLong(x) \
|
||||
: ::PyInt_FromLong(x))
|
||||
|
||||
// Bool is not signed.
|
||||
BOOST_PYTHON_TO_PYTHON_BY_VALUE(bool, PyInt_FromLong(x))
|
||||
BOOST_PYTHON_TO_PYTHON_BY_VALUE(bool, ::PyInt_FromLong(x))
|
||||
|
||||
// note: handles signed char and unsigned char, but not char (see below)
|
||||
BOOST_PYTHON_TO_INT(char)
|
||||
@@ -103,23 +104,31 @@ BOOST_PYTHON_TO_INT(long)
|
||||
// using Python's macro instead of Boost's - we don't seem to get the
|
||||
// config right all the time.
|
||||
# ifdef HAVE_LONG_LONG
|
||||
BOOST_PYTHON_TO_PYTHON_BY_VALUE(signed LONG_LONG, PyLong_FromLongLong(x))
|
||||
BOOST_PYTHON_TO_PYTHON_BY_VALUE(unsigned LONG_LONG, PyLong_FromUnsignedLongLong(x))
|
||||
BOOST_PYTHON_TO_PYTHON_BY_VALUE(signed BOOST_PYTHON_LONG_LONG, ::PyLong_FromLongLong(x))
|
||||
BOOST_PYTHON_TO_PYTHON_BY_VALUE(unsigned BOOST_PYTHON_LONG_LONG, ::PyLong_FromUnsignedLongLong(x))
|
||||
# endif
|
||||
|
||||
# undef BOOST_TO_PYTHON_INT
|
||||
|
||||
BOOST_PYTHON_TO_PYTHON_BY_VALUE(char, converter::do_return_to_python(x))
|
||||
BOOST_PYTHON_TO_PYTHON_BY_VALUE(char const*, converter::do_return_to_python(x))
|
||||
BOOST_PYTHON_TO_PYTHON_BY_VALUE(std::string, PyString_FromStringAndSize(x.c_str(),x.size()))
|
||||
BOOST_PYTHON_TO_PYTHON_BY_VALUE(float, PyFloat_FromDouble(x))
|
||||
BOOST_PYTHON_TO_PYTHON_BY_VALUE(double, PyFloat_FromDouble(x))
|
||||
BOOST_PYTHON_TO_PYTHON_BY_VALUE(long double, PyFloat_FromDouble(x))
|
||||
BOOST_PYTHON_TO_PYTHON_BY_VALUE(std::string, ::PyString_FromStringAndSize(x.data(),implicit_cast<int>(x.size())))
|
||||
# ifndef BOOST_NO_STD_WSTRING
|
||||
BOOST_PYTHON_TO_PYTHON_BY_VALUE(std::wstring, ::PyUnicode_FromWideChar(x.data(),implicit_cast<int>(x.size())))
|
||||
# endif
|
||||
BOOST_PYTHON_TO_PYTHON_BY_VALUE(float, ::PyFloat_FromDouble(x))
|
||||
BOOST_PYTHON_TO_PYTHON_BY_VALUE(double, ::PyFloat_FromDouble(x))
|
||||
BOOST_PYTHON_TO_PYTHON_BY_VALUE(long double, ::PyFloat_FromDouble(x))
|
||||
BOOST_PYTHON_RETURN_TO_PYTHON_BY_VALUE(PyObject*, converter::do_return_to_python(x))
|
||||
BOOST_PYTHON_TO_PYTHON_BY_VALUE(std::complex<float>, PyComplex_FromDoubles(x.real(), x.imag()))
|
||||
BOOST_PYTHON_TO_PYTHON_BY_VALUE(std::complex<double>, PyComplex_FromDoubles(x.real(), x.imag()))
|
||||
BOOST_PYTHON_TO_PYTHON_BY_VALUE(std::complex<long double>, PyComplex_FromDoubles(x.real(), x.imag()))
|
||||
BOOST_PYTHON_TO_PYTHON_BY_VALUE(std::complex<float>, ::PyComplex_FromDoubles(x.real(), x.imag()))
|
||||
BOOST_PYTHON_TO_PYTHON_BY_VALUE(std::complex<double>, ::PyComplex_FromDoubles(x.real(), x.imag()))
|
||||
BOOST_PYTHON_TO_PYTHON_BY_VALUE(std::complex<long double>, ::PyComplex_FromDoubles(x.real(), x.imag()))
|
||||
|
||||
# undef BOOST_PYTHON_RETURN_TO_PYTHON_BY_VALUE
|
||||
# undef BOOST_PYTHON_ARG_TO_PYTHON_BY_VALUE
|
||||
# undef BOOST_PYTHON_TO_PYTHON_BY_VALUE
|
||||
# undef BOOST_PYTHON_TO_INT
|
||||
|
||||
namespace converter
|
||||
{
|
||||
|
||||
|
||||
18
include/boost/python/converter/context_result_converter.hpp
Executable file
18
include/boost/python/converter/context_result_converter.hpp
Executable file
@@ -0,0 +1,18 @@
|
||||
// Copyright David Abrahams 2003. Permission to copy, use,
|
||||
// modify, sell and distribute this software is granted provided this
|
||||
// copyright notice appears in all copies. This software is provided
|
||||
// "as is" without express or implied warranty, and with no claim as
|
||||
// to its suitability for any purpose.
|
||||
#ifndef CONTEXT_RESULT_CONVERTER_DWA2003917_HPP
|
||||
# define CONTEXT_RESULT_CONVERTER_DWA2003917_HPP
|
||||
|
||||
namespace boost { namespace python { namespace converter {
|
||||
|
||||
// A ResultConverter base class used to indicate that this result
|
||||
// converter should be constructed with the original Python argument
|
||||
// list.
|
||||
struct context_result_converter {};
|
||||
|
||||
}}} // namespace boost::python::converter
|
||||
|
||||
#endif // CONTEXT_RESULT_CONVERTER_DWA2003917_HPP
|
||||
@@ -6,8 +6,7 @@
|
||||
#ifndef FIND_FROM_PYTHON_DWA2002223_HPP
|
||||
# define FIND_FROM_PYTHON_DWA2002223_HPP
|
||||
|
||||
# include <boost/python/detail/config.hpp>
|
||||
# include <boost/python/detail/wrap_python.hpp>
|
||||
# include <boost/python/detail/prefix.hpp>
|
||||
# include <boost/python/converter/rvalue_from_python_data.hpp>
|
||||
|
||||
namespace boost { namespace python { namespace converter {
|
||||
|
||||
@@ -6,7 +6,7 @@
|
||||
#ifndef OBJ_MGR_ARG_FROM_PYTHON_DWA2002628_HPP
|
||||
# define OBJ_MGR_ARG_FROM_PYTHON_DWA2002628_HPP
|
||||
|
||||
# include <boost/python/detail/wrap_python.hpp>
|
||||
# include <boost/python/detail/prefix.hpp>
|
||||
# include <boost/python/detail/referent_storage.hpp>
|
||||
# include <boost/python/detail/destroy.hpp>
|
||||
# include <boost/python/detail/construct.hpp>
|
||||
@@ -27,7 +27,7 @@ struct object_manager_value_arg_from_python
|
||||
|
||||
object_manager_value_arg_from_python(PyObject*);
|
||||
bool convertible() const;
|
||||
T operator()(PyObject*) const;
|
||||
T operator()() const;
|
||||
private:
|
||||
PyObject* m_source;
|
||||
};
|
||||
@@ -48,7 +48,7 @@ struct object_manager_ref_arg_from_python
|
||||
|
||||
object_manager_ref_arg_from_python(PyObject*);
|
||||
bool convertible() const;
|
||||
Ref operator()(PyObject*) const;
|
||||
Ref operator()() const;
|
||||
~object_manager_ref_arg_from_python();
|
||||
private:
|
||||
typename python::detail::referent_storage<Ref>::type m_result;
|
||||
@@ -71,9 +71,9 @@ inline bool object_manager_value_arg_from_python<T>::convertible() const
|
||||
}
|
||||
|
||||
template <class T>
|
||||
inline T object_manager_value_arg_from_python<T>::operator()(PyObject* x) const
|
||||
inline T object_manager_value_arg_from_python<T>::operator()() const
|
||||
{
|
||||
return T(python::detail::borrowed_reference(x));
|
||||
return T(python::detail::borrowed_reference(m_source));
|
||||
}
|
||||
|
||||
template <class Ref>
|
||||
@@ -111,7 +111,7 @@ inline bool object_manager_ref_arg_from_python<Ref>::convertible() const
|
||||
}
|
||||
|
||||
template <class Ref>
|
||||
inline Ref object_manager_ref_arg_from_python<Ref>::operator()(PyObject*) const
|
||||
inline Ref object_manager_ref_arg_from_python<Ref>::operator()() const
|
||||
{
|
||||
return python::detail::void_ptr_to_reference(
|
||||
this->m_result.bytes, (Ref(*)())0);
|
||||
|
||||
@@ -6,7 +6,7 @@
|
||||
#ifndef PYOBJECT_TRAITS_DWA2002720_HPP
|
||||
# define PYOBJECT_TRAITS_DWA2002720_HPP
|
||||
|
||||
# include <boost/python/detail/wrap_python.hpp>
|
||||
# include <boost/python/detail/prefix.hpp>
|
||||
# include <boost/python/converter/pyobject_type.hpp>
|
||||
|
||||
namespace boost { namespace python { namespace converter {
|
||||
|
||||
@@ -6,8 +6,6 @@
|
||||
#ifndef PYOBJECT_TYPE_DWA2002720_HPP
|
||||
# define PYOBJECT_TYPE_DWA2002720_HPP
|
||||
|
||||
# include <boost/python/detail/config.hpp>
|
||||
# include <boost/python/detail/wrap_python.hpp>
|
||||
# include <boost/python/cast.hpp>
|
||||
|
||||
namespace boost { namespace python { namespace converter {
|
||||
|
||||
@@ -1,99 +0,0 @@
|
||||
// Copyright David Abrahams 2002. Permission to copy, use,
|
||||
// modify, sell and distribute this software is granted provided this
|
||||
// copyright notice appears in all copies. This software is provided
|
||||
// "as is" without express or implied warranty, and with no claim as
|
||||
// to its suitability for any purpose.
|
||||
#ifndef PYTYPE_ARG_FROM_PYTHON_DWA2002628_HPP
|
||||
# define PYTYPE_ARG_FROM_PYTHON_DWA2002628_HPP
|
||||
|
||||
# include <boost/python/detail/wrap_python.hpp>
|
||||
|
||||
//
|
||||
// arg_from_python converters for Python type wrappers, to be used as
|
||||
// base classes for specializations.
|
||||
//
|
||||
namespace boost { namespace python { namespace converter {
|
||||
|
||||
template <PyTypeObject* python_type>
|
||||
struct pytype_arg_from_python
|
||||
{
|
||||
pytype_arg_from_python(PyObject*);
|
||||
bool convertible() const;
|
||||
private:
|
||||
PyObject* m_src;
|
||||
};
|
||||
|
||||
// rvalue converter base
|
||||
template <class Wrapper, PyTypeObject* python_type>
|
||||
struct pytype_wrapper_value_arg_from_python
|
||||
: pytype_arg_from_python<python_type>
|
||||
{
|
||||
typedef Wrapper result_type;
|
||||
|
||||
pytype_wrapper_value_arg_from_python(PyObject*);
|
||||
Wrapper operator()(PyObject*) const;
|
||||
};
|
||||
|
||||
// Special case for Wrapper& - must store an lvalue internally. This
|
||||
// OK because the entire state of the object is actually in the Python
|
||||
// object.
|
||||
template <class Wrapper, PyTypeObject* python_type>
|
||||
struct pytype_wrapper_ref_arg_from_python
|
||||
: pytype_arg_from_python<python_type>
|
||||
{
|
||||
typedef Wrapper& result_type;
|
||||
|
||||
pytype_wrapper_ref_arg_from_python(PyObject*);
|
||||
Wrapper& operator()(PyObject*) const;
|
||||
private:
|
||||
mutable Wrapper m_result;
|
||||
};
|
||||
|
||||
//
|
||||
// implementations
|
||||
//
|
||||
|
||||
template <PyTypeObject* python_type>
|
||||
inline pytype_arg_from_python<python_type>::pytype_arg_from_python(PyObject* x)
|
||||
: m_src(x)
|
||||
{
|
||||
}
|
||||
|
||||
template <PyTypeObject* python_type>
|
||||
inline bool pytype_arg_from_python<python_type>::convertible() const
|
||||
{
|
||||
return PyObject_IsInstance(m_src, (PyObject*)python_type);
|
||||
}
|
||||
|
||||
template <class Wrapper, PyTypeObject* python_type>
|
||||
pytype_wrapper_value_arg_from_python<Wrapper,python_type>::pytype_wrapper_value_arg_from_python(
|
||||
PyObject* p)
|
||||
: pytype_arg_from_python<python_type>(p)
|
||||
{
|
||||
}
|
||||
|
||||
template <class Wrapper, PyTypeObject* python_type>
|
||||
Wrapper pytype_wrapper_value_arg_from_python<Wrapper,python_type>::operator()(
|
||||
PyObject* x) const
|
||||
{
|
||||
return Wrapper(python::detail::borrowed_reference(x));
|
||||
}
|
||||
|
||||
template <class Wrapper, PyTypeObject* python_type>
|
||||
pytype_wrapper_ref_arg_from_python<Wrapper,python_type>::pytype_wrapper_ref_arg_from_python(
|
||||
PyObject* p)
|
||||
: pytype_arg_from_python<python_type>(p)
|
||||
, m_result(python::detail::borrowed_reference(p))
|
||||
{
|
||||
}
|
||||
|
||||
template <class Wrapper, PyTypeObject* python_type>
|
||||
Wrapper& pytype_wrapper_ref_arg_from_python<Wrapper,python_type>::operator()(
|
||||
PyObject* x) const
|
||||
{
|
||||
return m_result;
|
||||
}
|
||||
|
||||
}}} // namespace boost::python::converter
|
||||
|
||||
#endif // PYTYPE_ARG_FROM_PYTHON_DWA2002628_HPP
|
||||
@@ -6,9 +6,9 @@
|
||||
#ifndef PYTYPE_OBJECT_MANAGER_TRAITS_DWA2002716_HPP
|
||||
# define PYTYPE_OBJECT_MANAGER_TRAITS_DWA2002716_HPP
|
||||
|
||||
# include <boost/python/detail/prefix.hpp>
|
||||
# include <boost/python/detail/raw_pyobject.hpp>
|
||||
# include <boost/python/cast.hpp>
|
||||
# include <boost/python/detail/wrap_python.hpp>
|
||||
# include <boost/python/converter/pyobject_type.hpp>
|
||||
# include <boost/python/errors.hpp>
|
||||
|
||||
|
||||
@@ -10,6 +10,7 @@
|
||||
# include <boost/python/converter/registrations.hpp>
|
||||
# include <boost/type_traits/transform_traits.hpp>
|
||||
# include <boost/type_traits/cv_traits.hpp>
|
||||
# include <boost/detail/workaround.hpp>
|
||||
|
||||
namespace boost { namespace python { namespace converter {
|
||||
|
||||
@@ -34,10 +35,15 @@ struct registered
|
||||
{
|
||||
};
|
||||
|
||||
# ifndef BOOST_NO_TEMPLATE_PARTIAL_SPECIALIZATION
|
||||
// collapses a few more types to the same static instance
|
||||
# if !defined(BOOST_NO_TEMPLATE_PARTIAL_SPECIALIZATION) \
|
||||
&& !BOOST_WORKAROUND(BOOST_MSVC, BOOST_TESTED_AT(1310))
|
||||
// collapses a few more types to the same static instance. MSVC7.1
|
||||
// fails to strip cv-qualification from array types in typeid. For
|
||||
// some reason we can't use this collapse there or array converters
|
||||
// will not be found.
|
||||
template <class T>
|
||||
struct registered<T&> : registered<T> {};
|
||||
struct registered<T&>
|
||||
: registered<T> {};
|
||||
# endif
|
||||
|
||||
//
|
||||
|
||||
@@ -6,14 +6,14 @@
|
||||
#ifndef REGISTRATIONS_DWA2002223_HPP
|
||||
# define REGISTRATIONS_DWA2002223_HPP
|
||||
|
||||
# include <boost/python/detail/prefix.hpp>
|
||||
|
||||
# include <boost/python/type_id.hpp>
|
||||
|
||||
# include <boost/python/converter/convertible_function.hpp>
|
||||
# include <boost/python/converter/constructor_function.hpp>
|
||||
# include <boost/python/converter/to_python_function_type.hpp>
|
||||
|
||||
# include <boost/python/detail/wrap_python.hpp>
|
||||
|
||||
# include <boost/detail/workaround.hpp>
|
||||
|
||||
namespace boost { namespace python { namespace converter {
|
||||
|
||||
@@ -6,8 +6,6 @@
|
||||
#ifndef REGISTRY_DWA20011127_HPP
|
||||
# define REGISTRY_DWA20011127_HPP
|
||||
# include <boost/python/type_id.hpp>
|
||||
# include <boost/python/detail/config.hpp>
|
||||
# include <boost/python/detail/wrap_python.hpp>
|
||||
# include <boost/python/converter/to_python_function_type.hpp>
|
||||
# include <boost/python/converter/rvalue_from_python_data.hpp>
|
||||
# include <boost/python/converter/constructor_function.hpp>
|
||||
|
||||
@@ -19,14 +19,13 @@ struct shared_ptr_from_python
|
||||
converter::registry::insert(&convertible, &construct, type_id<shared_ptr<T> >());
|
||||
}
|
||||
|
||||
static shared_ptr_from_python const registration;
|
||||
private:
|
||||
static void* convertible(PyObject* p)
|
||||
{
|
||||
return p == Py_None
|
||||
? p
|
||||
: converter::get_lvalue_from_python(p, registered<T>::converters)
|
||||
;
|
||||
if (p == Py_None)
|
||||
return p;
|
||||
|
||||
return converter::get_lvalue_from_python(p, registered<T>::converters);
|
||||
}
|
||||
|
||||
static void construct(PyObject* source, rvalue_from_python_stage1_data* data)
|
||||
@@ -45,9 +44,6 @@ struct shared_ptr_from_python
|
||||
}
|
||||
};
|
||||
|
||||
template <class T>
|
||||
shared_ptr_from_python<T> const shared_ptr_from_python<T>::registration;
|
||||
|
||||
}}} // namespace boost::python::converter
|
||||
|
||||
#endif // SHARED_PTR_FROM_PYTHON_DWA20021130_HPP
|
||||
|
||||
@@ -9,14 +9,17 @@
|
||||
# include <boost/python/refcount.hpp>
|
||||
# include <boost/python/converter/shared_ptr_deleter.hpp>
|
||||
# include <boost/shared_ptr.hpp>
|
||||
# include <boost/get_pointer.hpp>
|
||||
|
||||
namespace boost { namespace python { namespace converter {
|
||||
|
||||
template <class T>
|
||||
PyObject* shared_ptr_to_python(shared_ptr<T> const& x)
|
||||
{
|
||||
if (shared_ptr_deleter* d = boost::get_deleter<shared_ptr_deleter>(x))
|
||||
return incref(d->owner.get());
|
||||
if (!x)
|
||||
return python::detail::none();
|
||||
else if (shared_ptr_deleter* d = boost::get_deleter<shared_ptr_deleter>(x))
|
||||
return incref( get_pointer( d->owner ) );
|
||||
else
|
||||
return converter::registered<shared_ptr<T> const&>::converters.to_python(&x);
|
||||
}
|
||||
|
||||
@@ -5,7 +5,7 @@
|
||||
// to its suitability for any purpose.
|
||||
#ifndef TO_PYTHON_FUNCTION_TYPE_DWA200236_HPP
|
||||
# define TO_PYTHON_FUNCTION_TYPE_DWA200236_HPP
|
||||
# include <boost/python/detail/wrap_python.hpp>
|
||||
# include <boost/python/detail/prefix.hpp>
|
||||
# include <boost/static_assert.hpp>
|
||||
|
||||
namespace boost { namespace python { namespace converter {
|
||||
|
||||
@@ -5,6 +5,8 @@
|
||||
// to its suitability for any purpose.
|
||||
#ifndef COPY_CONST_REFERENCE_DWA2002131_HPP
|
||||
# define COPY_CONST_REFERENCE_DWA2002131_HPP
|
||||
|
||||
# include <boost/python/detail/prefix.hpp>
|
||||
# include <boost/python/detail/indirect_traits.hpp>
|
||||
# include <boost/mpl/if.hpp>
|
||||
# include <boost/python/to_python_value.hpp>
|
||||
|
||||
@@ -5,6 +5,8 @@
|
||||
// to its suitability for any purpose.
|
||||
#ifndef COPY_NON_CONST_REFERENCE_DWA2002131_HPP
|
||||
# define COPY_NON_CONST_REFERENCE_DWA2002131_HPP
|
||||
|
||||
# include <boost/python/detail/prefix.hpp>
|
||||
# include <boost/python/detail/indirect_traits.hpp>
|
||||
# include <boost/mpl/if.hpp>
|
||||
# include <boost/python/to_python_value.hpp>
|
||||
|
||||
@@ -6,139 +6,319 @@
|
||||
#ifndef DATA_MEMBERS_DWA2002328_HPP
|
||||
# define DATA_MEMBERS_DWA2002328_HPP
|
||||
|
||||
# include <boost/python/detail/prefix.hpp>
|
||||
|
||||
# include <boost/python/handle.hpp>
|
||||
|
||||
# include <boost/python/return_value_policy.hpp>
|
||||
# include <boost/python/return_by_value.hpp>
|
||||
# include <boost/python/return_internal_reference.hpp>
|
||||
# include <boost/python/arg_from_python.hpp>
|
||||
|
||||
# include <boost/python/object/function_object.hpp>
|
||||
# include <boost/python/make_function.hpp>
|
||||
|
||||
# include <boost/python/converter/builtin_converters.hpp>
|
||||
|
||||
# include <boost/python/detail/indirect_traits.hpp>
|
||||
# include <boost/python/detail/config.hpp>
|
||||
# include <boost/python/detail/wrap_python.hpp>
|
||||
# include <boost/python/detail/not_specified.hpp>
|
||||
|
||||
# include <boost/type_traits/transform_traits.hpp>
|
||||
# include <boost/type_traits/add_const.hpp>
|
||||
# include <boost/type_traits/add_reference.hpp>
|
||||
# include <boost/type_traits/is_member_pointer.hpp>
|
||||
|
||||
# if BOOST_WORKAROUND(__MWERKS__, BOOST_TESTED_AT(0x3003))
|
||||
# include <boost/type_traits/remove_cv.hpp>
|
||||
# endif
|
||||
|
||||
# include <boost/mpl/apply_if.hpp>
|
||||
# include <boost/mpl/if.hpp>
|
||||
# include <boost/mpl/vector/vector10.hpp>
|
||||
|
||||
# include <boost/bind.hpp>
|
||||
# include <boost/detail/workaround.hpp>
|
||||
|
||||
namespace boost { namespace python {
|
||||
|
||||
//
|
||||
// This file defines the make_getter and make_setter function
|
||||
// families, which are responsible for turning pointers, references,
|
||||
// and pointers-to-data-members into callable Python objects which
|
||||
// can be used for attribute access on wrapped classes.
|
||||
//
|
||||
|
||||
namespace detail
|
||||
{
|
||||
template <class Data, class Class, class Policies>
|
||||
|
||||
// A small function object which handles the getting and setting of
|
||||
// data members.
|
||||
template <class Data, class Class>
|
||||
struct member
|
||||
{
|
||||
static PyObject* get(Data Class::*pm, PyObject* args_, PyObject*, Policies const& policies)
|
||||
{
|
||||
arg_from_python<Class*> c0(PyTuple_GET_ITEM(args_, 0));
|
||||
if (!c0.convertible()) return 0;
|
||||
|
||||
// find the result converter
|
||||
typedef typename Policies::result_converter result_converter;
|
||||
typedef typename boost::add_reference<Data>::type source;
|
||||
typename mpl::apply1<result_converter,source>::type cr;
|
||||
|
||||
if (!policies.precall(args_)) return 0;
|
||||
|
||||
PyObject* result = cr( (c0(PyTuple_GET_ITEM(args_, 0)))->*pm );
|
||||
|
||||
return policies.postcall(args_, result);
|
||||
}
|
||||
|
||||
static PyObject* set(Data Class::*pm, PyObject* args_, PyObject*, Policies const& policies)
|
||||
{
|
||||
// check that each of the arguments is convertible
|
||||
arg_from_python<Class&> c0(PyTuple_GET_ITEM(args_, 0));
|
||||
if (!c0.convertible()) return 0;
|
||||
|
||||
typedef typename add_const<Data>::type target1;
|
||||
typedef typename add_reference<target1>::type target;
|
||||
arg_from_python<target> c1(PyTuple_GET_ITEM(args_, 1));
|
||||
private:
|
||||
typedef typename add_const<Data>::type data_const;
|
||||
typedef typename add_reference<data_const>::type data_cref;
|
||||
|
||||
if (!c1.convertible()) return 0;
|
||||
|
||||
if (!policies.precall(args_)) return 0;
|
||||
|
||||
(c0(PyTuple_GET_ITEM(args_, 0))).*pm = c1(PyTuple_GET_ITEM(args_, 1));
|
||||
|
||||
return policies.postcall(args_, detail::none());
|
||||
public:
|
||||
member(Data Class::*which) : m_which(which) {}
|
||||
|
||||
Data& operator()(Class& c) const
|
||||
{
|
||||
return c.*m_which;
|
||||
}
|
||||
|
||||
void operator()(Class& c, data_cref d) const
|
||||
{
|
||||
c.*m_which = d;
|
||||
}
|
||||
private:
|
||||
Data Class::*m_which;
|
||||
};
|
||||
|
||||
// A small function object which handles the getting and setting of
|
||||
// non-member objects.
|
||||
template <class Data>
|
||||
struct datum
|
||||
{
|
||||
private:
|
||||
typedef typename add_const<Data>::type data_const;
|
||||
typedef typename add_reference<data_const>::type data_cref;
|
||||
|
||||
public:
|
||||
datum(Data *which) : m_which(which) {}
|
||||
|
||||
Data& operator()() const
|
||||
{
|
||||
return *m_which;
|
||||
}
|
||||
|
||||
void operator()(data_cref d) const
|
||||
{
|
||||
*m_which = d;
|
||||
}
|
||||
private:
|
||||
Data *m_which;
|
||||
};
|
||||
|
||||
//
|
||||
// Helper metafunction for determining the default CallPolicy to use
|
||||
// for attribute access. If T is a [reference to a] class type X
|
||||
// whose conversion to python would normally produce a new copy of X
|
||||
// in a wrapped X class instance (as opposed to types such as
|
||||
// std::string, which are converted to native Python types, and
|
||||
// smart pointer types which produce a wrapped class instance of the
|
||||
// pointee type), to-python conversions will attempt to produce an
|
||||
// object which refers to the original C++ object, rather than a
|
||||
// copy. See default_member_getter_policy for rationale.
|
||||
//
|
||||
template <class T>
|
||||
struct default_getter_by_ref
|
||||
: mpl::and_<
|
||||
mpl::bool_<
|
||||
to_python_value<
|
||||
typename add_reference<typename add_const<T>::type>::type
|
||||
>::uses_registry
|
||||
>
|
||||
, is_reference_to_class<
|
||||
typename add_reference<typename add_const<T>::type>::type
|
||||
>
|
||||
>
|
||||
{
|
||||
};
|
||||
|
||||
// Metafunction computing the default CallPolicy to use for reading
|
||||
// data members
|
||||
//
|
||||
// If it's a regular class type (not an object manager or other
|
||||
// type for which we have to_python specializations, use
|
||||
// return_internal_reference so that we can do things like
|
||||
// x.y.z = 1
|
||||
// and get the right result.
|
||||
template <class T>
|
||||
struct default_getter_policy
|
||||
{
|
||||
typedef typename add_reference<
|
||||
typename add_const<T>::type
|
||||
>::type t_cref;
|
||||
|
||||
BOOST_STATIC_CONSTANT(
|
||||
bool, by_ref = to_python_value<t_cref>::uses_registry
|
||||
&& is_reference_to_class<t_cref>::value);
|
||||
|
||||
typedef typename mpl::if_c<
|
||||
by_ref
|
||||
struct default_member_getter_policy
|
||||
: mpl::if_<
|
||||
default_getter_by_ref<T>
|
||||
, return_internal_reference<>
|
||||
, return_value_policy<return_by_value>
|
||||
>::type type;
|
||||
};
|
||||
>
|
||||
{};
|
||||
|
||||
// Metafunction computing the default CallPolicy to use for reading
|
||||
// non-member data.
|
||||
template <class T>
|
||||
struct default_datum_getter_policy
|
||||
: mpl::if_<
|
||||
default_getter_by_ref<T>
|
||||
, return_value_policy<reference_existing_object>
|
||||
, return_value_policy<return_by_value>
|
||||
>
|
||||
{};
|
||||
|
||||
//
|
||||
// make_getter helper function family -- These helpers to
|
||||
// boost::python::make_getter are used to dispatch behavior. The
|
||||
// third argument is a workaround for a CWPro8 partial ordering bug
|
||||
// with pointers to data members. It should be convertible to
|
||||
// mpl::true_ iff the first argument is a pointer-to-member, and
|
||||
// mpl::false_ otherwise. The fourth argument is for compilers
|
||||
// which don't support partial ordering at all and should always be
|
||||
// passed 0L.
|
||||
//
|
||||
|
||||
#if BOOST_WORKAROUND(__EDG_VERSION__, <= 238)
|
||||
template <class D, class P>
|
||||
inline object make_getter(D& d, P& p, mpl::false_, ...);
|
||||
#endif
|
||||
|
||||
// Handle non-member pointers with policies
|
||||
template <class D, class Policies>
|
||||
inline object make_getter(D* d, Policies const& policies, mpl::false_, int)
|
||||
{
|
||||
return python::make_function(
|
||||
detail::datum<D>(d), policies, mpl::vector1<D&>()
|
||||
);
|
||||
}
|
||||
|
||||
// Handle non-member pointers without policies
|
||||
template <class D>
|
||||
inline object make_getter(D* d, not_specified, mpl::false_, long)
|
||||
{
|
||||
typedef typename default_datum_getter_policy<D>::type policies;
|
||||
return detail::make_getter(d, policies(), mpl::false_(), 0);
|
||||
}
|
||||
|
||||
// Handle pointers-to-members with policies
|
||||
template <class C, class D, class Policies>
|
||||
inline object make_getter(D C::*pm, Policies const& policies, mpl::true_, int)
|
||||
{
|
||||
#if BOOST_WORKAROUND(__MWERKS__, BOOST_TESTED_AT(0x3003))
|
||||
typedef typename remove_cv<C>::type Class;
|
||||
#else
|
||||
typedef C Class;
|
||||
#endif
|
||||
return python::make_function(
|
||||
detail::member<D,Class>(pm)
|
||||
, policies
|
||||
, mpl::vector2<D&,Class&>()
|
||||
);
|
||||
}
|
||||
|
||||
// Handle pointers-to-members without policies
|
||||
template <class C, class D>
|
||||
inline object make_getter(D C::*pm, not_specified, mpl::true_, long)
|
||||
{
|
||||
typedef typename default_member_getter_policy<D>::type policies;
|
||||
return detail::make_getter(pm, policies(), mpl::true_(), 0);
|
||||
}
|
||||
|
||||
// Handle references
|
||||
template <class D, class P>
|
||||
inline object make_getter(D& d, P& p, mpl::false_, ...)
|
||||
{
|
||||
// Just dispatch to the handler for pointer types.
|
||||
return detail::make_getter(&d, p, mpl::false_(), 0L);
|
||||
}
|
||||
|
||||
//
|
||||
// make_setter helper function family -- These helpers to
|
||||
// boost::python::make_setter are used to dispatch behavior. The
|
||||
// third argument is for compilers which don't support partial
|
||||
// ordering at all and should always be passed 0.
|
||||
//
|
||||
|
||||
|
||||
// Handle non-member pointers
|
||||
template <class D, class Policies>
|
||||
inline object make_setter(D* p, Policies const& policies, mpl::false_, int)
|
||||
{
|
||||
return python::make_function(
|
||||
detail::datum<D>(p), policies, mpl::vector2<void,D const&>()
|
||||
);
|
||||
}
|
||||
|
||||
// Handle pointers-to-members
|
||||
template <class C, class D, class Policies>
|
||||
inline object make_setter(D C::*pm, Policies const& policies, mpl::true_, int)
|
||||
{
|
||||
return python::make_function(
|
||||
detail::member<D,C>(pm)
|
||||
, policies
|
||||
, mpl::vector3<void, C&, D const&>()
|
||||
);
|
||||
}
|
||||
|
||||
// Handle references
|
||||
template <class D, class Policies>
|
||||
inline object make_setter(D& x, Policies const& policies, mpl::false_, ...)
|
||||
{
|
||||
return detail::make_setter(&x, policies, mpl::false_(), 0L);
|
||||
}
|
||||
}
|
||||
|
||||
template <class C, class D>
|
||||
object make_getter(D C::*pm)
|
||||
//
|
||||
// make_getter function family -- build a callable object which
|
||||
// retrieves data through the first argument and is appropriate for
|
||||
// use as the `get' function in Python properties . The second,
|
||||
// policies argument, is optional. We need both D& and D const&
|
||||
// overloads in order be able to handle rvalues.
|
||||
//
|
||||
template <class D, class Policies>
|
||||
inline object make_getter(D& d, Policies const& policies)
|
||||
{
|
||||
typedef typename detail::default_getter_policy<D>::type policy;
|
||||
|
||||
return objects::function_object(
|
||||
::boost::bind(
|
||||
&detail::member<D,C,policy>::get, pm, _1, _2
|
||||
, policy())
|
||||
, 1);
|
||||
|
||||
return detail::make_getter(d, policies, is_member_pointer<D>(), 0L);
|
||||
}
|
||||
|
||||
template <class C, class D, class Policies>
|
||||
object make_getter(D C::*pm, Policies const& policies)
|
||||
template <class D, class Policies>
|
||||
inline object make_getter(D const& d, Policies const& policies)
|
||||
{
|
||||
return objects::function_object(
|
||||
::boost::bind(
|
||||
&detail::member<D,C,Policies>::get, pm, _1, _2
|
||||
, policies)
|
||||
, 1);
|
||||
return detail::make_getter(d, policies, is_member_pointer<D>(), 0L);
|
||||
}
|
||||
|
||||
template <class C, class D>
|
||||
object make_setter(D C::*pm)
|
||||
template <class D>
|
||||
inline object make_getter(D& x)
|
||||
{
|
||||
return objects::function_object(
|
||||
::boost::bind(
|
||||
&detail::member<D,C,default_call_policies>::set, pm, _1, _2
|
||||
, default_call_policies())
|
||||
, 2);
|
||||
detail::not_specified policy;
|
||||
return detail::make_getter(x, policy, is_member_pointer<D>(), 0L);
|
||||
}
|
||||
|
||||
template <class C, class D, class Policies>
|
||||
object make_setter(D C::*pm, Policies const& policies)
|
||||
# if !BOOST_WORKAROUND(__EDG_VERSION__, <= 238) && !BOOST_WORKAROUND(BOOST_MSVC, <= 1300)
|
||||
template <class D>
|
||||
inline object make_getter(D const& d)
|
||||
{
|
||||
return objects::function_object(
|
||||
::boost::bind(
|
||||
&detail::member<D,C,Policies>::set, pm, _1, _2
|
||||
, policies)
|
||||
, 2);
|
||||
detail::not_specified policy;
|
||||
return detail::make_getter(d, policy, is_member_pointer<D>(), 0L);
|
||||
}
|
||||
# endif
|
||||
|
||||
//
|
||||
// make_setter function family -- build a callable object which
|
||||
// writes data through the first argument and is appropriate for
|
||||
// use as the `set' function in Python properties . The second,
|
||||
// policies argument, is optional. We need both D& and D const&
|
||||
// overloads in order be able to handle rvalues.
|
||||
//
|
||||
template <class D, class Policies>
|
||||
inline object make_setter(D& x, Policies const& policies)
|
||||
{
|
||||
return detail::make_setter(x, policies, is_member_pointer<D>(), 0);
|
||||
}
|
||||
|
||||
|
||||
template <class D, class Policies>
|
||||
inline object make_setter(D const& x, Policies const& policies)
|
||||
{
|
||||
return detail::make_setter(x, policies, is_member_pointer<D>(), 0);
|
||||
}
|
||||
|
||||
template <class D>
|
||||
inline object make_setter(D& x)
|
||||
{
|
||||
return detail::make_setter(x, default_call_policies(), is_member_pointer<D>(), 0);
|
||||
}
|
||||
|
||||
# if !(BOOST_WORKAROUND(BOOST_MSVC, <= 1300) || BOOST_WORKAROUND(__EDG_VERSION__, <= 238))
|
||||
template <class D>
|
||||
inline object make_setter(D const& x)
|
||||
{
|
||||
return detail::make_setter(x, default_call_policies(), is_member_pointer<D>(), 0);
|
||||
}
|
||||
# endif
|
||||
|
||||
}} // namespace boost::python
|
||||
|
||||
#endif // DATA_MEMBERS_DWA2002328_HPP
|
||||
|
||||
@@ -6,6 +6,8 @@
|
||||
#ifndef DEF_DWA200292_HPP
|
||||
# define DEF_DWA200292_HPP
|
||||
|
||||
# include <boost/python/detail/prefix.hpp>
|
||||
|
||||
# include <boost/python/object_fwd.hpp>
|
||||
# include <boost/python/make_function.hpp>
|
||||
# include <boost/python/detail/def_helper.hpp>
|
||||
|
||||
87
include/boost/python/def_visitor.hpp
Executable file
87
include/boost/python/def_visitor.hpp
Executable file
@@ -0,0 +1,87 @@
|
||||
// Copyright David Abrahams 2003. Permission to copy, use,
|
||||
// modify, sell and distribute this software is granted provided this
|
||||
// copyright notice appears in all copies. This software is provided
|
||||
// "as is" without express or implied warranty, and with no claim as
|
||||
// to its suitability for any purpose.
|
||||
#ifndef DEF_VISITOR_DWA2003810_HPP
|
||||
# define DEF_VISITOR_DWA2003810_HPP
|
||||
|
||||
# include <boost/python/detail/prefix.hpp>
|
||||
# include <boost/detail/workaround.hpp>
|
||||
|
||||
namespace boost { namespace python {
|
||||
|
||||
template <class DerivedVisitor> class def_visitor;
|
||||
template <class T, class X1, class X2, class X3> class class_;
|
||||
|
||||
class def_visitor_access
|
||||
{
|
||||
# if defined(BOOST_NO_MEMBER_TEMPLATE_FRIENDS) \
|
||||
|| BOOST_WORKAROUND(__BORLANDC__, BOOST_TESTED_AT(0x551))
|
||||
// Tasteless as this may seem, making all members public allows member templates
|
||||
// to work in the absence of member template friends.
|
||||
public:
|
||||
# else
|
||||
template <class Derived> friend class def_visitor;
|
||||
# endif
|
||||
|
||||
// unnamed visit, c.f. init<...>, container suites
|
||||
template <class V, class classT>
|
||||
static void visit(V const& v, classT& c)
|
||||
{
|
||||
v.derived_visitor().visit(c);
|
||||
}
|
||||
|
||||
// named visit, c.f. object, pure_virtual
|
||||
template <class V, class classT, class OptionalArgs>
|
||||
static void visit(
|
||||
V const& v
|
||||
, classT& c
|
||||
, char const* name
|
||||
, OptionalArgs const& options
|
||||
)
|
||||
{
|
||||
v.derived_visitor().visit(c, name, options);
|
||||
}
|
||||
|
||||
};
|
||||
|
||||
|
||||
template <class DerivedVisitor>
|
||||
class def_visitor
|
||||
{
|
||||
friend class def_visitor_access;
|
||||
|
||||
# if defined(BOOST_NO_MEMBER_TEMPLATE_FRIENDS) \
|
||||
|| BOOST_WORKAROUND(__BORLANDC__, BOOST_TESTED_AT(0x551))
|
||||
// Tasteless as this may seem, making all members public allows member templates
|
||||
// to work in the absence of member template friends.
|
||||
public:
|
||||
# else
|
||||
template <class T, class X1, class X2, class X3> friend class class_;
|
||||
# endif
|
||||
|
||||
// unnamed visit, c.f. init<...>, container suites
|
||||
template <class classT>
|
||||
void visit(classT& c) const
|
||||
{
|
||||
def_visitor_access::visit(*this, c);
|
||||
}
|
||||
|
||||
// named visit, c.f. object, pure_virtual
|
||||
template <class classT, class OptionalArgs>
|
||||
void visit(classT& c, char const* name, OptionalArgs const& options) const
|
||||
{
|
||||
def_visitor_access::visit(*this, c, name, options);
|
||||
}
|
||||
|
||||
protected:
|
||||
DerivedVisitor const& derived_visitor() const
|
||||
{
|
||||
return static_cast<DerivedVisitor const&>(*this);
|
||||
}
|
||||
};
|
||||
|
||||
}} // namespace boost::python
|
||||
|
||||
#endif // DEF_VISITOR_DWA2003810_HPP
|
||||
@@ -5,7 +5,8 @@
|
||||
// to its suitability for any purpose.
|
||||
#ifndef DEFAULT_CALL_POLICIES_DWA2002131_HPP
|
||||
# define DEFAULT_CALL_POLICIES_DWA2002131_HPP
|
||||
# include <boost/python/detail/wrap_python.hpp>
|
||||
|
||||
# include <boost/python/detail/prefix.hpp>
|
||||
# include <boost/mpl/if.hpp>
|
||||
# include <boost/python/to_python_value.hpp>
|
||||
# include <boost/type_traits/transform_traits.hpp>
|
||||
@@ -28,19 +29,23 @@ struct default_result_converter;
|
||||
|
||||
struct default_call_policies
|
||||
{
|
||||
// Nothing to do
|
||||
static bool precall(PyObject*)
|
||||
// Ownership of this argument tuple will ultimately be adopted by
|
||||
// the caller.
|
||||
template <class ArgumentPackage>
|
||||
static bool precall(ArgumentPackage const&)
|
||||
{
|
||||
return true;
|
||||
}
|
||||
|
||||
// Pass the result through
|
||||
static PyObject* postcall(PyObject*, PyObject* result)
|
||||
template <class ArgumentPackage>
|
||||
static PyObject* postcall(ArgumentPackage const&, PyObject* result)
|
||||
{
|
||||
return result;
|
||||
}
|
||||
|
||||
typedef default_result_converter result_converter;
|
||||
typedef PyObject* argument_package;
|
||||
};
|
||||
|
||||
struct default_result_converter
|
||||
|
||||
@@ -6,7 +6,7 @@
|
||||
#ifndef AIX_INIT_MODULE_DWA2002529_HPP
|
||||
# define AIX_INIT_MODULE_DWA2002529_HPP
|
||||
# ifdef _AIX
|
||||
# include <boost/python/detail/wrap_python.hpp>
|
||||
# include <boost/python/detail/prefix.hpp>
|
||||
# include <cstdio>
|
||||
# ifdef __KCC
|
||||
# include <iostream> // this works around a problem in KCC 4.0f
|
||||
|
||||
@@ -9,63 +9,99 @@
|
||||
# ifndef CALLER_DWA20021121_HPP
|
||||
# define CALLER_DWA20021121_HPP
|
||||
|
||||
# include <boost/compressed_pair.hpp>
|
||||
|
||||
# include <boost/mpl/apply.hpp>
|
||||
# include <boost/mpl/if.hpp>
|
||||
# include <boost/mpl/size.hpp>
|
||||
# include <boost/type_traits/is_same.hpp>
|
||||
# include <boost/python/type_id.hpp>
|
||||
# include <boost/python/handle.hpp>
|
||||
|
||||
# include <boost/python/detail/invoke.hpp>
|
||||
# include <boost/python/detail/signature.hpp>
|
||||
# include <boost/python/detail/preprocessor.hpp>
|
||||
|
||||
# include <boost/python/arg_from_python.hpp>
|
||||
# include <boost/python/converter/context_result_converter.hpp>
|
||||
|
||||
# include <boost/preprocessor/iterate.hpp>
|
||||
# include <boost/preprocessor/iteration/local.hpp>
|
||||
# include <boost/preprocessor/repetition/enum_trailing_params.hpp>
|
||||
# include <boost/preprocessor/repetition/repeat.hpp>
|
||||
# include <boost/preprocessor/cat.hpp>
|
||||
# include <boost/preprocessor/dec.hpp>
|
||||
# include <boost/preprocessor/if.hpp>
|
||||
# include <boost/preprocessor/iteration/local.hpp>
|
||||
# include <boost/preprocessor/repetition/enum_trailing_params.hpp>
|
||||
# include <boost/preprocessor/repetition/repeat.hpp>
|
||||
|
||||
# include <boost/python/detail/invoke.hpp>
|
||||
# include <boost/compressed_pair.hpp>
|
||||
|
||||
# include <boost/type_traits/is_same.hpp>
|
||||
# include <boost/type_traits/is_convertible.hpp>
|
||||
|
||||
# include <boost/mpl/apply.hpp>
|
||||
# include <boost/mpl/apply_if.hpp>
|
||||
# include <boost/mpl/identity.hpp>
|
||||
# include <boost/mpl/size.hpp>
|
||||
# include <boost/mpl/at.hpp>
|
||||
# include <boost/mpl/int.hpp>
|
||||
|
||||
namespace boost { namespace python { namespace detail {
|
||||
|
||||
template <int N>
|
||||
inline PyObject* get(mpl::int_<N>, PyObject* const& args_)
|
||||
{
|
||||
return PyTuple_GET_ITEM(args_,N);
|
||||
}
|
||||
|
||||
inline unsigned arity(PyObject* const& args_)
|
||||
{
|
||||
return PyTuple_GET_SIZE(args_);
|
||||
}
|
||||
|
||||
// This "result converter" is really just used as
|
||||
// a dispatch tag to invoke(...), selecting the appropriate
|
||||
// implementation
|
||||
typedef int void_result_to_python;
|
||||
|
||||
// A metafunction taking an iterator FunctionIter to a metafunction
|
||||
// class and an iterator ArgIter to an argument, which applies the
|
||||
// result of dereferencing FunctionIter to the result of dereferencing
|
||||
// ArgIter
|
||||
template <class FunctionIter, class ArgIter>
|
||||
struct apply_iter1
|
||||
: mpl::apply1<typename FunctionIter::type, typename ArgIter::type> {};
|
||||
|
||||
// Given a model of CallPolicies and a C++ result type, this
|
||||
// metafunction selects the appropriate converter to use for
|
||||
// converting the result to python.
|
||||
template <class Policies, class Result>
|
||||
struct select_result_converter
|
||||
: mpl::if_<
|
||||
: mpl::apply_if<
|
||||
is_same<Result,void>
|
||||
, void_result_to_python
|
||||
, typename mpl::apply1<typename Policies::result_converter,Result>::type*
|
||||
, mpl::identity<void_result_to_python>
|
||||
, mpl::apply1<typename Policies::result_converter,Result>
|
||||
>
|
||||
{
|
||||
};
|
||||
|
||||
|
||||
template <class ArgPackage, class ResultConverter>
|
||||
inline ResultConverter create_result_converter(
|
||||
ArgPackage const& args_
|
||||
, ResultConverter*
|
||||
, converter::context_result_converter*
|
||||
)
|
||||
{
|
||||
return ResultConverter(args_);
|
||||
}
|
||||
|
||||
template <class ArgPackage, class ResultConverter>
|
||||
inline ResultConverter create_result_converter(
|
||||
ArgPackage const& args_
|
||||
, ResultConverter*
|
||||
, ...
|
||||
)
|
||||
{
|
||||
return ResultConverter();
|
||||
}
|
||||
|
||||
template <unsigned> struct caller_arity;
|
||||
|
||||
template <class F, class CallPolicies, class Sig>
|
||||
struct caller;
|
||||
|
||||
# define BOOST_PYTHON_NEXT(init,name,n) \
|
||||
typedef BOOST_PP_IF(n,typename BOOST_PP_CAT(name,BOOST_PP_DEC(n)) ::next, init) name##n;
|
||||
|
||||
# define BOOST_PYTHON_ARG_CONVERTER(n) \
|
||||
BOOST_PYTHON_NEXT(typename first::next, arg_iter,n) \
|
||||
BOOST_PYTHON_NEXT(ConverterGenerators, conv_iter,n) \
|
||||
typedef typename apply_iter1<conv_iter##n,arg_iter##n>::type c_t##n; \
|
||||
c_t##n c##n(PyTuple_GET_ITEM(args_, n)); \
|
||||
BOOST_PYTHON_NEXT(typename first::next, arg_iter,n) \
|
||||
typedef arg_from_python<BOOST_DEDUCED_TYPENAME arg_iter##n::type> c_t##n; \
|
||||
c_t##n c##n(get(mpl::int_<n>(), inner_args)); \
|
||||
if (!c##n.convertible()) \
|
||||
return 0;
|
||||
|
||||
@@ -78,11 +114,11 @@ template <unsigned> struct caller_arity;
|
||||
|
||||
// A metafunction returning the base class used for caller<class F,
|
||||
// class ConverterGenerators, class CallPolicies, class Sig>.
|
||||
template <class F, class ConverterGenerators, class CallPolicies, class Sig>
|
||||
template <class F, class CallPolicies, class Sig>
|
||||
struct caller_base_select
|
||||
{
|
||||
enum { arity = mpl::size<Sig>::value - 1 };
|
||||
typedef typename caller_arity<arity>::template impl<F,ConverterGenerators,CallPolicies,Sig> type;
|
||||
typedef typename caller_arity<arity>::template impl<F,CallPolicies,Sig> type;
|
||||
};
|
||||
|
||||
// A function object type which wraps C++ objects as Python callable
|
||||
@@ -95,11 +131,6 @@ struct caller_base_select
|
||||
// actually be any data for which an appropriate invoke_tag() can
|
||||
// be generated. invoke(...) takes care of the actual invocation syntax.
|
||||
//
|
||||
// ConverterGenerators -
|
||||
// An MPL iterator type over a sequence of metafunction classes
|
||||
// that can be applied to element 1...N of Sig to produce
|
||||
// argument from_python converters for the arguments
|
||||
//
|
||||
// CallPolicies -
|
||||
// The precall, postcall, and what kind of resultconverter to
|
||||
// generate for mpl::front<Sig>::type
|
||||
@@ -108,19 +139,19 @@ struct caller_base_select
|
||||
// The `intended signature' of the function. An MPL sequence
|
||||
// beginning with a result type and continuing with a list of
|
||||
// argument types.
|
||||
template <class F, class ConverterGenerators, class CallPolicies, class Sig>
|
||||
template <class F, class CallPolicies, class Sig>
|
||||
struct caller
|
||||
: caller_base_select<F,ConverterGenerators,CallPolicies,Sig>::type
|
||||
: caller_base_select<F,CallPolicies,Sig>::type
|
||||
{
|
||||
typedef typename caller_base_select<
|
||||
F,ConverterGenerators,CallPolicies,Sig
|
||||
F,CallPolicies,Sig
|
||||
>::type base;
|
||||
|
||||
typedef PyObject* result_type;
|
||||
|
||||
caller(F f, CallPolicies p) : base(f,p) {}
|
||||
};
|
||||
|
||||
};
|
||||
|
||||
}}} // namespace boost::python::detail
|
||||
|
||||
@@ -133,7 +164,7 @@ struct caller
|
||||
template <>
|
||||
struct caller_arity<N>
|
||||
{
|
||||
template <class F, class ConverterGenerators, class Policies, class Sig>
|
||||
template <class F, class Policies, class Sig>
|
||||
struct impl
|
||||
{
|
||||
impl(F f, Policies p) : m_data(f,p) {}
|
||||
@@ -146,6 +177,10 @@ struct caller_arity<N>
|
||||
typedef typename mpl::begin<Sig>::type first;
|
||||
typedef typename first::type result_t;
|
||||
typedef typename select_result_converter<Policies, result_t>::type result_converter;
|
||||
typedef typename Policies::argument_package argument_package;
|
||||
|
||||
argument_package inner_args(args_);
|
||||
|
||||
# if N
|
||||
# define BOOST_PP_LOCAL_MACRO(i) BOOST_PYTHON_ARG_CONVERTER(i)
|
||||
# define BOOST_PP_LOCAL_LIMITS (0, N-1)
|
||||
@@ -153,16 +188,26 @@ struct caller_arity<N>
|
||||
# endif
|
||||
// all converters have been checked. Now we can do the
|
||||
// precall part of the policy
|
||||
if (!m_data.second().precall(args_))
|
||||
if (!m_data.second().precall(inner_args))
|
||||
return 0;
|
||||
|
||||
typedef typename detail::invoke_tag<F>::type tag;
|
||||
|
||||
PyObject* result = detail::invoke(
|
||||
tag(), result_converter(), m_data.first() BOOST_PP_ENUM_TRAILING_PARAMS(N, c));
|
||||
detail::invoke_tag<result_t,F>()
|
||||
, create_result_converter(args_, (result_converter*)0, (result_converter*)0)
|
||||
, m_data.first()
|
||||
BOOST_PP_ENUM_TRAILING_PARAMS(N, c)
|
||||
);
|
||||
|
||||
return m_data.second().postcall(args_, result);
|
||||
return m_data.second().postcall(inner_args, result);
|
||||
}
|
||||
|
||||
static unsigned min_arity() { return N; }
|
||||
|
||||
static signature_element const* signature()
|
||||
{
|
||||
return detail::signature<Sig>::elements();
|
||||
}
|
||||
|
||||
private:
|
||||
compressed_pair<F,Policies> m_data;
|
||||
};
|
||||
|
||||
@@ -71,7 +71,7 @@
|
||||
# define BOOST_PYTHON_NO_TEMPLATE_EXPORT
|
||||
#endif
|
||||
|
||||
#if defined(BOOST_PYTHON_DYNAMIC_LIB) && defined(_WIN32)
|
||||
#if defined(BOOST_PYTHON_DYNAMIC_LIB) && (defined(_WIN32) || defined(__CYGWIN__))
|
||||
# if defined(BOOST_PYTHON_SOURCE)
|
||||
# define BOOST_PYTHON_DECL __declspec(dllexport)
|
||||
# define BOOST_PYTHON_BUILD_DLL
|
||||
|
||||
@@ -24,9 +24,12 @@ typedef cv_tag<true,true> const_volatile_;
|
||||
template <class T>
|
||||
struct cv_category
|
||||
{
|
||||
BOOST_STATIC_CONSTANT(bool, c = is_const<T>::value);
|
||||
BOOST_STATIC_CONSTANT(bool, v = is_volatile<T>::value);
|
||||
typedef cv_tag<c,v> type;
|
||||
// BOOST_STATIC_CONSTANT(bool, c = is_const<T>::value);
|
||||
// BOOST_STATIC_CONSTANT(bool, v = is_volatile<T>::value);
|
||||
typedef cv_tag<
|
||||
::boost::is_const<T>::value
|
||||
, ::boost::is_volatile<T>::value
|
||||
> type;
|
||||
};
|
||||
|
||||
}}} // namespace boost::python::detail
|
||||
|
||||
18
include/boost/python/detail/dealloc.hpp
Normal file
18
include/boost/python/detail/dealloc.hpp
Normal file
@@ -0,0 +1,18 @@
|
||||
// Copyright Gottfried Ganßauge 2003. Permission to copy, use,
|
||||
// modify, sell and distribute this software is granted provided this
|
||||
// copyright notice appears in all copies. This software is provided
|
||||
// "as is" without express or implied warranty, and with no claim as
|
||||
// to its suitability for any purpose.
|
||||
|
||||
# ifndef BOOST_PYTHON_DETAIL_DEALLOC_HPP_
|
||||
# define BOOST_PYTHON_DETAIL_DEALLOC_HPP_
|
||||
namespace boost { namespace python { namespace detail {
|
||||
extern "C"
|
||||
{
|
||||
inline void dealloc(PyObject* self)
|
||||
{
|
||||
PyObject_Del(self);
|
||||
}
|
||||
}
|
||||
}}} // namespace boost::python::detail
|
||||
# endif // BOOST_PYTHON_DETAIL_DEALLOC_HPP_
|
||||
@@ -18,6 +18,7 @@
|
||||
# include <boost/mpl/apply.hpp>
|
||||
# include <boost/tuple/tuple.hpp>
|
||||
# include <boost/python/detail/not_specified.hpp>
|
||||
# include <boost/python/detail/def_helper_fwd.hpp>
|
||||
|
||||
namespace boost { namespace python {
|
||||
|
||||
@@ -143,7 +144,7 @@ namespace detail
|
||||
// are expected to be the types of the actual (optional) arguments
|
||||
// passed to def().
|
||||
//
|
||||
template <class T1, class T2 = not_specified, class T3 = not_specified, class T4 = not_specified>
|
||||
template <class T1, class T2, class T3, class T4>
|
||||
struct def_helper
|
||||
{
|
||||
// A tuple type which begins with references to the supplied
|
||||
|
||||
18
include/boost/python/detail/def_helper_fwd.hpp
Executable file
18
include/boost/python/detail/def_helper_fwd.hpp
Executable file
@@ -0,0 +1,18 @@
|
||||
// Copyright David Abrahams 2003. Permission to copy, use,
|
||||
// modify, sell and distribute this software is granted provided this
|
||||
// copyright notice appears in all copies. This software is provided
|
||||
// "as is" without express or implied warranty, and with no claim as
|
||||
// to its suitability for any purpose.
|
||||
#ifndef DEF_HELPER_FWD_DWA2003810_HPP
|
||||
# define DEF_HELPER_FWD_DWA2003810_HPP
|
||||
|
||||
# include <boost/python/detail/not_specified.hpp>
|
||||
|
||||
namespace boost { namespace python { namespace detail {
|
||||
|
||||
template <class T1, class T2 = not_specified, class T3 = not_specified, class T4 = not_specified>
|
||||
struct def_helper;
|
||||
|
||||
}}} // namespace boost::python::detail
|
||||
|
||||
#endif // DEF_HELPER_FWD_DWA2003810_HPP
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user