Compare commits
432 Commits
boost-0.9.
...
svn-branch
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
eceab34284 | ||
|
|
5f505d6ba8 | ||
|
|
dd30e8c45c | ||
|
|
c39836ddc8 | ||
|
|
fb35a82bf1 | ||
|
|
44c5c18f45 | ||
|
|
e0cceeb88c | ||
|
|
4a5f6f2e24 | ||
|
|
8b1748fea0 | ||
|
|
82919f0d5c | ||
|
|
1f6ded7b4e | ||
|
|
a0d2873156 | ||
|
|
0519d54229 | ||
|
|
c181874335 | ||
|
|
203a42c35f | ||
|
|
8eba0eb25b | ||
|
|
152e76220a | ||
|
|
8897cc9ce6 | ||
|
|
335cd02c2d | ||
|
|
758d92b33e | ||
|
|
28eef45d28 | ||
|
|
d8790a34d3 | ||
|
|
3b058185c6 | ||
|
|
2261e7eedc | ||
|
|
19a196493f | ||
|
|
d10b5e8d1a | ||
|
|
1cacefc226 | ||
|
|
efcd2833f1 | ||
|
|
2f9323d9e9 | ||
|
|
8b2f4b4ce0 | ||
|
|
ab046dc634 | ||
|
|
ef3f9b15f0 | ||
|
|
68463e2fd2 | ||
|
|
f75eca94e0 | ||
|
|
a23030b83e | ||
|
|
321cf2502a | ||
|
|
4996f912b4 | ||
|
|
09e24cb17d | ||
|
|
ac32d13e10 | ||
|
|
b0496d1207 | ||
|
|
a076239fc8 | ||
|
|
7cf0f9090f | ||
|
|
479f068673 | ||
|
|
9b326f15fa | ||
|
|
f094a5b9eb | ||
|
|
4367850e5d | ||
|
|
f44a4d6468 | ||
|
|
5206dd55d2 | ||
|
|
988bf849a1 | ||
|
|
6fee43fc6f | ||
|
|
6ec4387ea1 | ||
|
|
e2f59ef548 | ||
|
|
92a6fafd20 | ||
|
|
4721f5f9af | ||
|
|
3864838da2 | ||
|
|
8e77df69d5 | ||
|
|
12770b03e8 | ||
|
|
c8a692b4b4 | ||
|
|
2571ebb0c2 | ||
|
|
283dbfb593 | ||
|
|
83f227034f | ||
|
|
c5f514a4e6 | ||
|
|
9fb15f631e | ||
|
|
3d8f4c90ba | ||
|
|
5597dcb321 | ||
|
|
ab2912e3c2 | ||
|
|
b705931ff0 | ||
|
|
2974286209 | ||
|
|
1cec514b39 | ||
|
|
8ecd49cbf0 | ||
|
|
67a7669ff4 | ||
|
|
e80545a7d3 | ||
|
|
6afe0d4732 | ||
|
|
f8280b0e1a | ||
|
|
aa20ce7d2c | ||
|
|
6074a23242 | ||
|
|
9ceac3ff8f | ||
|
|
126a3efb92 | ||
|
|
9205f507b0 | ||
|
|
bff975f08c | ||
|
|
262bcee750 | ||
|
|
a3f12b18b1 | ||
|
|
ad635ec2d1 | ||
|
|
affd36e857 | ||
|
|
332a45f333 | ||
|
|
6cc48f7e5d | ||
|
|
5b6192d738 | ||
|
|
980733a96d | ||
|
|
331209d8b5 | ||
|
|
9116cf382b | ||
|
|
8cc2b7a5df | ||
|
|
dab01ad668 | ||
|
|
1fca114f6a | ||
|
|
70ee460a14 | ||
|
|
07c95aea4e | ||
|
|
a3d8a384fa | ||
|
|
432d4782a5 | ||
|
|
424f5bdf31 | ||
|
|
13b16f9729 | ||
|
|
82563df3bf | ||
|
|
adb7b62a62 | ||
|
|
02c0b2b486 | ||
|
|
c876db8cae | ||
|
|
3ce88daa8b | ||
|
|
4cec6c4f2f | ||
|
|
e38bf06257 | ||
|
|
0deed1ff9b | ||
|
|
a05a0ae46b | ||
|
|
fe3906a7cb | ||
|
|
e5ed3a1c6c | ||
|
|
2bbff71109 | ||
|
|
c492551111 | ||
|
|
b217c4ffa8 | ||
|
|
96e9d6a872 | ||
|
|
fef288fed2 | ||
|
|
2fdb98079d | ||
|
|
bbabf21abf | ||
|
|
6d24977dd2 | ||
|
|
c2b5925600 | ||
|
|
91e76a296f | ||
|
|
e4eee902d4 | ||
|
|
db71f17dba | ||
|
|
b754037949 | ||
|
|
7bd76d869b | ||
|
|
c25967a094 | ||
|
|
bcb6370b0e | ||
|
|
17faf4504c | ||
|
|
53c335f106 | ||
|
|
cd8951439e | ||
|
|
0e5e2dc92e | ||
|
|
4d50bf0ad9 | ||
|
|
1cfa79554d | ||
|
|
567e620565 | ||
|
|
5933fdbf39 | ||
|
|
4c21a29a9f | ||
|
|
7c21f3b48d | ||
|
|
6f4167700c | ||
|
|
efae35bbd8 | ||
|
|
8dbd926d9e | ||
|
|
c6e658cfca | ||
|
|
b77dcf4bea | ||
|
|
1e3cfbca03 | ||
|
|
1ed231747b | ||
|
|
a926eaa86d | ||
|
|
acd8ec2c31 | ||
|
|
441a9dbea0 | ||
|
|
63e92c49df | ||
|
|
49dd8bcf51 | ||
|
|
942f4c4ffd | ||
|
|
43791f3a71 | ||
|
|
321bea59fb | ||
|
|
601fd16cba | ||
|
|
a9cddc10a9 | ||
|
|
03fc159aec | ||
|
|
59b596e1ee | ||
|
|
1fe6626edb | ||
|
|
fa8cffb3a2 | ||
|
|
11daf8dde8 | ||
|
|
0d6ac67c04 | ||
|
|
978dc88499 | ||
|
|
655868d803 | ||
|
|
92ff4ab76f | ||
|
|
48a6db6598 | ||
|
|
a97d050016 | ||
|
|
e888d8aa88 | ||
|
|
59ca82128a | ||
|
|
0620462efb | ||
|
|
f99f1e187c | ||
|
|
937a851baa | ||
|
|
8e396f8e91 | ||
|
|
bd74676685 | ||
|
|
70e012bc45 | ||
|
|
3bb3434a8d | ||
|
|
2121039a2b | ||
|
|
5bab5a2398 | ||
|
|
2ca8be0bb2 | ||
|
|
227448f061 | ||
|
|
0b026dc5a2 | ||
|
|
3ba268ed9c | ||
|
|
c4b09c7526 | ||
|
|
164e517a54 | ||
|
|
fd75e791a7 | ||
|
|
7eb9f910ba | ||
|
|
78cd3298aa | ||
|
|
2f5dfbb728 | ||
|
|
3750668aad | ||
|
|
dc2acc5bf5 | ||
|
|
f7db275bc4 | ||
|
|
7171a34364 | ||
|
|
f1260e6869 | ||
|
|
0b4f2bafe6 | ||
|
|
c5cf576deb | ||
|
|
bfd7f71601 | ||
|
|
87718f91ab | ||
|
|
3918395715 | ||
|
|
dec9c6d96e | ||
|
|
0c651a890c | ||
|
|
e00462992c | ||
|
|
951c65e5a1 | ||
|
|
0f19b148f6 | ||
|
|
c750be6fc6 | ||
|
|
d1003f08de | ||
|
|
386c45fd4d | ||
|
|
725d203c32 | ||
|
|
07a14ce350 | ||
|
|
77c2c8d77c | ||
|
|
9ea7f100cc | ||
|
|
51487a75e9 | ||
|
|
500b8e190d | ||
|
|
9102c12c6d | ||
|
|
cb45ee8879 | ||
|
|
ecae47236e | ||
|
|
d0ca0886bb | ||
|
|
18411f4b5f | ||
|
|
2c383e7216 | ||
|
|
cac6d3e5ac | ||
|
|
bd985d67d8 | ||
|
|
6f0a70fa66 | ||
|
|
cbe6de2a2d | ||
|
|
4885d65ec9 | ||
|
|
047896ac16 | ||
|
|
fbe3a563c3 | ||
|
|
0c453fda0b | ||
|
|
a1f74e9c63 | ||
|
|
763fa1cf0c | ||
|
|
c8e8ccfa22 | ||
|
|
597342bf15 | ||
|
|
8338b2fb49 | ||
|
|
fed0b09c4e | ||
|
|
3e76482713 | ||
|
|
d6325d902e | ||
|
|
615adc5fe6 | ||
|
|
2bdb728e87 | ||
|
|
5e82d653a1 | ||
|
|
27653b7fbf | ||
|
|
af1530953e | ||
|
|
87290af774 | ||
|
|
8469d7727d | ||
|
|
44e9ffc5ca | ||
|
|
2e86d1f9bb | ||
|
|
112c999818 | ||
|
|
858e5e9720 | ||
|
|
f2f7b10d15 | ||
|
|
4e3c2f237c | ||
|
|
c246e918f4 | ||
|
|
b76f185cb6 | ||
|
|
9d7097177d | ||
|
|
c6587596b1 | ||
|
|
b661aad9ac | ||
|
|
ca0a0a4a3d | ||
|
|
a9cd67873c | ||
|
|
b58812e7f1 | ||
|
|
9e2b4380d5 | ||
|
|
8ae8430e7c | ||
|
|
2ee25fda61 | ||
|
|
e766286d92 | ||
|
|
4df59a752a | ||
|
|
e0bf57ae36 | ||
|
|
5df66bb179 | ||
|
|
b5256ef70b | ||
|
|
6c8fec96b6 | ||
|
|
cd139bd4ec | ||
|
|
17b0c819e4 | ||
|
|
79c7d736f0 | ||
|
|
b627f93cf1 | ||
|
|
7d632ab3dd | ||
|
|
bdf80a683c | ||
|
|
ed7292abd3 | ||
|
|
e92f042677 | ||
|
|
53cf9e7422 | ||
|
|
954afd78b2 | ||
|
|
957ad2b4b1 | ||
|
|
7187c6132a | ||
|
|
b3f0d7c756 | ||
|
|
0cdfdee18f | ||
|
|
a283f56d05 | ||
|
|
e6fd78ce93 | ||
|
|
aeed5f029e | ||
|
|
04484d55de | ||
|
|
476cba228d | ||
|
|
115f9f0644 | ||
|
|
a9c2a95366 | ||
|
|
29f3891a68 | ||
|
|
7b602ef607 | ||
|
|
15e555c7f1 | ||
|
|
f4fb49d32f | ||
|
|
89be2fb736 | ||
|
|
62f0885852 | ||
|
|
355e155e69 | ||
|
|
ae1584ff3c | ||
|
|
4a7686cd33 | ||
|
|
799eeb0cb8 | ||
|
|
8452e275d0 | ||
|
|
53268000e7 | ||
|
|
52febfe3fc | ||
|
|
8fcfed495a | ||
|
|
2dfe76b082 | ||
|
|
11d8751d29 | ||
|
|
b03c3a29e0 | ||
|
|
53e8982e05 | ||
|
|
4a30841ad8 | ||
|
|
234ebadb8d | ||
|
|
11ee20fa36 | ||
|
|
440599545f | ||
|
|
44ba088cb4 | ||
|
|
08d3798722 | ||
|
|
56ff8e438e | ||
|
|
3590a3589d | ||
|
|
7674c82e1f | ||
|
|
b93b21a7f2 | ||
|
|
f53925848c | ||
|
|
eedc88b56a | ||
|
|
1102fec2a0 | ||
|
|
589fefe4b9 | ||
|
|
cfc867bd18 | ||
|
|
5bc28e3016 | ||
|
|
23b7ccca7f | ||
|
|
e9d6286a1d | ||
|
|
48321857e4 | ||
|
|
156da15715 | ||
|
|
4a0d7965cb | ||
|
|
1f522823ff | ||
|
|
6795a280fd | ||
|
|
f369e22638 | ||
|
|
a278da2eba | ||
|
|
37b2bdba79 | ||
|
|
e9519db974 | ||
|
|
dd7a24ebce | ||
|
|
bc92a7d155 | ||
|
|
a68db84df6 | ||
|
|
7b9bba3190 | ||
|
|
bcec0af232 | ||
|
|
0d437c4102 | ||
|
|
feff7bccd3 | ||
|
|
b12de3f01b | ||
|
|
0d108f12e4 | ||
|
|
4aca2ca33b | ||
|
|
9a967ae514 | ||
|
|
9481c39874 | ||
|
|
1e02065982 | ||
|
|
1fee0da689 | ||
|
|
c760cf8418 | ||
|
|
cdee5997af | ||
|
|
4289280cdc | ||
|
|
962dfa17c5 | ||
|
|
0a21aef601 | ||
|
|
8cbbd504cf | ||
|
|
91b23c8367 | ||
|
|
3729be263f | ||
|
|
ea91f4217a | ||
|
|
7fab3ce0b1 | ||
|
|
ef7d675d67 | ||
|
|
2b9d29a0fc | ||
|
|
95b95d012c | ||
|
|
4af7d5bca7 | ||
|
|
d879eb235f | ||
|
|
4f129d035b | ||
|
|
7a354c4ff4 | ||
|
|
364826b3b3 | ||
|
|
e9b308da46 | ||
|
|
94cfa2602f | ||
|
|
3533bd0504 | ||
|
|
1a51a7df9e | ||
|
|
615be89951 | ||
|
|
912ca36a1f | ||
|
|
fba93805dc | ||
|
|
96d66f4624 | ||
|
|
c3bae63e41 | ||
|
|
6c22aceabc | ||
|
|
92a77dfe7f | ||
|
|
4f2dbeda28 | ||
|
|
bec2de08fe | ||
|
|
db192e1e01 | ||
|
|
454654a9cc | ||
|
|
1018bc56eb | ||
|
|
f920dc87d0 | ||
|
|
8b97caae46 | ||
|
|
3b74aab818 | ||
|
|
e78b4939b3 | ||
|
|
621b5fc2db | ||
|
|
6ada069d5a | ||
|
|
50db384be1 | ||
|
|
ae7225ae83 | ||
|
|
911ba333a2 | ||
|
|
5cd8cce531 | ||
|
|
6a2a76cea9 | ||
|
|
7a9a3d30c9 | ||
|
|
034ca4d5eb | ||
|
|
00e3fa32fb | ||
|
|
0133bdfbe3 | ||
|
|
e563def5ba | ||
|
|
b3910f4e4d | ||
|
|
4a7b8fe839 | ||
|
|
fc56544da4 | ||
|
|
c839d25722 | ||
|
|
c6b5ecbbdb | ||
|
|
d3473afa23 | ||
|
|
379b28eb85 | ||
|
|
7f5bd33ead | ||
|
|
eef6fb9891 | ||
|
|
4a7f52ab2c | ||
|
|
10b249a162 | ||
|
|
5fc5fce663 | ||
|
|
f00fe3c0b1 | ||
|
|
3047d51613 | ||
|
|
f9f7146960 | ||
|
|
ca9dc3103a | ||
|
|
c03afa379c | ||
|
|
cbacc98e3f | ||
|
|
84daf14f1b | ||
|
|
4af28b2a46 | ||
|
|
acbc01933c | ||
|
|
7ec78eecbd | ||
|
|
87c5e37f5e | ||
|
|
d02959e3ed | ||
|
|
b844d8b750 | ||
|
|
0a3010b29f | ||
|
|
2b380d03c9 | ||
|
|
3f70253a3f | ||
|
|
165e294298 | ||
|
|
f7c9f45508 | ||
|
|
af2a924301 | ||
|
|
3981e83de5 | ||
|
|
88b9721e3f | ||
|
|
4946af1448 | ||
|
|
9959dcfa49 | ||
|
|
cfb13fad22 | ||
|
|
4e3f3a052d | ||
|
|
dc7ae9ed20 | ||
|
|
929badf4c6 | ||
|
|
c4a3f2c04f | ||
|
|
a933e458b3 |
@@ -10,8 +10,7 @@
|
|||||||
subproject libs/python/build ;
|
subproject libs/python/build ;
|
||||||
|
|
||||||
# bring in the rules for python
|
# bring in the rules for python
|
||||||
SEARCH on <module@>python.jam = $(BOOST_BUILD_PATH) ;
|
import python ;
|
||||||
include <module@>python.jam ;
|
|
||||||
|
|
||||||
if [ check-python-config ]
|
if [ check-python-config ]
|
||||||
{
|
{
|
||||||
@@ -35,6 +34,7 @@ if [ check-python-config ]
|
|||||||
dict.cpp
|
dict.cpp
|
||||||
tuple.cpp
|
tuple.cpp
|
||||||
str.cpp
|
str.cpp
|
||||||
|
slice.cpp
|
||||||
|
|
||||||
aix_init_module.cpp
|
aix_init_module.cpp
|
||||||
converter/from_python.cpp
|
converter/from_python.cpp
|
||||||
@@ -51,8 +51,12 @@ if [ check-python-config ]
|
|||||||
converter/builtin_converters.cpp
|
converter/builtin_converters.cpp
|
||||||
converter/arg_to_python_base.cpp
|
converter/arg_to_python_base.cpp
|
||||||
object/iterator.cpp
|
object/iterator.cpp
|
||||||
|
object/stl_iterator.cpp
|
||||||
object_protocol.cpp
|
object_protocol.cpp
|
||||||
object_operators.cpp
|
object_operators.cpp
|
||||||
|
wrapper.cpp
|
||||||
|
exec.cpp
|
||||||
|
import.cpp
|
||||||
;
|
;
|
||||||
|
|
||||||
dll boost_python
|
dll boost_python
|
||||||
@@ -61,8 +65,15 @@ if [ check-python-config ]
|
|||||||
<define>BOOST_PYTHON_SOURCE
|
<define>BOOST_PYTHON_SOURCE
|
||||||
$(bpl-linkflags)
|
$(bpl-linkflags)
|
||||||
<msvc-stlport><release>$(msvc-stlport-workarounds)
|
<msvc-stlport><release>$(msvc-stlport-workarounds)
|
||||||
|
<darwin><*><linkflags>-bind_at_load
|
||||||
|
<gcc-3_3-darwin><*><linkflags>-bind_at_load
|
||||||
;
|
;
|
||||||
|
|
||||||
|
template extension
|
||||||
|
: <dll>boost_python
|
||||||
|
: <sysinclude>../../..
|
||||||
|
;
|
||||||
|
|
||||||
lib boost_python
|
lib boost_python
|
||||||
: # sources
|
: # sources
|
||||||
../src/$(sources)
|
../src/$(sources)
|
||||||
@@ -81,4 +92,8 @@ if [ check-python-config ]
|
|||||||
:
|
:
|
||||||
debug release
|
debug release
|
||||||
;
|
;
|
||||||
}
|
|
||||||
|
install python lib
|
||||||
|
: <dll>boost_python <lib>boost_python
|
||||||
|
;
|
||||||
|
}
|
||||||
|
|||||||
@@ -1,65 +1,39 @@
|
|||||||
import os ;
|
import os ;
|
||||||
|
import modules ;
|
||||||
|
|
||||||
# Use a very crude way to sense there python is locatted
|
import python ;
|
||||||
|
|
||||||
local PYTHON_PATH ;
|
if [ python.configured ] {
|
||||||
|
|
||||||
if [ GLOB /usr/local/include/python2.2 : * ]
|
|
||||||
{
|
|
||||||
PYTHON_PATH = /usr/local ;
|
|
||||||
}
|
|
||||||
else if [ GLOB /usr/include/python2.2 : * ]
|
|
||||||
{
|
|
||||||
PYTHON_PATH = /usr ;
|
|
||||||
}
|
|
||||||
|
|
||||||
if [ os.name ] in CYGWIN NT
|
|
||||||
{
|
|
||||||
lib_condition = <link>shared: ;
|
|
||||||
defines = USE_DL_IMPORT ;
|
|
||||||
|
|
||||||
# Declare a target for the python interpreter library
|
|
||||||
lib python : : <name>python2.2.dll ;
|
|
||||||
PYTHON_LIB = python ;
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
lib python : : <name>python2.2 ;
|
|
||||||
PYTHON_LIB = python ;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
if $(PYTHON_PATH) {
|
|
||||||
|
|
||||||
|
|
||||||
project boost/python
|
project boost/python
|
||||||
: source-location ../src
|
: source-location ../src
|
||||||
: requirements <include>$(PYTHON_PATH)/include/python2.2
|
: requirements
|
||||||
$(lib_condition)<library-path>$(PYTHON_PATH)/lib/python2.2/config
|
#<include>$(PYTHON_PATH)/include
|
||||||
<link>shared:<library>$(PYTHON_LIB)
|
# $(lib_condition)<library-path>$(PYTHON_PATH)/libs
|
||||||
<define>$(defines)
|
# <link>shared:<library>$(PYTHON_LIB)
|
||||||
: usage-requirements # requirement that will be propageted to *users* of this library
|
# <define>$(defines)
|
||||||
<include>$(PYTHON_PATH)/include/python2.2
|
#: usage-requirements # requirement that will be propageted to *users* of this library
|
||||||
|
# <include>$(PYTHON_PATH)/include
|
||||||
|
|
||||||
# We have a bug which causes us to conclude that conditionalized
|
# We have a bug which causes us to conclude that conditionalized
|
||||||
# properties in this section are not free.
|
# properties in this section are not free.
|
||||||
# $(lib_condition)<library-path>$(PYTHON_PATH)/lib/python2.2/config
|
# $(lib_condition)<library-path>$(PYTHON_PATH)/lib/python2.2/config
|
||||||
# <shared>true:<find-library>$(PYTHON_LIB)
|
# <shared>true:<find-library>$(PYTHON_LIB)
|
||||||
|
|
||||||
<library-path>$(PYTHON_PATH)/lib/python2.2/config
|
# <library-path>$(PYTHON_PATH)/lib/python2.2/config
|
||||||
<library>$(PYTHON_LIB)
|
# <library>$(PYTHON_LIB)
|
||||||
;
|
;
|
||||||
|
|
||||||
lib boost_python
|
lib boost_python
|
||||||
:
|
:
|
||||||
numeric.cpp
|
numeric.cpp
|
||||||
|
|
||||||
list.cpp
|
list.cpp
|
||||||
long.cpp
|
long.cpp
|
||||||
dict.cpp
|
dict.cpp
|
||||||
tuple.cpp
|
tuple.cpp
|
||||||
str.cpp
|
str.cpp
|
||||||
|
slice.cpp
|
||||||
|
|
||||||
aix_init_module.cpp
|
aix_init_module.cpp
|
||||||
converter/from_python.cpp
|
converter/from_python.cpp
|
||||||
@@ -76,10 +50,20 @@ lib boost_python
|
|||||||
converter/builtin_converters.cpp
|
converter/builtin_converters.cpp
|
||||||
converter/arg_to_python_base.cpp
|
converter/arg_to_python_base.cpp
|
||||||
object/iterator.cpp
|
object/iterator.cpp
|
||||||
|
object/stl_iterator.cpp
|
||||||
object_protocol.cpp
|
object_protocol.cpp
|
||||||
object_operators.cpp
|
object_operators.cpp
|
||||||
|
wrapper.cpp
|
||||||
|
import.cpp
|
||||||
|
exec.cpp
|
||||||
: <link>static:<define>BOOST_PYTHON_STATIC_LIB
|
: <link>static:<define>BOOST_PYTHON_STATIC_LIB
|
||||||
<define>BOOST_PYTHON_SOURCE
|
<define>BOOST_PYTHON_SOURCE
|
||||||
|
<library>/python//python
|
||||||
: <link>shared
|
: <link>shared
|
||||||
;
|
;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
ECHO "warning: Python location is not configured" ;
|
||||||
|
ECHO "warning: the Boost.Python library won't be built" ;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -175,6 +175,14 @@ SOURCE=..\..\src\converter\registry.cpp
|
|||||||
# End Source File
|
# End Source File
|
||||||
# Begin Source File
|
# Begin Source File
|
||||||
|
|
||||||
|
SOURCE=..\..\src\slice.cpp
|
||||||
|
# End Source File
|
||||||
|
# Begin Source File
|
||||||
|
|
||||||
|
SOURCE=..\..\src\object\stl_iterator.cpp
|
||||||
|
# End Source File
|
||||||
|
# Begin Source File
|
||||||
|
|
||||||
SOURCE=..\..\src\str.cpp
|
SOURCE=..\..\src\str.cpp
|
||||||
# End Source File
|
# End Source File
|
||||||
# Begin Source File
|
# Begin Source File
|
||||||
@@ -185,6 +193,18 @@ SOURCE=..\..\src\tuple.cpp
|
|||||||
|
|
||||||
SOURCE=..\..\src\converter\type_id.cpp
|
SOURCE=..\..\src\converter\type_id.cpp
|
||||||
# End Source File
|
# End Source File
|
||||||
|
# Begin Source File
|
||||||
|
|
||||||
|
SOURCE=..\..\src\wrapper.cpp
|
||||||
|
# End Source File
|
||||||
|
# Begin Source File
|
||||||
|
|
||||||
|
SOURCE=..\..\src\import.cpp
|
||||||
|
# End Source File
|
||||||
|
# Begin Source File
|
||||||
|
|
||||||
|
SOURCE=..\..\src\exec.cpp
|
||||||
|
# End Source File
|
||||||
# End Group
|
# End Group
|
||||||
# Begin Group "Header Files"
|
# Begin Group "Header Files"
|
||||||
|
|
||||||
@@ -586,6 +606,10 @@ SOURCE=..\..\..\..\boost\python\object\select_holder.hpp
|
|||||||
# End Source File
|
# End Source File
|
||||||
# Begin Source File
|
# Begin Source File
|
||||||
|
|
||||||
|
SOURCE=..\..\..\..\boost\python\object\stl_iterator_core.hpp
|
||||||
|
# End Source File
|
||||||
|
# Begin Source File
|
||||||
|
|
||||||
SOURCE=..\..\..\..\boost\python\object\value_holder.hpp
|
SOURCE=..\..\..\..\boost\python\object\value_holder.hpp
|
||||||
# End Source File
|
# End Source File
|
||||||
# Begin Source File
|
# Begin Source File
|
||||||
@@ -843,6 +867,10 @@ SOURCE=..\..\..\..\boost\python\slice_nil.hpp
|
|||||||
# End Source File
|
# End Source File
|
||||||
# Begin Source File
|
# Begin Source File
|
||||||
|
|
||||||
|
SOURCE=..\..\..\..\boost\python\stl_iterator.hpp
|
||||||
|
# End Source File
|
||||||
|
# Begin Source File
|
||||||
|
|
||||||
SOURCE=..\..\..\..\boost\python\str.hpp
|
SOURCE=..\..\..\..\boost\python\str.hpp
|
||||||
# End Source File
|
# End Source File
|
||||||
# Begin Source File
|
# Begin Source File
|
||||||
|
|||||||
@@ -1,947 +1 @@
|
|||||||
+++++++++++++++++++++++++++++++++++++++++++
|
This file has been moved to http://www.boost-consulting.com/writing/bpl.txt.
|
||||||
Building Hybrid Systems with Boost.Python
|
|
||||||
+++++++++++++++++++++++++++++++++++++++++++
|
|
||||||
|
|
||||||
:Author: David Abrahams
|
|
||||||
:Contact: dave@boost-consulting.com
|
|
||||||
:organization: `Boost Consulting`_
|
|
||||||
:date: $Date$
|
|
||||||
|
|
||||||
:Author: Ralf W. Grosse-Kunstleve
|
|
||||||
|
|
||||||
:copyright: Copyright David Abrahams and Ralf W. Grosse-Kunstleve 2003. All rights reserved
|
|
||||||
|
|
||||||
.. contents:: Table of Contents
|
|
||||||
|
|
||||||
.. _`Boost Consulting`: http://www.boost-consulting.com
|
|
||||||
|
|
||||||
==========
|
|
||||||
Abstract
|
|
||||||
==========
|
|
||||||
|
|
||||||
Boost.Python is an open source C++ library which provides a concise
|
|
||||||
IDL-like interface for binding C++ classes and functions to
|
|
||||||
Python. Leveraging the full power of C++ compile-time introspection
|
|
||||||
and of recently developed metaprogramming techniques, this is achieved
|
|
||||||
entirely in pure C++, without introducing a new syntax.
|
|
||||||
Boost.Python's rich set of features and high-level interface make it
|
|
||||||
possible to engineer packages from the ground up as hybrid systems,
|
|
||||||
giving programmers easy and coherent access to both the efficient
|
|
||||||
compile-time polymorphism of C++ and the extremely convenient run-time
|
|
||||||
polymorphism of Python.
|
|
||||||
|
|
||||||
==============
|
|
||||||
Introduction
|
|
||||||
==============
|
|
||||||
|
|
||||||
Python and C++ are in many ways as different as two languages could
|
|
||||||
be: while C++ is usually compiled to machine-code, Python is
|
|
||||||
interpreted. Python's dynamic type system is often cited as the
|
|
||||||
foundation of its flexibility, while in C++ static typing is the
|
|
||||||
cornerstone of its efficiency. C++ has an intricate and difficult
|
|
||||||
compile-time meta-language, while in Python, practically everything
|
|
||||||
happens at runtime.
|
|
||||||
|
|
||||||
Yet for many programmers, these very differences mean that Python and
|
|
||||||
C++ complement one another perfectly. Performance bottlenecks in
|
|
||||||
Python programs can be rewritten in C++ for maximal speed, and
|
|
||||||
authors of powerful C++ libraries choose Python as a middleware
|
|
||||||
language for its flexible system integration capabilities.
|
|
||||||
Furthermore, the surface differences mask some strong similarities:
|
|
||||||
|
|
||||||
* 'C'-family control structures (if, while, for...)
|
|
||||||
|
|
||||||
* Support for object-orientation, functional programming, and generic
|
|
||||||
programming (these are both *multi-paradigm* programming languages.)
|
|
||||||
|
|
||||||
* Comprehensive operator overloading facilities, recognizing the
|
|
||||||
importance of syntactic variability for readability and
|
|
||||||
expressivity.
|
|
||||||
|
|
||||||
* High-level concepts such as collections and iterators.
|
|
||||||
|
|
||||||
* High-level encapsulation facilities (C++: namespaces, Python: modules)
|
|
||||||
to support the design of re-usable libraries.
|
|
||||||
|
|
||||||
* Exception-handling for effective management of error conditions.
|
|
||||||
|
|
||||||
* C++ idioms in common use, such as handle/body classes and
|
|
||||||
reference-counted smart pointers mirror Python reference semantics.
|
|
||||||
|
|
||||||
Given Python's rich 'C' interoperability API, it should in principle
|
|
||||||
be possible to expose C++ type and function interfaces to Python with
|
|
||||||
an analogous interface to their C++ counterparts. However, the
|
|
||||||
facilities provided by Python alone for integration with C++ are
|
|
||||||
relatively meager. Compared to C++ and Python, 'C' has only very
|
|
||||||
rudimentary abstraction facilities, and support for exception-handling
|
|
||||||
is completely missing. 'C' extension module writers are required to
|
|
||||||
manually manage Python reference counts, which is both annoyingly
|
|
||||||
tedious and extremely error-prone. Traditional extension modules also
|
|
||||||
tend to contain a great deal of boilerplate code repetition which
|
|
||||||
makes them difficult to maintain, especially when wrapping an evolving
|
|
||||||
API.
|
|
||||||
|
|
||||||
These limitations have lead to the development of a variety of wrapping
|
|
||||||
systems. SWIG_ is probably the most popular package for the
|
|
||||||
integration of C/C++ and Python. A more recent development is SIP_,
|
|
||||||
which was specifically designed for interfacing Python with the Qt_
|
|
||||||
graphical user interface library. Both SWIG and SIP introduce their
|
|
||||||
own specialized languages for customizing inter-language bindings.
|
|
||||||
This has certain advantages, but having to deal with three different
|
|
||||||
languages (Python, C/C++ and the interface language) also introduces
|
|
||||||
practical and mental difficulties. The CXX_ package demonstrates an
|
|
||||||
interesting alternative. It shows that at least some parts of
|
|
||||||
Python's 'C' API can be wrapped and presented through a much more
|
|
||||||
user-friendly C++ interface. However, unlike SWIG and SIP, CXX does
|
|
||||||
not include support for wrapping C++ classes as new Python types.
|
|
||||||
|
|
||||||
The features and goals of Boost.Python_ overlap significantly with
|
|
||||||
many of these other systems. That said, Boost.Python attempts to
|
|
||||||
maximize convenience and flexibility without introducing a separate
|
|
||||||
wrapping language. Instead, it presents the user with a high-level
|
|
||||||
C++ interface for wrapping C++ classes and functions, managing much of
|
|
||||||
the complexity behind-the-scenes with static metaprogramming.
|
|
||||||
Boost.Python also goes beyond the scope of earlier systems by
|
|
||||||
providing:
|
|
||||||
|
|
||||||
* Support for C++ virtual functions that can be overridden in Python.
|
|
||||||
|
|
||||||
* Comprehensive lifetime management facilities for low-level C++
|
|
||||||
pointers and references.
|
|
||||||
|
|
||||||
* Support for organizing extensions as Python packages,
|
|
||||||
with a central registry for inter-language type conversions.
|
|
||||||
|
|
||||||
* A safe and convenient mechanism for tying into Python's powerful
|
|
||||||
serialization engine (pickle).
|
|
||||||
|
|
||||||
* Coherence with the rules for handling C++ lvalues and rvalues that
|
|
||||||
can only come from a deep understanding of both the Python and C++
|
|
||||||
type systems.
|
|
||||||
|
|
||||||
The key insight that sparked the development of Boost.Python is that
|
|
||||||
much of the boilerplate code in traditional extension modules could be
|
|
||||||
eliminated using C++ compile-time introspection. Each argument of a
|
|
||||||
wrapped C++ function must be extracted from a Python object using a
|
|
||||||
procedure that depends on the argument type. Similarly the function's
|
|
||||||
return type determines how the return value will be converted from C++
|
|
||||||
to Python. Of course argument and return types are part of each
|
|
||||||
function's type, and this is exactly the source from which
|
|
||||||
Boost.Python deduces most of the information required.
|
|
||||||
|
|
||||||
This approach leads to *user guided wrapping*: as much information is
|
|
||||||
extracted directly from the source code to be wrapped as is possible
|
|
||||||
within the framework of pure C++, and some additional information is
|
|
||||||
supplied explicitly by the user. Mostly the guidance is mechanical
|
|
||||||
and little real intervention is required. Because the interface
|
|
||||||
specification is written in the same full-featured language as the
|
|
||||||
code being exposed, the user has unprecedented power available when
|
|
||||||
she does need to take control.
|
|
||||||
|
|
||||||
.. _Python: http://www.python.org/
|
|
||||||
.. _SWIG: http://www.swig.org/
|
|
||||||
.. _SIP: http://www.riverbankcomputing.co.uk/sip/index.php
|
|
||||||
.. _Qt: http://www.trolltech.com/
|
|
||||||
.. _CXX: http://cxx.sourceforge.net/
|
|
||||||
.. _Boost.Python: http://www.boost.org/libs/python/doc
|
|
||||||
|
|
||||||
===========================
|
|
||||||
Boost.Python Design Goals
|
|
||||||
===========================
|
|
||||||
|
|
||||||
The primary goal of Boost.Python is to allow users to expose C++
|
|
||||||
classes and functions to Python using nothing more than a C++
|
|
||||||
compiler. In broad strokes, the user experience should be one of
|
|
||||||
directly manipulating C++ objects from Python.
|
|
||||||
|
|
||||||
However, it's also important not to translate all interfaces *too*
|
|
||||||
literally: the idioms of each language must be respected. For
|
|
||||||
example, though C++ and Python both have an iterator concept, they are
|
|
||||||
expressed very differently. Boost.Python has to be able to bridge the
|
|
||||||
interface gap.
|
|
||||||
|
|
||||||
It must be possible to insulate Python users from crashes resulting
|
|
||||||
from trivial misuses of C++ interfaces, such as accessing
|
|
||||||
already-deleted objects. By the same token the library should
|
|
||||||
insulate C++ users from low-level Python 'C' API, replacing
|
|
||||||
error-prone 'C' interfaces like manual reference-count management and
|
|
||||||
raw ``PyObject`` pointers with more-robust alternatives.
|
|
||||||
|
|
||||||
Support for component-based development is crucial, so that C++ types
|
|
||||||
exposed in one extension module can be passed to functions exposed in
|
|
||||||
another without loss of crucial information like C++ inheritance
|
|
||||||
relationships.
|
|
||||||
|
|
||||||
Finally, all wrapping must be *non-intrusive*, without modifying or
|
|
||||||
even seeing the original C++ source code. Existing C++ libraries have
|
|
||||||
to be wrappable by third parties who only have access to header files
|
|
||||||
and binaries.
|
|
||||||
|
|
||||||
==========================
|
|
||||||
Hello Boost.Python World
|
|
||||||
==========================
|
|
||||||
|
|
||||||
And now for a preview of Boost.Python, and how it improves on the raw
|
|
||||||
facilities offered by Python. Here's a function we might want to
|
|
||||||
expose::
|
|
||||||
|
|
||||||
char const* greet(unsigned x)
|
|
||||||
{
|
|
||||||
static char const* const msgs[] = { "hello", "Boost.Python", "world!" };
|
|
||||||
|
|
||||||
if (x > 2)
|
|
||||||
throw std::range_error("greet: index out of range");
|
|
||||||
|
|
||||||
return msgs[x];
|
|
||||||
}
|
|
||||||
|
|
||||||
To wrap this function in standard C++ using the Python 'C' API, we'd
|
|
||||||
need something like this::
|
|
||||||
|
|
||||||
extern "C" // all Python interactions use 'C' linkage and calling convention
|
|
||||||
{
|
|
||||||
// Wrapper to handle argument/result conversion and checking
|
|
||||||
PyObject* greet_wrap(PyObject* args, PyObject * keywords)
|
|
||||||
{
|
|
||||||
int x;
|
|
||||||
if (PyArg_ParseTuple(args, "i", &x)) // extract/check arguments
|
|
||||||
{
|
|
||||||
char const* result = greet(x); // invoke wrapped function
|
|
||||||
return PyString_FromString(result); // convert result to Python
|
|
||||||
}
|
|
||||||
return 0; // error occurred
|
|
||||||
}
|
|
||||||
|
|
||||||
// Table of wrapped functions to be exposed by the module
|
|
||||||
static PyMethodDef methods[] = {
|
|
||||||
{ "greet", greet_wrap, METH_VARARGS, "return one of 3 parts of a greeting" }
|
|
||||||
, { NULL, NULL, 0, NULL } // sentinel
|
|
||||||
};
|
|
||||||
|
|
||||||
// module initialization function
|
|
||||||
DL_EXPORT init_hello()
|
|
||||||
{
|
|
||||||
(void) Py_InitModule("hello", methods); // add the methods to the module
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
Now here's the wrapping code we'd use to expose it with Boost.Python::
|
|
||||||
|
|
||||||
#include <boost/python.hpp>
|
|
||||||
using namespace boost::python;
|
|
||||||
BOOST_PYTHON_MODULE(hello)
|
|
||||||
{
|
|
||||||
def("greet", greet, "return one of 3 parts of a greeting");
|
|
||||||
}
|
|
||||||
|
|
||||||
and here it is in action::
|
|
||||||
|
|
||||||
>>> import hello
|
|
||||||
>>> for x in range(3):
|
|
||||||
... print hello.greet(x)
|
|
||||||
...
|
|
||||||
hello
|
|
||||||
Boost.Python
|
|
||||||
world!
|
|
||||||
|
|
||||||
Aside from the fact that the 'C' API version is much more verbose,
|
|
||||||
it's worth noting a few things that it doesn't handle correctly:
|
|
||||||
|
|
||||||
* The original function accepts an unsigned integer, and the Python
|
|
||||||
'C' API only gives us a way of extracting signed integers. The
|
|
||||||
Boost.Python version will raise a Python exception if we try to pass
|
|
||||||
a negative number to ``hello.greet``, but the other one will proceed
|
|
||||||
to do whatever the C++ implementation does when converting an
|
|
||||||
negative integer to unsigned (usually wrapping to some very large
|
|
||||||
number), and pass the incorrect translation on to the wrapped
|
|
||||||
function.
|
|
||||||
|
|
||||||
* That brings us to the second problem: if the C++ ``greet()``
|
|
||||||
function is called with a number greater than 2, it will throw an
|
|
||||||
exception. Typically, if a C++ exception propagates across the
|
|
||||||
boundary with code generated by a 'C' compiler, it will cause a
|
|
||||||
crash. As you can see in the first version, there's no C++
|
|
||||||
scaffolding there to prevent this from happening. Functions wrapped
|
|
||||||
by Boost.Python automatically include an exception-handling layer
|
|
||||||
which protects Python users by translating unhandled C++ exceptions
|
|
||||||
into a corresponding Python exception.
|
|
||||||
|
|
||||||
* A slightly more-subtle limitation is that the argument conversion
|
|
||||||
used in the Python 'C' API case can only get that integer ``x`` in
|
|
||||||
*one way*. PyArg_ParseTuple can't convert Python ``long`` objects
|
|
||||||
(arbitrary-precision integers) which happen to fit in an ``unsigned
|
|
||||||
int`` but not in a ``signed long``, nor will it ever handle a
|
|
||||||
wrapped C++ class with a user-defined implicit ``operator unsigned
|
|
||||||
int()`` conversion. Boost.Python's dynamic type conversion
|
|
||||||
registry allows users to add arbitrary conversion methods.
|
|
||||||
|
|
||||||
==================
|
|
||||||
Library Overview
|
|
||||||
==================
|
|
||||||
|
|
||||||
This section outlines some of the library's major features. Except as
|
|
||||||
neccessary to avoid confusion, details of library implementation are
|
|
||||||
omitted.
|
|
||||||
|
|
||||||
------------------
|
|
||||||
Exposing Classes
|
|
||||||
------------------
|
|
||||||
|
|
||||||
C++ classes and structs are exposed with a similarly-terse interface.
|
|
||||||
Given::
|
|
||||||
|
|
||||||
struct World
|
|
||||||
{
|
|
||||||
void set(std::string msg) { this->msg = msg; }
|
|
||||||
std::string greet() { return msg; }
|
|
||||||
std::string msg;
|
|
||||||
};
|
|
||||||
|
|
||||||
The following code will expose it in our extension module::
|
|
||||||
|
|
||||||
#include <boost/python.hpp>
|
|
||||||
BOOST_PYTHON_MODULE(hello)
|
|
||||||
{
|
|
||||||
class_<World>("World")
|
|
||||||
.def("greet", &World::greet)
|
|
||||||
.def("set", &World::set)
|
|
||||||
;
|
|
||||||
}
|
|
||||||
|
|
||||||
Although this code has a certain pythonic familiarity, people
|
|
||||||
sometimes find the syntax bit confusing because it doesn't look like
|
|
||||||
most of the C++ code they're used to. All the same, this is just
|
|
||||||
standard C++. Because of their flexible syntax and operator
|
|
||||||
overloading, C++ and Python are great for defining domain-specific
|
|
||||||
(sub)languages
|
|
||||||
(DSLs), and that's what we've done in Boost.Python. To break it down::
|
|
||||||
|
|
||||||
class_<World>("World")
|
|
||||||
|
|
||||||
constructs an unnamed object of type ``class_<World>`` and passes
|
|
||||||
``"World"`` to its constructor. This creates a new-style Python class
|
|
||||||
called ``World`` in the extension module, and associates it with the
|
|
||||||
C++ type ``World`` in the Boost.Python type conversion registry. We
|
|
||||||
might have also written::
|
|
||||||
|
|
||||||
class_<World> w("World");
|
|
||||||
|
|
||||||
but that would've been more verbose, since we'd have to name ``w``
|
|
||||||
again to invoke its ``def()`` member function::
|
|
||||||
|
|
||||||
w.def("greet", &World::greet)
|
|
||||||
|
|
||||||
There's nothing special about the location of the dot for member
|
|
||||||
access in the original example: C++ allows any amount of whitespace on
|
|
||||||
either side of a token, and placing the dot at the beginning of each
|
|
||||||
line allows us to chain as many successive calls to member functions
|
|
||||||
as we like with a uniform syntax. The other key fact that allows
|
|
||||||
chaining is that ``class_<>`` member functions all return a reference
|
|
||||||
to ``*this``.
|
|
||||||
|
|
||||||
So the example is equivalent to::
|
|
||||||
|
|
||||||
class_<World> w("World");
|
|
||||||
w.def("greet", &World::greet);
|
|
||||||
w.def("set", &World::set);
|
|
||||||
|
|
||||||
It's occasionally useful to be able to break down the components of a
|
|
||||||
Boost.Python class wrapper in this way, but the rest of this article
|
|
||||||
will stick to the terse syntax.
|
|
||||||
|
|
||||||
For completeness, here's the wrapped class in use: ::
|
|
||||||
|
|
||||||
>>> import hello
|
|
||||||
>>> planet = hello.World()
|
|
||||||
>>> planet.set('howdy')
|
|
||||||
>>> planet.greet()
|
|
||||||
'howdy'
|
|
||||||
|
|
||||||
Constructors
|
|
||||||
============
|
|
||||||
|
|
||||||
Since our ``World`` class is just a plain ``struct``, it has an
|
|
||||||
implicit no-argument (nullary) constructor. Boost.Python exposes the
|
|
||||||
nullary constructor by default, which is why we were able to write: ::
|
|
||||||
|
|
||||||
>>> planet = hello.World()
|
|
||||||
|
|
||||||
However, well-designed classes in any language may require constructor
|
|
||||||
arguments in order to establish their invariants. Unlike Python,
|
|
||||||
where ``__init__`` is just a specially-named method, In C++
|
|
||||||
constructors cannot be handled like ordinary member functions. In
|
|
||||||
particular, we can't take their address: ``&World::World`` is an
|
|
||||||
error. The library provides a different interface for specifying
|
|
||||||
constructors. Given::
|
|
||||||
|
|
||||||
struct World
|
|
||||||
{
|
|
||||||
World(std::string msg); // added constructor
|
|
||||||
...
|
|
||||||
|
|
||||||
we can modify our wrapping code as follows::
|
|
||||||
|
|
||||||
class_<World>("World", init<std::string>())
|
|
||||||
...
|
|
||||||
|
|
||||||
of course, a C++ class may have additional constructors, and we can
|
|
||||||
expose those as well by passing more instances of ``init<...>`` to
|
|
||||||
``def()``::
|
|
||||||
|
|
||||||
class_<World>("World", init<std::string>())
|
|
||||||
.def(init<double, double>())
|
|
||||||
...
|
|
||||||
|
|
||||||
Boost.Python allows wrapped functions, member functions, and
|
|
||||||
constructors to be overloaded to mirror C++ overloading.
|
|
||||||
|
|
||||||
Data Members and Properties
|
|
||||||
===========================
|
|
||||||
|
|
||||||
Any publicly-accessible data members in a C++ class can be easily
|
|
||||||
exposed as either ``readonly`` or ``readwrite`` attributes::
|
|
||||||
|
|
||||||
class_<World>("World", init<std::string>())
|
|
||||||
.def_readonly("msg", &World::msg)
|
|
||||||
...
|
|
||||||
|
|
||||||
and can be used directly in Python: ::
|
|
||||||
|
|
||||||
>>> planet = hello.World('howdy')
|
|
||||||
>>> planet.msg
|
|
||||||
'howdy'
|
|
||||||
|
|
||||||
This does *not* result in adding attributes to the ``World`` instance
|
|
||||||
``__dict__``, which can result in substantial memory savings when
|
|
||||||
wrapping large data structures. In fact, no instance ``__dict__``
|
|
||||||
will be created at all unless attributes are explicitly added from
|
|
||||||
Python. Boost.Python owes this capability to the new Python 2.2 type
|
|
||||||
system, in particular the descriptor interface and ``property`` type.
|
|
||||||
|
|
||||||
In C++, publicly-accessible data members are considered a sign of poor
|
|
||||||
design because they break encapsulation, and style guides usually
|
|
||||||
dictate the use of "getter" and "setter" functions instead. In
|
|
||||||
Python, however, ``__getattr__``, ``__setattr__``, and since 2.2,
|
|
||||||
``property`` mean that attribute access is just one more
|
|
||||||
well-encapsulated syntactic tool at the programmer's disposal.
|
|
||||||
Boost.Python bridges this idiomatic gap by making Python ``property``
|
|
||||||
creation directly available to users. If ``msg`` were private, we
|
|
||||||
could still expose it as attribute in Python as follows::
|
|
||||||
|
|
||||||
class_<World>("World", init<std::string>())
|
|
||||||
.add_property("msg", &World::greet, &World::set)
|
|
||||||
...
|
|
||||||
|
|
||||||
The example above mirrors the familiar usage of properties in Python
|
|
||||||
2.2+: ::
|
|
||||||
|
|
||||||
>>> class World(object):
|
|
||||||
... __init__(self, msg):
|
|
||||||
... self.__msg = msg
|
|
||||||
... def greet(self):
|
|
||||||
... return self.__msg
|
|
||||||
... def set(self, msg):
|
|
||||||
... self.__msg = msg
|
|
||||||
... msg = property(greet, set)
|
|
||||||
|
|
||||||
Operator Overloading
|
|
||||||
====================
|
|
||||||
|
|
||||||
The ability to write arithmetic operators for user-defined types has
|
|
||||||
been a major factor in the success of both languages for numerical
|
|
||||||
computation, and the success of packages like NumPy_ attests to the
|
|
||||||
power of exposing operators in extension modules. Boost.Python
|
|
||||||
provides a concise mechanism for wrapping operator overloads. The
|
|
||||||
example below shows a fragment from a wrapper for the Boost rational
|
|
||||||
number library::
|
|
||||||
|
|
||||||
class_<rational<int> >("rational_int")
|
|
||||||
.def(init<int, int>()) // constructor, e.g. rational_int(3,4)
|
|
||||||
.def("numerator", &rational<int>::numerator)
|
|
||||||
.def("denominator", &rational<int>::denominator)
|
|
||||||
.def(-self) // __neg__ (unary minus)
|
|
||||||
.def(self + self) // __add__ (homogeneous)
|
|
||||||
.def(self * self) // __mul__
|
|
||||||
.def(self + int()) // __add__ (heterogenous)
|
|
||||||
.def(int() + self) // __radd__
|
|
||||||
...
|
|
||||||
|
|
||||||
The magic is performed using a simplified application of "expression
|
|
||||||
templates" [VELD1995]_, a technique originally developed for
|
|
||||||
optimization of high-performance matrix algebra expressions. The
|
|
||||||
essence is that instead of performing the computation immediately,
|
|
||||||
operators are overloaded to construct a type *representing* the
|
|
||||||
computation. In matrix algebra, dramatic optimizations are often
|
|
||||||
available when the structure of an entire expression can be taken into
|
|
||||||
account, rather than evaluating each operation "greedily".
|
|
||||||
Boost.Python uses the same technique to build an appropriate Python
|
|
||||||
method object based on expressions involving ``self``.
|
|
||||||
|
|
||||||
.. _NumPy: http://www.pfdubois.com/numpy/
|
|
||||||
|
|
||||||
Inheritance
|
|
||||||
===========
|
|
||||||
|
|
||||||
C++ inheritance relationships can be represented to Boost.Python by adding
|
|
||||||
an optional ``bases<...>`` argument to the ``class_<...>`` template
|
|
||||||
parameter list as follows::
|
|
||||||
|
|
||||||
class_<Derived, bases<Base1,Base2> >("Derived")
|
|
||||||
...
|
|
||||||
|
|
||||||
This has two effects:
|
|
||||||
|
|
||||||
1. When the ``class_<...>`` is created, Python type objects
|
|
||||||
corresponding to ``Base1`` and ``Base2`` are looked up in
|
|
||||||
Boost.Python's registry, and are used as bases for the new Python
|
|
||||||
``Derived`` type object, so methods exposed for the Python ``Base1``
|
|
||||||
and ``Base2`` types are automatically members of the ``Derived``
|
|
||||||
type. Because the registry is global, this works correctly even if
|
|
||||||
``Derived`` is exposed in a different module from either of its
|
|
||||||
bases.
|
|
||||||
|
|
||||||
2. C++ conversions from ``Derived`` to its bases are added to the
|
|
||||||
Boost.Python registry. Thus wrapped C++ methods expecting (a
|
|
||||||
pointer or reference to) an object of either base type can be
|
|
||||||
called with an object wrapping a ``Derived`` instance. Wrapped
|
|
||||||
member functions of class ``T`` are treated as though they have an
|
|
||||||
implicit first argument of ``T&``, so these conversions are
|
|
||||||
neccessary to allow the base class methods to be called for derived
|
|
||||||
objects.
|
|
||||||
|
|
||||||
Of course it's possible to derive new Python classes from wrapped C++
|
|
||||||
class instances. Because Boost.Python uses the new-style class
|
|
||||||
system, that works very much as for the Python built-in types. There
|
|
||||||
is one significant detail in which it differs: the built-in types
|
|
||||||
generally establish their invariants in their ``__new__`` function, so
|
|
||||||
that derived classes do not need to call ``__init__`` on the base
|
|
||||||
class before invoking its methods : ::
|
|
||||||
|
|
||||||
>>> class L(list):
|
|
||||||
... def __init__(self):
|
|
||||||
... pass
|
|
||||||
...
|
|
||||||
>>> L().reverse()
|
|
||||||
>>>
|
|
||||||
|
|
||||||
Because C++ object construction is a one-step operation, C++ instance
|
|
||||||
data cannot be constructed until the arguments are available, in the
|
|
||||||
``__init__`` function: ::
|
|
||||||
|
|
||||||
>>> class D(SomeBoostPythonClass):
|
|
||||||
... def __init__(self):
|
|
||||||
... pass
|
|
||||||
...
|
|
||||||
>>> D().some_boost_python_method()
|
|
||||||
Traceback (most recent call last):
|
|
||||||
File "<stdin>", line 1, in ?
|
|
||||||
TypeError: bad argument type for built-in operation
|
|
||||||
|
|
||||||
This happened because Boost.Python couldn't find instance data of type
|
|
||||||
``SomeBoostPythonClass`` within the ``D`` instance; ``D``'s ``__init__``
|
|
||||||
function masked construction of the base class. It could be corrected
|
|
||||||
by either removing ``D``'s ``__init__`` function or having it call
|
|
||||||
``SomeBoostPythonClass.__init__(...)`` explicitly.
|
|
||||||
|
|
||||||
Virtual Functions
|
|
||||||
=================
|
|
||||||
|
|
||||||
Deriving new types in Python from extension classes is not very
|
|
||||||
interesting unless they can be used polymorphically from C++. In
|
|
||||||
other words, Python method implementations should appear to override
|
|
||||||
the implementation of C++ virtual functions when called *through base
|
|
||||||
class pointers/references from C++*. Since the only way to alter the
|
|
||||||
behavior of a virtual function is to override it in a derived class,
|
|
||||||
the user must build a special derived class to dispatch a polymorphic
|
|
||||||
class' virtual functions::
|
|
||||||
|
|
||||||
//
|
|
||||||
// interface to wrap:
|
|
||||||
//
|
|
||||||
class Base
|
|
||||||
{
|
|
||||||
public:
|
|
||||||
virtual int f(std::string x) { return 42; }
|
|
||||||
virtual ~Base();
|
|
||||||
};
|
|
||||||
|
|
||||||
int calls_f(Base const& b, std::string x) { return b.f(x); }
|
|
||||||
|
|
||||||
//
|
|
||||||
// Wrapping Code
|
|
||||||
//
|
|
||||||
|
|
||||||
// Dispatcher class
|
|
||||||
struct BaseWrap : Base
|
|
||||||
{
|
|
||||||
// Store a pointer to the Python object
|
|
||||||
BaseWrap(PyObject* self_) : self(self_) {}
|
|
||||||
PyObject* self;
|
|
||||||
|
|
||||||
// Default implementation, for when f is not overridden
|
|
||||||
int f_default(std::string x) { return this->Base::f(x); }
|
|
||||||
// Dispatch implementation
|
|
||||||
int f(std::string x) { return call_method<int>(self, "f", x); }
|
|
||||||
};
|
|
||||||
|
|
||||||
...
|
|
||||||
def("calls_f", calls_f);
|
|
||||||
class_<Base, BaseWrap>("Base")
|
|
||||||
.def("f", &Base::f, &BaseWrap::f_default)
|
|
||||||
;
|
|
||||||
|
|
||||||
Now here's some Python code which demonstrates: ::
|
|
||||||
|
|
||||||
>>> class Derived(Base):
|
|
||||||
... def f(self, s):
|
|
||||||
... return len(s)
|
|
||||||
...
|
|
||||||
>>> calls_f(Base(), 'foo')
|
|
||||||
42
|
|
||||||
>>> calls_f(Derived(), 'forty-two')
|
|
||||||
9
|
|
||||||
|
|
||||||
Things to notice about the dispatcher class:
|
|
||||||
|
|
||||||
* The key element which allows overriding in Python is the
|
|
||||||
``call_method`` invocation, which uses the same global type
|
|
||||||
conversion registry as the C++ function wrapping does to convert its
|
|
||||||
arguments from C++ to Python and its return type from Python to C++.
|
|
||||||
|
|
||||||
* Any constructor signatures you wish to wrap must be replicated with
|
|
||||||
an initial ``PyObject*`` argument
|
|
||||||
|
|
||||||
* The dispatcher must store this argument so that it can be used to
|
|
||||||
invoke ``call_method``
|
|
||||||
|
|
||||||
* The ``f_default`` member function is needed when the function being
|
|
||||||
exposed is not pure virtual; there's no other way ``Base::f`` can be
|
|
||||||
called on an object of type ``BaseWrap``, since it overrides ``f``.
|
|
||||||
|
|
||||||
Deeper Reflection on the Horizon?
|
|
||||||
=================================
|
|
||||||
|
|
||||||
Admittedly, this formula is tedious to repeat, especially on a project
|
|
||||||
with many polymorphic classes. That it is neccessary reflects some
|
|
||||||
limitations in C++'s compile-time introspection capabilities: there's
|
|
||||||
no way to enumerate the members of a class and find out which are
|
|
||||||
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_ 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
|
|
||||||
---------------
|
|
||||||
|
|
||||||
*Serialization* is the process of converting objects in memory to a
|
|
||||||
form that can be stored on disk or sent over a network connection. The
|
|
||||||
serialized object (most often a plain string) can be retrieved and
|
|
||||||
converted back to the original object. A good serialization system will
|
|
||||||
automatically convert entire object hierarchies. Python's standard
|
|
||||||
``pickle`` module is just such a system. It leverages the language's strong
|
|
||||||
runtime introspection facilities for serializing practically arbitrary
|
|
||||||
user-defined objects. With a few simple and unintrusive provisions this
|
|
||||||
powerful machinery can be extended to also work for wrapped C++ objects.
|
|
||||||
Here is an example::
|
|
||||||
|
|
||||||
#include <string>
|
|
||||||
|
|
||||||
struct World
|
|
||||||
{
|
|
||||||
World(std::string a_msg) : msg(a_msg) {}
|
|
||||||
std::string greet() const { return msg; }
|
|
||||||
std::string msg;
|
|
||||||
};
|
|
||||||
|
|
||||||
#include <boost/python.hpp>
|
|
||||||
using namespace boost::python;
|
|
||||||
|
|
||||||
struct World_picklers : pickle_suite
|
|
||||||
{
|
|
||||||
static tuple
|
|
||||||
getinitargs(World const& w) { return make_tuple(w.greet()); }
|
|
||||||
};
|
|
||||||
|
|
||||||
BOOST_PYTHON_MODULE(hello)
|
|
||||||
{
|
|
||||||
class_<World>("World", init<std::string>())
|
|
||||||
.def("greet", &World::greet)
|
|
||||||
.def_pickle(World_picklers())
|
|
||||||
;
|
|
||||||
}
|
|
||||||
|
|
||||||
Now let's create a ``World`` object and put it to rest on disk::
|
|
||||||
|
|
||||||
>>> import hello
|
|
||||||
>>> import pickle
|
|
||||||
>>> a_world = hello.World("howdy")
|
|
||||||
>>> pickle.dump(a_world, open("my_world", "w"))
|
|
||||||
|
|
||||||
In a potentially *different script* on a potentially *different
|
|
||||||
computer* with a potentially *different operating system*::
|
|
||||||
|
|
||||||
>>> import pickle
|
|
||||||
>>> resurrected_world = pickle.load(open("my_world", "r"))
|
|
||||||
>>> resurrected_world.greet()
|
|
||||||
'howdy'
|
|
||||||
|
|
||||||
Of course the ``cPickle`` module can also be used for faster
|
|
||||||
processing.
|
|
||||||
|
|
||||||
Boost.Python's ``pickle_suite`` fully supports the ``pickle`` protocol
|
|
||||||
defined in the standard Python documentation. Like a __getinitargs__
|
|
||||||
function in Python, the pickle_suite's getinitargs() is responsible for
|
|
||||||
creating the argument tuple that will be use to reconstruct the pickled
|
|
||||||
object. The other elements of the Python pickling protocol,
|
|
||||||
__getstate__ and __setstate__ can be optionally provided via C++
|
|
||||||
getstate and setstate functions. C++'s static type system allows the
|
|
||||||
library to ensure at compile-time that nonsensical combinations of
|
|
||||||
functions (e.g. getstate without setstate) are not used.
|
|
||||||
|
|
||||||
Enabling serialization of more complex C++ objects requires a little
|
|
||||||
more work than is shown in the example above. Fortunately the
|
|
||||||
``object`` interface (see next section) greatly helps in keeping the
|
|
||||||
code manageable.
|
|
||||||
|
|
||||||
------------------
|
|
||||||
Object interface
|
|
||||||
------------------
|
|
||||||
|
|
||||||
Experienced 'C' language extension module authors will be familiar
|
|
||||||
with the ubiquitous ``PyObject*``, manual reference-counting, and the
|
|
||||||
need to remember which API calls return "new" (owned) references or
|
|
||||||
"borrowed" (raw) references. These constraints are not just
|
|
||||||
cumbersome but also a major source of errors, especially in the
|
|
||||||
presence of exceptions.
|
|
||||||
|
|
||||||
Boost.Python provides a class ``object`` which automates reference
|
|
||||||
counting and provides conversion to Python from C++ objects of
|
|
||||||
arbitrary type. This significantly reduces the learning effort for
|
|
||||||
prospective extension module writers.
|
|
||||||
|
|
||||||
Creating an ``object`` from any other type is extremely simple::
|
|
||||||
|
|
||||||
object s("hello, world"); // s manages a Python string
|
|
||||||
|
|
||||||
``object`` has templated interactions with all other types, with
|
|
||||||
automatic to-python conversions. It happens so naturally that it's
|
|
||||||
easily overlooked::
|
|
||||||
|
|
||||||
object ten_Os = 10 * s[4]; // -> "oooooooooo"
|
|
||||||
|
|
||||||
In the example above, ``4`` and ``10`` are converted to Python objects
|
|
||||||
before the indexing and multiplication operations are invoked.
|
|
||||||
|
|
||||||
The ``extract<T>`` class template can be used to convert Python objects
|
|
||||||
to C++ types::
|
|
||||||
|
|
||||||
double x = extract<double>(o);
|
|
||||||
|
|
||||||
If a conversion in either direction cannot be performed, an
|
|
||||||
appropriate exception is thrown at runtime.
|
|
||||||
|
|
||||||
The ``object`` type is accompanied by a set of derived types
|
|
||||||
that mirror the Python built-in types such as ``list``, ``dict``,
|
|
||||||
``tuple``, etc. as much as possible. This enables convenient
|
|
||||||
manipulation of these high-level types from C++::
|
|
||||||
|
|
||||||
dict d;
|
|
||||||
d["some"] = "thing";
|
|
||||||
d["lucky_number"] = 13;
|
|
||||||
list l = d.keys();
|
|
||||||
|
|
||||||
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.
|
|
||||||
|
|
||||||
=================
|
|
||||||
Thinking hybrid
|
|
||||||
=================
|
|
||||||
|
|
||||||
Because of the practical and mental difficulties of combining
|
|
||||||
programming languages, it is common to settle a single language at the
|
|
||||||
outset of any development effort. For many applications, performance
|
|
||||||
considerations dictate the use of a compiled language for the core
|
|
||||||
algorithms. Unfortunately, due to the complexity of the static type
|
|
||||||
system, the price we pay for runtime performance is often a
|
|
||||||
significant increase in development time. Experience shows that
|
|
||||||
writing maintainable C++ code usually takes longer and requires *far*
|
|
||||||
more hard-earned working experience than developing comparable Python
|
|
||||||
code. Even when developers are comfortable working exclusively in
|
|
||||||
compiled languages, they often augment their systems by some type of
|
|
||||||
ad hoc scripting layer for the benefit of their users without ever
|
|
||||||
availing themselves of the same advantages.
|
|
||||||
|
|
||||||
Boost.Python enables us to *think hybrid*. Python can be used for
|
|
||||||
rapidly prototyping a new application; its ease of use and the large
|
|
||||||
pool of standard libraries give us a head start on the way to a
|
|
||||||
working system. If necessary, the working code can be used to
|
|
||||||
discover rate-limiting hotspots. To maximize performance these can
|
|
||||||
be reimplemented in C++, together with the Boost.Python bindings
|
|
||||||
needed to tie them back into the existing higher-level procedure.
|
|
||||||
|
|
||||||
Of course, this *top-down* approach is less attractive if it is clear
|
|
||||||
from the start that many algorithms will eventually have to be
|
|
||||||
implemented in C++. Fortunately Boost.Python also enables us to
|
|
||||||
pursue a *bottom-up* approach. We have used this approach very
|
|
||||||
successfully in the development of a toolbox for scientific
|
|
||||||
applications. The toolbox started out mainly as a library of C++
|
|
||||||
classes with Boost.Python bindings, and for a while the growth was
|
|
||||||
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.jpg
|
|
||||||
|
|
||||||
This figure shows the estimated ratio of newly added C++ and Python
|
|
||||||
code over time as new algorithms are implemented. We expect this
|
|
||||||
ratio to level out near 70% Python. Being able to solve new problems
|
|
||||||
mostly in Python rather than a more difficult statically typed
|
|
||||||
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
|
|
||||||
=============
|
|
||||||
|
|
||||||
Boost.Python achieves seamless interoperability between two rich and
|
|
||||||
complimentary language environments. Because it leverages template
|
|
||||||
metaprogramming to introspect about types and functions, the user
|
|
||||||
never has to learn a third syntax: the interface definitions are
|
|
||||||
written in concise and maintainable C++. Also, the wrapping system
|
|
||||||
doesn't have to parse C++ headers or represent the type system: the
|
|
||||||
compiler does that work for us.
|
|
||||||
|
|
||||||
Computationally intensive tasks play to the strengths of C++ and are
|
|
||||||
often impossible to implement efficiently in pure Python, while jobs
|
|
||||||
like serialization that are trivial in Python can be very difficult in
|
|
||||||
pure C++. Given the luxury of building a hybrid software system from
|
|
||||||
the ground up, we can approach design with new confidence and power.
|
|
||||||
|
|
||||||
===========
|
|
||||||
Citations
|
|
||||||
===========
|
|
||||||
|
|
||||||
.. [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
|
|
||||||
|
|||||||
@@ -273,7 +273,7 @@ correctly:
|
|||||||
==================
|
==================
|
||||||
|
|
||||||
This section outlines some of the library's major features. Except as
|
This section outlines some of the library's major features. Except as
|
||||||
neccessary to avoid confusion, details of library implementation are
|
necessary to avoid confusion, details of library implementation are
|
||||||
omitted.
|
omitted.
|
||||||
|
|
||||||
-------------------------------------------
|
-------------------------------------------
|
||||||
@@ -537,7 +537,7 @@ This has two effects:
|
|||||||
called with an object wrapping a ``Derived`` instance. Wrapped
|
called with an object wrapping a ``Derived`` instance. Wrapped
|
||||||
member functions of class ``T`` are treated as though they have an
|
member functions of class ``T`` are treated as though they have an
|
||||||
implicit first argument of ``T&``, so these conversions are
|
implicit first argument of ``T&``, so these conversions are
|
||||||
neccessary to allow the base class methods to be called for derived
|
necessary to allow the base class methods to be called for derived
|
||||||
objects.
|
objects.
|
||||||
|
|
||||||
Of course it's possible to derive new Python classes from wrapped C++
|
Of course it's possible to derive new Python classes from wrapped C++
|
||||||
@@ -650,7 +650,7 @@ Things to notice about the dispatcher class:
|
|||||||
called on an object of type ``BaseWrap``, since it overrides ``f``.
|
called on an object of type ``BaseWrap``, since it overrides ``f``.
|
||||||
|
|
||||||
Admittedly, this formula is tedious to repeat, especially on a project
|
Admittedly, this formula is tedious to repeat, especially on a project
|
||||||
with many polymorphic classes; that it is neccessary reflects
|
with many polymorphic classes; that it is necessary reflects
|
||||||
limitations in C++'s compile-time reflection capabilities. Several
|
limitations in C++'s compile-time reflection capabilities. Several
|
||||||
efforts are underway to write front-ends for Boost.Python which can
|
efforts are underway to write front-ends for Boost.Python which can
|
||||||
generate these dispatchers (and other wrapping code) automatically.
|
generate these dispatchers (and other wrapping code) automatically.
|
||||||
|
|||||||
@@ -16,7 +16,7 @@
|
|||||||
<tr>
|
<tr>
|
||||||
<td valign="top" width="300">
|
<td valign="top" width="300">
|
||||||
<h3><a href="../../../index.htm"><img height="86" width="277" alt=
|
<h3><a href="../../../index.htm"><img height="86" width="277" alt=
|
||||||
"C++ Boost" src="../../../c++boost.gif" border="0"></a></h3>
|
"C++ Boost" src="../../../boost.png" border="0"></a></h3>
|
||||||
</td>
|
</td>
|
||||||
|
|
||||||
<td valign="top">
|
<td valign="top">
|
||||||
@@ -55,15 +55,6 @@
|
|||||||
|
|
||||||
<dt><a href="#building_ext">Building your Extension Module</a></dt>
|
<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="#variants">Build Variants</a></dt>
|
||||||
|
|
||||||
<dt><a href="#VisualStudio">Building Using the Microsoft Visual Studio
|
<dt><a href="#VisualStudio">Building Using the Microsoft Visual Studio
|
||||||
@@ -83,17 +74,20 @@
|
|||||||
<p>Normally, Boost.Python extension modules must be linked with the
|
<p>Normally, Boost.Python extension modules must be linked with the
|
||||||
<code>boost_python</code> shared library. In special circumstances you
|
<code>boost_python</code> shared library. In special circumstances you
|
||||||
may want to link to a static version of the <code>boost_python</code>
|
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
|
together, it will prevent sharing of types across extension modules, and
|
||||||
consume extra code space. To build <code>boost_python</code>, use <a
|
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
|
||||||
from the <code>libs/python/build</code> subdirectory of your boost
|
usual way from the <code>libs/python/build</code> subdirectory of your
|
||||||
installation (if you have already built boost from the top level this may
|
boost installation (if you have already built boost from the top level
|
||||||
have no effect, since the work is already done).</p>
|
this may have no effect, since the work is already done).</p>
|
||||||
|
|
||||||
<h3><a name="configuration">Basic Configuration</a></h3>
|
<h3><a name="configuration">Basic Configuration</a></h3> You may
|
||||||
You may need to configure the following variables to point Boost.Build at
|
need to configure the following variables to point Boost.Build at
|
||||||
your Python installation:
|
your Python installation. Variables can be either set in the
|
||||||
|
environment or passed on the <code>bjam</code> command-line
|
||||||
|
as <code>-s</code><i>name</i><code>=</code><i>value</i>. Variable
|
||||||
|
names are case-sensitive.
|
||||||
|
|
||||||
<table border="1" summary="build configuration variables">
|
<table border="1" summary="build configuration variables">
|
||||||
<tr>
|
<tr>
|
||||||
@@ -107,28 +101,29 @@
|
|||||||
</tr>
|
</tr>
|
||||||
|
|
||||||
<tr>
|
<tr>
|
||||||
<td><code>PYTHON_ROOT</code></td>
|
|
||||||
|
|
||||||
<td>The root directory of your Python installation</td>
|
|
||||||
|
|
||||||
<td>Windows: <code>c:/tools/python</code>
|
|
||||||
Unix: <code>/usr/local</code></td>
|
|
||||||
|
|
||||||
<td>On Unix, this is the <code>--with-prefix=</code> directory used
|
|
||||||
to configure Python</td>
|
|
||||||
</tr>
|
|
||||||
|
|
||||||
<tr>
|
<tr>
|
||||||
<td><code>PYTHON_VERSION</code></td>
|
<td><code>PYTHON_VERSION</code></td>
|
||||||
|
|
||||||
<td>The The 2-part python Major.Minor version number</td>
|
<td>The The 2-part python Major.Minor version number</td>
|
||||||
|
|
||||||
<td><code>2.2</code></td>
|
<td><code>2.4</code></td>
|
||||||
|
|
||||||
<td>Be sure not to include a third number, e.g. <b>not</b>
|
<td>Be sure not to include a third number, e.g. <b>not</b>
|
||||||
"<code>2.2.1</code>", even if that's the version you have.</td>
|
"<code>2.2.1</code>", even if that's the version you have.</td>
|
||||||
</tr>
|
</tr>
|
||||||
|
|
||||||
|
<td><code>PYTHON_ROOT</code></td>
|
||||||
|
|
||||||
|
<td>The root directory of your Python installation</td>
|
||||||
|
|
||||||
|
<td>Windows: <code>c:/Python</code><i>(10*Version)</i>, e.g. <code>c:/Python24</code>
|
||||||
|
<br>
|
||||||
|
*nix/Cygwin: <code>/usr</code></td>
|
||||||
|
|
||||||
|
<td>On *nix, this should be the <code>--prefix=</code> directory used
|
||||||
|
to configure Python when it was built and installed.</td>
|
||||||
|
</tr>
|
||||||
|
|
||||||
<tr>
|
<tr>
|
||||||
<td><code>PYTHON_INCLUDES</code></td>
|
<td><code>PYTHON_INCLUDES</code></td>
|
||||||
|
|
||||||
@@ -181,7 +176,7 @@
|
|||||||
<tr>
|
<tr>
|
||||||
<td><code>CYGWIN_PYTHON_[DEBUG_]ROOT</code></td>
|
<td><code>CYGWIN_PYTHON_[DEBUG_]ROOT</code></td>
|
||||||
|
|
||||||
<td>unix-style path containing the <code>include/</code> directory
|
<td>*nix-style path containing the <code>include/</code> directory
|
||||||
containing
|
containing
|
||||||
<code>python$(CYGWIN_PYTHON_[DEBUG_]VERSION)/python.h</code>.</td>
|
<code>python$(CYGWIN_PYTHON_[DEBUG_]VERSION)/python.h</code>.</td>
|
||||||
|
|
||||||
@@ -228,8 +223,10 @@
|
|||||||
<h3><a name="mingw">Notes for MinGW (and Cygwin with -mno-cygwin) GCC
|
<h3><a name="mingw">Notes for MinGW (and Cygwin with -mno-cygwin) GCC
|
||||||
Users</a></h3>
|
Users</a></h3>
|
||||||
|
|
||||||
<p>You will need to create a MinGW-compatible version of the Python
|
<p>If you are using a version of Python prior to 2.4.1 with a
|
||||||
library; the one shipped with Python will only work with a
|
MinGW prior to 3.0.0 (with binutils-2.13.90-20030111-1), 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
|
Microsoft-compatible linker. Follow the instructions in the
|
||||||
"Non-Microsoft" section of the "Building Extensions: Tips And Tricks"
|
"Non-Microsoft" section of the "Building Extensions: Tips And Tricks"
|
||||||
chapter in <a href=
|
chapter in <a href=
|
||||||
@@ -258,68 +255,102 @@
|
|||||||
<blockquote>
|
<blockquote>
|
||||||
<pre>
|
<pre>
|
||||||
bjam -sTOOLS=<i><a href=
|
bjam -sTOOLS=<i><a href=
|
||||||
"../../../tools/build/index.html#Tools">toolset</a></i> test
|
"../../../more/getting_started.html#Tools">toolset</a></i> test
|
||||||
</pre>
|
</pre>
|
||||||
</blockquote>
|
</blockquote>
|
||||||
This will update all of the Boost.Python v1 test and example targets. The
|
This will update all of the Boost.Python v1 test and example targets. The
|
||||||
tests are relatively quiet by default. To get more-verbose output, you
|
tests are relatively verbose by default. To get less-verbose output, you
|
||||||
might try
|
might try
|
||||||
|
|
||||||
<blockquote>
|
<blockquote>
|
||||||
<pre>
|
<pre>
|
||||||
bjam -sTOOLS=<i><a href=
|
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= test
|
||||||
</pre>
|
</pre>
|
||||||
</blockquote>
|
</blockquote>
|
||||||
which will print each test's Python code with the expected output as it
|
By default, <code>PYTHON_TEST_ARGS</code> is set to <code>-v</code>.
|
||||||
passes.
|
|
||||||
|
|
||||||
<h2><a name="building_ext">Building your Extension Module</a></h2>
|
<h2><a name="building_ext">Building your Extension Module</a></h2>
|
||||||
Though there are other approaches, the best way to build an extension
|
Though there are other approaches, the smoothest and most reliable way to
|
||||||
module using Boost.Python is with Boost.Build. If you have to use another
|
build an extension module using Boost.Python is with Boost.Build. If you
|
||||||
build system, you should use Boost.Build at least once with the
|
have to use another build system, you should use Boost.Build at least
|
||||||
"<code><b>-n</b></code>" option so you can see the command-lines it uses,
|
once with the "<code><b>-n</b></code>" option so you can see the
|
||||||
and replicate them. You are likely to run into compilation or linking
|
command-lines it uses, and replicate them. You are likely to run into
|
||||||
problems otherwise.
|
compilation or linking problems otherwise.
|
||||||
|
|
||||||
<h3><a name="easy">The Easy Way</a></h3>
|
<p>The files required to build a Boost.Python extension module using bjam
|
||||||
Until Boost.Build v2 is released, cross-project build dependencies are
|
are the "local" files <tt>Jamfile</tt>, <tt>Jamrules</tt>, and
|
||||||
not supported, so it works most smoothly if you add a new subproject to
|
<tt>boost_build.jam</tt>, and the <tt>boost/</tt>
|
||||||
your boost installation. The <code>libs/python/example</code>
|
and <tt>tools/build/v1/</tt> subdirectories of your Boost
|
||||||
subdirectory of your boost installation contains a minimal example (along
|
tree. The latter directory contains the source code of the
|
||||||
with many extra sources). To copy the example subproject:
|
Boost.Build system, which is used to generate the correct build
|
||||||
|
commands for your extension module. The '<tt>v1</tt>' refers to
|
||||||
|
Boost.Build version 1. Version 2 is pre-release and currently not
|
||||||
|
ready for general use.
|
||||||
|
|
||||||
|
<p>
|
||||||
|
The <tt>libs/python/example/</tt> project we're going to build is
|
||||||
|
set up to automatically rebuild the Boost.Python library in place
|
||||||
|
whenever it's out-of-date rather than just reusing an existing
|
||||||
|
library, so you'll also need the Boost.Python library sources in
|
||||||
|
<tt>boost/python/src/</tt>.
|
||||||
|
</p>
|
||||||
|
|
||||||
|
<blockquote>
|
||||||
|
<b>Note:</b> Third-party package and distribution maintainers
|
||||||
|
for various operating systems sometimes split up Boost's
|
||||||
|
structure or omit parts of it, so if you didn't download an
|
||||||
|
official <a href=
|
||||||
|
"http://sourceforge.net/project/showfiles.php?group_id=7586">Boost
|
||||||
|
release</a> you might want to <a href=
|
||||||
|
"http://cvs.sourceforge.net/viewcvs.py/boost/boost/">browse our CVS
|
||||||
|
structure</a> to make sure you have everything you need, and in the
|
||||||
|
right places.
|
||||||
|
</blockquote>
|
||||||
|
|
||||||
|
<p>The <code>libs/python/example</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:</p>
|
||||||
|
|
||||||
<ol>
|
<ol>
|
||||||
<li>Create a new subdirectory in, <code>libs/python</code>, say
|
<li>
|
||||||
<code>libs/python/my_project</code>.</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=
|
<blockquote>
|
||||||
"../example/Jamfile">libs/python/example/Jamfile</a></code> to your new
|
<pre>
|
||||||
directory.</li>
|
boost-build ../../../tools/build/v1 ;
|
||||||
|
</pre>
|
||||||
|
</blockquote>
|
||||||
|
so that the path refers to the <code>tools/build/v1</code>
|
||||||
|
subdirectory of your Boost installation.
|
||||||
|
</li>
|
||||||
|
|
||||||
<li>Edit the Jamfile as appropriate for your project. You'll want to
|
<li>
|
||||||
change the "<code>subproject</code>" rule invocation at the top, and
|
<code><a href="../example/Jamrules"><b>Jamrules</b></a></code> - edit
|
||||||
the names of some of the source files and/or targets.</li>
|
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.
|
||||||
|
</li>
|
||||||
</ol>
|
</ol>
|
||||||
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
|
<p>The instructions <a href="#testing">above</a> for testing Boost.Python
|
||||||
tree</a></h3>
|
apply equally to your new extension modules in this subproject.</p>
|
||||||
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>
|
<h2><a name="variants">Build Variants</a></h2>
|
||||||
Three <a href=
|
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
|
configurations of all python-related targets are supported, and can be
|
||||||
selected by setting the <code><a href=
|
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:
|
variable:
|
||||||
|
|
||||||
<ul>
|
<ul>
|
||||||
@@ -334,7 +365,7 @@ bjam -sTOOLS=<i><a href=
|
|||||||
<p>The first two variants of the <code>boost_python</code> library are
|
<p>The first two variants of the <code>boost_python</code> library are
|
||||||
built by default, and are compatible with the default Python
|
built by default, and are compatible with the default Python
|
||||||
distribution. The <code>debug-python</code> variant corresponds to a
|
distribution. The <code>debug-python</code> variant corresponds to a
|
||||||
specially-built debugging version of Python. On Unix platforms, this
|
specially-built debugging version of Python. On *nix platforms, this
|
||||||
python is built by adding <code>--with-pydebug</code> when configuring
|
python is built by adding <code>--with-pydebug</code> when configuring
|
||||||
the Python build. On Windows, the debugging version of Python is
|
the Python build. On Windows, the debugging version of Python is
|
||||||
generated by the "Win32 Debug" target of the <code>PCBuild.dsw</code>
|
generated by the "Win32 Debug" target of the <code>PCBuild.dsw</code>
|
||||||
@@ -371,8 +402,8 @@ bjam -sTOOLS=<i><a href=
|
|||||||
IDE</a></h2>
|
IDE</a></h2>
|
||||||
|
|
||||||
<p>For the those of you who feel more comfortable in the IDE world, a
|
<p>For the those of you who feel more comfortable in the IDE world, a
|
||||||
workspace and project file have been included in the <a href=
|
workspace and project file have been included in the <code>
|
||||||
"../build/VisualStudio">libs/python/build/VisualStudio</a> subdirectory.
|
libs/python/build/VisualStudio</code> subdirectory.
|
||||||
It builds release and debug versions of the Boost.Python libraries and
|
It builds release and debug versions of the Boost.Python libraries and
|
||||||
places them and the same directory as Jamfile build does, though the
|
places them and the same directory as Jamfile build does, though the
|
||||||
intermediate object files are placed in a different directory. The files
|
intermediate object files are placed in a different directory. The files
|
||||||
@@ -412,18 +443,18 @@ bjam -sTOOLS=<i><a href=
|
|||||||
|
|
||||||
<blockquote>
|
<blockquote>
|
||||||
<em>The Visual Studio project files are graciously contributed and
|
<em>The Visual Studio project files are graciously contributed and
|
||||||
maintained by <a href="mailto:brett.calcott@paradise.net.nz">Brett
|
maintained by <a href="mailto:brett.calcott@gmail.com">Brett
|
||||||
Calcott</a></em>.
|
Calcott</a></em>.
|
||||||
</blockquote>
|
</blockquote>
|
||||||
<hr>
|
<hr>
|
||||||
|
|
||||||
<p>© Copyright David Abrahams 2002. Permission to copy, use, modify,
|
<p>© Copyright David Abrahams 2002-2004. Permission to copy,
|
||||||
sell and distribute this document is granted provided this copyright
|
use, modify, sell and distribute this document is granted provided
|
||||||
notice appears in all copies. This document is provided ``as is'' without
|
this copyright notice appears in all copies. This document is
|
||||||
express or implied warranty, and with no claim as to its suitability for
|
provided ``as is'' without express or implied warranty, and with
|
||||||
any purpose.</p>
|
no claim as to its suitability for any purpose.</p>
|
||||||
|
|
||||||
<p>Updated: 29 December, 2002 (David Abrahams)</p>
|
<p>Updated: 13 April 2004 (David Abrahams)</p>
|
||||||
</body>
|
</body>
|
||||||
</html>
|
</html>
|
||||||
|
|
||||||
|
|||||||
@@ -5,7 +5,7 @@
|
|||||||
<meta name="generator" content=
|
<meta name="generator" content=
|
||||||
"HTML Tidy for Windows (vers 1st August 2002), see www.w3.org">
|
"HTML Tidy for Windows (vers 1st August 2002), see www.w3.org">
|
||||||
<meta http-equiv="Content-Type" content="text/html; charset=iso-8859-1">
|
<meta http-equiv="Content-Type" content="text/html; charset=iso-8859-1">
|
||||||
<link rel="stylesheet" type="text/css" href="boost.css">
|
<link rel="stylesheet" type="text/css" href="../../../boost.css">
|
||||||
|
|
||||||
<title>Boost.Python</title>
|
<title>Boost.Python</title>
|
||||||
</head>
|
</head>
|
||||||
@@ -16,7 +16,7 @@
|
|||||||
<tr>
|
<tr>
|
||||||
<td valign="top" width="300">
|
<td valign="top" width="300">
|
||||||
<h3><a href="../../../index.htm"><img height="86" width="277" alt=
|
<h3><a href="../../../index.htm"><img height="86" width="277" alt=
|
||||||
"C++ Boost" src="../../../c++boost.gif" border="0"></a></h3>
|
"C++ Boost" src="../../../boost.png" border="0"></a></h3>
|
||||||
</td>
|
</td>
|
||||||
|
|
||||||
<td valign="top">
|
<td valign="top">
|
||||||
@@ -24,10 +24,60 @@
|
|||||||
|
|
||||||
<h2 align="center">Index</h2>
|
<h2 align="center">Index</h2>
|
||||||
</td>
|
</td>
|
||||||
|
|
||||||
|
|
||||||
|
<td align="right">
|
||||||
|
|
||||||
|
<form method="get" action="http://www.google.com/custom">
|
||||||
|
<p>
|
||||||
|
<span id= "search-choice">
|
||||||
|
Search
|
||||||
|
<select name="hq" id="hq">
|
||||||
|
<option label="All Documentation" value=
|
||||||
|
"site:www.boost.org inurl:www.boost.org/libs/python/doc">
|
||||||
|
All Documentation
|
||||||
|
</option>
|
||||||
|
<option label="Tutorial" value=
|
||||||
|
"site:www.boost.org inurl:www.boost.org/libs/python/doc/tutorial">
|
||||||
|
Tutorial
|
||||||
|
</option>
|
||||||
|
<option label="Reference" value=
|
||||||
|
"site:www.boost.org inurl:www.boost.org/libs/python/doc/v2">
|
||||||
|
Reference
|
||||||
|
</option>
|
||||||
|
</select>
|
||||||
|
<br>
|
||||||
|
</span>
|
||||||
|
|
||||||
|
<span id="search-text">
|
||||||
|
<input type="text" name="q" id="q" size="31" maxlength="255" alt="Search Text" />
|
||||||
|
</span>
|
||||||
|
|
||||||
|
<br>
|
||||||
|
<span id= "google">
|
||||||
|
<a href= "http://www.google.com/search">
|
||||||
|
<img src="../../../more/google_logo_25wht.gif" alt="Google" border="0" /></a>Powered
|
||||||
|
</span>
|
||||||
|
|
||||||
|
<span id="go">
|
||||||
|
<input type="image" name="search" src="../../../more/space.gif" alt="Search" id="search-button" />
|
||||||
|
</span>
|
||||||
|
|
||||||
|
<br>
|
||||||
|
<input type="hidden" name="cof" value= "LW:277;L:http://www.boost.org/boost.png;LH:86;AH:center;GL:0;S:http://www.boost.org;AWFID:9b83d16ce652ed5a;" />
|
||||||
|
<input type="hidden" name="sa" value= "Google Search" />
|
||||||
|
<input type="hidden" name= "domains" value= "www.boost.org;mail.python.org" /></p>
|
||||||
|
</form>
|
||||||
|
|
||||||
|
</td>
|
||||||
|
</tr>
|
||||||
|
<tr>
|
||||||
|
|
||||||
</tr>
|
</tr>
|
||||||
</table>
|
</table>
|
||||||
<hr>
|
<hr>
|
||||||
|
|
||||||
|
|
||||||
<h2>Synopsis</h2>
|
<h2>Synopsis</h2>
|
||||||
Welcome to version 2 of <b>Boost.Python</b>, a C++ library which enables
|
Welcome to version 2 of <b>Boost.Python</b>, a C++ library which enables
|
||||||
seamless interoperability between C++ and the <a href=
|
seamless interoperability between C++ and the <a href=
|
||||||
@@ -73,6 +123,14 @@
|
|||||||
|
|
||||||
<dt><a href="v2/reference.html">Reference Manual</a></dt>
|
<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/configuration.html">Configuration Information</a></dt>
|
||||||
|
|
||||||
<dt><a href="v2/platforms.html">Known Working Platforms and
|
<dt><a href="v2/platforms.html">Known Working Platforms and
|
||||||
@@ -91,8 +149,10 @@
|
|||||||
<dt><a href="internals.html">Internals Documentation</a></dt>
|
<dt><a href="internals.html">Internals Documentation</a></dt>
|
||||||
|
|
||||||
<dt><a href="news.html">News/Change Log</a></dt>
|
<dt><a href="news.html">News/Change Log</a></dt>
|
||||||
|
|
||||||
|
<dt><a href="../todo.html">TODO list</a></dt>
|
||||||
|
|
||||||
<dt><a href="v2/progress_reports.html">LLNL Progress Reports</a></dt>
|
<dt><a href="v2/progress_reports.html">LLNL Progress Reports</a></dt>
|
||||||
|
|
||||||
<dt><a href="v2/acknowledgments.html">Acknowledgments</a></dt>
|
<dt><a href="v2/acknowledgments.html">Acknowledgments</a></dt>
|
||||||
</dl>
|
</dl>
|
||||||
@@ -108,12 +168,12 @@
|
|||||||
|
|
||||||
<p>Revised
|
<p>Revised
|
||||||
<!--webbot bot="Timestamp" S-Type="EDITED" S-Format="%d %B, %Y" startspan -->
|
<!--webbot bot="Timestamp" S-Type="EDITED" S-Format="%d %B, %Y" startspan -->
|
||||||
18 March, 2003
|
26 August, 2003
|
||||||
<!--webbot bot="Timestamp" endspan i-checksum="39359" -->
|
<!--webbot bot="Timestamp" endspan i-checksum="39359" -->
|
||||||
</p>
|
</p>
|
||||||
|
|
||||||
<p><i>© Copyright <a href="../../people/dave_abrahams.htm">Dave
|
<p><i>© Copyright <a href="../../../people/dave_abrahams.htm">Dave
|
||||||
Abrahams</a> 2002. All Rights Reserved.</i></p>
|
Abrahams</a> 2002-2003.</i></p>
|
||||||
</body>
|
</body>
|
||||||
</html>
|
</html>
|
||||||
|
|
||||||
|
|||||||
@@ -4,21 +4,21 @@
|
|||||||
<head>
|
<head>
|
||||||
<meta http-equiv="Content-Type" content="text/html; charset=utf-8" />
|
<meta http-equiv="Content-Type" content="text/html; charset=utf-8" />
|
||||||
<meta name="generator" content="Docutils 0.3.0: http://docutils.sourceforge.net/" />
|
<meta name="generator" content="Docutils 0.3.0: http://docutils.sourceforge.net/" />
|
||||||
<title>Boost Python Internals</title>
|
<title>Boost.Python Internals Boost</title>
|
||||||
<meta name="copyright" content="Copyright Brett Calcott and David Abrahams 2003. All rights reserved." />
|
|
||||||
<link rel="stylesheet" href="../../../rst.css" type="text/css" />
|
<link rel="stylesheet" href="../../../rst.css" type="text/css" />
|
||||||
</head>
|
</head>
|
||||||
<body>
|
<body>
|
||||||
<div class="document" id="boost-python-internals">
|
<div class="document" id="boost-python-internals-logo">
|
||||||
<h1 class="title">Boost Python Internals</h1>
|
<h1 class="title"><a class="reference" href="index.html">Boost.Python</a> Internals <a class="reference" href="../../../index.htm"><img alt="Boost" src="../../../boost.png" /></a></h1>
|
||||||
<h2 class="subtitle" id="a-conversation-between-brett-calcott-and-david-abrahams">A conversation between Brett Calcott and David Abrahams</h2>
|
<div class="section" id="a-conversation-between-brett-calcott-and-david-abrahams">
|
||||||
<table class="docinfo" frame="void" rules="none">
|
<h1><a name="a-conversation-between-brett-calcott-and-david-abrahams">A conversation between Brett Calcott and David Abrahams</a></h1>
|
||||||
<col class="docinfo-name" />
|
<table class="field-list" frame="void" rules="none">
|
||||||
<col class="docinfo-content" />
|
<col class="field-name" />
|
||||||
|
<col class="field-body" />
|
||||||
<tbody valign="top">
|
<tbody valign="top">
|
||||||
<tr><th class="docinfo-name">Copyright:</th>
|
<tr class="field"><th class="field-name">copyright:</th><td class="field-body">Copyright David Abrahams and Brett Calcott 2003. See
|
||||||
<td>Copyright Brett Calcott and David Abrahams 2003. All
|
accompanying <a class="reference" href="../../../LICENSE_1_0.txt">license</a> for terms of use.</td>
|
||||||
rights reserved.</td></tr>
|
</tr>
|
||||||
</tbody>
|
</tbody>
|
||||||
</table>
|
</table>
|
||||||
<p>In both of these cases, I'm quite capable of reading code - but the
|
<p>In both of these cases, I'm quite capable of reading code - but the
|
||||||
@@ -118,10 +118,11 @@ way from c++ to python and back again.</p>
|
|||||||
info in the LLNL progress reports and the messages they link to.
|
info in the LLNL progress reports and the messages they link to.
|
||||||
Also,</p>
|
Also,</p>
|
||||||
<blockquote>
|
<blockquote>
|
||||||
<a class="reference" href="http://mail.python.org/pipermail/c++-sig/2002-May/001023.html">http://mail.python.org/pipermail/c++-sig/2002-May/001023.html</a>
|
<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>
|
||||||
<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><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>
|
||||||
<a class="reference" href="http://aspn.activestate.com/ASPN/Mail/Message/1280898">http://aspn.activestate.com/ASPN/Mail/Message/1280898</a>
|
<p><a class="reference" href="http://aspn.activestate.com/ASPN/Mail/Message/1280898">http://aspn.activestate.com/ASPN/Mail/Message/1280898</a></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></blockquote>
|
<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>
|
<p>from c++ to python:</p>
|
||||||
<blockquote>
|
<blockquote>
|
||||||
<p>It depends on the type and the call policies in use or, for
|
<p>It depends on the type and the call policies in use or, for
|
||||||
@@ -174,10 +175,11 @@ possible, then construct the converted object as a second step.</p>
|
|||||||
</blockquote>
|
</blockquote>
|
||||||
</blockquote>
|
</blockquote>
|
||||||
</div>
|
</div>
|
||||||
|
</div>
|
||||||
<hr class="footer"/>
|
<hr class="footer"/>
|
||||||
<div class="footer">
|
<div class="footer">
|
||||||
<a class="reference" href="internals.rst">View document source</a>.
|
<a class="reference" href="internals.rst">View document source</a>.
|
||||||
Generated on: 2003-07-31 17:58 UTC.
|
Generated on: 2003-09-12 14:51 UTC.
|
||||||
Generated by <a class="reference" href="http://docutils.sourceforge.net/">Docutils</a> from <a class="reference" href="http://docutils.sourceforge.net/rst.html">reStructuredText</a> source.
|
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>
|
</div>
|
||||||
</body>
|
</body>
|
||||||
|
|||||||
@@ -1,13 +1,24 @@
|
|||||||
========================
|
===================================
|
||||||
Boost Python Internals
|
Boost.Python_ Internals |(logo)|__
|
||||||
========================
|
===================================
|
||||||
|
|
||||||
|
.. |(logo)| image:: ../../../boost.png
|
||||||
|
:alt: Boost
|
||||||
|
:class: boost-logo
|
||||||
|
|
||||||
|
__ ../../../index.htm
|
||||||
|
|
||||||
|
.. _`Boost.Python`: index.html
|
||||||
|
|
||||||
|
.. _license: ../../../LICENSE_1_0.txt
|
||||||
|
|
||||||
|
|
||||||
-------------------------------------------------------
|
-------------------------------------------------------
|
||||||
A conversation between Brett Calcott and David Abrahams
|
A conversation between Brett Calcott and David Abrahams
|
||||||
-------------------------------------------------------
|
-------------------------------------------------------
|
||||||
|
|
||||||
:copyright: Copyright Brett Calcott and David Abrahams 2003. All
|
:copyright: Copyright David Abrahams and Brett Calcott 2003. See
|
||||||
rights reserved.
|
accompanying license_ for terms of use.
|
||||||
|
|
||||||
In both of these cases, I'm quite capable of reading code - but the
|
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
|
thing I don't get from scanning the source is a sense of the
|
||||||
@@ -107,8 +118,11 @@ Can you gesture in the general direction where these things are done?
|
|||||||
Also,
|
Also,
|
||||||
|
|
||||||
http://mail.python.org/pipermail/c++-sig/2002-May/001023.html
|
http://mail.python.org/pipermail/c++-sig/2002-May/001023.html
|
||||||
|
|
||||||
http://mail.python.org/pipermail/c++-sig/2002-December/003115.html
|
http://mail.python.org/pipermail/c++-sig/2002-December/003115.html
|
||||||
|
|
||||||
http://aspn.activestate.com/ASPN/Mail/Message/1280898
|
http://aspn.activestate.com/ASPN/Mail/Message/1280898
|
||||||
|
|
||||||
http://mail.python.org/pipermail/c++-sig/2002-July/001755.html
|
http://mail.python.org/pipermail/c++-sig/2002-July/001755.html
|
||||||
|
|
||||||
from c++ to python:
|
from c++ to python:
|
||||||
|
|||||||
@@ -1,328 +0,0 @@
|
|||||||
<html>
|
|
||||||
|
|
||||||
<head>
|
|
||||||
<meta http-equiv="Content-Type" content="text/html; charset=windows-1252">
|
|
||||||
<title>A New Type Conversion Mechanism for Boost.Python</title>
|
|
||||||
</head>
|
|
||||||
|
|
||||||
<body bgcolor="#FFFFFF" text="#000000">
|
|
||||||
|
|
||||||
<p><img border="0" src="../../../c++boost.gif" width="277" height="86"
|
|
||||||
alt="boost logo"></p>
|
|
||||||
|
|
||||||
<h1>A New Type Conversion Mechanism for Boost.Python</h1>
|
|
||||||
|
|
||||||
<p>By <a href="../../../people/dave_abrahams.htm">David Abrahams</a>.
|
|
||||||
|
|
||||||
<h2>Introduction</h2>
|
|
||||||
|
|
||||||
This document describes a redesign of the mechanism for automatically
|
|
||||||
converting objects between C++ and Python. The current implementation
|
|
||||||
uses two functions for any type <tt>T</tt>:
|
|
||||||
|
|
||||||
<blockquote><pre>
|
|
||||||
U from_python(PyObject*, type<T>);
|
|
||||||
void to_python(V);
|
|
||||||
</pre></blockquote>
|
|
||||||
|
|
||||||
where U is convertible to T and T is convertible to V. These functions
|
|
||||||
are at the heart of C++/Python interoperability in Boost.Python, so
|
|
||||||
why would we want to change them? There are many reasons:
|
|
||||||
|
|
||||||
<h3>Bugs</h3>
|
|
||||||
<p>Firstly, the current mechanism relies on a common C++ compiler
|
|
||||||
bug. This is not just embarrassing: as compilers get to be more
|
|
||||||
conformant, the library stops working. The issue, in detail, is the
|
|
||||||
use of inline friend functions in templates to generate
|
|
||||||
conversions. It is a very powerful, and legal technique as long as
|
|
||||||
it's used correctly:
|
|
||||||
|
|
||||||
<blockquote><pre>
|
|
||||||
template <class Derived>
|
|
||||||
struct add_some_functions
|
|
||||||
{
|
|
||||||
friend <i>return-type</i> some_function1(..., Derived <i>cv-*-&-opt</i>, ...);
|
|
||||||
friend <i>return-type</i> some_function2(..., Derived <i>cv-*-&-opt</i>, ...);
|
|
||||||
};
|
|
||||||
|
|
||||||
template <class T>
|
|
||||||
struct some_template : add_some_functions<some_template<T> >
|
|
||||||
{
|
|
||||||
};
|
|
||||||
</pre></blockquote>
|
|
||||||
|
|
||||||
The <tt>add_some_functions</tt> template generates free functions
|
|
||||||
which operate on <tt>Derived</tt>, or on related types. Strictly
|
|
||||||
speaking the related types are not just cv-qualified <tt>Derived</tt>
|
|
||||||
values, pointers and/or references. Section 3.4.2 in the standard
|
|
||||||
describes exactly which types you must use as parameters to these
|
|
||||||
functions if you want the functions to be found
|
|
||||||
(there is also a less-technical description in section 11.5.1 of
|
|
||||||
C++PL3 <a href="#ref_1">[1]</a>). Suffice it to say that
|
|
||||||
with the current design, the <tt>from_python</tt> and
|
|
||||||
<tt>to_python</tt> functions are not supposed to be callable under any
|
|
||||||
conditions!
|
|
||||||
|
|
||||||
<h3>Compilation and Linking Time</h3>
|
|
||||||
|
|
||||||
The conversion functions generated for each wrapped class using the
|
|
||||||
above technique are not function templates, but regular functions. The
|
|
||||||
upshot is that they must <i>all</i> be generated regardless of whether
|
|
||||||
they are actually used. Generating all of those functions can slow
|
|
||||||
down module compilation, and resolving the references can slow down
|
|
||||||
linking.
|
|
||||||
|
|
||||||
<h3>Efficiency</h3>
|
|
||||||
|
|
||||||
The conversion functions are primarily used in (member) function
|
|
||||||
wrappers to convert the arguments and return values. Being functions,
|
|
||||||
converters have no interface which allows us to ask "will the
|
|
||||||
conversion succeed?" without calling the function. Since the
|
|
||||||
return value of the function must be the object to be passed as an
|
|
||||||
argument, Boost.Python currently uses C++ exception-handling to detect
|
|
||||||
an unsuccessful conversion. It's not a particularly good use of
|
|
||||||
exception-handling, since the failure is not handled very far from
|
|
||||||
where it occurred. More importantly, it means that C++ exceptions are
|
|
||||||
thrown during overload resolution as we seek an overload that matches
|
|
||||||
the arguments passed. Depending on the implementation, this approach
|
|
||||||
can result in significant slowdowns.
|
|
||||||
|
|
||||||
<p>It is also unclear that the current library generates a minimal
|
|
||||||
amount of code for any type conversion. Many of the conversion
|
|
||||||
functions are nontrivial, and partly because of compiler limitations,
|
|
||||||
they are declared <tt>inline</tt>. Also, we could have done a better
|
|
||||||
job separating the type-specific conversion code from the code which
|
|
||||||
is type-independent.
|
|
||||||
|
|
||||||
<h3>Cross-module Support</h3>
|
|
||||||
|
|
||||||
The current strategy requires every module to contain the definition
|
|
||||||
of conversions it uses. In general, a new module can never supply
|
|
||||||
conversion code which is used by another module. Ralf Grosse-Kunstleve
|
|
||||||
designed a clever system which imports conversions directly from one
|
|
||||||
library into another using some explicit declarations, but it has some
|
|
||||||
disadvantages also:
|
|
||||||
|
|
||||||
<ol>
|
|
||||||
<li>The system Ullrich Koethe designed for implicit conversion between
|
|
||||||
wrapped classes related through inheritance does not currently work if
|
|
||||||
the classes are defined in separate modules.
|
|
||||||
|
|
||||||
<li>The writer of the importing module is required to know the name of
|
|
||||||
the module supplying the imported conversions.
|
|
||||||
|
|
||||||
<li>There can be only one way to extract any given C++ type from a
|
|
||||||
Python object in a given module.
|
|
||||||
</ol>
|
|
||||||
|
|
||||||
The first item might be addressed by moving Boost.Python into a shared
|
|
||||||
library, but the other two cannot. Ralf turned the limitation in item
|
|
||||||
two into a feature: the required module is loaded implicitly when a
|
|
||||||
conversion it defines is invoked. We will probably want to provide
|
|
||||||
that functionality anyway, but it's not clear that we should require
|
|
||||||
the declaration of all such conversions. The final item is a more
|
|
||||||
serious limitation. If, for example, new numeric types are defined in
|
|
||||||
separate modules, and these types can all be converted to
|
|
||||||
<tt>double</tt>s, we have to choose just one conversion method.
|
|
||||||
|
|
||||||
<h3>Ease-of-use</h3>
|
|
||||||
|
|
||||||
One persistent source of confusion for users of Boost.Python has been
|
|
||||||
the fact that conversions for a class are not be visible at
|
|
||||||
compile-time until the declaration of that class has been seen. When
|
|
||||||
the user tries to expose a (member) function operating on or returning
|
|
||||||
an instance of the class in question, compilation fails...even though
|
|
||||||
the user goes on to expose the class in the same translation unit!
|
|
||||||
|
|
||||||
<p>
|
|
||||||
The new system lifts all compile-time checks for the existence of
|
|
||||||
particular type conversions and replaces them with runtime checks, in
|
|
||||||
true Pythonic style. While this might seem cavalier, the compile-time
|
|
||||||
checks are actually not much use in the current system if many classes
|
|
||||||
are wrapped in separate modules, since the checks are based only on
|
|
||||||
the user's declaration that the conversions exist.
|
|
||||||
|
|
||||||
<h2>The New Design</h2>
|
|
||||||
|
|
||||||
<h3>Motivation</h3>
|
|
||||||
|
|
||||||
The new design was heavily influenced by a desire to generate as
|
|
||||||
little code as possible in extension modules. Some of Boost.Python's
|
|
||||||
clients are enormous projects where link time is proportional to the
|
|
||||||
amount of object code, and there are many Python extension modules. As
|
|
||||||
such, we try to keep type-specific conversion code out of modules
|
|
||||||
other than the one the converters are defined in, and rely as much as
|
|
||||||
possible on centralized control through a shared library.
|
|
||||||
|
|
||||||
<h3>The Basics</h3>
|
|
||||||
|
|
||||||
The library contains a <tt>registry</tt> which maps runtime type
|
|
||||||
identifiers (actually an extension of <tt>std::type_info</tt> which
|
|
||||||
preserves references and constness) to entries containing type
|
|
||||||
converters. An <tt>entry</tt> can contain only one converter from C++ to Python
|
|
||||||
(<tt>wrapper</tt>), but many converters from Python to C++
|
|
||||||
(<tt>unwrapper</tt>s). <font color="#ff0000">What should happen if
|
|
||||||
multiple modules try to register wrappers for the same type?</font>. Wrappers
|
|
||||||
and unwrappers are known as <tt>body</tt> objects, and are accessed
|
|
||||||
by the user and the library (in its function-wrapping code) through
|
|
||||||
corresponding <tt>handle</tt> (<tt>wrap<T></tt> and
|
|
||||||
<tt>unwrap<T></tt>) objects. The <tt>handle</tt> objects are
|
|
||||||
extremely lightweight, and delegate <i>all</i> of their operations to
|
|
||||||
the corresponding <tt>body</tt>.
|
|
||||||
|
|
||||||
<p>
|
|
||||||
When a <tt>handle</tt> object is constructed, it accesses the
|
|
||||||
registry to find a corresponding <tt>body</tt> that can convert the
|
|
||||||
handle's constructor argument. Actually the registry record for any
|
|
||||||
type
|
|
||||||
<tt>T</tt>used in a module is looked up only once and stored in a
|
|
||||||
static <tt>registration<T></tt> object for efficiency. For
|
|
||||||
example, if the handle is an <tt>unwrap<Foo&></tt> object,
|
|
||||||
the <tt>entry</tt> for <tt>Foo&</tt> is looked up in the
|
|
||||||
<tt>registry</tt>, and each <tt>unwrapper</tt> it contains is queried
|
|
||||||
to determine if it can convert the
|
|
||||||
<tt>PyObject*</tt> with which the <tt>unwrap</tt> was constructed. If
|
|
||||||
a body object which can perform the conversion is found, a pointer to
|
|
||||||
it is stored in the handle. A body object may at any point store
|
|
||||||
additional data in the handle to speed up the conversion process.
|
|
||||||
|
|
||||||
<p>
|
|
||||||
Now that the handle has been constructed, the user can ask it whether
|
|
||||||
the conversion can be performed. All handles can be tested as though
|
|
||||||
they were convertible to <tt>bool</tt>; a <tt>true</tt> value
|
|
||||||
indicates success. If the user forges ahead and tries to do the
|
|
||||||
conversion without checking when no conversion is possible, an
|
|
||||||
exception will be thrown as usual. The conversion itself is performed
|
|
||||||
by the body object.
|
|
||||||
|
|
||||||
<h3>Handling complex conversions</h3>
|
|
||||||
|
|
||||||
<p>Some conversions may require a dynamic allocation. For example,
|
|
||||||
when a Python tuple is converted to a <tt>std::vector<double>
|
|
||||||
const&</tt>, we need some storage into which to construct the
|
|
||||||
vector so that a reference to it can be formed. Furthermore, multiple
|
|
||||||
conversions of the same type may need to be "active"
|
|
||||||
simultaneously, so we can't keep a single copy of the storage
|
|
||||||
anywhere. We could keep the storage in the <tt>body</tt> object, and
|
|
||||||
have the body clone itself in case the storage is used, but in that
|
|
||||||
case the storage in the body which lives in the registry is never
|
|
||||||
used. If the storage was actually an object of the target type (the
|
|
||||||
safest way in C++), we'd have to find a way to construct one for the
|
|
||||||
body in the registry, since it may not have a default constructor.
|
|
||||||
|
|
||||||
<p>
|
|
||||||
The most obvious way out of this quagmire is to allocate the object using a
|
|
||||||
<i>new-expression</i>, and store a pointer to it in the handle. Since
|
|
||||||
the <tt>body</tt> object knows everything about the data it needs to
|
|
||||||
allocate (if any), it is also given responsibility for destroying that
|
|
||||||
data. When the <tt>handle</tt> is destroyed it asks the <tt>body</tt>
|
|
||||||
object to tear down any data it may have stored there. In many ways,
|
|
||||||
you can think of the <tt>body</tt> as a "dynamically-determined
|
|
||||||
vtable" for the handle.
|
|
||||||
|
|
||||||
<h3>Eliminating Redundancy</h3>
|
|
||||||
|
|
||||||
If you look at the current Boost.Python code, you'll see that there
|
|
||||||
are an enormous number of conversion functions generated for each
|
|
||||||
wrapped class. For a given class <tt>T</tt>, functions are generated
|
|
||||||
to extract the following types <tt>from_python</tt>:
|
|
||||||
|
|
||||||
<blockquote><pre>
|
|
||||||
T*
|
|
||||||
T const*
|
|
||||||
T const* const&
|
|
||||||
T* const&
|
|
||||||
T&
|
|
||||||
T const&
|
|
||||||
T
|
|
||||||
std::auto_ptr<T>&
|
|
||||||
std::auto_ptr<T>
|
|
||||||
std::auto_ptr<T> const&
|
|
||||||
boost::shared_ptr<T>&
|
|
||||||
boost::shared_ptr<T>
|
|
||||||
boost::shared_ptr<T> const&
|
|
||||||
</pre></blockquote>
|
|
||||||
|
|
||||||
Most of these are implemented in terms of just a few conversions, and
|
|
||||||
<t>if you're lucky</t>, they will be inlined and cause no extra
|
|
||||||
overhead. In the new system, however, a significant amount of data
|
|
||||||
will be associated with each type that needs to be converted. We
|
|
||||||
certainly don't want to register a separate unwrapper object for all
|
|
||||||
of the above types.
|
|
||||||
|
|
||||||
<p>Fortunately, much of the redundancy can be eliminated. For example,
|
|
||||||
if we generate an unwrapper for <tt>T&</tt>, we don't need an
|
|
||||||
unwrapper for <tt>T const&</tt> or <tt>T</tt>. Accordingly, the user's
|
|
||||||
request to wrap/unwrap a given type is translated at compile-time into
|
|
||||||
a request which helps to eliminate redundancy. The rules used to
|
|
||||||
<tt>unwrap</tt> a type are:
|
|
||||||
|
|
||||||
<ol>
|
|
||||||
<li> Treat built-in types specially: when unwrapping a value or
|
|
||||||
constant reference to one of these, use a value for the target
|
|
||||||
type. It will bind to a const reference if neccessary, and more
|
|
||||||
importantly, avoids having to dynamically allocate room for
|
|
||||||
an lvalue of types which can be cheaply copied.
|
|
||||||
<li>
|
|
||||||
Reduce everything else to a reference to an un-cv-qualified type
|
|
||||||
where possible. Since cv-qualification is lost on Python
|
|
||||||
anyway, there's no point in trying to convert to a
|
|
||||||
<tt>const&</tt>. <font color="#ff0000">What about conversions
|
|
||||||
to values like the tuple->vector example above? It seems to me
|
|
||||||
that we don't want to make a <tt>vector<double>&</tt>
|
|
||||||
(non-const) converter available for that case. We may need to
|
|
||||||
rethink this slightly.</font>
|
|
||||||
</ol>
|
|
||||||
|
|
||||||
<p>To handle the problem described above in item 2, we modify the
|
|
||||||
procedure slightly. To unwrap any non-scalar <tt>T</tt>, we seek an
|
|
||||||
unwrapper for <tt>add_reference<T>::type</tt>. Unwrappers for
|
|
||||||
<tt>T const&</tt> always return <tt>T&</tt>, and are
|
|
||||||
registered under both <tt>T &</tt> and
|
|
||||||
<tt>T const&</tt>.
|
|
||||||
|
|
||||||
<p>For compilers not supporting partial specialization, unwrappers for
|
|
||||||
<tt>T const&</tt> must return <tt>T const&</tt>
|
|
||||||
(since constness can't be stripped), but a separate unwrapper object
|
|
||||||
need to be registered for <tt>T &</tt> and
|
|
||||||
<tt>T const&</tt> anyway, for the same reasons.
|
|
||||||
|
|
||||||
<font color="#ff0000">We may want to make it possible to compile as
|
|
||||||
though partial specialization were unavailable even on compilers where
|
|
||||||
it is available, in case modules could be compiled by different
|
|
||||||
compilers with compatible ABIs (e.g. Intel C++ and MSVC6).</font>
|
|
||||||
|
|
||||||
<h3>Efficient Argument Conversion</h3>
|
|
||||||
|
|
||||||
Since type conversions are primarily used in function wrappers, an
|
|
||||||
optimization is provided for the case where a group of conversions are
|
|
||||||
used together. Each <tt>handle</tt> class has a corresponding
|
|
||||||
"<tt>_more</tt>" class which does the same job, but has a
|
|
||||||
trivial destructor. Instead of asking each "<tt>_more</tt>"
|
|
||||||
handle to destroy its own body, it is linked into an endogenous list
|
|
||||||
managed by the first (ordinary) handle. The <tt>wrap</tt> and
|
|
||||||
<tt>unwrap</tt> destructors are responsible for traversing that list
|
|
||||||
and asking each <tt>body</tt> class to tear down its
|
|
||||||
<tt>handle</tt>. This mechanism is also used to determine if all of
|
|
||||||
the argument/return-value conversions can succeed with a single
|
|
||||||
function call in the function wrapping code. <font color="#ff0000">We
|
|
||||||
might need to handle return values in a separate step for Python
|
|
||||||
callbacks, since the availablility of a conversion won't be known
|
|
||||||
until the result object is retrieved.</font>
|
|
||||||
|
|
||||||
<br>
|
|
||||||
<hr>
|
|
||||||
<h2>References</h2>
|
|
||||||
|
|
||||||
<p><a name="ref_1">[1]</a>B. Stroustrup, The C++ Programming Language
|
|
||||||
Special Edition Addison-Wesley, ISBN 0-201-70073-5.
|
|
||||||
|
|
||||||
<hr>
|
|
||||||
<p>Revised <!--webbot bot="Timestamp" s-type="EDITED" s-format="%d %B %Y" startspan -->
|
|
||||||
13 November, 2002
|
|
||||||
<!--webbot bot="Timestamp" endspan i-checksum="31283" --></p>
|
|
||||||
<p>© Copyright David Abrahams, 2001</p>
|
|
||||||
|
|
||||||
</body>
|
|
||||||
|
|
||||||
</html>
|
|
||||||
@@ -1,111 +0,0 @@
|
|||||||
This hierarchy contains converter handle classes.
|
|
||||||
|
|
||||||
|
|
||||||
+-------------+
|
|
||||||
| noncopyable |
|
|
||||||
+-------------+
|
|
||||||
^
|
|
||||||
| A common base class used so that
|
|
||||||
+--------+--------+ conversions can be linked into a
|
|
||||||
| conversion_base | chain for efficient argument
|
|
||||||
+-----------------+ conversion
|
|
||||||
^
|
|
||||||
|
|
|
||||||
+---------+-----------+
|
|
||||||
| |
|
|
||||||
+-----------+----+ +------+-------+ only used for
|
|
||||||
| unwrap_more<T> | | wrap_more<T> | chaining, and don't manage any
|
|
||||||
+----------------+ +--------------+ resources.
|
|
||||||
^ ^
|
|
||||||
| |
|
|
||||||
+-----+-----+ +-------+-+ These converters are what users
|
|
||||||
| unwrap<T> | | wrap<T> | actually touch, but they do so
|
|
||||||
+-----------+ +---------+ through a type generator which
|
|
||||||
minimizes the number of converters
|
|
||||||
that must be generated, so they
|
|
||||||
|
|
||||||
|
|
||||||
Each unwrap<T>, unwrap_more<T>, wrap<T>, wrap_more<T> converter holds
|
|
||||||
a reference to an appropriate converter object
|
|
||||||
|
|
||||||
This hierarchy contains converter body classes
|
|
||||||
|
|
||||||
Exposes use/release which
|
|
||||||
are needed in case the converter
|
|
||||||
+-----------+ in the registry needs to be
|
|
||||||
| converter | cloned. That occurs when a
|
|
||||||
+-----------+ unwrap target type is not
|
|
||||||
^ contained within the Python object.
|
|
||||||
|
|
|
||||||
+------------------+-----+
|
|
||||||
| |
|
|
||||||
+--------+-------+ Exposes |
|
|
||||||
| unwrapper_base | convertible() |
|
|
||||||
+----------------+ |
|
|
||||||
^ |
|
|
||||||
| |
|
|
||||||
+--------+----+ +-----+-----+
|
|
||||||
| unwrapper<T>| | wrapper<T>|
|
|
||||||
+-------------+ +-----------+
|
|
||||||
Exposes T convert(PyObject*) Exposes PyObject* convert(T)
|
|
||||||
|
|
||||||
|
|
||||||
unwrap:
|
|
||||||
|
|
||||||
constructed with a PyObject*, whose reference count is
|
|
||||||
incremented.
|
|
||||||
|
|
||||||
find the registry entry for the target type
|
|
||||||
|
|
||||||
look in the collection of converters for one which claims to be
|
|
||||||
able to convert the PyObject to the target type.
|
|
||||||
|
|
||||||
stick a pointer to the unwrapper in the unwrap object
|
|
||||||
|
|
||||||
when unwrap is queried for convertibility, it checks to see
|
|
||||||
if it has a pointer to an unwrapper.
|
|
||||||
|
|
||||||
on conversion, the unwrapper is asked to allocate an
|
|
||||||
implementation if the unwrap object isn't already holding
|
|
||||||
one. The unwrap object "takes ownership" of the unwrapper's
|
|
||||||
implementation. No memory allocation will actually take place
|
|
||||||
unless this is a value conversion.
|
|
||||||
|
|
||||||
on destruction, the unwrapper is asked to free any implementation
|
|
||||||
held by the unwrap object. No memory deallocation actually
|
|
||||||
takes place unless this is a value conversion
|
|
||||||
|
|
||||||
on destruction, the reference count on the held PyObject is
|
|
||||||
decremented.
|
|
||||||
|
|
||||||
We need to make sure that by default, you can't instantiate
|
|
||||||
callback<> for reference and pointer return types: although the
|
|
||||||
unwrappers may exist, they may convert by-value, which would cause
|
|
||||||
the referent to be destroyed upon return.
|
|
||||||
|
|
||||||
wrap:
|
|
||||||
|
|
||||||
find the registry entry for the source type
|
|
||||||
|
|
||||||
see if there is a converter. If found, stick a pointer to it in
|
|
||||||
the wrap object.
|
|
||||||
|
|
||||||
when queried for convertibility, it checks to see if it has a
|
|
||||||
pointer to a converter.
|
|
||||||
|
|
||||||
on conversion, a reference to the target PyObject is held by the
|
|
||||||
converter. Generally, the PyObject will have been created by the
|
|
||||||
converter, but in certain cases it may be a pre-existing object,
|
|
||||||
whose reference count will have been incremented.
|
|
||||||
|
|
||||||
when a wrap<T> x is used to return from a C++ function,
|
|
||||||
x.release() is returned so that x no longer holds a reference to
|
|
||||||
the PyObject when destroyed.
|
|
||||||
|
|
||||||
Otherwise, on destruction, any PyObject still held has its
|
|
||||||
reference-count decremented.
|
|
||||||
|
|
||||||
|
|
||||||
When a converter is created by the user, the appropriate element must
|
|
||||||
be added to the registry; when it is destroyed, it must be removed
|
|
||||||
from the registry.
|
|
||||||
344
doc/news.html
@@ -1,48 +1,184 @@
|
|||||||
<!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN">
|
<!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN">
|
||||||
|
|
||||||
<html>
|
<html>
|
||||||
<head>
|
<head>
|
||||||
<meta name="generator" content=
|
<meta name="generator" content=
|
||||||
"HTML Tidy for Cygwin (vers 1st April 2002), see www.w3.org">
|
"HTML Tidy for Cygwin (vers 1st September 2004), see www.w3.org">
|
||||||
<meta http-equiv="Content-Type" content="text/html; charset=iso-8859-1">
|
<meta http-equiv="Content-Type" content="text/html; charset=us-ascii">
|
||||||
<link rel="stylesheet" type="text/css" href="boost.css">
|
<link rel="stylesheet" type="text/css" href="boost.css">
|
||||||
|
|
||||||
<title>Boost.Python - News/Change Log</title>
|
<title>Boost.Python - News/Change Log</title>
|
||||||
</head>
|
</head>
|
||||||
|
|
||||||
<body link="#0000ff" vlink="#800080">
|
<body link="#0000FF" vlink="#800080">
|
||||||
<table border="0" cellpadding="7" cellspacing="0" width="100%" summary=
|
<table border="0" cellpadding="7" cellspacing="0" width="100%" summary=
|
||||||
"header">
|
"header">
|
||||||
<tr>
|
<tr>
|
||||||
<td valign="top" width="300">
|
<td valign="top" width="300">
|
||||||
<h3><a href="../../../index.htm"><img height="86" width="277" alt=
|
<h3><a href="../../../index.htm"><img height="86" width="277" alt=
|
||||||
"C++ Boost" src="../../../c++boost.gif" border="0"></a></h3>
|
"C++ Boost" src="../../../boost.png" border="0"></a></h3>
|
||||||
</td>
|
</td>
|
||||||
|
|
||||||
<td valign="top">
|
<td valign="top">
|
||||||
<h1 align="center"><a href="index.html">Boost.Python</a></h1>
|
<h1 align="center"><a href="index.html">Boost.Python</a></h1>
|
||||||
|
|
||||||
<h2 align="center">News/Change Log</h2>
|
<h2 align="center">News/Change Log</h2>
|
||||||
</td>
|
</td>
|
||||||
</tr>
|
</tr>
|
||||||
</table>
|
</table>
|
||||||
<hr>
|
<hr>
|
||||||
|
|
||||||
<dl class="page-index">
|
<dl class="page-index">
|
||||||
<dt>10 August 2003</dt>
|
<dt>Current CVS</dt>
|
||||||
|
|
||||||
<dd>Added the new <code>properties</code> unit tests contributed by <a
|
<dd>
|
||||||
href="mailto:romany-at-actimize.com">Roman Yakovenko</a> and documented
|
<ul>
|
||||||
<code>add_static_property</code> at his urging.</dd>
|
<li>C++ signatures are now automatically appended to the
|
||||||
|
docstrings.
|
||||||
|
|
||||||
<dt>1 August 2003</dt>
|
<li>New <a href="v2/docstring_options.html"
|
||||||
|
><code>docstring_options.hpp</code></a> header to
|
||||||
|
control the content of docstrings.
|
||||||
|
</ul>
|
||||||
|
</dd>
|
||||||
|
|
||||||
<dd>
|
<dt>19 October 2005 - 1.33.1 release</dt>
|
||||||
Added the new <code>arg</code> class contributed by <a href=
|
|
||||||
"mailto:nickm-at-sitius.com">Nikolay Mladenov</a> which supplies the
|
<dd>
|
||||||
ability to wrap functions that can be called with ommitted arguments
|
<ul>
|
||||||
in the middle:
|
<li><code>wrapper<T></code> can now be used as expected with a
|
||||||
<pre>
|
held type of <i>some-smart-pointer</i><code><T></code></li>
|
||||||
|
|
||||||
|
<li>The build now assumes Python 2.4 by default, rather than 2.2</li>
|
||||||
|
|
||||||
|
<li>Support Python that's built without Unicode support</li>
|
||||||
|
|
||||||
|
<li>Support for wrapping classes with overloaded address-of
|
||||||
|
(<code>&</code>) operators</li>
|
||||||
|
</ul>
|
||||||
|
</dd>
|
||||||
|
|
||||||
|
<dt>14 August 2005 - 1.33 release</dt>
|
||||||
|
|
||||||
|
<dd>
|
||||||
|
<ul>
|
||||||
|
<li>Support for docstrings on nonstatic properties.</li>
|
||||||
|
|
||||||
|
<li>We now export the client-provided docstrings for
|
||||||
|
<code>init<optional<> ></code> and
|
||||||
|
<i>XXX</i><code>_FUNCTION_OVERLOADS()</code> for only the last
|
||||||
|
overload.</li>
|
||||||
|
|
||||||
|
<li>Fixed some support for Embedded VC++ 4</li>
|
||||||
|
|
||||||
|
<li>Better support for rvalue from-python conversions of shared_ptr:
|
||||||
|
always return a pointer that holds the owning python object *unless*
|
||||||
|
the python object contains a NULL shared_ptr holder of the right
|
||||||
|
type.</li>
|
||||||
|
|
||||||
|
<li>Support for exposing <code>vector<T*></code> with the
|
||||||
|
indexing suite.</li>
|
||||||
|
|
||||||
|
<li>Support for GCC-3.3 on MacOS.</li>
|
||||||
|
|
||||||
|
<li>updated visual studio project build file to include two new files
|
||||||
|
(slice.cpp and wrapper.cpp)</li>
|
||||||
|
|
||||||
|
<li>Added search feature to the index page.</li>
|
||||||
|
|
||||||
|
<li>Numerous fixes to the tutorial</li>
|
||||||
|
|
||||||
|
<li>Numerous workarounds for MSVC 6 and 7, GCC 2.96, and EDG
|
||||||
|
2.45</li>
|
||||||
|
</ul>
|
||||||
|
</dd>
|
||||||
|
|
||||||
|
<dt>11 March 2005</dt>
|
||||||
|
|
||||||
|
<dd>
|
||||||
|
<ul>
|
||||||
|
<li>Added a hack that will fool PyDoc into working with Boost.Python,
|
||||||
|
thanks to Nick Rasmussen</li>
|
||||||
|
</ul>
|
||||||
|
</dd>
|
||||||
|
|
||||||
|
<dt>19 November 2004 - 1.32 release</dt>
|
||||||
|
|
||||||
|
<dd>
|
||||||
|
<ul>
|
||||||
|
<li>Updated to use the Boost Software License.</li>
|
||||||
|
|
||||||
|
<li>A new, <a href=
|
||||||
|
"tutorial/doc/html/python/exposing.html#python.class_virtual_functions">
|
||||||
|
better method of wrapping classes with virtual functions</a> has been
|
||||||
|
implemented.</li>
|
||||||
|
|
||||||
|
<li>Support for upcoming GCC symbol export control features have been
|
||||||
|
folded in, thanks to Niall Douglas.</li>
|
||||||
|
|
||||||
|
<li>Improved support for <code>std::auto_ptr</code>-like types.</li>
|
||||||
|
|
||||||
|
<li>The Visual C++ bug that makes top-level <i>cv-qualification</i>
|
||||||
|
of function parameter types part of the function type has been worked
|
||||||
|
around.</li>
|
||||||
|
|
||||||
|
<li>Components used by other libraries have been moved out of
|
||||||
|
<code>python/detail</code> and into <code>boost/detail</code> to
|
||||||
|
improve dependency relationships.</li>
|
||||||
|
|
||||||
|
<li>Miscellaneous bug fixes and compiler workarounds.</li>
|
||||||
|
</ul>
|
||||||
|
</dd>
|
||||||
|
|
||||||
|
<dt>8 Sept 2004</dt>
|
||||||
|
|
||||||
|
<dd>Support for Python's Bool type, thanks to <a href=
|
||||||
|
"mailto:dholth-at-fastmail.fm">Daniel Holth</a>.</dd>
|
||||||
|
|
||||||
|
<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"));
|
void f(int x = 0, double y = 3.14, std::string z = std::string("foo"));
|
||||||
|
|
||||||
BOOST_PYTHON_MODULE(test)
|
BOOST_PYTHON_MODULE(test)
|
||||||
@@ -51,110 +187,104 @@ BOOST_PYTHON_MODULE(test)
|
|||||||
, (arg("x", 0), arg("y", 3.14), arg("z", "foo")));
|
, (arg("x", 0), arg("y", 3.14), arg("z", "foo")));
|
||||||
}
|
}
|
||||||
|
|
||||||
</pre>
|
</pre>And in Python:
|
||||||
And in Python:
|
<pre>
|
||||||
<pre>
|
|
||||||
>>> import test
|
>>> import test
|
||||||
>>> f(0, z = "bar")
|
>>> f(0, z = "bar")
|
||||||
>>> f(z = "bar", y = 0.0)
|
>>> f(z = "bar", y = 0.0)
|
||||||
</pre>
|
</pre>Thanks, Nikolay!
|
||||||
Thanks, Nikolay!
|
</dd>
|
||||||
</dd>
|
|
||||||
|
|
||||||
<dt>22 July 2003</dt>
|
<dt>22 July 2003</dt>
|
||||||
|
|
||||||
<dd>Killed the dreaded "bad argument type for builtin operation" error.
|
<dd>Killed the dreaded "bad argument type for builtin operation" error.
|
||||||
Argument errors now show the actual and expected argument types!</dd>
|
Argument errors now show the actual and expected argument types!</dd>
|
||||||
|
|
||||||
<dt>19 July 2003</dt>
|
<dt>19 July 2003</dt>
|
||||||
|
|
||||||
<dd>Added the new <code><a href=
|
<dd>Added the new <code><a href=
|
||||||
"v2/return_arg.html">return_arg</a></code> policy from <a href=
|
"v2/return_arg.html">return_arg</a></code> policy from <a href=
|
||||||
"mailto:nickm-at-sitius.com">Nikolay Mladenov</a>. Thanks,
|
"mailto:nickm-at-sitius.com">Nikolay Mladenov</a>. Thanks, Nikolay!</dd>
|
||||||
Nikolay!</dd>
|
|
||||||
|
|
||||||
<dt>18 March, 2003</dt>
|
<dt>18 March, 2003</dt>
|
||||||
|
|
||||||
<dd><a href="mailto:Gottfried.Ganssauge-at-haufe.de">Gottfried
|
<dd><a href="mailto:Gottfried.Ganssauge-at-haufe.de">Gottfried
|
||||||
Ganßauge</a> has contributed <a href=
|
Ganßauge</a> has contributed <a href=
|
||||||
"v2/opaque_pointer_converter.html">opaque pointer support</a>.<br>
|
"v2/opaque_pointer_converter.html">opaque pointer support</a>.<br>
|
||||||
<a href="nicodemus-at-globalite.com.br">Bruno da Silva de Oliveira</a>
|
<a href="mailto:nicodemus-at-globalite.com.br">Bruno da Silva de
|
||||||
has contributed the exciting <a href="../pyste/index.html">Pyste</a>
|
Oliveira</a> has contributed the exciting <a href=
|
||||||
("Pie-steh") package.</dd>
|
"../pyste/index.html">Pyste</a> ("Pie-steh") package.</dd>
|
||||||
|
|
||||||
<dt>24 February 2003</dt>
|
<dt>24 February 2003</dt>
|
||||||
|
|
||||||
<dd>Finished improved support for <code>boost::shared_ptr</code>. Now
|
<dd>Finished improved support for <code>boost::shared_ptr</code>. Now any
|
||||||
any wrapped object of C++ class <code>X</code> can be converted
|
wrapped object of C++ class <code>X</code> can be converted automatically
|
||||||
automatically to <code>shared_ptr<X></code>, regardless of how it
|
to <code>shared_ptr<X></code>, regardless of how it was wrapped.
|
||||||
was wrapped. The <code>shared_ptr</code> will manage the lifetime of
|
The <code>shared_ptr</code> will manage the lifetime of the Python object
|
||||||
the Python object which supplied the <code>X</code>, rather than just
|
which supplied the <code>X</code>, rather than just the <code>X</code>
|
||||||
the <code>X</code> object itself, and when such a
|
object itself, and when such a <code>shared_ptr</code> is converted back
|
||||||
<code>shared_ptr</code> is converted back to Python, the original
|
to Python, the original Python object will be returned.</dd>
|
||||||
Python object will be returned.</dd>
|
|
||||||
|
|
||||||
<dt>19 January 2003</dt>
|
<dt>19 January 2003</dt>
|
||||||
|
|
||||||
<dd>Integrated <code>staticmethod</code> support from <a href=
|
<dd>Integrated <code>staticmethod</code> support from <a href=
|
||||||
"mailto:nickm-at-sitius.com">Nikolay Mladenov</a>. Thanks,
|
"mailto:nickm-at-sitius.com">Nikolay Mladenov</a>. Thanks, Nikolay!</dd>
|
||||||
Nikolay!</dd>
|
|
||||||
|
|
||||||
<dt>29 December 2002</dt>
|
<dt>29 December 2002</dt>
|
||||||
|
|
||||||
<dd>Added Visual Studio project file and instructions from Brett
|
<dd>Added Visual Studio project file and instructions from Brett Calcott.
|
||||||
Calcott. Thanks, Brett!</dd>
|
Thanks, Brett!</dd>
|
||||||
|
|
||||||
<dt>20 December 2002</dt>
|
<dt>20 December 2002</dt>
|
||||||
|
|
||||||
<dd>Added automatic downcasting for pointers, references, and smart
|
<dd>Added automatic downcasting for pointers, references, and smart
|
||||||
pointers to polymorphic class types upon conversion to python</dd>
|
pointers to polymorphic class types upon conversion to python</dd>
|
||||||
|
|
||||||
<dt>18 December 2002</dt>
|
<dt>18 December 2002</dt>
|
||||||
|
|
||||||
<dd>Optimized from_python conversions for wrapped classes by putting
|
<dd>Optimized from_python conversions for wrapped classes by putting the
|
||||||
the conversion logic in the shared library instead of registering
|
conversion logic in the shared library instead of registering separate
|
||||||
separate converters for each class in each extension module</dd>
|
converters for each class in each extension module</dd>
|
||||||
|
|
||||||
<dt>19 November 2002</dt>
|
<dt>19 November 2002</dt>
|
||||||
|
|
||||||
<dd>Removed the need for users to cast base class member function
|
<dd>Removed the need for users to cast base class member function
|
||||||
pointers when used as arguments to <a href=
|
pointers when used as arguments to <a href=
|
||||||
"v2/class.html#class_-spec-modifiers">add_property</a></dd>
|
"v2/class.html#class_-spec-modifiers">add_property</a></dd>
|
||||||
|
|
||||||
<dt>13 December 2002</dt>
|
<dt>13 December 2002</dt>
|
||||||
|
|
||||||
<dd>Allow exporting of <a href=
|
<dd>Allow exporting of <a href=
|
||||||
"v2/enum.html#enum_-spec"><code>enum_</code></a> values into enclosing
|
"v2/enum.html#enum_-spec"><code>enum_</code></a> values into enclosing
|
||||||
<a href="v2/scope.html#scope-spec"><code>scope</code></a>.<br>
|
<a href="v2/scope.html#scope-spec"><code>scope</code></a>.<br>
|
||||||
Fixed unsigned integer conversions to deal correctly with numbers that
|
Fixed unsigned integer conversions to deal correctly with numbers that
|
||||||
are out-of-range of <code>signed long</code>.</dd>
|
are out-of-range of <code>signed long</code>.</dd>
|
||||||
|
|
||||||
<dt>14 November 2002</dt>
|
<dt>14 November 2002</dt>
|
||||||
|
|
||||||
<dd>Auto-detection of class data members wrapped with <a href=
|
<dd>Auto-detection of class data members wrapped with <a href=
|
||||||
"v2/data_members.html#make_getter-spec"><code>make_getter</code></a></dd>
|
"v2/data_members.html#make_getter-spec"><code>make_getter</code></a></dd>
|
||||||
|
|
||||||
<dt>13 November 2002</dt>
|
<dt>13 November 2002</dt>
|
||||||
|
|
||||||
<dd>Full Support for <code>std::auto_ptr<></code> added.</dd>
|
<dd>Full Support for <code>std::auto_ptr<></code> added.</dd>
|
||||||
|
|
||||||
<dt>October 2002</dt>
|
<dt>October 2002</dt>
|
||||||
|
|
||||||
<dd>Ongoing updates and improvements to tutorial documentation</dd>
|
<dd>Ongoing updates and improvements to tutorial documentation</dd>
|
||||||
|
|
||||||
<dt>10 October 2002</dt>
|
<dt>10 October 2002</dt>
|
||||||
|
|
||||||
<dd>Boost.Python V2 is released!</dd>
|
<dd>Boost.Python V2 is released!</dd>
|
||||||
</dl>
|
</dl>
|
||||||
<hr>
|
<hr>
|
||||||
|
|
||||||
<p>Revised
|
<p>Revised
|
||||||
<!--webbot bot="Timestamp" S-Type="EDITED" S-Format="%d %B, %Y" startspan -->
|
<!--webbot bot="Timestamp" S-Type="EDITED" S-Format="%d %B, %Y" startspan -->
|
||||||
1 August 2003 <!--webbot bot="Timestamp" endspan i-checksum="39359" -->
|
19 November 2004
|
||||||
</p>
|
<!--webbot bot="Timestamp" endspan i-checksum="39359" --></p>
|
||||||
|
|
||||||
<p><i>© Copyright <a href="../../../people/dave_abrahams.htm">Dave
|
<p><i>© Copyright <a href="../../../people/dave_abrahams.htm">Dave
|
||||||
Abrahams</a> 2002-2003. All Rights Reserved.</i></p>
|
Abrahams</a> 2002-2003.</i></p>
|
||||||
</body>
|
</body>
|
||||||
</html>
|
</html>
|
||||||
|
|
||||||
|
|||||||
@@ -4,7 +4,7 @@
|
|||||||
<head>
|
<head>
|
||||||
<meta name="generator" content=
|
<meta name="generator" content=
|
||||||
"HTML Tidy for Cygwin (vers 1st April 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">
|
<meta http-equiv="Content-Type" content="text/html; charset="utf-8">
|
||||||
<link rel="stylesheet" type="text/css" href="boost.css">
|
<link rel="stylesheet" type="text/css" href="boost.css">
|
||||||
|
|
||||||
<title>Boost.Python - Projects using Boost.Python</title>
|
<title>Boost.Python - Projects using Boost.Python</title>
|
||||||
@@ -16,7 +16,7 @@
|
|||||||
<tr>
|
<tr>
|
||||||
<td valign="top" width="300">
|
<td valign="top" width="300">
|
||||||
<h3><a href="../../../index.htm"><img height="86" width="277" alt=
|
<h3><a href="../../../index.htm"><img height="86" width="277" alt=
|
||||||
"C++ Boost" src="../../../c++boost.gif" border="0"></a></h3>
|
"C++ Boost" src="../../../boost.png" border="0"></a></h3>
|
||||||
</td>
|
</td>
|
||||||
|
|
||||||
<td valign="top">
|
<td valign="top">
|
||||||
@@ -42,7 +42,7 @@
|
|||||||
|
|
||||||
<dl class="page-index">
|
<dl class="page-index">
|
||||||
<dt><b><a href=
|
<dt><b><a href=
|
||||||
"http://www.neuralynx.com/neuralab/index.htm">NeuraLab</a></b></dt>
|
"http://www.neuralynx.com">NeuraLab</a></b></dt>
|
||||||
|
|
||||||
<dd>Neuralab is a data analysis environment specifically tailored for
|
<dd>Neuralab is a data analysis environment specifically tailored for
|
||||||
neural data from <a href="http://www.neuralynx.com">Neuralynx</a>
|
neural data from <a href="http://www.neuralynx.com">Neuralynx</a>
|
||||||
@@ -139,6 +139,59 @@
|
|||||||
</dd>
|
</dd>
|
||||||
</dl>
|
</dl>
|
||||||
|
|
||||||
|
<h3>Games</h3>
|
||||||
|
|
||||||
|
<dl>
|
||||||
|
<dt><b><a href="http://www.firaxis.com">Civilization IV</a></b></dt>
|
||||||
|
</dl>
|
||||||
|
|
||||||
|
<blockquote>
|
||||||
|
“The fourth game in the PC strategy series that has
|
||||||
|
sold over five million copies, Sid Meier's Civilization IV is a bold
|
||||||
|
step forward for the franchise, with spectacular new 3D graphics and
|
||||||
|
all-new single and multiplayer content. Civilization IV will also set a
|
||||||
|
new standard for user-modification, allowing gamers to create their own
|
||||||
|
add-ons using Python and XML.
|
||||||
|
|
||||||
|
<p>Sid Meier's Civilization IV will be released for PC in late 2005.
|
||||||
|
For more information please visit <a href=
|
||||||
|
"http://www.firaxis.com">http://www.firaxis.com</a> or write <a href=
|
||||||
|
"mailto:kgilmore@firaxis.com">kgilmore@firaxis.com</a>”</p>
|
||||||
|
</blockquote>
|
||||||
|
|
||||||
|
<p>Boost.Python is used as the interface layer between the C++ game code
|
||||||
|
and Python. Python is used for many purposes in the game, including map
|
||||||
|
generation, interface screens, game events, tools, tutorials, etc. Most
|
||||||
|
high-level game operations have been exposed to Python in order to give
|
||||||
|
modders the power they need to customize the game.</p>
|
||||||
|
|
||||||
|
<blockquote>
|
||||||
|
-Mustafa Thamer, Civ4 Lead Programmer
|
||||||
|
</blockquote>
|
||||||
|
|
||||||
|
<dl class="page-index">
|
||||||
|
<dt><b><a href="http://vegastrike.sourceforge.net">Vega
|
||||||
|
Strike</a></b></dt>
|
||||||
|
|
||||||
|
<dd>
|
||||||
|
<a href="http://vegastrike.sourceforge.net">Vega Strike</a> is the 3D
|
||||||
|
Space Simulator that allows you to trade and bounty hunt in a vast
|
||||||
|
universe. Players face dangers, decisions, piracy, and aliens.
|
||||||
|
|
||||||
|
<p><a href="http://vegastrike.sourceforge.net">Vega Strike</a> has
|
||||||
|
decided to base its scripting on python, using boost as the layer
|
||||||
|
between the class hierarchy in python and the class hierarchy in C++.
|
||||||
|
The result is a very flexible scripting system that treats units as
|
||||||
|
native python classes when designing missions or writing AI's.</p>
|
||||||
|
|
||||||
|
<p>A large economic and planetary simulation is currently being run
|
||||||
|
in the background in python and the results are returned back into
|
||||||
|
C++ in the form of various factions' spaceships appearing near worlds
|
||||||
|
that they are simulated to be near in python if the player is in the
|
||||||
|
general neighborhood.</p>
|
||||||
|
</dd>
|
||||||
|
</dl>
|
||||||
|
|
||||||
<h3>Graphics</h3>
|
<h3>Graphics</h3>
|
||||||
|
|
||||||
<dl class="page-index">
|
<dl class="page-index">
|
||||||
@@ -151,14 +204,6 @@
|
|||||||
C++/OpenGL library for the real-time visualization.<br>
|
C++/OpenGL library for the real-time visualization.<br>
|
||||||
</dd>
|
</dd>
|
||||||
|
|
||||||
<dt><a href=
|
|
||||||
"http://www.procoders.net/pythonmagick"><b>PythonMagick</b></a></dt>
|
|
||||||
|
|
||||||
<dd>PythonMagick binds the <a href=
|
|
||||||
"http://www.graphicsmagick.org">GraphicsMagick</a> image manipulation
|
|
||||||
library to Python.<br>
|
|
||||||
</dd>
|
|
||||||
|
|
||||||
<dt><b><a href=
|
<dt><b><a href=
|
||||||
"http://www.slac.stanford.edu/grp/ek/hippodraw/index.html">HippoDraw</a></b></dt>
|
"http://www.slac.stanford.edu/grp/ek/hippodraw/index.html">HippoDraw</a></b></dt>
|
||||||
|
|
||||||
@@ -182,6 +227,35 @@
|
|||||||
Which was just too cool a piece of trivia to omit.<br>
|
Which was just too cool a piece of trivia to omit.<br>
|
||||||
|
|
||||||
</dd>
|
</dd>
|
||||||
|
|
||||||
|
<dt><a href="http://www.iplt.org"><b>IPLT</b></a></dt>
|
||||||
|
|
||||||
|
<dd>
|
||||||
|
<a href="mailto:ansgar.philippsen-at-unibas.ch">Ansgar Philippsen</a>
|
||||||
|
writes:
|
||||||
|
|
||||||
|
<blockquote>
|
||||||
|
IPLT is an image processing library and toolbox for the structural
|
||||||
|
biology electron microscopy community. I would call it a
|
||||||
|
budding/evolving project, since it is currently not in production
|
||||||
|
stage, but rather under heavy development. Python is used as the
|
||||||
|
main scripting/interaction level, but also for rapid prototyping,
|
||||||
|
since the underlying C++ class library is pretty much fully exposed
|
||||||
|
via boost.python (at least the high-level interface). The combined
|
||||||
|
power of C++ and Python for this project turned out to be just
|
||||||
|
awesome.
|
||||||
|
</blockquote>
|
||||||
|
<br>
|
||||||
|
|
||||||
|
</dd>
|
||||||
|
|
||||||
|
<dt><a href=
|
||||||
|
"http://www.procoders.net/pythonmagick"><b>PythonMagick</b></a></dt>
|
||||||
|
|
||||||
|
<dd>PythonMagick binds the <a href=
|
||||||
|
"http://www.graphicsmagick.org">GraphicsMagick</a> image manipulation
|
||||||
|
library to Python.<br>
|
||||||
|
</dd>
|
||||||
</dl>
|
</dl>
|
||||||
|
|
||||||
<h3>Scientific Computing</h3>
|
<h3>Scientific Computing</h3>
|
||||||
@@ -277,13 +351,13 @@
|
|||||||
|
|
||||||
<p>Two projects have been developed so far with this technology:</p>
|
<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>
|
<p><b><a href="http://www.esss.com.br/index.php?pg=dev_projetos">Simba</a></b>
|
||||||
provides 3D visualization of geological formations gattered from the
|
provides 3D visualization of geological formations gattered from the
|
||||||
simulation of the evolution of oil systems, allowing the user to
|
simulation of the evolution of oil systems, allowing the user to
|
||||||
analyse various aspects of the simulation, like deformation, pressure
|
analyse various aspects of the simulation, like deformation, pressure
|
||||||
and fluids, along the time of the simulation.</p>
|
and fluids, along the time of the simulation.</p>
|
||||||
|
|
||||||
<p><b><a href="http://www.esss.com.br/dev_aero.phtml">Aero</a></b>
|
<p><b><a href="http://www.esss.com.br/index.php?pg=dev_projetos">Aero</a></b>
|
||||||
aims to construct a CFD with brazilian technology, which involves
|
aims to construct a CFD with brazilian technology, which involves
|
||||||
various companies and universities. ESSS is responsible for various
|
various companies and universities. ESSS is responsible for various
|
||||||
of the application modules, including GUI and post-processing of
|
of the application modules, including GUI and post-processing of
|
||||||
@@ -314,6 +388,24 @@
|
|||||||
</dd>
|
</dd>
|
||||||
</dl>
|
</dl>
|
||||||
|
|
||||||
|
<h3>Systems Libraries</h3>
|
||||||
|
|
||||||
|
<dl>
|
||||||
|
<dt><a href="http://itamarst.org/software"><b>Fusion</b></a></dt>
|
||||||
|
|
||||||
|
<dd>
|
||||||
|
<p>Fusion is a library that supports implementing protocols in C++
|
||||||
|
for use with Twisted, allowing control over memory allocation
|
||||||
|
strategies, fast method calls internally, etc.. Fusion supports TCP,
|
||||||
|
UDP and multicast, and is implemented using the Boost.Python python
|
||||||
|
bindings.</p>
|
||||||
|
|
||||||
|
<p>Fusion is licensed under the MIT license, and available for
|
||||||
|
download from <a href=
|
||||||
|
"http://itamarst.org/software">http://itamarst.org/software</a>.</p>
|
||||||
|
</dd>
|
||||||
|
</dl>
|
||||||
|
|
||||||
<h3>Tools</h3>
|
<h3>Tools</h3>
|
||||||
|
|
||||||
<dl>
|
<dl>
|
||||||
@@ -338,7 +430,7 @@
|
|||||||
15 July, 2003</p>
|
15 July, 2003</p>
|
||||||
|
|
||||||
<p><i>© Copyright <a href="../../../people/dave_abrahams.htm">Dave
|
<p><i>© Copyright <a href="../../../people/dave_abrahams.htm">Dave
|
||||||
Abrahams</a> 2002-2003. All Rights Reserved.</i></p>
|
Abrahams</a> 2002-2003.</i></p>
|
||||||
</body>
|
</body>
|
||||||
</html>
|
</html>
|
||||||
|
|
||||||
|
|||||||
@@ -3,7 +3,7 @@
|
|||||||
<html>
|
<html>
|
||||||
<head>
|
<head>
|
||||||
<meta name="generator" content=
|
<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">
|
<meta http-equiv="Content-Type" content="text/html; charset=iso-8859-1">
|
||||||
<link rel="stylesheet" type="text/css" href="boost.css">
|
<link rel="stylesheet" type="text/css" href="boost.css">
|
||||||
|
|
||||||
@@ -16,7 +16,7 @@
|
|||||||
<tr>
|
<tr>
|
||||||
<td valign="top" width="300">
|
<td valign="top" width="300">
|
||||||
<h3><a href="../../../index.htm"><img height="86" width="277" alt=
|
<h3><a href="../../../index.htm"><img height="86" width="277" alt=
|
||||||
"C++ Boost" src="../../../c++boost.gif" border="0"></a></h3>
|
"C++ Boost" src="../../../boost.png" border="0"></a></h3>
|
||||||
</td>
|
</td>
|
||||||
|
|
||||||
<td valign="top">
|
<td valign="top">
|
||||||
@@ -31,7 +31,9 @@
|
|||||||
<h2>Synopsis</h2>
|
<h2>Synopsis</h2>
|
||||||
|
|
||||||
<p>This is a list of available resources for support with Boost.Python
|
<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>
|
<hr>
|
||||||
|
|
||||||
<dl class="page-index">
|
<dl class="page-index">
|
||||||
@@ -41,9 +43,11 @@
|
|||||||
you Boost.Python.<br>
|
you Boost.Python.<br>
|
||||||
</dt>
|
</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++
|
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>
|
||||||
|
|
||||||
<dt>The <b>Boost.Python <a href=
|
<dt>The <b>Boost.Python <a href=
|
||||||
@@ -51,18 +55,17 @@
|
|||||||
Pages</a></b> established by Mike Rovner as part of the <a href=
|
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
|
"http://www.python.org/cgi-bin/moinmoin">PythonInfo Wiki</a> serves as
|
||||||
a forum to gather peoples' experience and as a cookbook.<br>
|
a forum to gather peoples' experience and as a cookbook.<br>
|
||||||
</dt>
|
</dt>
|
||||||
</dl>
|
</dl>
|
||||||
<hr>
|
<hr>
|
||||||
|
|
||||||
<p>Revised
|
<p>Revised
|
||||||
<!--webbot bot="Timestamp" S-Type="EDITED" S-Format="%d %B, %Y" startspan -->
|
<!--webbot bot="Timestamp" S-Type="EDITED" S-Format="%d %B, %Y" startspan -->
|
||||||
17 November, 2002
|
12 Sept, 2003 <!--webbot bot="Timestamp" endspan i-checksum="39359" -->
|
||||||
<!--webbot bot="Timestamp" endspan i-checksum="39359" -->
|
|
||||||
</p>
|
</p>
|
||||||
|
|
||||||
<p><i>© Copyright <a href="../../../people/dave_abrahams.htm">Dave
|
<p><i>© Copyright <a href="../../../people/dave_abrahams.htm">Dave
|
||||||
Abrahams</a> 2002. All Rights Reserved.</i></p>
|
Abrahams</a> 2003.</i></p>
|
||||||
</body>
|
</body>
|
||||||
</html>
|
</html>
|
||||||
|
|
||||||
|
|||||||
12
doc/tutorial/doc/Jamfile.v2
Normal file
@@ -0,0 +1,12 @@
|
|||||||
|
project boost/libs/python/doc/tutorial/doc ;
|
||||||
|
|
||||||
|
import boostbook : boostbook ;
|
||||||
|
using quickbook ;
|
||||||
|
|
||||||
|
boostbook tutorial
|
||||||
|
:
|
||||||
|
tutorial.qbk
|
||||||
|
:
|
||||||
|
<xsl:param>boost.root=../../../../../..
|
||||||
|
<xsl:param>boost.libraries=../../../../../../libs/libraries.htm
|
||||||
|
;
|
||||||
@@ -1,112 +0,0 @@
|
|||||||
<html>
|
|
||||||
<head>
|
|
||||||
<!-- Generated by the Spirit (http://spirit.sf.net) QuickDoc -->
|
|
||||||
<title>Auto-Overloading</title>
|
|
||||||
<link rel="stylesheet" href="theme/style.css" type="text/css">
|
|
||||||
<link rel="prev" href="default_arguments.html">
|
|
||||||
<link rel="next" href="object_interface.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>Auto-Overloading</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="default_arguments.html"><img src="theme/l_arr.gif" border="0"></a></td>
|
|
||||||
<td width="20"><a href="object_interface.html"><img src="theme/r_arr.gif" border="0"></a></td>
|
|
||||||
</tr>
|
|
||||||
</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>
|
|
||||||
can also be used for overloaded functions and member functions with a
|
|
||||||
common sequence of initial arguments. Here is an example:</p>
|
|
||||||
<code><pre>
|
|
||||||
<span class=keyword>void </span><span class=identifier>foo</span><span class=special>()
|
|
||||||
{
|
|
||||||
/*...*/
|
|
||||||
}
|
|
||||||
|
|
||||||
</span><span class=keyword>void </span><span class=identifier>foo</span><span class=special>(</span><span class=keyword>bool </span><span class=identifier>a</span><span class=special>)
|
|
||||||
{
|
|
||||||
/*...*/
|
|
||||||
}
|
|
||||||
|
|
||||||
</span><span class=keyword>void </span><span class=identifier>foo</span><span class=special>(</span><span class=keyword>bool </span><span class=identifier>a</span><span class=special>, </span><span class=keyword>int </span><span class=identifier>b</span><span class=special>)
|
|
||||||
{
|
|
||||||
/*...*/
|
|
||||||
}
|
|
||||||
|
|
||||||
</span><span class=keyword>void </span><span class=identifier>foo</span><span class=special>(</span><span class=keyword>bool </span><span class=identifier>a</span><span class=special>, </span><span class=keyword>int </span><span class=identifier>b</span><span class=special>, </span><span class=keyword>char </span><span class=identifier>c</span><span class=special>)
|
|
||||||
{
|
|
||||||
/*...*/
|
|
||||||
}
|
|
||||||
</span></pre></code>
|
|
||||||
<p>
|
|
||||||
Like in the previous section, we can generate thin wrappers for these
|
|
||||||
overloaded functions in one-shot:</p>
|
|
||||||
<code><pre>
|
|
||||||
<span class=identifier>BOOST_PYTHON_FUNCTION_OVERLOADS</span><span class=special>(</span><span class=identifier>foo_overloads</span><span class=special>, </span><span class=identifier>foo</span><span class=special>, </span><span class=number>0</span><span class=special>, </span><span class=number>3</span><span class=special>)
|
|
||||||
</span></pre></code>
|
|
||||||
<p>
|
|
||||||
Then...</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></pre></code>
|
|
||||||
<p>
|
|
||||||
Notice though that we have a situation now where we have a minimum of zero
|
|
||||||
(0) arguments and a maximum of 3 arguments.</p>
|
|
||||||
<a name="manual_wrapping"></a><h2>Manual Wrapping</h2><p>
|
|
||||||
It is important to emphasize however that <b>the overloaded functions must
|
|
||||||
have a common sequence of initial arguments</b>. Otherwise, our scheme above
|
|
||||||
will not work. If this is not the case, we have to wrap our functions
|
|
||||||
<a href="overloading.html">
|
|
||||||
manually</a>.</p>
|
|
||||||
<p>
|
|
||||||
Actually, we can mix and match manual wrapping of overloaded functions and
|
|
||||||
automatic wrapping through <tt>BOOST_PYTHON_MEMBER_FUNCTION_OVERLOADS</tt> and
|
|
||||||
its sister, <tt>BOOST_PYTHON_FUNCTION_OVERLOADS</tt>. Following up on our example
|
|
||||||
presented in the section <a href="overloading.html">
|
|
||||||
on overloading</a>, since the
|
|
||||||
first 4 overload functins have a common sequence of initial arguments, we
|
|
||||||
can use <tt>BOOST_PYTHON_MEMBER_FUNCTION_OVERLOADS</tt> to automatically wrap the
|
|
||||||
first three of the <tt>def</tt>s and manually wrap just the last. Here's
|
|
||||||
how we'll do this:</p>
|
|
||||||
<code><pre>
|
|
||||||
<span class=identifier>BOOST_PYTHON_MEMBER_FUNCTION_OVERLOADS</span><span class=special>(</span><span class=identifier>xf_overloads</span><span class=special>, </span><span class=identifier>f</span><span class=special>, </span><span class=number>1</span><span class=special>, </span><span class=number>4</span><span class=special>)
|
|
||||||
</span></pre></code>
|
|
||||||
<p>
|
|
||||||
Create a member function pointers as above for both X::f overloads:</p>
|
|
||||||
<code><pre>
|
|
||||||
<span class=keyword>bool </span><span class=special>(</span><span class=identifier>X</span><span class=special>::*</span><span class=identifier>fx1</span><span class=special>)(</span><span class=keyword>int</span><span class=special>, </span><span class=keyword>double</span><span class=special>, </span><span class=keyword>char</span><span class=special>) = &</span><span class=identifier>X</span><span class=special>::</span><span class=identifier>f</span><span class=special>;
|
|
||||||
</span><span class=keyword>int </span><span class=special>(</span><span class=identifier>X</span><span class=special>::*</span><span class=identifier>fx2</span><span class=special>)(</span><span class=keyword>int</span><span class=special>, </span><span class=keyword>int</span><span class=special>, </span><span class=keyword>int</span><span class=special>) = &</span><span class=identifier>X</span><span class=special>::</span><span class=identifier>f</span><span class=special>;
|
|
||||||
</span></pre></code>
|
|
||||||
<p>
|
|
||||||
Then...</p>
|
|
||||||
<code><pre>
|
|
||||||
<span class=special>.</span><span class=identifier>def</span><span class=special>(</span><span class=string>"f"</span><span class=special>, </span><span class=identifier>fx1</span><span class=special>, </span><span class=identifier>xf_overloads</span><span class=special>());
|
|
||||||
.</span><span class=identifier>def</span><span class=special>(</span><span class=string>"f"</span><span class=special>, </span><span class=identifier>fx2</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="default_arguments.html"><img src="theme/l_arr.gif" border="0"></a></td>
|
|
||||||
<td width="20"><a href="object_interface.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>
|
|
||||||
@@ -1,77 +0,0 @@
|
|||||||
<html>
|
|
||||||
<head>
|
|
||||||
<!-- Generated by the Spirit (http://spirit.sf.net) QuickDoc -->
|
|
||||||
<title>Basic Interface</title>
|
|
||||||
<link rel="stylesheet" href="theme/style.css" type="text/css">
|
|
||||||
<link rel="prev" href="object_interface.html">
|
|
||||||
<link rel="next" href="derived_object_types.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>Basic Interface</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="object_interface.html"><img src="theme/l_arr.gif" border="0"></a></td>
|
|
||||||
<td width="20"><a href="derived_object_types.html"><img src="theme/r_arr.gif" border="0"></a></td>
|
|
||||||
</tr>
|
|
||||||
</table>
|
|
||||||
<p>
|
|
||||||
Class <tt>object</tt> wraps <tt>PyObject*</tt>. All the intricacies of dealing with
|
|
||||||
<tt>PyObject</tt>s such as managing reference counting are handled by the
|
|
||||||
<tt>object</tt> class. C++ object interoperability is seamless. Boost.Python C++
|
|
||||||
<tt>object</tt>s can in fact be explicitly constructed from any C++ object.</p>
|
|
||||||
<p>
|
|
||||||
To illustrate, this Python code snippet:</p>
|
|
||||||
<code><pre>
|
|
||||||
<span class=identifier>def </span><span class=identifier>f</span><span class=special>(</span><span class=identifier>x</span><span class=special>, </span><span class=identifier>y</span><span class=special>):
|
|
||||||
</span><span class=keyword>if </span><span class=special>(</span><span class=identifier>y </span><span class=special>== </span><span class=literal>'foo'</span><span class=special>):
|
|
||||||
</span><span class=identifier>x</span><span class=special>[</span><span class=number>3</span><span class=special>:</span><span class=number>7</span><span class=special>] = </span><span class=literal>'bar'
|
|
||||||
</span><span class=keyword>else</span><span class=special>:
|
|
||||||
</span><span class=identifier>x</span><span class=special>.</span><span class=identifier>items </span><span class=special>+= </span><span class=identifier>y</span><span class=special>(</span><span class=number>3</span><span class=special>, </span><span class=identifier>x</span><span class=special>)
|
|
||||||
</span><span class=keyword>return </span><span class=identifier>x
|
|
||||||
|
|
||||||
</span><span class=identifier>def </span><span class=identifier>getfunc</span><span class=special>():
|
|
||||||
</span><span class=keyword>return </span><span class=identifier>f</span><span class=special>;
|
|
||||||
</span></pre></code>
|
|
||||||
<p>
|
|
||||||
Can be rewritten in C++ using Boost.Python facilities this way:</p>
|
|
||||||
<code><pre>
|
|
||||||
<span class=identifier>object </span><span class=identifier>f</span><span class=special>(</span><span class=identifier>object </span><span class=identifier>x</span><span class=special>, </span><span class=identifier>object </span><span class=identifier>y</span><span class=special>) {
|
|
||||||
</span><span class=keyword>if </span><span class=special>(</span><span class=identifier>y </span><span class=special>== </span><span class=string>"foo"</span><span class=special>)
|
|
||||||
</span><span class=identifier>x</span><span class=special>.</span><span class=identifier>slice</span><span class=special>(</span><span class=number>3</span><span class=special>,</span><span class=number>7</span><span class=special>) = </span><span class=string>"bar"</span><span class=special>;
|
|
||||||
</span><span class=keyword>else
|
|
||||||
</span><span class=identifier>x</span><span class=special>.</span><span class=identifier>attr</span><span class=special>(</span><span class=string>"items"</span><span class=special>) += </span><span class=identifier>y</span><span class=special>(</span><span class=number>3</span><span class=special>, </span><span class=identifier>x</span><span class=special>);
|
|
||||||
</span><span class=keyword>return </span><span class=identifier>x</span><span class=special>;
|
|
||||||
}
|
|
||||||
</span><span class=identifier>object </span><span class=identifier>getfunc</span><span class=special>() {
|
|
||||||
</span><span class=keyword>return </span><span class=identifier>object</span><span class=special>(</span><span class=identifier>f</span><span class=special>);
|
|
||||||
}
|
|
||||||
</span></pre></code>
|
|
||||||
<p>
|
|
||||||
Apart from cosmetic differences due to the fact that we are writing the
|
|
||||||
code in C++, the look and feel should be immediately apparent to the Python
|
|
||||||
coder.</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="object_interface.html"><img src="theme/l_arr.gif" border="0"></a></td>
|
|
||||||
<td width="20"><a href="derived_object_types.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>
|
|
||||||
@@ -1,191 +0,0 @@
|
|||||||
<html>
|
|
||||||
<head>
|
|
||||||
<!-- Generated by the Spirit (http://spirit.sf.net) QuickDoc -->
|
|
||||||
<title>Building Hello World</title>
|
|
||||||
<link rel="stylesheet" href="theme/style.css" type="text/css">
|
|
||||||
<link rel="prev" href="quickstart.html">
|
|
||||||
<link rel="next" href="exposing_classes.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>Building Hello World</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="quickstart.html"><img src="theme/l_arr.gif" border="0"></a></td>
|
|
||||||
<td width="20"><a href="exposing_classes.html"><img src="theme/r_arr.gif" border="0"></a></td>
|
|
||||||
</tr>
|
|
||||||
</table>
|
|
||||||
<a name="from_start_to_finish"></a><h2>From Start To Finish</h2><p>
|
|
||||||
Now the first thing you'd want to do is to build the Hello World module and
|
|
||||||
try it for yourself in Python. In this section, we shall outline the steps
|
|
||||||
necessary to achieve that. We shall use the build tool that comes bundled
|
|
||||||
with every boost distribution: <b>bjam</b>.</p>
|
|
||||||
<table width="80%" border="0" align="center">
|
|
||||||
<tr>
|
|
||||||
<td class="note_box">
|
|
||||||
<img src="theme/lens.gif"></img> <b>Building without bjam</b><br><br>
|
|
||||||
|
|
||||||
Besides bjam, there are of course other ways to get your module built.
|
|
||||||
What's written here should not be taken as "the one and only way".
|
|
||||||
There are of course other build tools apart from <tt>bjam</tt>.
|
|
||||||
</td>
|
|
||||||
</tr>
|
|
||||||
</table>
|
|
||||||
<p>
|
|
||||||
We shall skip over the details. Our objective will be to simply create the
|
|
||||||
hello world module and run it in Python. For a complete reference to
|
|
||||||
building Boost.Python, check out: <a href="../../building.html">
|
|
||||||
building.html</a>.
|
|
||||||
After this brief <i>bjam</i> tutorial, we should have built two DLLs:</p>
|
|
||||||
<ul><li>boost_python.dll</li><li>hello.pyd</li></ul><p>
|
|
||||||
if you are on Windows, and</p>
|
|
||||||
<ul><li>libboost_python.so</li><li>hello.so</li></ul><p>
|
|
||||||
if you are on Unix.</p>
|
|
||||||
<p>
|
|
||||||
The tutorial example can be found in the directory:
|
|
||||||
<tt>libs/python/example/tutorial</tt>. There, you can find:</p>
|
|
||||||
<ul><li>hello.cpp</li><li>Jamfile</li></ul><p>
|
|
||||||
The <tt>hello.cpp</tt> file is our C++ hello world example. The <tt>Jamfile</tt> is a
|
|
||||||
minimalist <i>bjam</i> script that builds the DLLs for us.</p>
|
|
||||||
<p>
|
|
||||||
Before anything else, you should have the bjam executable in your boost
|
|
||||||
directory or somewhere in your path such that <tt>bjam</tt> can be executed in
|
|
||||||
the command line. Pre-built Boost.Jam executables are available for most
|
|
||||||
platforms. For example, a pre-built Microsoft Windows bjam executable can
|
|
||||||
be downloaded <a href="http://boost.sourceforge.net/jam-executables/bin.ntx86/bjam.zip">
|
|
||||||
here</a>.
|
|
||||||
The complete list of bjam pre-built
|
|
||||||
executables can be found <a href="../../../../../tools/build/index.html#Jam">
|
|
||||||
here</a>.</p>
|
|
||||||
<a name="lets_jam_"></a><h2>Lets Jam!</h2><p>
|
|
||||||
<img src="theme/jam.png"></img></p>
|
|
||||||
<p>
|
|
||||||
Here is our minimalist Jamfile:</p>
|
|
||||||
<code><pre>
|
|
||||||
subproject libs/python/example/tutorial ;
|
|
||||||
|
|
||||||
SEARCH on python.jam = $(BOOST_BUILD_PATH) ;
|
|
||||||
include python.jam ;
|
|
||||||
|
|
||||||
extension hello # Declare a Python extension called hello
|
|
||||||
: hello.cpp # source
|
|
||||||
<dll>../../build/boost_python # dependencies
|
|
||||||
;
|
|
||||||
</pre></code><p>
|
|
||||||
First, we need to specify our location in the boost project hierarchy.
|
|
||||||
It so happens that the tutorial example is located in <tt>/libs/python/example/tutorial</tt>.
|
|
||||||
Thus:</p>
|
|
||||||
<code><pre>
|
|
||||||
subproject libs/python/example/tutorial ;
|
|
||||||
</pre></code><p>
|
|
||||||
Then we will include the definitions needed by Python modules:</p>
|
|
||||||
<code><pre>
|
|
||||||
SEARCH on python.jam = $(BOOST_BUILD_PATH) ;
|
|
||||||
include python.jam ;
|
|
||||||
</pre></code><p>
|
|
||||||
Finally we declare our <tt>hello</tt> extension:</p>
|
|
||||||
<code><pre>
|
|
||||||
extension hello # Declare a Python extension called hello
|
|
||||||
: hello.cpp # source
|
|
||||||
<dll>../../build/boost_python # dependencies
|
|
||||||
;
|
|
||||||
</pre></code><a name="running_bjam"></a><h2>Running bjam</h2><p>
|
|
||||||
<i>bjam</i> is run using your operating system's command line interpreter.</p>
|
|
||||||
<blockquote><p>Start it up.</p></blockquote><p>
|
|
||||||
Make sure that the environment is set so that we can invoke the C++
|
|
||||||
compiler. With MSVC, that would mean running the <tt>Vcvars32.bat</tt> batch
|
|
||||||
file. For instance:</p>
|
|
||||||
<code><pre>
|
|
||||||
<span class=identifier>C</span><span class=special>:\</span><span class=identifier>Program </span><span class=identifier>Files</span><span class=special>\</span><span class=identifier>Microsoft </span><span class=identifier>Visual </span><span class=identifier>Studio</span><span class=special>\</span><span class=identifier>VC98</span><span class=special>\</span><span class=identifier>bin</span><span class=special>\</span><span class=identifier>Vcvars32</span><span class=special>.</span><span class=identifier>bat
|
|
||||||
</span></pre></code>
|
|
||||||
<p>
|
|
||||||
Some environment variables will have to be setup for proper building of our
|
|
||||||
Python modules. Example:</p>
|
|
||||||
<code><pre>
|
|
||||||
<span class=identifier>set </span><span class=identifier>PYTHON_ROOT</span><span class=special>=</span><span class=identifier>c</span><span class=special>:/</span><span class=identifier>dev</span><span class=special>/</span><span class=identifier>tools</span><span class=special>/</span><span class=identifier>python
|
|
||||||
</span><span class=identifier>set </span><span class=identifier>PYTHON_VERSION</span><span class=special>=</span><span class=number>2.2
|
|
||||||
</span></pre></code>
|
|
||||||
<p>
|
|
||||||
The above assumes that the Python installation is in <tt>c:/dev/tools/python</tt>
|
|
||||||
and that we are using Python version 2.2. You'll have to tweak this path
|
|
||||||
appropriately. <img src="theme/note.gif"></img> Be sure not to include a third number, e.g. <b>not</b> "2.2.1",
|
|
||||||
even if that's the version you have.</p>
|
|
||||||
<p>
|
|
||||||
Now we are ready... Be sure to <tt>cd</tt> to <tt>libs/python/example/tutorial</tt>
|
|
||||||
where the tutorial <tt>"hello.cpp"</tt> and the <tt>"Jamfile"</tt> is situated.</p>
|
|
||||||
<p>
|
|
||||||
Finally:</p>
|
|
||||||
<code><pre>
|
|
||||||
<span class=identifier>bjam </span><span class=special>-</span><span class=identifier>sTOOLS</span><span class=special>=</span><span class=identifier>msvc
|
|
||||||
</span></pre></code>
|
|
||||||
<p>
|
|
||||||
We are again assuming that we are using Microsoft Visual C++ version 6. If
|
|
||||||
not, then you will have to specify the appropriate tool. See
|
|
||||||
<a href="../../../../../tools/build/index.html">
|
|
||||||
Building Boost Libraries</a> for
|
|
||||||
further details.</p>
|
|
||||||
<p>
|
|
||||||
It should be building now:</p>
|
|
||||||
<code><pre>
|
|
||||||
cd C:\dev\boost\libs\python\example\tutorial
|
|
||||||
bjam -sTOOLS=msvc
|
|
||||||
...patience...
|
|
||||||
...found 1703 targets...
|
|
||||||
...updating 40 targets...
|
|
||||||
</pre></code><p>
|
|
||||||
And so on... Finally:</p>
|
|
||||||
<code><pre>
|
|
||||||
vc-C++ ..\..\..\..\libs\python\example\tutorial\bin\hello.pyd\msvc\debug\
|
|
||||||
runtime-link-dynamic\hello.obj
|
|
||||||
hello.cpp
|
|
||||||
vc-Link ..\..\..\..\libs\python\example\tutorial\bin\hello.pyd\msvc\debug\
|
|
||||||
runtime-link-dynamic\hello.pyd ..\..\..\..\libs\python\example\tutorial\bin\
|
|
||||||
hello.pyd\msvc\debug\runtime-link-dynamic\hello.lib
|
|
||||||
Creating library ..\..\..\..\libs\python\example\tutorial\bin\hello.pyd\
|
|
||||||
msvc\debug\runtime-link-dynamic\hello.lib and object ..\..\..\..\libs\python\
|
|
||||||
example\tutorial\bin\hello.pyd\msvc\debug\runtime-link-dynamic\hello.exp
|
|
||||||
...updated 40 targets...
|
|
||||||
</pre></code><p>
|
|
||||||
If all is well, you should now have:</p>
|
|
||||||
<ul><li>boost_python.dll</li><li>hello.pyd</li></ul><p>
|
|
||||||
if you are on Windows, and</p>
|
|
||||||
<ul><li>libboost_python.so</li><li>hello.so</li></ul><p>
|
|
||||||
if you are on Unix.</p>
|
|
||||||
<p>
|
|
||||||
<tt>boost_python.dll</tt> can be found somewhere in <tt>libs\python\build\bin</tt>
|
|
||||||
while <tt>hello.pyd</tt> can be found somewhere in
|
|
||||||
<tt>libs\python\example\tutorial\bin</tt>. After a successful build, you can just
|
|
||||||
link in these DLLs with the Python interpreter. In Windows for example, you
|
|
||||||
can simply put these libraries inside the directory where the Python
|
|
||||||
executable is.</p>
|
|
||||||
<p>
|
|
||||||
You may now fire up Python and run our hello module:</p>
|
|
||||||
<code><pre>
|
|
||||||
<span class=special>>>> </span><span class=identifier>import </span><span class=identifier>hello
|
|
||||||
</span><span class=special>>>> </span><span class=identifier>print </span><span class=identifier>hello</span><span class=special>.</span><span class=identifier>greet</span><span class=special>()
|
|
||||||
</span><span class=identifier>hello</span><span class=special>, </span><span class=identifier>world
|
|
||||||
</span></pre></code>
|
|
||||||
<blockquote><p><b>There you go... Have fun!</b></p></blockquote><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="quickstart.html"><img src="theme/l_arr.gif" border="0"></a></td>
|
|
||||||
<td width="20"><a href="exposing_classes.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>
|
|
||||||
@@ -1,169 +0,0 @@
|
|||||||
<html>
|
|
||||||
<head>
|
|
||||||
<!-- Generated by the Spirit (http://spirit.sf.net) QuickDoc -->
|
|
||||||
<title>Call Policies</title>
|
|
||||||
<link rel="stylesheet" href="theme/style.css" type="text/css">
|
|
||||||
<link rel="prev" href="functions.html">
|
|
||||||
<link rel="next" href="overloading.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>Call Policies</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="functions.html"><img src="theme/l_arr.gif" border="0"></a></td>
|
|
||||||
<td width="20"><a href="overloading.html"><img src="theme/r_arr.gif" border="0"></a></td>
|
|
||||||
</tr>
|
|
||||||
</table>
|
|
||||||
<p>
|
|
||||||
In C++, we often deal with arguments and return types such as pointers
|
|
||||||
and references. Such primitive types are rather, ummmm, low level and
|
|
||||||
they really don't tell us much. At the very least, we don't know the
|
|
||||||
owner of the pointer or the referenced object. No wonder languages
|
|
||||||
such as Java and Python never deal with such low level entities. In
|
|
||||||
C++, it's usually considered a good practice to use smart pointers
|
|
||||||
which exactly describe ownership semantics. Still, even good C++
|
|
||||||
interfaces use raw references and pointers sometimes, so Boost.Python
|
|
||||||
must deal with them. To do this, it may need your help. Consider the
|
|
||||||
following C++ function:</p>
|
|
||||||
<code><pre>
|
|
||||||
<span class=identifier>X</span><span class=special>& </span><span class=identifier>f</span><span class=special>(</span><span class=identifier>Y</span><span class=special>& </span><span class=identifier>y</span><span class=special>, </span><span class=identifier>Z</span><span class=special>* </span><span class=identifier>z</span><span class=special>);
|
|
||||||
</span></pre></code>
|
|
||||||
<p>
|
|
||||||
How should the library wrap this function? A naive approach builds a
|
|
||||||
Python X object around result reference. This strategy might or might
|
|
||||||
not work out. Here's an example where it didn't</p>
|
|
||||||
<code><pre>
|
|
||||||
<span class=special>>>> </span><span class=identifier>x </span><span class=special>= </span><span class=identifier>f</span><span class=special>(</span><span class=identifier>y</span><span class=special>, </span><span class=identifier>z</span><span class=special>) </span>##<span class=identifier>x </span><span class=identifier>refers </span><span class=identifier>to </span><span class=identifier>some </span><span class=identifier>C</span><span class=special>++ </span><span class=identifier>X
|
|
||||||
</span><span class=special>>>> </span><span class=identifier>del </span><span class=identifier>y
|
|
||||||
</span><span class=special>>>> </span><span class=identifier>x</span><span class=special>.</span><span class=identifier>some_method</span><span class=special>() </span>##<span class=identifier>CRASH</span><span class=special>!
|
|
||||||
</span></pre></code>
|
|
||||||
<p>
|
|
||||||
What's the problem?</p>
|
|
||||||
<p>
|
|
||||||
Well, what if f() was implemented as shown below:</p>
|
|
||||||
<code><pre>
|
|
||||||
<span class=identifier>X</span><span class=special>& </span><span class=identifier>f</span><span class=special>(</span><span class=identifier>Y</span><span class=special>& </span><span class=identifier>y</span><span class=special>, </span><span class=identifier>Z</span><span class=special>* </span><span class=identifier>z</span><span class=special>)
|
|
||||||
{
|
|
||||||
</span><span class=identifier>y</span><span class=special>.</span><span class=identifier>z </span><span class=special>= </span><span class=identifier>z</span><span class=special>;
|
|
||||||
</span><span class=keyword>return </span><span class=identifier>y</span><span class=special>.</span><span class=identifier>x</span><span class=special>;
|
|
||||||
}
|
|
||||||
</span></pre></code>
|
|
||||||
<p>
|
|
||||||
The problem is that the lifetime of result X& is tied to the lifetime
|
|
||||||
of y, because the f() returns a reference to a member of the y
|
|
||||||
object. This idiom is is not uncommon and perfectly acceptable in the
|
|
||||||
context of C++. However, Python users should not be able to crash the
|
|
||||||
system just by using our C++ interface. In this case deleting y will
|
|
||||||
invalidate the reference to X. We have a dangling reference.</p>
|
|
||||||
<p>
|
|
||||||
Here's what's happening:</p>
|
|
||||||
<ol><li><tt>f</tt> is called passing in a reference to <tt>y</tt> and a pointer to <tt>z</tt></li><li>A reference to <tt>y.x</tt> is returned</li><li><tt>y</tt> is deleted. <tt>x</tt> is a dangling reference</li><li><tt>x.some_method()</tt> is called</li><li><b>BOOM!</b></li></ol><p>
|
|
||||||
We could copy result into a new object:</p>
|
|
||||||
<code><pre>
|
|
||||||
<span class=special>>>> </span><span class=identifier>f</span><span class=special>(</span><span class=identifier>y</span><span class=special>, </span><span class=identifier>z</span><span class=special>).</span><span class=identifier>set</span><span class=special>(</span><span class=number>42</span><span class=special>) </span>##<span class=identifier>Result </span><span class=identifier>disappears
|
|
||||||
</span><span class=special>>>> </span><span class=identifier>y</span><span class=special>.</span><span class=identifier>x</span><span class=special>.</span><span class=identifier>get</span><span class=special>() </span>##<span class=identifier>No </span><span class=identifier>crash</span><span class=special>, </span><span class=identifier>but </span><span class=identifier>still </span><span class=identifier>bad
|
|
||||||
</span><span class=number>3.14
|
|
||||||
</span></pre></code>
|
|
||||||
<p>
|
|
||||||
This is not really our intent of our C++ interface. We've broken our
|
|
||||||
promise that the Python interface should reflect the C++ interface as
|
|
||||||
closely as possible.</p>
|
|
||||||
<p>
|
|
||||||
Our problems do not end there. Suppose Y is implemented as follows:</p>
|
|
||||||
<code><pre>
|
|
||||||
<span class=keyword>struct </span><span class=identifier>Y
|
|
||||||
</span><span class=special>{
|
|
||||||
</span><span class=identifier>X </span><span class=identifier>x</span><span class=special>; </span><span class=identifier>Z</span><span class=special>* </span><span class=identifier>z</span><span class=special>;
|
|
||||||
</span><span class=keyword>int </span><span class=identifier>z_value</span><span class=special>() { </span><span class=keyword>return </span><span class=identifier>z</span><span class=special>-></span><span class=identifier>value</span><span class=special>(); }
|
|
||||||
};
|
|
||||||
</span></pre></code>
|
|
||||||
<p>
|
|
||||||
Notice that the data member <tt>z</tt> is held by class Y using a raw
|
|
||||||
pointer. Now we have a potential dangling pointer problem inside Y:</p>
|
|
||||||
<code><pre>
|
|
||||||
<span class=special>>>> </span><span class=identifier>x </span><span class=special>= </span><span class=identifier>f</span><span class=special>(</span><span class=identifier>y</span><span class=special>, </span><span class=identifier>z</span><span class=special>) </span>##<span class=identifier>y </span><span class=identifier>refers </span><span class=identifier>to </span><span class=identifier>z
|
|
||||||
</span><span class=special>>>> </span><span class=identifier>del </span><span class=identifier>z </span>##<span class=identifier>Kill </span><span class=identifier>the </span><span class=identifier>z </span><span class=identifier>object
|
|
||||||
</span><span class=special>>>> </span><span class=identifier>y</span><span class=special>.</span><span class=identifier>z_value</span><span class=special>() </span>##<span class=identifier>CRASH</span><span class=special>!
|
|
||||||
</span></pre></code>
|
|
||||||
<p>
|
|
||||||
For reference, here's the implementation of <tt>f</tt> again:</p>
|
|
||||||
<code><pre>
|
|
||||||
<span class=identifier>X</span><span class=special>& </span><span class=identifier>f</span><span class=special>(</span><span class=identifier>Y</span><span class=special>& </span><span class=identifier>y</span><span class=special>, </span><span class=identifier>Z</span><span class=special>* </span><span class=identifier>z</span><span class=special>)
|
|
||||||
{
|
|
||||||
</span><span class=identifier>y</span><span class=special>.</span><span class=identifier>z </span><span class=special>= </span><span class=identifier>z</span><span class=special>;
|
|
||||||
</span><span class=keyword>return </span><span class=identifier>y</span><span class=special>.</span><span class=identifier>x</span><span class=special>;
|
|
||||||
}
|
|
||||||
</span></pre></code>
|
|
||||||
<p>
|
|
||||||
Here's what's happening:</p>
|
|
||||||
<ol><li><tt>f</tt> is called passing in a reference to <tt>y</tt> and a pointer to <tt>z</tt></li><li>A pointer to <tt>z</tt> is held by <tt>y</tt></li><li>A reference to <tt>y.x</tt> is returned</li><li><tt>z</tt> is deleted. <tt>y.z</tt> is a dangling pointer</li><li><tt>y.z_value()</tt> is called</li><li><tt>z->value()</tt> is called</li><li><b>BOOM!</b></li></ol><a name="call_policies"></a><h2>Call Policies</h2><p>
|
|
||||||
Call Policies may be used in situations such as the example detailed above.
|
|
||||||
In our example, <tt>return_internal_reference</tt> and <tt>with_custodian_and_ward</tt>
|
|
||||||
are our friends:</p>
|
|
||||||
<code><pre>
|
|
||||||
<span class=identifier>def</span><span class=special>(</span><span class=string>"f"</span><span class=special>, </span><span class=identifier>f</span><span class=special>,
|
|
||||||
</span><span class=identifier>return_internal_reference</span><span class=special><</span><span class=number>1</span><span class=special>,
|
|
||||||
</span><span class=identifier>with_custodian_and_ward</span><span class=special><</span><span class=number>1</span><span class=special>, </span><span class=number>2</span><span class=special>> >());
|
|
||||||
</span></pre></code>
|
|
||||||
<p>
|
|
||||||
What are the <tt>1</tt> and <tt>2</tt> parameters, you ask?</p>
|
|
||||||
<code><pre>
|
|
||||||
<span class=identifier>return_internal_reference</span><span class=special><</span><span class=number>1
|
|
||||||
</span></pre></code>
|
|
||||||
<p>
|
|
||||||
Informs Boost.Python that the first argument, in our case <tt>Y& y</tt>, is the
|
|
||||||
owner of the returned reference: <tt>X&</tt>. The "<tt>1</tt>" simply specifies the
|
|
||||||
first argument. In short: "return an internal reference <tt>X&</tt> owned by the
|
|
||||||
1st argument <tt>Y& y</tt>".</p>
|
|
||||||
<code><pre>
|
|
||||||
<span class=identifier>with_custodian_and_ward</span><span class=special><</span><span class=number>1</span><span class=special>, </span><span class=number>2</span><span class=special>>
|
|
||||||
</span></pre></code>
|
|
||||||
<p>
|
|
||||||
Informs Boost.Python that the lifetime of the argument indicated by ward
|
|
||||||
(i.e. the 2nd argument: <tt>Z* z</tt>) is dependent on the lifetime of the
|
|
||||||
argument indicated by custodian (i.e. the 1st argument: <tt>Y& y</tt>).</p>
|
|
||||||
<p>
|
|
||||||
It is also important to note that we have defined two policies above. Two
|
|
||||||
or more policies can be composed by chaining. Here's the general syntax:</p>
|
|
||||||
<code><pre>
|
|
||||||
<span class=identifier>policy1</span><span class=special><</span><span class=identifier>args</span><span class=special>...,
|
|
||||||
</span><span class=identifier>policy2</span><span class=special><</span><span class=identifier>args</span><span class=special>...,
|
|
||||||
</span><span class=identifier>policy3</span><span class=special><</span><span class=identifier>args</span><span class=special>...> > >
|
|
||||||
</span></pre></code>
|
|
||||||
<p>
|
|
||||||
Here is the list of predefined call policies. A complete reference detailing
|
|
||||||
these can be found <a href="../../v2/reference.html#models_of_call_policies">
|
|
||||||
here</a>.</p>
|
|
||||||
<ul><li><b>with_custodian_and_ward</b><br> Ties lifetimes of the arguments</li><li><b>with_custodian_and_ward_postcall</b><br> Ties lifetimes of the arguments and results</li><li><b>return_internal_reference</b><br> Ties lifetime of one argument to that of result</li><li><b>return_value_policy<T> with T one of:</b><br></li><li><b>reference_existing_object</b><br>naïve (dangerous) approach</li><li><b>copy_const_reference</b><br>Boost.Python v1 approach</li><li><b>copy_non_const_reference</b><br></li><li><b>manage_new_object</b><br> Adopt a pointer and hold the instance</li></ul><table width="80%" border="0" align="center">
|
|
||||||
<tr>
|
|
||||||
<td class="note_box">
|
|
||||||
<img src="theme/smiley.gif"></img> <b>Remember the Zen, Luke:</b><br><br>
|
|
||||||
"Explicit is better than implicit"<br>
|
|
||||||
"In the face of ambiguity, refuse the temptation to guess"<br> </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="functions.html"><img src="theme/l_arr.gif" border="0"></a></td>
|
|
||||||
<td width="20"><a href="overloading.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>
|
|
||||||
@@ -1,78 +0,0 @@
|
|||||||
<html>
|
|
||||||
<head>
|
|
||||||
<!-- Generated by the Spirit (http://spirit.sf.net) QuickDoc -->
|
|
||||||
<title>Class Data Members</title>
|
|
||||||
<link rel="stylesheet" href="theme/style.css" type="text/css">
|
|
||||||
<link rel="prev" href="constructors.html">
|
|
||||||
<link rel="next" href="class_properties.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>Class Data Members</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="constructors.html"><img src="theme/l_arr.gif" border="0"></a></td>
|
|
||||||
<td width="20"><a href="class_properties.html"><img src="theme/r_arr.gif" border="0"></a></td>
|
|
||||||
</tr>
|
|
||||||
</table>
|
|
||||||
<p>
|
|
||||||
Data members may also be exposed to Python so that they can be
|
|
||||||
accessed as attributes of the corresponding Python class. Each data
|
|
||||||
member that we wish to be exposed may be regarded as <b>read-only</b> or
|
|
||||||
<b>read-write</b>. Consider this class <tt>Var</tt>:</p>
|
|
||||||
<code><pre>
|
|
||||||
<span class=keyword>struct </span><span class=identifier>Var
|
|
||||||
</span><span class=special>{
|
|
||||||
</span><span class=identifier>Var</span><span class=special>(</span><span class=identifier>std</span><span class=special>::</span><span class=identifier>string </span><span class=identifier>name</span><span class=special>) : </span><span class=identifier>name</span><span class=special>(</span><span class=identifier>name</span><span class=special>), </span><span class=identifier>value</span><span class=special>() {}
|
|
||||||
</span><span class=identifier>std</span><span class=special>::</span><span class=identifier>string </span><span class=keyword>const </span><span class=identifier>name</span><span class=special>;
|
|
||||||
</span><span class=keyword>float </span><span class=identifier>value</span><span class=special>;
|
|
||||||
};
|
|
||||||
</span></pre></code>
|
|
||||||
<p>
|
|
||||||
Our C++ <tt>Var</tt> class and its data members can be exposed to Python:</p>
|
|
||||||
<code><pre>
|
|
||||||
<span class=identifier>class_</span><span class=special><</span><span class=identifier>Var</span><span class=special>>(</span><span class=string>"Var"</span><span class=special>, </span><span class=identifier>init</span><span class=special><</span><span class=identifier>std</span><span class=special>::</span><span class=identifier>string</span><span class=special>>())
|
|
||||||
.</span><span class=identifier>def_readonly</span><span class=special>(</span><span class=string>"name"</span><span class=special>, &</span><span class=identifier>Var</span><span class=special>::</span><span class=identifier>name</span><span class=special>)
|
|
||||||
.</span><span class=identifier>def_readwrite</span><span class=special>(</span><span class=string>"value"</span><span class=special>, &</span><span class=identifier>Var</span><span class=special>::</span><span class=identifier>value</span><span class=special>);
|
|
||||||
</span></pre></code>
|
|
||||||
<p>
|
|
||||||
Then, in Python, assuming we have placed our Var class inside the namespace
|
|
||||||
hello as we did before:</p>
|
|
||||||
<code><pre>
|
|
||||||
<span class=special>>>> </span><span class=identifier>x </span><span class=special>= </span><span class=identifier>hello</span><span class=special>.</span><span class=identifier>Var</span><span class=special>(</span><span class=literal>'pi'</span><span class=special>)
|
|
||||||
>>> </span><span class=identifier>x</span><span class=special>.</span><span class=identifier>value </span><span class=special>= </span><span class=number>3.14
|
|
||||||
</span><span class=special>>>> </span><span class=identifier>print </span><span class=identifier>x</span><span class=special>.</span><span class=identifier>name</span><span class=special>, </span><span class=literal>'is around'</span><span class=special>, </span><span class=identifier>x</span><span class=special>.</span><span class=identifier>value
|
|
||||||
</span><span class=identifier>pi </span><span class=identifier>is </span><span class=identifier>around </span><span class=number>3.14
|
|
||||||
</span></pre></code>
|
|
||||||
<p>
|
|
||||||
Note that <tt>name</tt> is exposed as <b>read-only</b> while <tt>value</tt> is exposed
|
|
||||||
as <b>read-write</b>.</p>
|
|
||||||
<code><pre>
|
|
||||||
>>> x.name = 'e' # can't change name
|
|
||||||
Traceback (most recent call last):
|
|
||||||
File "<stdin>", line 1, in ?
|
|
||||||
AttributeError: can't set attribute
|
|
||||||
</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="constructors.html"><img src="theme/l_arr.gif" border="0"></a></td>
|
|
||||||
<td width="20"><a href="class_properties.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>
|
|
||||||
@@ -1,109 +0,0 @@
|
|||||||
<html>
|
|
||||||
<head>
|
|
||||||
<!-- Generated by the Spirit (http://spirit.sf.net) QuickDoc -->
|
|
||||||
<title>Class Operators/Special Functions</title>
|
|
||||||
<link rel="stylesheet" href="theme/style.css" type="text/css">
|
|
||||||
<link rel="prev" href="virtual_functions_with_default_implementations.html">
|
|
||||||
<link rel="next" href="functions.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>Class Operators/Special Functions</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="virtual_functions_with_default_implementations.html"><img src="theme/l_arr.gif" border="0"></a></td>
|
|
||||||
<td width="20"><a href="functions.html"><img src="theme/r_arr.gif" border="0"></a></td>
|
|
||||||
</tr>
|
|
||||||
</table>
|
|
||||||
<a name="python_operators"></a><h2>Python Operators</h2><p>
|
|
||||||
C is well known for the abundance of operators. C++ extends this to the
|
|
||||||
extremes by allowing operator overloading. Boost.Python takes advantage of
|
|
||||||
this and makes it easy to wrap C++ operator-powered classes.</p>
|
|
||||||
<p>
|
|
||||||
Consider a file position class <tt>FilePos</tt> and a set of operators that take
|
|
||||||
on FilePos instances:</p>
|
|
||||||
<code><pre>
|
|
||||||
<span class=keyword>class </span><span class=identifier>FilePos </span><span class=special>{ /*...*/ };
|
|
||||||
|
|
||||||
</span><span class=identifier>FilePos </span><span class=keyword>operator</span><span class=special>+(</span><span class=identifier>FilePos</span><span class=special>, </span><span class=keyword>int</span><span class=special>);
|
|
||||||
</span><span class=identifier>FilePos </span><span class=keyword>operator</span><span class=special>+(</span><span class=keyword>int</span><span class=special>, </span><span class=identifier>FilePos</span><span class=special>);
|
|
||||||
</span><span class=keyword>int </span><span class=keyword>operator</span><span class=special>-(</span><span class=identifier>FilePos</span><span class=special>, </span><span class=identifier>FilePos</span><span class=special>);
|
|
||||||
</span><span class=identifier>FilePos </span><span class=keyword>operator</span><span class=special>-(</span><span class=identifier>FilePos</span><span class=special>, </span><span class=keyword>int</span><span class=special>);
|
|
||||||
</span><span class=identifier>FilePos</span><span class=special>& </span><span class=keyword>operator</span><span class=special>+=(</span><span class=identifier>FilePos</span><span class=special>&, </span><span class=keyword>int</span><span class=special>);
|
|
||||||
</span><span class=identifier>FilePos</span><span class=special>& </span><span class=keyword>operator</span><span class=special>-=(</span><span class=identifier>FilePos</span><span class=special>&, </span><span class=keyword>int</span><span class=special>);
|
|
||||||
</span><span class=keyword>bool </span><span class=keyword>operator</span><span class=special><(</span><span class=identifier>FilePos</span><span class=special>, </span><span class=identifier>FilePos</span><span class=special>);
|
|
||||||
</span></pre></code>
|
|
||||||
<p>
|
|
||||||
The class and the various operators can be mapped to Python rather easily
|
|
||||||
and intuitively:</p>
|
|
||||||
<code><pre>
|
|
||||||
<span class=identifier>class_</span><span class=special><</span><span class=identifier>FilePos</span><span class=special>>(</span><span class=string>"FilePos"</span><span class=special>)
|
|
||||||
.</span><span class=identifier>def</span><span class=special>(</span><span class=identifier>self </span><span class=special>+ </span><span class=keyword>int</span><span class=special>()) // </span><span class=identifier>__add__
|
|
||||||
</span><span class=special>.</span><span class=identifier>def</span><span class=special>(</span><span class=keyword>int</span><span class=special>() + </span><span class=identifier>self</span><span class=special>) // </span><span class=identifier>__radd__
|
|
||||||
</span><span class=special>.</span><span class=identifier>def</span><span class=special>(</span><span class=identifier>self </span><span class=special>- </span><span class=identifier>self</span><span class=special>) // </span><span class=identifier>__sub__
|
|
||||||
</span><span class=special>.</span><span class=identifier>def</span><span class=special>(</span><span class=identifier>self </span><span class=special>- </span><span class=keyword>int</span><span class=special>()) // </span><span class=identifier>__sub__
|
|
||||||
</span><span class=special>.</span><span class=identifier>def</span><span class=special>(</span><span class=identifier>self </span><span class=special>+= </span><span class=keyword>int</span><span class=special>()) // </span><span class=identifier>__iadd__
|
|
||||||
</span><span class=special>.</span><span class=identifier>def</span><span class=special>(</span><span class=identifier>self </span><span class=special>-= </span><span class=identifier>other</span><span class=special><</span><span class=keyword>int</span><span class=special>>())
|
|
||||||
.</span><span class=identifier>def</span><span class=special>(</span><span class=identifier>self </span><span class=special>< </span><span class=identifier>self</span><span class=special>); // </span><span class=identifier>__lt__
|
|
||||||
</span></pre></code>
|
|
||||||
<p>
|
|
||||||
The code snippet above is very clear and needs almost no explanation at
|
|
||||||
all. It is virtually the same as the operators' signatures. Just take
|
|
||||||
note that <tt>self</tt> refers to FilePos object. Also, not every class <tt>T</tt> that
|
|
||||||
you might need to interact with in an operator expression is (cheaply)
|
|
||||||
default-constructible. You can use <tt>other<T>()</tt> in place of an actual
|
|
||||||
<tt>T</tt> instance when writing "self expressions".</p>
|
|
||||||
<a name="special_methods"></a><h2>Special Methods</h2><p>
|
|
||||||
Python has a few more <i>Special Methods</i>. Boost.Python supports all of the
|
|
||||||
standard special method names supported by real Python class instances. A
|
|
||||||
similar set of intuitive interfaces can also be used to wrap C++ functions
|
|
||||||
that correspond to these Python <i>special functions</i>. Example:</p>
|
|
||||||
<code><pre>
|
|
||||||
<span class=keyword>class </span><span class=identifier>Rational
|
|
||||||
</span><span class=special>{ </span><span class=keyword>operator </span><span class=keyword>double</span><span class=special>() </span><span class=keyword>const</span><span class=special>; };
|
|
||||||
|
|
||||||
</span><span class=identifier>Rational </span><span class=identifier>pow</span><span class=special>(</span><span class=identifier>Rational</span><span class=special>, </span><span class=identifier>Rational</span><span class=special>);
|
|
||||||
</span><span class=identifier>Rational </span><span class=identifier>abs</span><span class=special>(</span><span class=identifier>Rational</span><span class=special>);
|
|
||||||
</span><span class=identifier>ostream</span><span class=special>& </span><span class=keyword>operator</span><span class=special><<(</span><span class=identifier>ostream</span><span class=special>&,</span><span class=identifier>Rational</span><span class=special>);
|
|
||||||
|
|
||||||
</span><span class=identifier>class_</span><span class=special><</span><span class=identifier>Rational</span><span class=special>>()
|
|
||||||
.</span><span class=identifier>def</span><span class=special>(</span><span class=identifier>float_</span><span class=special>(</span><span class=identifier>self</span><span class=special>)) // </span><span class=identifier>__float__
|
|
||||||
</span><span class=special>.</span><span class=identifier>def</span><span class=special>(</span><span class=identifier>pow</span><span class=special>(</span><span class=identifier>self</span><span class=special>, </span><span class=identifier>other</span><span class=special><</span><span class=identifier>Rational</span><span class=special>>)) // </span><span class=identifier>__pow__
|
|
||||||
</span><span class=special>.</span><span class=identifier>def</span><span class=special>(</span><span class=identifier>abs</span><span class=special>(</span><span class=identifier>self</span><span class=special>)) // </span><span class=identifier>__abs__
|
|
||||||
</span><span class=special>.</span><span class=identifier>def</span><span class=special>(</span><span class=identifier>str</span><span class=special>(</span><span class=identifier>self</span><span class=special>)) // </span><span class=identifier>__str__
|
|
||||||
</span><span class=special>;
|
|
||||||
</span></pre></code>
|
|
||||||
<p>
|
|
||||||
Need we say more?</p>
|
|
||||||
<table width="80%" border="0" align="center">
|
|
||||||
<tr>
|
|
||||||
<td class="note_box">
|
|
||||||
<img src="theme/lens.gif"></img> What is the business of <tt>operator<<</tt> <tt>.def(str(self))</tt>?
|
|
||||||
Well, the method <tt>str</tt> requires the <tt>operator<<</tt> to do its work (i.e.
|
|
||||||
<tt>operator<<</tt> is used by the method defined by def(str(self)). </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="virtual_functions_with_default_implementations.html"><img src="theme/l_arr.gif" border="0"></a></td>
|
|
||||||
<td width="20"><a href="functions.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>
|
|
||||||
@@ -1,81 +0,0 @@
|
|||||||
<html>
|
|
||||||
<head>
|
|
||||||
<!-- Generated by the Spirit (http://spirit.sf.net) QuickDoc -->
|
|
||||||
<title>Class Properties</title>
|
|
||||||
<link rel="stylesheet" href="theme/style.css" type="text/css">
|
|
||||||
<link rel="prev" href="class_data_members.html">
|
|
||||||
<link rel="next" href="inheritance.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>Class Properties</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="class_data_members.html"><img src="theme/l_arr.gif" border="0"></a></td>
|
|
||||||
<td width="20"><a href="inheritance.html"><img src="theme/r_arr.gif" border="0"></a></td>
|
|
||||||
</tr>
|
|
||||||
</table>
|
|
||||||
<p>
|
|
||||||
In C++, classes with public data members are usually frowned
|
|
||||||
upon. Well designed classes that take advantage of encapsulation hide
|
|
||||||
the class' data members. The only way to access the class' data is
|
|
||||||
through access (getter/setter) functions. Access functions expose class
|
|
||||||
properties. Here's an example:</p>
|
|
||||||
<code><pre>
|
|
||||||
<span class=keyword>struct </span><span class=identifier>Num
|
|
||||||
</span><span class=special>{
|
|
||||||
</span><span class=identifier>Num</span><span class=special>();
|
|
||||||
</span><span class=keyword>float </span><span class=identifier>get</span><span class=special>() </span><span class=keyword>const</span><span class=special>;
|
|
||||||
</span><span class=keyword>void </span><span class=identifier>set</span><span class=special>(</span><span class=keyword>float </span><span class=identifier>value</span><span class=special>);
|
|
||||||
...
|
|
||||||
};
|
|
||||||
</span></pre></code>
|
|
||||||
<p>
|
|
||||||
However, in Python attribute access is fine; it doesn't neccessarily break
|
|
||||||
encapsulation to let users handle attributes directly, because the
|
|
||||||
attributes can just be a different syntax for a method call. Wrapping our
|
|
||||||
<tt>Num</tt> class using Boost.Python:</p>
|
|
||||||
<code><pre>
|
|
||||||
<span class=identifier>class_</span><span class=special><</span><span class=identifier>Num</span><span class=special>>(</span><span class=string>"Num"</span><span class=special>)
|
|
||||||
.</span><span class=identifier>add_property</span><span class=special>(</span><span class=string>"rovalue"</span><span class=special>, &</span><span class=identifier>Num</span><span class=special>::</span><span class=identifier>get</span><span class=special>)
|
|
||||||
.</span><span class=identifier>add_property</span><span class=special>(</span><span class=string>"value"</span><span class=special>, &</span><span class=identifier>Num</span><span class=special>::</span><span class=identifier>get</span><span class=special>, &</span><span class=identifier>Num</span><span class=special>::</span><span class=identifier>set</span><span class=special>);
|
|
||||||
</span></pre></code>
|
|
||||||
<p>
|
|
||||||
And at last, in Python:</p>
|
|
||||||
<code><pre>
|
|
||||||
<span class=special>>>> </span><span class=identifier>x </span><span class=special>= </span><span class=identifier>Num</span><span class=special>()
|
|
||||||
>>> </span><span class=identifier>x</span><span class=special>.</span><span class=identifier>value </span><span class=special>= </span><span class=number>3.14
|
|
||||||
</span><span class=special>>>> </span><span class=identifier>x</span><span class=special>.</span><span class=identifier>value</span><span class=special>, </span><span class=identifier>x</span><span class=special>.</span><span class=identifier>rovalue
|
|
||||||
</span><span class=special>(</span><span class=number>3.14</span><span class=special>, </span><span class=number>3.14</span><span class=special>)
|
|
||||||
>>> </span><span class=identifier>x</span><span class=special>.</span><span class=identifier>rovalue </span><span class=special>= </span><span class=number>2.17 </span>##<span class=identifier>error</span><span class=special>!
|
|
||||||
</span></pre></code>
|
|
||||||
<p>
|
|
||||||
Take note that the class property <tt>rovalue</tt> is exposed as <b>read-only</b>
|
|
||||||
since the <tt>rovalue</tt> setter member function is not passed in:</p>
|
|
||||||
<code><pre>
|
|
||||||
<span class=special>.</span><span class=identifier>add_property</span><span class=special>(</span><span class=string>"rovalue"</span><span class=special>, &</span><span class=identifier>Num</span><span class=special>::</span><span class=identifier>get</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="class_data_members.html"><img src="theme/l_arr.gif" border="0"></a></td>
|
|
||||||
<td width="20"><a href="inheritance.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>
|
|
||||||
@@ -1,129 +0,0 @@
|
|||||||
<html>
|
|
||||||
<head>
|
|
||||||
<!-- Generated by the Spirit (http://spirit.sf.net) QuickDoc -->
|
|
||||||
<title>Class Virtual Functions</title>
|
|
||||||
<link rel="stylesheet" href="theme/style.css" type="text/css">
|
|
||||||
<link rel="prev" href="inheritance.html">
|
|
||||||
<link rel="next" href="deriving_a_python_class.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>Class Virtual Functions</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="inheritance.html"><img src="theme/l_arr.gif" border="0"></a></td>
|
|
||||||
<td width="20"><a href="deriving_a_python_class.html"><img src="theme/r_arr.gif" border="0"></a></td>
|
|
||||||
</tr>
|
|
||||||
</table>
|
|
||||||
<p>
|
|
||||||
In this section, we shall learn how to make functions behave
|
|
||||||
polymorphically through virtual functions. Continuing our example, let us
|
|
||||||
add a virtual function to our <tt>Base</tt> class:</p>
|
|
||||||
<code><pre>
|
|
||||||
<span class=keyword>struct </span><span class=identifier>Base
|
|
||||||
</span><span class=special>{
|
|
||||||
</span><span class=keyword>virtual </span><span class=keyword>int </span><span class=identifier>f</span><span class=special>() = </span><span class=number>0</span><span class=special>;
|
|
||||||
};
|
|
||||||
</span></pre></code>
|
|
||||||
<p>
|
|
||||||
Since <tt>f</tt> is a pure virtual function, <tt>Base</tt> is now an abstract
|
|
||||||
class. Given an instance of our class, the free function <tt>call_f</tt>
|
|
||||||
calls some implementation of this virtual function in a concrete
|
|
||||||
derived class:</p>
|
|
||||||
<code><pre>
|
|
||||||
<span class=keyword>int </span><span class=identifier>call_f</span><span class=special>(</span><span class=identifier>Base</span><span class=special>& </span><span class=identifier>b</span><span class=special>) { </span><span class=keyword>return </span><span class=identifier>b</span><span class=special>.</span><span class=identifier>f</span><span class=special>(); }
|
|
||||||
</span></pre></code>
|
|
||||||
<p>
|
|
||||||
To allow this function to be implemented in a Python derived class, we
|
|
||||||
need to create a class wrapper:</p>
|
|
||||||
<code><pre>
|
|
||||||
<span class=keyword>struct </span><span class=identifier>BaseWrap </span><span class=special>: </span><span class=identifier>Base
|
|
||||||
</span><span class=special>{
|
|
||||||
</span><span class=identifier>BaseWrap</span><span class=special>(</span><span class=identifier>PyObject</span><span class=special>* </span><span class=identifier>self_</span><span class=special>)
|
|
||||||
: </span><span class=identifier>self</span><span class=special>(</span><span class=identifier>self_</span><span class=special>) {}
|
|
||||||
</span><span class=keyword>int </span><span class=identifier>f</span><span class=special>() { </span><span class=keyword>return </span><span class=identifier>call_method</span><span class=special><</span><span class=keyword>int</span><span class=special>>(</span><span class=identifier>self</span><span class=special>, </span><span class=string>"f"</span><span class=special>); }
|
|
||||||
</span><span class=identifier>PyObject</span><span class=special>* </span><span class=identifier>self</span><span class=special>;
|
|
||||||
};
|
|
||||||
</span></pre></code>
|
|
||||||
<table width="80%" border="0" align="center">
|
|
||||||
<tr>
|
|
||||||
<td class="note_box">
|
|
||||||
<img src="theme/lens.gif"></img> <b>member function and methods</b><br><br> Python, like
|
|
||||||
many object oriented languages uses the term <b>methods</b>. Methods
|
|
||||||
correspond roughly to C++'s <b>member functions</b> </td>
|
|
||||||
</tr>
|
|
||||||
</table>
|
|
||||||
<p>
|
|
||||||
Our class wrapper <tt>BaseWrap</tt> is derived from <tt>Base</tt>. Its overridden
|
|
||||||
virtual member function <tt>f</tt> in effect calls the corresponding method
|
|
||||||
of the Python object <tt>self</tt>, which is a pointer back to the Python
|
|
||||||
<tt>Base</tt> object holding our <tt>BaseWrap</tt> instance.</p>
|
|
||||||
<table width="80%" border="0" align="center">
|
|
||||||
<tr>
|
|
||||||
<td class="note_box">
|
|
||||||
<img src="theme/note.gif"></img> <b>Why do we need BaseWrap?</b><br><br>
|
|
||||||
|
|
||||||
<i>You may ask</i>, "Why do we need the <tt>BaseWrap</tt> derived class? This could
|
|
||||||
have been designed so that everything gets done right inside of
|
|
||||||
Base."<br><br>
|
|
||||||
|
|
||||||
One of the goals of Boost.Python is to be minimally intrusive on an
|
|
||||||
existing C++ design. In principle, it should be possible to expose the
|
|
||||||
interface for a 3rd party library without changing it. To unintrusively
|
|
||||||
hook into the virtual functions so that a Python override may be called, we
|
|
||||||
must use a derived class.<br><br>
|
|
||||||
|
|
||||||
Note however that you don't need to do this to get methods overridden
|
|
||||||
in Python to behave virtually when called <i>from</i> <b>Python</b>. The only
|
|
||||||
time you need to do the <tt>BaseWrap</tt> dance is when you have a virtual
|
|
||||||
function that's going to be overridden in Python and called
|
|
||||||
polymorphically <i>from</i> <b>C++</b>. </td>
|
|
||||||
</tr>
|
|
||||||
</table>
|
|
||||||
<p>
|
|
||||||
Wrapping <tt>Base</tt> and the free function <tt>call_f</tt>:</p>
|
|
||||||
<code><pre>
|
|
||||||
<span class=identifier>class_</span><span class=special><</span><span class=identifier>Base</span><span class=special>, </span><span class=identifier>BaseWrap</span><span class=special>, </span><span class=identifier>boost</span><span class=special>::</span><span class=identifier>noncopyable</span><span class=special>>(</span><span class=string>"Base"</span><span class=special>, </span><span class=identifier>no_init</span><span class=special>)
|
|
||||||
;
|
|
||||||
</span><span class=identifier>def</span><span class=special>(</span><span class=string>"call_f"</span><span class=special>, </span><span class=identifier>call_f</span><span class=special>);
|
|
||||||
</span></pre></code>
|
|
||||||
<p>
|
|
||||||
Notice that we parameterized the <tt>class_</tt> template with <tt>BaseWrap</tt> as the
|
|
||||||
second parameter. What is <tt>noncopyable</tt>? Without it, the library will try
|
|
||||||
to create code for converting Base return values of wrapped functions to
|
|
||||||
Python. To do that, it needs Base's copy constructor... which isn't
|
|
||||||
available, since Base is an abstract class.</p>
|
|
||||||
<p>
|
|
||||||
In Python, let us try to instantiate our <tt>Base</tt> class:</p>
|
|
||||||
<code><pre>
|
|
||||||
<span class=special>>>> </span><span class=identifier>base </span><span class=special>= </span><span class=identifier>Base</span><span class=special>()
|
|
||||||
</span><span class=identifier>RuntimeError</span><span class=special>: </span><span class=identifier>This </span><span class=keyword>class </span><span class=identifier>cannot </span><span class=identifier>be </span><span class=identifier>instantiated </span><span class=identifier>from </span><span class=identifier>Python
|
|
||||||
</span></pre></code>
|
|
||||||
<p>
|
|
||||||
Why is it an error? <tt>Base</tt> is an abstract class. As such it is advisable
|
|
||||||
to define the Python wrapper with <tt>no_init</tt> as we have done above. Doing
|
|
||||||
so will disallow abstract base classes such as <tt>Base</tt> to be instantiated.</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="inheritance.html"><img src="theme/l_arr.gif" border="0"></a></td>
|
|
||||||
<td width="20"><a href="deriving_a_python_class.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>
|
|
||||||
@@ -1,102 +0,0 @@
|
|||||||
<html>
|
|
||||||
<head>
|
|
||||||
<!-- Generated by the Spirit (http://spirit.sf.net) QuickDoc -->
|
|
||||||
<title>Constructors</title>
|
|
||||||
<link rel="stylesheet" href="theme/style.css" type="text/css">
|
|
||||||
<link rel="prev" href="exposing_classes.html">
|
|
||||||
<link rel="next" href="class_data_members.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>Constructors</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="exposing_classes.html"><img src="theme/l_arr.gif" border="0"></a></td>
|
|
||||||
<td width="20"><a href="class_data_members.html"><img src="theme/r_arr.gif" border="0"></a></td>
|
|
||||||
</tr>
|
|
||||||
</table>
|
|
||||||
<p>
|
|
||||||
Our previous example didn't have any explicit constructors.
|
|
||||||
Since <tt>World</tt> is declared as a plain struct, it has an implicit default
|
|
||||||
constructor. Boost.Python exposes the default constructor by default,
|
|
||||||
which is why we were able to write</p>
|
|
||||||
<code><pre>
|
|
||||||
<span class=special>>>> </span><span class=identifier>planet </span><span class=special>= </span><span class=identifier>hello</span><span class=special>.</span><span class=identifier>World</span><span class=special>()
|
|
||||||
</span></pre></code>
|
|
||||||
<p>
|
|
||||||
We may wish to wrap a class with a non-default constructor. Let us
|
|
||||||
build on our previous example:</p>
|
|
||||||
<code><pre>
|
|
||||||
<span class=keyword>struct </span><span class=identifier>World
|
|
||||||
</span><span class=special>{
|
|
||||||
</span><span class=identifier>World</span><span class=special>(</span><span class=identifier>std</span><span class=special>::</span><span class=identifier>string </span><span class=identifier>msg</span><span class=special>): </span><span class=identifier>msg</span><span class=special>(</span><span class=identifier>msg</span><span class=special>) {} // </span><span class=identifier>added </span><span class=identifier>constructor
|
|
||||||
</span><span class=keyword>void </span><span class=identifier>set</span><span class=special>(</span><span class=identifier>std</span><span class=special>::</span><span class=identifier>string </span><span class=identifier>msg</span><span class=special>) { </span><span class=keyword>this</span><span class=special>-></span><span class=identifier>msg </span><span class=special>= </span><span class=identifier>msg</span><span class=special>; }
|
|
||||||
</span><span class=identifier>std</span><span class=special>::</span><span class=identifier>string </span><span class=identifier>greet</span><span class=special>() { </span><span class=keyword>return </span><span class=identifier>msg</span><span class=special>; }
|
|
||||||
</span><span class=identifier>std</span><span class=special>::</span><span class=identifier>string </span><span class=identifier>msg</span><span class=special>;
|
|
||||||
};
|
|
||||||
</span></pre></code>
|
|
||||||
<p>
|
|
||||||
This time <tt>World</tt> has no default constructor; our previous
|
|
||||||
wrapping code would fail to compile when the library tried to expose
|
|
||||||
it. We have to tell <tt>class_<World></tt> about the constructor we want to
|
|
||||||
expose instead.</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=keyword>using </span><span class=keyword>namespace </span><span class=identifier>boost</span><span class=special>::</span><span class=identifier>python</span><span class=special>;
|
|
||||||
|
|
||||||
</span><span class=identifier>BOOST_PYTHON_MODULE</span><span class=special>(</span><span class=identifier>hello</span><span class=special>)
|
|
||||||
{
|
|
||||||
</span><span class=identifier>class_</span><span class=special><</span><span class=identifier>World</span><span class=special>>(</span><span class=string>"World"</span><span class=special>, </span><span class=identifier>init</span><span class=special><</span><span class=identifier>std</span><span class=special>::</span><span class=identifier>string</span><span class=special>>())
|
|
||||||
.</span><span class=identifier>def</span><span class=special>(</span><span class=string>"greet"</span><span class=special>, &</span><span class=identifier>World</span><span class=special>::</span><span class=identifier>greet</span><span class=special>)
|
|
||||||
.</span><span class=identifier>def</span><span class=special>(</span><span class=string>"set"</span><span class=special>, &</span><span class=identifier>World</span><span class=special>::</span><span class=identifier>set</span><span class=special>)
|
|
||||||
;
|
|
||||||
}
|
|
||||||
</span></pre></code>
|
|
||||||
<p>
|
|
||||||
<tt>init<std::string>()</tt> exposes the constructor taking in a
|
|
||||||
<tt>std::string</tt> (in Python, constructors are spelled
|
|
||||||
"<tt>"__init__"</tt>").</p>
|
|
||||||
<p>
|
|
||||||
We can expose additional constructors by passing more <tt>init<...></tt>s to
|
|
||||||
the <tt>def()</tt> member function. Say for example we have another World
|
|
||||||
constructor taking in two doubles:</p>
|
|
||||||
<code><pre>
|
|
||||||
<span class=identifier>class_</span><span class=special><</span><span class=identifier>World</span><span class=special>>(</span><span class=string>"World"</span><span class=special>, </span><span class=identifier>init</span><span class=special><</span><span class=identifier>std</span><span class=special>::</span><span class=identifier>string</span><span class=special>>())
|
|
||||||
.</span><span class=identifier>def</span><span class=special>(</span><span class=identifier>init</span><span class=special><</span><span class=keyword>double</span><span class=special>, </span><span class=keyword>double</span><span class=special>>())
|
|
||||||
.</span><span class=identifier>def</span><span class=special>(</span><span class=string>"greet"</span><span class=special>, &</span><span class=identifier>World</span><span class=special>::</span><span class=identifier>greet</span><span class=special>)
|
|
||||||
.</span><span class=identifier>def</span><span class=special>(</span><span class=string>"set"</span><span class=special>, &</span><span class=identifier>World</span><span class=special>::</span><span class=identifier>set</span><span class=special>)
|
|
||||||
;
|
|
||||||
</span></pre></code>
|
|
||||||
<p>
|
|
||||||
On the other hand, if we do not wish to expose any constructors at
|
|
||||||
all, we may use <tt>no_init</tt> instead:</p>
|
|
||||||
<code><pre>
|
|
||||||
<span class=identifier>class_</span><span class=special><</span><span class=identifier>Abstract</span><span class=special>>(</span><span class=string>"Abstract"</span><span class=special>, </span><span class=identifier>no_init</span><span class=special>)
|
|
||||||
</span></pre></code>
|
|
||||||
<p>
|
|
||||||
This actually adds an <tt>__init__</tt> method which always raises a
|
|
||||||
Python RuntimeError exception.</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="exposing_classes.html"><img src="theme/l_arr.gif" border="0"></a></td>
|
|
||||||
<td width="20"><a href="class_data_members.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>
|
|
||||||
@@ -1,158 +0,0 @@
|
|||||||
<html>
|
|
||||||
<head>
|
|
||||||
<!-- Generated by the Spirit (http://spirit.sf.net) QuickDoc -->
|
|
||||||
<title>Default Arguments</title>
|
|
||||||
<link rel="stylesheet" href="theme/style.css" type="text/css">
|
|
||||||
<link rel="prev" href="overloading.html">
|
|
||||||
<link rel="next" href="auto_overloading.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>Default Arguments</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="overloading.html"><img src="theme/l_arr.gif" border="0"></a></td>
|
|
||||||
<td width="20"><a href="auto_overloading.html"><img src="theme/r_arr.gif" border="0"></a></td>
|
|
||||||
</tr>
|
|
||||||
</table>
|
|
||||||
<p>
|
|
||||||
Boost.Python wraps (member) function pointers. Unfortunately, C++ function
|
|
||||||
pointers carry no default argument info. Take a function <tt>f</tt> with default
|
|
||||||
arguments:</p>
|
|
||||||
<code><pre>
|
|
||||||
<span class=keyword>int </span><span class=identifier>f</span><span class=special>(</span><span class=keyword>int</span><span class=special>, </span><span class=keyword>double </span><span class=special>= </span><span class=number>3.14</span><span class=special>, </span><span class=keyword>char </span><span class=keyword>const</span><span class=special>* = </span><span class=string>"hello"</span><span class=special>);
|
|
||||||
</span></pre></code>
|
|
||||||
<p>
|
|
||||||
But the type of a pointer to the function <tt>f</tt> has no information
|
|
||||||
about its default arguments:</p>
|
|
||||||
<code><pre>
|
|
||||||
<span class=keyword>int</span><span class=special>(*</span><span class=identifier>g</span><span class=special>)(</span><span class=keyword>int</span><span class=special>,</span><span class=keyword>double</span><span class=special>,</span><span class=keyword>char </span><span class=keyword>const</span><span class=special>*) = </span><span class=identifier>f</span><span class=special>; // </span><span class=identifier>defaults </span><span class=identifier>lost</span><span class=special>!
|
|
||||||
</span></pre></code>
|
|
||||||
<p>
|
|
||||||
When we pass this function pointer to the <tt>def</tt> function, there is no way
|
|
||||||
to retrieve the default arguments:</p>
|
|
||||||
<code><pre>
|
|
||||||
<span class=identifier>def</span><span class=special>(</span><span class=string>"f"</span><span class=special>, </span><span class=identifier>f</span><span class=special>); // </span><span class=identifier>defaults </span><span class=identifier>lost</span><span class=special>!
|
|
||||||
</span></pre></code>
|
|
||||||
<p>
|
|
||||||
Because of this, when wrapping C++ code, we had to resort to manual
|
|
||||||
wrapping as outlined in the <a href="overloading.html">
|
|
||||||
previous section</a>, or
|
|
||||||
writing thin wrappers:</p>
|
|
||||||
<code><pre>
|
|
||||||
<span class=comment>// write "thin wrappers"
|
|
||||||
</span><span class=keyword>int </span><span class=identifier>f1</span><span class=special>(</span><span class=keyword>int </span><span class=identifier>x</span><span class=special>) { </span><span class=identifier>f</span><span class=special>(</span><span class=identifier>x</span><span class=special>); }
|
|
||||||
</span><span class=keyword>int </span><span class=identifier>f2</span><span class=special>(</span><span class=keyword>int </span><span class=identifier>x</span><span class=special>, </span><span class=keyword>double </span><span class=identifier>y</span><span class=special>) { </span><span class=identifier>f</span><span class=special>(</span><span class=identifier>x</span><span class=special>,</span><span class=identifier>y</span><span class=special>); }
|
|
||||||
|
|
||||||
/*...*/
|
|
||||||
|
|
||||||
// </span><span class=identifier>in </span><span class=identifier>module </span><span class=identifier>init
|
|
||||||
</span><span class=identifier>def</span><span class=special>(</span><span class=string>"f"</span><span class=special>, </span><span class=identifier>f</span><span class=special>); // </span><span class=identifier>all </span><span class=identifier>arguments
|
|
||||||
</span><span class=identifier>def</span><span class=special>(</span><span class=string>"f"</span><span class=special>, </span><span class=identifier>f2</span><span class=special>); // </span><span class=identifier>two </span><span class=identifier>arguments
|
|
||||||
</span><span class=identifier>def</span><span class=special>(</span><span class=string>"f"</span><span class=special>, </span><span class=identifier>f1</span><span class=special>); // </span><span class=identifier>one </span><span class=identifier>argument
|
|
||||||
</span></pre></code>
|
|
||||||
<p>
|
|
||||||
When you want to wrap functions (or member functions) that either:</p>
|
|
||||||
<ul><li>have default arguments, or</li><li>are overloaded with a common sequence of initial arguments</li></ul><a name="boost_python_function_overloads"></a><h2>BOOST_PYTHON_FUNCTION_OVERLOADS</h2><p>
|
|
||||||
Boost.Python now has a way to make it easier. For instance, given a function:</p>
|
|
||||||
<code><pre>
|
|
||||||
<span class=keyword>int </span><span class=identifier>foo</span><span class=special>(</span><span class=keyword>int </span><span class=identifier>a</span><span class=special>, </span><span class=keyword>char </span><span class=identifier>b </span><span class=special>= </span><span class=number>1</span><span class=special>, </span><span class=keyword>unsigned </span><span class=identifier>c </span><span class=special>= </span><span class=number>2</span><span class=special>, </span><span class=keyword>double </span><span class=identifier>d </span><span class=special>= </span><span class=number>3</span><span class=special>)
|
|
||||||
{
|
|
||||||
/*...*/
|
|
||||||
}
|
|
||||||
</span></pre></code>
|
|
||||||
<p>
|
|
||||||
The macro invocation:</p>
|
|
||||||
<code><pre>
|
|
||||||
<span class=identifier>BOOST_PYTHON_FUNCTION_OVERLOADS</span><span class=special>(</span><span class=identifier>foo_overloads</span><span class=special>, </span><span class=identifier>foo</span><span class=special>, </span><span class=number>1</span><span class=special>, </span><span class=number>4</span><span class=special>)
|
|
||||||
</span></pre></code>
|
|
||||||
<p>
|
|
||||||
will automatically create the thin wrappers for us. This macro will create
|
|
||||||
a class <tt>foo_overloads</tt> that can be passed on to <tt>def(...)</tt>. The third
|
|
||||||
and fourth macro argument are the minimum arguments and maximum arguments,
|
|
||||||
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=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
|
|
||||||
than anything else, we need to expose member functions of our classes to
|
|
||||||
Python. Then again, we have the same inconveniences as before when default
|
|
||||||
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
|
|
||||||
the thin wrappers for wrapping member functions. Let's have an example:</p>
|
|
||||||
<code><pre>
|
|
||||||
<span class=keyword>struct </span><span class=identifier>george
|
|
||||||
</span><span class=special>{
|
|
||||||
</span><span class=keyword>void
|
|
||||||
</span><span class=identifier>wack_em</span><span class=special>(</span><span class=keyword>int </span><span class=identifier>a</span><span class=special>, </span><span class=keyword>int </span><span class=identifier>b </span><span class=special>= </span><span class=number>0</span><span class=special>, </span><span class=keyword>char </span><span class=identifier>c </span><span class=special>= </span><span class=literal>'x'</span><span class=special>)
|
|
||||||
{
|
|
||||||
/*...*/
|
|
||||||
}
|
|
||||||
};
|
|
||||||
</span></pre></code>
|
|
||||||
<p>
|
|
||||||
The macro invocation:</p>
|
|
||||||
<code><pre>
|
|
||||||
<span class=identifier>BOOST_PYTHON_MEMBER_FUNCTION_OVERLOADS</span><span class=special>(</span><span class=identifier>george_overloads</span><span class=special>, </span><span class=identifier>wack_em</span><span class=special>, </span><span class=number>1</span><span class=special>, </span><span class=number>3</span><span class=special>)
|
|
||||||
</span></pre></code>
|
|
||||||
<p>
|
|
||||||
will generate a set of thin wrappers for george's <tt>wack_em</tt> member function
|
|
||||||
accepting a minimum of 1 and a maximum of 3 arguments (i.e. the third and
|
|
||||||
fourth macro argument). The thin wrappers are all enclosed in a class named
|
|
||||||
<tt>george_overloads</tt> that can then be used as an argument to <tt>def(...)</tt>:</p>
|
|
||||||
<code><pre>
|
|
||||||
<span class=special>.</span><span class=identifier>def</span><span class=special>(</span><span class=string>"wack_em"</span><span class=special>, &</span><span class=identifier>george</span><span class=special>::</span><span class=identifier>wack_em</span><span class=special>, </span><span class=identifier>george_overloads</span><span class=special>());
|
|
||||||
</span></pre></code>
|
|
||||||
<p>
|
|
||||||
See the <a href="../../v2/overloads.html#BOOST_PYTHON_FUNCTION_OVERLOADS-spec">
|
|
||||||
overloads reference</a>
|
|
||||||
for details.</p>
|
|
||||||
<a name="init_and_optional"></a><h2>init and optional</h2><p>
|
|
||||||
A similar facility is provided for class constructors, again, with
|
|
||||||
default arguments or a sequence of overloads. Remember <tt>init<...></tt>? For example,
|
|
||||||
given a class X with a constructor:</p>
|
|
||||||
<code><pre>
|
|
||||||
<span class=keyword>struct </span><span class=identifier>X
|
|
||||||
</span><span class=special>{
|
|
||||||
</span><span class=identifier>X</span><span class=special>(</span><span class=keyword>int </span><span class=identifier>a</span><span class=special>, </span><span class=keyword>char </span><span class=identifier>b </span><span class=special>= </span><span class=literal>'D'</span><span class=special>, </span><span class=identifier>std</span><span class=special>::</span><span class=identifier>string </span><span class=identifier>c </span><span class=special>= </span><span class=string>"constructor"</span><span class=special>, </span><span class=keyword>double </span><span class=identifier>d </span><span class=special>= </span><span class=number>0.0</span><span class=special>);
|
|
||||||
/*...*/
|
|
||||||
}
|
|
||||||
</span></pre></code>
|
|
||||||
<p>
|
|
||||||
You can easily add this constructor to Boost.Python in one shot:</p>
|
|
||||||
<code><pre>
|
|
||||||
<span class=special>.</span><span class=identifier>def</span><span class=special>(</span><span class=identifier>init</span><span class=special><</span><span class=keyword>int</span><span class=special>, </span><span class=identifier>optional</span><span class=special><</span><span class=keyword>char</span><span class=special>, </span><span class=identifier>std</span><span class=special>::</span><span class=identifier>string</span><span class=special>, </span><span class=keyword>double</span><span class=special>> >())
|
|
||||||
</span></pre></code>
|
|
||||||
<p>
|
|
||||||
Notice the use of <tt>init<...></tt> and <tt>optional<...></tt> to signify the default
|
|
||||||
(optional arguments).</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="overloading.html"><img src="theme/l_arr.gif" border="0"></a></td>
|
|
||||||
<td width="20"><a href="auto_overloading.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>
|
|
||||||
@@ -1,117 +0,0 @@
|
|||||||
<html>
|
|
||||||
<head>
|
|
||||||
<!-- Generated by the Spirit (http://spirit.sf.net) QuickDoc -->
|
|
||||||
<title>Derived Object types</title>
|
|
||||||
<link rel="stylesheet" href="theme/style.css" type="text/css">
|
|
||||||
<link rel="prev" href="basic_interface.html">
|
|
||||||
<link rel="next" href="extracting_c___objects.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>Derived Object types</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="basic_interface.html"><img src="theme/l_arr.gif" border="0"></a></td>
|
|
||||||
<td width="20"><a href="extracting_c___objects.html"><img src="theme/r_arr.gif" border="0"></a></td>
|
|
||||||
</tr>
|
|
||||||
</table>
|
|
||||||
<p>
|
|
||||||
Boost.Python comes with a set of derived <tt>object</tt> types corresponding to
|
|
||||||
that of Python's:</p>
|
|
||||||
<ul><li>list</li><li>dict</li><li>tuple</li><li>str</li><li>long_</li><li>enum</li></ul><p>
|
|
||||||
These derived <tt>object</tt> types act like real Python types. For instance:</p>
|
|
||||||
<code><pre>
|
|
||||||
<span class=identifier>str</span><span class=special>(</span><span class=number>1</span><span class=special>) ==> </span><span class=string>"1"
|
|
||||||
</span></pre></code>
|
|
||||||
<p>
|
|
||||||
Wherever appropriate, a particular derived <tt>object</tt> has corresponding
|
|
||||||
Python type's methods. For instance, <tt>dict</tt> has a <tt>keys()</tt> method:</p>
|
|
||||||
<code><pre>
|
|
||||||
<span class=identifier>d</span><span class=special>.</span><span class=identifier>keys</span><span class=special>()
|
|
||||||
</span></pre></code>
|
|
||||||
<p>
|
|
||||||
<tt>make_tuple</tt> is provided for declaring <i>tuple literals</i>. Example:</p>
|
|
||||||
<code><pre>
|
|
||||||
<span class=identifier>make_tuple</span><span class=special>(</span><span class=number>123</span><span class=special>, </span><span class=literal>'D'</span><span class=special>, </span><span class=string>"Hello, World"</span><span class=special>, </span><span class=number>0.0</span><span class=special>);
|
|
||||||
</span></pre></code>
|
|
||||||
<p>
|
|
||||||
In C++, when Boost.Python <tt>object</tt>s are used as arguments to functions,
|
|
||||||
subtype matching is required. For example, when a function <tt>f</tt>, as
|
|
||||||
declared below, is wrapped, it will only accept instances of Python's
|
|
||||||
<tt>str</tt> type and subtypes.</p>
|
|
||||||
<code><pre>
|
|
||||||
<span class=keyword>void </span><span class=identifier>f</span><span class=special>(</span><span class=identifier>str </span><span class=identifier>name</span><span class=special>)
|
|
||||||
{
|
|
||||||
</span><span class=identifier>object </span><span class=identifier>n2 </span><span class=special>= </span><span class=identifier>name</span><span class=special>.</span><span class=identifier>attr</span><span class=special>(</span><span class=string>"upper"</span><span class=special>)(); // </span><span class=identifier>NAME </span><span class=special>= </span><span class=identifier>name</span><span class=special>.</span><span class=identifier>upper</span><span class=special>()
|
|
||||||
</span><span class=identifier>str </span><span class=identifier>NAME </span><span class=special>= </span><span class=identifier>name</span><span class=special>.</span><span class=identifier>upper</span><span class=special>(); // </span><span class=identifier>better
|
|
||||||
</span><span class=identifier>object </span><span class=identifier>msg </span><span class=special>= </span><span class=string>"%s is bigger than %s" </span><span class=special>% </span><span class=identifier>make_tuple</span><span class=special>(</span><span class=identifier>NAME</span><span class=special>,</span><span class=identifier>name</span><span class=special>);
|
|
||||||
}
|
|
||||||
</span></pre></code>
|
|
||||||
<p>
|
|
||||||
In finer detail:</p>
|
|
||||||
<code><pre>
|
|
||||||
<span class=identifier>str </span><span class=identifier>NAME </span><span class=special>= </span><span class=identifier>name</span><span class=special>.</span><span class=identifier>upper</span><span class=special>();
|
|
||||||
</span></pre></code>
|
|
||||||
<p>
|
|
||||||
Illustrates that we provide versions of the str type's methods as C++
|
|
||||||
member functions.</p>
|
|
||||||
<code><pre>
|
|
||||||
<span class=identifier>object </span><span class=identifier>msg </span><span class=special>= </span><span class=string>"%s is bigger than %s" </span><span class=special>% </span><span class=identifier>make_tuple</span><span class=special>(</span><span class=identifier>NAME</span><span class=special>,</span><span class=identifier>name</span><span class=special>);
|
|
||||||
</span></pre></code>
|
|
||||||
<p>
|
|
||||||
Demonstrates that you can write the C++ equivalent of <tt>"format" % x,y,z</tt>
|
|
||||||
in Python, which is useful since there's no easy way to do that in std C++.</p>
|
|
||||||
<p>
|
|
||||||
<img src="theme/alert.gif"></img> <b>Beware</b> the common pitfall of forgetting that the constructors
|
|
||||||
of most of Python's mutable types make copies, just as in Python.</p>
|
|
||||||
<p>
|
|
||||||
Python:</p>
|
|
||||||
<code><pre>
|
|
||||||
<span class=special>>>> </span><span class=identifier>d </span><span class=special>= </span><span class=identifier>dict</span><span class=special>(</span><span class=identifier>x</span><span class=special>.</span><span class=identifier>__dict__</span><span class=special>) </span>##<span class=identifier>copies </span><span class=identifier>x</span><span class=special>.</span><span class=identifier>__dict__
|
|
||||||
</span><span class=special>>>> </span><span class=identifier>d</span><span class=special>[</span><span class=literal>'whatever'</span><span class=special>] </span>##<span class=identifier>modifies </span><span class=identifier>the </span><span class=identifier>copy
|
|
||||||
</span></pre></code>
|
|
||||||
<p>
|
|
||||||
C++:</p>
|
|
||||||
<code><pre>
|
|
||||||
<span class=identifier>dict </span><span class=identifier>d</span><span class=special>(</span><span class=identifier>x</span><span class=special>.</span><span class=identifier>attr</span><span class=special>(</span><span class=string>"__dict__"</span><span class=special>)); </span>##<span class=identifier>copies </span><span class=identifier>x</span><span class=special>.</span><span class=identifier>__dict__
|
|
||||||
</span><span class=identifier>d</span><span class=special>[</span><span class=literal>'whatever'</span><span class=special>] = </span><span class=number>3</span><span class=special>; </span>##<span class=identifier>modifies </span><span class=identifier>the </span><span class=identifier>copy
|
|
||||||
</span></pre></code>
|
|
||||||
<a name="class__lt_t_gt__as_objects"></a><h2>class_<T> as objects</h2><p>
|
|
||||||
Due to the dynamic nature of Boost.Python objects, any <tt>class_<T></tt> may
|
|
||||||
also be one of these types! The following code snippet wraps the class
|
|
||||||
(type) object.</p>
|
|
||||||
<p>
|
|
||||||
We can use this to create wrapped instances. Example:</p>
|
|
||||||
<code><pre>
|
|
||||||
<span class=identifier>object </span><span class=identifier>vec345 </span><span class=special>= (
|
|
||||||
</span><span class=identifier>class_</span><span class=special><</span><span class=identifier>Vec2</span><span class=special>>(</span><span class=string>"Vec2"</span><span class=special>, </span><span class=identifier>init</span><span class=special><</span><span class=keyword>double</span><span class=special>, </span><span class=keyword>double</span><span class=special>>())
|
|
||||||
.</span><span class=identifier>def_readonly</span><span class=special>(</span><span class=string>"length"</span><span class=special>, &</span><span class=identifier>Point</span><span class=special>::</span><span class=identifier>length</span><span class=special>)
|
|
||||||
.</span><span class=identifier>def_readonly</span><span class=special>(</span><span class=string>"angle"</span><span class=special>, &</span><span class=identifier>Point</span><span class=special>::</span><span class=identifier>angle</span><span class=special>)
|
|
||||||
)(</span><span class=number>3.0</span><span class=special>, </span><span class=number>4.0</span><span class=special>);
|
|
||||||
|
|
||||||
</span><span class=identifier>assert</span><span class=special>(</span><span class=identifier>vec345</span><span class=special>.</span><span class=identifier>attr</span><span class=special>(</span><span class=string>"length"</span><span class=special>) == </span><span class=number>5.0</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="basic_interface.html"><img src="theme/l_arr.gif" border="0"></a></td>
|
|
||||||
<td width="20"><a href="extracting_c___objects.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>
|
|
||||||
@@ -1,83 +0,0 @@
|
|||||||
<html>
|
|
||||||
<head>
|
|
||||||
<!-- Generated by the Spirit (http://spirit.sf.net) QuickDoc -->
|
|
||||||
<title>Deriving a Python Class</title>
|
|
||||||
<link rel="stylesheet" href="theme/style.css" type="text/css">
|
|
||||||
<link rel="prev" href="class_virtual_functions.html">
|
|
||||||
<link rel="next" href="virtual_functions_with_default_implementations.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>Deriving a Python Class</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="class_virtual_functions.html"><img src="theme/l_arr.gif" border="0"></a></td>
|
|
||||||
<td width="20"><a href="virtual_functions_with_default_implementations.html"><img src="theme/r_arr.gif" border="0"></a></td>
|
|
||||||
</tr>
|
|
||||||
</table>
|
|
||||||
<p>
|
|
||||||
Continuing, we can derive from our base class Base in Python and override
|
|
||||||
the virtual function in Python. Before we can do that, we have to set up
|
|
||||||
our <tt>class_</tt> wrapper as:</p>
|
|
||||||
<code><pre>
|
|
||||||
<span class=identifier>class_</span><span class=special><</span><span class=identifier>Base</span><span class=special>, </span><span class=identifier>BaseWrap</span><span class=special>, </span><span class=identifier>boost</span><span class=special>::</span><span class=identifier>noncopyable</span><span class=special>>(</span><span class=string>"Base"</span><span class=special>)
|
|
||||||
;
|
|
||||||
</span></pre></code>
|
|
||||||
<p>
|
|
||||||
Otherwise, we have to suppress the Base class' <tt>no_init</tt> by adding an
|
|
||||||
<tt>__init__()</tt> method to all our derived classes. <tt>no_init</tt> actually adds
|
|
||||||
an <tt>__init__</tt> method that raises a Python RuntimeError exception.</p>
|
|
||||||
<code><pre>
|
|
||||||
<span class=special>>>> </span><span class=keyword>class </span><span class=identifier>Derived</span><span class=special>(</span><span class=identifier>Base</span><span class=special>):
|
|
||||||
... </span><span class=identifier>def </span><span class=identifier>f</span><span class=special>(</span><span class=identifier>self</span><span class=special>):
|
|
||||||
... </span><span class=keyword>return </span><span class=number>42
|
|
||||||
</span><span class=special>...
|
|
||||||
</span></pre></code>
|
|
||||||
<p>
|
|
||||||
Cool eh? A Python class deriving from a C++ class!</p>
|
|
||||||
<p>
|
|
||||||
Let's now make an instance of our Python class <tt>Derived</tt>:</p>
|
|
||||||
<code><pre>
|
|
||||||
<span class=special>>>> </span><span class=identifier>derived </span><span class=special>= </span><span class=identifier>Derived</span><span class=special>()
|
|
||||||
</span></pre></code>
|
|
||||||
<p>
|
|
||||||
Calling <tt>derived.f()</tt>:</p>
|
|
||||||
<code><pre>
|
|
||||||
<span class=special>>>> </span><span class=identifier>derived</span><span class=special>.</span><span class=identifier>f</span><span class=special>()
|
|
||||||
</span><span class=number>42
|
|
||||||
</span></pre></code>
|
|
||||||
<p>
|
|
||||||
Will yield the expected result. Finally, calling calling the free function
|
|
||||||
<tt>call_f</tt> with <tt>derived</tt> as argument:</p>
|
|
||||||
<code><pre>
|
|
||||||
<span class=special>>>> </span><span class=identifier>call_f</span><span class=special>(</span><span class=identifier>derived</span><span class=special>)
|
|
||||||
</span><span class=number>42
|
|
||||||
</span></pre></code>
|
|
||||||
<p>
|
|
||||||
Will also yield the expected result.</p>
|
|
||||||
<p>
|
|
||||||
Here's what's happening:</p>
|
|
||||||
<ol><li><tt>call_f(derived)</tt> is called in Python</li><li>This corresponds to <tt>def("call_f", call_f);</tt>. Boost.Python dispatches this call.</li><li><tt>int call_f(Base& b) { return b.f(); }</tt> accepts the call.</li><li>The overridden virtual function <tt>f</tt> of <tt>BaseWrap</tt> is called.</li><li><tt>call_method<int>(self, "f");</tt> dispatches the call back to Python.</li><li><tt>def f(self): return 42</tt> is finally called.</li></ol><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="class_virtual_functions.html"><img src="theme/l_arr.gif" border="0"></a></td>
|
|
||||||
<td width="20"><a href="virtual_functions_with_default_implementations.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>
|
|
||||||
@@ -1,97 +0,0 @@
|
|||||||
<html>
|
|
||||||
<head>
|
|
||||||
<!-- Generated by the Spirit (http://spirit.sf.net) QuickDoc -->
|
|
||||||
<title>Embedding</title>
|
|
||||||
<link rel="stylesheet" href="theme/style.css" type="text/css">
|
|
||||||
<link rel="prev" href="enums.html">
|
|
||||||
<link rel="next" href="using_the_interpreter.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>Embedding</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="enums.html"><img src="theme/l_arr.gif" border="0"></a></td>
|
|
||||||
<td width="20"><a href="using_the_interpreter.html"><img src="theme/r_arr.gif" border="0"></a></td>
|
|
||||||
</tr>
|
|
||||||
</table>
|
|
||||||
<p>
|
|
||||||
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 <i>embed</i> the Python interpreter
|
|
||||||
into your C++ program.</p>
|
|
||||||
<p>
|
|
||||||
Currently, Boost.Python does not directly support everything you'll need
|
|
||||||
when embedding. Therefore you'll need to use the
|
|
||||||
<a href="http://www.python.org/doc/current/api/api.html">
|
|
||||||
Python/C API</a> 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... <img src="theme/smiley.gif"></img></p>
|
|
||||||
<a name="building_embedded_programs"></a><h2>Building embedded programs</h2><p>
|
|
||||||
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.</p>
|
|
||||||
<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>
|
|
||||||
<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
|
|
||||||
your major Python version number.</p>
|
|
||||||
<p>
|
|
||||||
Additionally, Python's <tt>/include</tt> subdirectory has to be added to your
|
|
||||||
include path.</p>
|
|
||||||
<p>
|
|
||||||
In a Jamfile, all the above boils down to:</p>
|
|
||||||
<code><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) ;
|
|
||||||
</pre></code><a name="getting_started"></a><h2>Getting started</h2><p>
|
|
||||||
Being able to build is nice, but there is nothing to build yet. Embedding
|
|
||||||
the Python interpreter into one of your C++ programs requires these 4
|
|
||||||
steps:</p>
|
|
||||||
<ol><li>#include <tt><boost/python.hpp></tt><br><br></li><li>Call <a href="http://www.python.org/doc/current/api/initialization.html#l2h-652">
|
|
||||||
Py_Initialize</a>() to start the interpreter and create the <tt>__main__</tt> module.<br><br></li><li>Call other Python C API routines to use the interpreter.<br><br></li><li>Call <a href="http://www.python.org/doc/current/api/initialization.html#l2h-656">
|
|
||||||
Py_Finalize</a>() to stop the interpreter and release its resources.</li></ol><p>
|
|
||||||
(Of course, there can be other C++ code between all of these steps.)</p>
|
|
||||||
<blockquote><p><i><b>Now that we can embed the interpreter in our programs, lets see how to put it to use...</b></i></p></blockquote><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="enums.html"><img src="theme/l_arr.gif" border="0"></a></td>
|
|
||||||
<td width="20"><a href="using_the_interpreter.html"><img src="theme/r_arr.gif" border="0"></a></td>
|
|
||||||
</tr>
|
|
||||||
</table>
|
|
||||||
<br>
|
|
||||||
<hr size="1"><p class="copyright">Copyright © 2002-2003 Dirk Gerrits<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>
|
|
||||||
@@ -1,95 +0,0 @@
|
|||||||
<html>
|
|
||||||
<head>
|
|
||||||
<!-- Generated by the Spirit (http://spirit.sf.net) QuickDoc -->
|
|
||||||
<title>Enums</title>
|
|
||||||
<link rel="stylesheet" href="theme/style.css" type="text/css">
|
|
||||||
<link rel="prev" href="extracting_c___objects.html">
|
|
||||||
<link rel="next" href="embedding.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>Enums</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="extracting_c___objects.html"><img src="theme/l_arr.gif" border="0"></a></td>
|
|
||||||
<td width="20"><a href="embedding.html"><img src="theme/r_arr.gif" border="0"></a></td>
|
|
||||||
</tr>
|
|
||||||
</table>
|
|
||||||
<p>
|
|
||||||
Boost.Python has a nifty facility to capture and wrap C++ enums. While
|
|
||||||
Python has no <tt>enum</tt> type, we'll often want to expose our C++ enums to
|
|
||||||
Python as an <tt>int</tt>. Boost.Python's enum facility makes this easy while
|
|
||||||
taking care of the proper conversions from Python's dynamic typing to C++'s
|
|
||||||
strong static typing (in C++, ints cannot be implicitly converted to
|
|
||||||
enums). To illustrate, given a C++ enum:</p>
|
|
||||||
<code><pre>
|
|
||||||
<span class=keyword>enum </span><span class=identifier>choice </span><span class=special>{ </span><span class=identifier>red</span><span class=special>, </span><span class=identifier>blue </span><span class=special>};
|
|
||||||
</span></pre></code>
|
|
||||||
<p>
|
|
||||||
the construct:</p>
|
|
||||||
<code><pre>
|
|
||||||
<span class=identifier>enum_</span><span class=special><</span><span class=identifier>choice</span><span class=special>>(</span><span class=string>"choice"</span><span class=special>)
|
|
||||||
.</span><span class=identifier>value</span><span class=special>(</span><span class=string>"red"</span><span class=special>, </span><span class=identifier>red</span><span class=special>)
|
|
||||||
.</span><span class=identifier>value</span><span class=special>(</span><span class=string>"blue"</span><span class=special>, </span><span class=identifier>blue</span><span class=special>)
|
|
||||||
;
|
|
||||||
</span></pre></code>
|
|
||||||
<p>
|
|
||||||
can be used to expose to Python. The new enum type is created in the
|
|
||||||
current <tt>scope()</tt>, which is usually the current module. The snippet above
|
|
||||||
creates a Python class derived from Python's <tt>int</tt> type which is
|
|
||||||
associated with the C++ type passed as its first parameter.</p>
|
|
||||||
<table width="80%" border="0" align="center">
|
|
||||||
<tr>
|
|
||||||
<td class="note_box">
|
|
||||||
<img src="theme/lens.gif"></img> <b>what is a scope?</b><br><br> The scope is a class that has an
|
|
||||||
associated global Python object which controls the Python namespace in
|
|
||||||
which new extension classes and wrapped functions will be defined as
|
|
||||||
attributes. Details can be found <a href="../../v2/scope.html">
|
|
||||||
here</a>. </td>
|
|
||||||
</tr>
|
|
||||||
</table>
|
|
||||||
<p>
|
|
||||||
You can access those values in Python as</p>
|
|
||||||
<code><pre>
|
|
||||||
<span class=special>>>> </span><span class=identifier>my_module</span><span class=special>.</span><span class=identifier>choice</span><span class=special>.</span><span class=identifier>red
|
|
||||||
</span><span class=identifier>my_module</span><span class=special>.</span><span class=identifier>choice</span><span class=special>.</span><span class=identifier>red
|
|
||||||
</span></pre></code>
|
|
||||||
<p>
|
|
||||||
where my_module is the module where the enum is declared. You can also
|
|
||||||
create a new scope around a class:</p>
|
|
||||||
<code><pre>
|
|
||||||
<span class=identifier>scope </span><span class=identifier>in_X </span><span class=special>= </span><span class=identifier>class_</span><span class=special><</span><span class=identifier>X</span><span class=special>>(</span><span class=string>"X"</span><span class=special>)
|
|
||||||
.</span><span class=identifier>def</span><span class=special>( ... )
|
|
||||||
.</span><span class=identifier>def</span><span class=special>( ... )
|
|
||||||
;
|
|
||||||
|
|
||||||
// </span><span class=identifier>Expose </span><span class=identifier>X</span><span class=special>::</span><span class=identifier>nested </span><span class=identifier>as </span><span class=identifier>X</span><span class=special>.</span><span class=identifier>nested
|
|
||||||
</span><span class=identifier>enum_</span><span class=special><</span><span class=identifier>X</span><span class=special>::</span><span class=identifier>nested</span><span class=special>>(</span><span class=string>"nested"</span><span class=special>)
|
|
||||||
.</span><span class=identifier>value</span><span class=special>(</span><span class=string>"red"</span><span class=special>, </span><span class=identifier>red</span><span class=special>)
|
|
||||||
.</span><span class=identifier>value</span><span class=special>(</span><span class=string>"blue"</span><span class=special>, </span><span class=identifier>blue</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="extracting_c___objects.html"><img src="theme/l_arr.gif" border="0"></a></td>
|
|
||||||
<td width="20"><a href="embedding.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>
|
|
||||||
@@ -1,60 +0,0 @@
|
|||||||
<html>
|
|
||||||
<head>
|
|
||||||
<!-- Generated by the Spirit (http://spirit.sf.net) QuickDoc -->
|
|
||||||
<title>Exception Translation</title>
|
|
||||||
<link rel="stylesheet" href="theme/style.css" type="text/css">
|
|
||||||
<link rel="prev" href="iterators.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>Exception Translation</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="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>
|
|
||||||
</tr>
|
|
||||||
</table>
|
|
||||||
<p>
|
|
||||||
All C++ exceptions must be caught at the boundary with Python code. This
|
|
||||||
boundary is the point where C++ meets Python. Boost.Python provides a
|
|
||||||
default exception handler that translates selected standard exceptions,
|
|
||||||
then gives up:</p>
|
|
||||||
<code><pre>
|
|
||||||
<span class=identifier>raise </span><span class=identifier>RuntimeError</span><span class=special>, </span><span class=literal>'unidentifiable C++ Exception'
|
|
||||||
</span></pre></code>
|
|
||||||
<p>
|
|
||||||
Users may provide custom translation. Here's an example:</p>
|
|
||||||
<code><pre>
|
|
||||||
<span class=keyword>struct </span><span class=identifier>PodBayDoorException</span><span class=special>;
|
|
||||||
</span><span class=keyword>void </span><span class=identifier>translator</span><span class=special>(</span><span class=identifier>PodBayDoorException </span><span class=keyword>const</span><span class=special>& </span><span class=identifier>x</span><span class=special>) {
|
|
||||||
</span><span class=identifier>PyErr_SetString</span><span class=special>(</span><span class=identifier>PyExc_UserWarning</span><span class=special>, </span><span class=string>"I'm sorry Dave..."</span><span class=special>);
|
|
||||||
}
|
|
||||||
</span><span class=identifier>BOOST_PYTHON_MODULE</span><span class=special>(</span><span class=identifier>kubrick</span><span class=special>) {
|
|
||||||
</span><span class=identifier>register_exception_translator</span><span class=special><
|
|
||||||
</span><span class=identifier>PodBayDoorException</span><span class=special>>(</span><span class=identifier>translator</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="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>
|
|
||||||
</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>
|
|
||||||
@@ -1,79 +0,0 @@
|
|||||||
<html>
|
|
||||||
<head>
|
|
||||||
<!-- Generated by the Spirit (http://spirit.sf.net) QuickDoc -->
|
|
||||||
<title>Exposing Classes</title>
|
|
||||||
<link rel="stylesheet" href="theme/style.css" type="text/css">
|
|
||||||
<link rel="prev" href="building_hello_world.html">
|
|
||||||
<link rel="next" href="constructors.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>Exposing Classes</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="building_hello_world.html"><img src="theme/l_arr.gif" border="0"></a></td>
|
|
||||||
<td width="20"><a href="constructors.html"><img src="theme/r_arr.gif" border="0"></a></td>
|
|
||||||
</tr>
|
|
||||||
</table>
|
|
||||||
<p>
|
|
||||||
Now let's expose a C++ class to Python.</p>
|
|
||||||
<p>
|
|
||||||
Consider a C++ class/struct that we want to expose to Python:</p>
|
|
||||||
<code><pre>
|
|
||||||
<span class=keyword>struct </span><span class=identifier>World
|
|
||||||
</span><span class=special>{
|
|
||||||
</span><span class=keyword>void </span><span class=identifier>set</span><span class=special>(</span><span class=identifier>std</span><span class=special>::</span><span class=identifier>string </span><span class=identifier>msg</span><span class=special>) { </span><span class=keyword>this</span><span class=special>-></span><span class=identifier>msg </span><span class=special>= </span><span class=identifier>msg</span><span class=special>; }
|
|
||||||
</span><span class=identifier>std</span><span class=special>::</span><span class=identifier>string </span><span class=identifier>greet</span><span class=special>() { </span><span class=keyword>return </span><span class=identifier>msg</span><span class=special>; }
|
|
||||||
</span><span class=identifier>std</span><span class=special>::</span><span class=identifier>string </span><span class=identifier>msg</span><span class=special>;
|
|
||||||
};
|
|
||||||
</span></pre></code>
|
|
||||||
<p>
|
|
||||||
We can expose this to Python by writing a corresponding Boost.Python
|
|
||||||
C++ Wrapper:</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=keyword>using </span><span class=keyword>namespace </span><span class=identifier>boost</span><span class=special>::</span><span class=identifier>python</span><span class=special>;
|
|
||||||
|
|
||||||
</span><span class=identifier>BOOST_PYTHON_MODULE</span><span class=special>(</span><span class=identifier>hello</span><span class=special>)
|
|
||||||
{
|
|
||||||
</span><span class=identifier>class_</span><span class=special><</span><span class=identifier>World</span><span class=special>>(</span><span class=string>"World"</span><span class=special>)
|
|
||||||
.</span><span class=identifier>def</span><span class=special>(</span><span class=string>"greet"</span><span class=special>, &</span><span class=identifier>World</span><span class=special>::</span><span class=identifier>greet</span><span class=special>)
|
|
||||||
.</span><span class=identifier>def</span><span class=special>(</span><span class=string>"set"</span><span class=special>, &</span><span class=identifier>World</span><span class=special>::</span><span class=identifier>set</span><span class=special>)
|
|
||||||
;
|
|
||||||
}
|
|
||||||
</span></pre></code>
|
|
||||||
<p>
|
|
||||||
Here, we wrote a C++ class wrapper that exposes the member functions
|
|
||||||
<tt>greet</tt> and <tt>set</tt>. Now, after building our module as a shared library, we
|
|
||||||
may use our class <tt>World</tt> in Python. Here's a sample Python session:</p>
|
|
||||||
<code><pre>
|
|
||||||
<span class=special>>>> </span><span class=identifier>import </span><span class=identifier>hello
|
|
||||||
</span><span class=special>>>> </span><span class=identifier>planet </span><span class=special>= </span><span class=identifier>hello</span><span class=special>.</span><span class=identifier>World</span><span class=special>()
|
|
||||||
>>> </span><span class=identifier>planet</span><span class=special>.</span><span class=identifier>set</span><span class=special>(</span><span class=literal>'howdy'</span><span class=special>)
|
|
||||||
>>> </span><span class=identifier>planet</span><span class=special>.</span><span class=identifier>greet</span><span class=special>()
|
|
||||||
</span><span class=literal>'howdy'
|
|
||||||
</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="building_hello_world.html"><img src="theme/l_arr.gif" border="0"></a></td>
|
|
||||||
<td width="20"><a href="constructors.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>
|
|
||||||
@@ -1,79 +0,0 @@
|
|||||||
<html>
|
|
||||||
<head>
|
|
||||||
<!-- Generated by the Spirit (http://spirit.sf.net) QuickDoc -->
|
|
||||||
<title>Extracting C++ objects</title>
|
|
||||||
<link rel="stylesheet" href="theme/style.css" type="text/css">
|
|
||||||
<link rel="prev" href="derived_object_types.html">
|
|
||||||
<link rel="next" href="enums.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>Extracting C++ objects</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="derived_object_types.html"><img src="theme/l_arr.gif" border="0"></a></td>
|
|
||||||
<td width="20"><a href="enums.html"><img src="theme/r_arr.gif" border="0"></a></td>
|
|
||||||
</tr>
|
|
||||||
</table>
|
|
||||||
<p>
|
|
||||||
At some point, we will need to get C++ values out of object instances. This
|
|
||||||
can be achieved with the <tt>extract<T></tt> function. Consider the following:</p>
|
|
||||||
<code><pre>
|
|
||||||
<span class=keyword>double </span><span class=identifier>x </span><span class=special>= </span><span class=identifier>o</span><span class=special>.</span><span class=identifier>attr</span><span class=special>(</span><span class=string>"length"</span><span class=special>); // </span><span class=identifier>compile </span><span class=identifier>error
|
|
||||||
</span></pre></code>
|
|
||||||
<p>
|
|
||||||
In the code above, we got a compiler error because Boost.Python
|
|
||||||
<tt>object</tt> can't be implicitly converted to <tt>double</tt>s. Instead, what
|
|
||||||
we wanted to do above can be achieved by writing:</p>
|
|
||||||
<code><pre>
|
|
||||||
<span class=keyword>double </span><span class=identifier>l </span><span class=special>= </span><span class=identifier>extract</span><span class=special><</span><span class=keyword>double</span><span class=special>>(</span><span class=identifier>o</span><span class=special>.</span><span class=identifier>attr</span><span class=special>(</span><span class=string>"length"</span><span class=special>));
|
|
||||||
</span><span class=identifier>Vec2</span><span class=special>& </span><span class=identifier>v </span><span class=special>= </span><span class=identifier>extract</span><span class=special><</span><span class=identifier>Vec2</span><span class=special>&>(</span><span class=identifier>o</span><span class=special>);
|
|
||||||
</span><span class=identifier>assert</span><span class=special>(</span><span class=identifier>l </span><span class=special>== </span><span class=identifier>v</span><span class=special>.</span><span class=identifier>length</span><span class=special>());
|
|
||||||
</span></pre></code>
|
|
||||||
<p>
|
|
||||||
The first line attempts to extract the "length" attribute of the
|
|
||||||
Boost.Python <tt>object</tt> <tt>o</tt>. The second line attempts to <i>extract</i> the
|
|
||||||
<tt>Vec2</tt> object from held by the Boost.Python <tt>object</tt> <tt>o</tt>.</p>
|
|
||||||
<p>
|
|
||||||
Take note that we said "attempt to" above. What if the Boost.Python
|
|
||||||
<tt>object</tt> <tt>o</tt> does not really hold a <tt>Vec2</tt> type? This is certainly
|
|
||||||
a possibility considering the dynamic nature of Python <tt>object</tt>s. To
|
|
||||||
be on the safe side, if the C++ type can't be extracted, an
|
|
||||||
appropriate exception is thrown. To avoid an exception, we need to
|
|
||||||
test for extractibility:</p>
|
|
||||||
<code><pre>
|
|
||||||
<span class=identifier>extract</span><span class=special><</span><span class=identifier>Vec2</span><span class=special>&> </span><span class=identifier>x</span><span class=special>(</span><span class=identifier>o</span><span class=special>);
|
|
||||||
</span><span class=keyword>if </span><span class=special>(</span><span class=identifier>x</span><span class=special>.</span><span class=identifier>check</span><span class=special>()) {
|
|
||||||
</span><span class=identifier>Vec2</span><span class=special>& </span><span class=identifier>v </span><span class=special>= </span><span class=identifier>x</span><span class=special>(); ...
|
|
||||||
</span></pre></code>
|
|
||||||
<p>
|
|
||||||
<img src="theme/bulb.gif"></img> The astute reader might have noticed that the <tt>extract<T></tt>
|
|
||||||
facility in fact solves the mutable copying problem:</p>
|
|
||||||
<code><pre>
|
|
||||||
<span class=identifier>dict </span><span class=identifier>d </span><span class=special>= </span><span class=identifier>extract</span><span class=special><</span><span class=identifier>dict</span><span class=special>>(</span><span class=identifier>x</span><span class=special>.</span><span class=identifier>attr</span><span class=special>(</span><span class=string>"__dict__"</span><span class=special>));
|
|
||||||
</span><span class=identifier>d</span><span class=special>[</span><span class=literal>'whatever'</span><span class=special>] = </span><span class=number>3</span><span class=special>; </span>##<span class=identifier>modifies </span><span class=identifier>x</span><span class=special>.</span><span class=identifier>__dict__ </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="derived_object_types.html"><img src="theme/l_arr.gif" border="0"></a></td>
|
|
||||||
<td width="20"><a href="enums.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>
|
|
||||||
@@ -1,73 +0,0 @@
|
|||||||
<html>
|
|
||||||
<head>
|
|
||||||
<!-- Generated by the Spirit (http://spirit.sf.net) QuickDoc -->
|
|
||||||
<title>Functions</title>
|
|
||||||
<link rel="stylesheet" href="theme/style.css" type="text/css">
|
|
||||||
<link rel="prev" href="class_operators_special_functions.html">
|
|
||||||
<link rel="next" href="call_policies.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>Functions</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="class_operators_special_functions.html"><img src="theme/l_arr.gif" border="0"></a></td>
|
|
||||||
<td width="20"><a href="call_policies.html"><img src="theme/r_arr.gif" border="0"></a></td>
|
|
||||||
</tr>
|
|
||||||
</table>
|
|
||||||
<p>
|
|
||||||
In this chapter, we'll look at Boost.Python powered functions in closer
|
|
||||||
detail. We shall see some facilities to make exposing C++ functions to
|
|
||||||
Python safe from potential pifalls such as dangling pointers and
|
|
||||||
references. We shall also see facilities that will make it even easier for
|
|
||||||
us to expose C++ functions that take advantage of C++ features such as
|
|
||||||
overloading and default arguments.</p>
|
|
||||||
<blockquote><p><i>Read on...</i></p></blockquote><p>
|
|
||||||
But before you do, you might want to fire up Python 2.2 or later and type
|
|
||||||
<tt>>>> import this</tt>.</p>
|
|
||||||
<code><pre>
|
|
||||||
>>> import this
|
|
||||||
The Zen of Python, by Tim Peters
|
|
||||||
Beautiful is better than ugly.
|
|
||||||
Explicit is better than implicit.
|
|
||||||
Simple is better than complex.
|
|
||||||
Complex is better than complicated.
|
|
||||||
Flat is better than nested.
|
|
||||||
Sparse is better than dense.
|
|
||||||
Readability counts.
|
|
||||||
Special cases aren't special enough to break the rules.
|
|
||||||
Although practicality beats purity.
|
|
||||||
Errors should never pass silently.
|
|
||||||
Unless explicitly silenced.
|
|
||||||
In the face of ambiguity, refuse the temptation to guess.
|
|
||||||
There should be one-- and preferably only one --obvious way to do it
|
|
||||||
Although that way may not be obvious at first unless you're Dutch.
|
|
||||||
Now is better than never.
|
|
||||||
Although never is often better than *right* now.
|
|
||||||
If the implementation is hard to explain, it's a bad idea.
|
|
||||||
If the implementation is easy to explain, it may be a good idea.
|
|
||||||
Namespaces are one honking great idea -- let's do more of those!
|
|
||||||
</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="class_operators_special_functions.html"><img src="theme/l_arr.gif" border="0"></a></td>
|
|
||||||
<td width="20"><a href="call_policies.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>
|
|
||||||
430
doc/tutorial/doc/html/boostbook.css
Normal file
@@ -0,0 +1,430 @@
|
|||||||
|
/*=============================================================================
|
||||||
|
Copyright (c) 2004 Joel de Guzman
|
||||||
|
http://spirit.sourceforge.net/
|
||||||
|
|
||||||
|
Use, modification and distribution is subject to the Boost Software
|
||||||
|
License, Version 1.0. (See accompanying file LICENSE_1_0.txt or copy at
|
||||||
|
http://www.boost.org/LICENSE_1_0.txt)
|
||||||
|
=============================================================================*/
|
||||||
|
|
||||||
|
/*=============================================================================
|
||||||
|
Body defaults
|
||||||
|
=============================================================================*/
|
||||||
|
|
||||||
|
body
|
||||||
|
{
|
||||||
|
margin: 1em;
|
||||||
|
font-family: sans-serif;
|
||||||
|
}
|
||||||
|
|
||||||
|
/*=============================================================================
|
||||||
|
Paragraphs
|
||||||
|
=============================================================================*/
|
||||||
|
|
||||||
|
p
|
||||||
|
{
|
||||||
|
text-align: justify;
|
||||||
|
font-size: 11pt;
|
||||||
|
line-height: 1.2;
|
||||||
|
}
|
||||||
|
|
||||||
|
/*=============================================================================
|
||||||
|
Program listings
|
||||||
|
=============================================================================*/
|
||||||
|
|
||||||
|
tt.computeroutput
|
||||||
|
{
|
||||||
|
font-size: 10pt;
|
||||||
|
}
|
||||||
|
|
||||||
|
pre.synopsis
|
||||||
|
{
|
||||||
|
font-size: 10pt;
|
||||||
|
margin: 1pc 4% 0pc 4%;
|
||||||
|
padding: 0.5pc 0.5pc 0.5pc 0.5pc;
|
||||||
|
}
|
||||||
|
|
||||||
|
.programlisting,
|
||||||
|
.screen
|
||||||
|
{
|
||||||
|
font-size: 10pt;
|
||||||
|
display: block;
|
||||||
|
margin: 1pc 4% 0pc 4%;
|
||||||
|
padding: 0.5pc 0.5pc 0.5pc 0.5pc;
|
||||||
|
}
|
||||||
|
|
||||||
|
/*=============================================================================
|
||||||
|
Headings
|
||||||
|
=============================================================================*/
|
||||||
|
|
||||||
|
h1,
|
||||||
|
h2,
|
||||||
|
h3,
|
||||||
|
h4,
|
||||||
|
h5,
|
||||||
|
h6
|
||||||
|
{
|
||||||
|
text-align: left;
|
||||||
|
margin-top: 2pc;
|
||||||
|
}
|
||||||
|
|
||||||
|
h1 { font: 170% }
|
||||||
|
h2 { font: bold 140% }
|
||||||
|
h3 { font: bold 120% }
|
||||||
|
h4 { font: bold 100% }
|
||||||
|
h5 { font: italic 100% }
|
||||||
|
h6 { font: italic 100% }
|
||||||
|
|
||||||
|
/* Top page titles */
|
||||||
|
title,
|
||||||
|
h1.title,
|
||||||
|
h2.title
|
||||||
|
h3.title,
|
||||||
|
h4.title,
|
||||||
|
h5.title,
|
||||||
|
h6.title,
|
||||||
|
.refentrytitle
|
||||||
|
{
|
||||||
|
font-weight: bold;
|
||||||
|
margin-bottom: 1pc;
|
||||||
|
}
|
||||||
|
|
||||||
|
h1.title { font-size: 220% }
|
||||||
|
h2.title { font-size: 220% }
|
||||||
|
h3.title { font-size: 170% }
|
||||||
|
h4.title { font-size: 140% }
|
||||||
|
h5.title { font-size: 120% }
|
||||||
|
h6.title { font-size: 120% }
|
||||||
|
|
||||||
|
/*=============================================================================
|
||||||
|
Lists
|
||||||
|
=============================================================================*/
|
||||||
|
|
||||||
|
li
|
||||||
|
{
|
||||||
|
font-size: 11pt;
|
||||||
|
line-height: 1.3;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Unordered lists */
|
||||||
|
ul
|
||||||
|
{
|
||||||
|
text-align: justify;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Ordered lists */
|
||||||
|
ol
|
||||||
|
{
|
||||||
|
text-align: justify;
|
||||||
|
}
|
||||||
|
|
||||||
|
/*=============================================================================
|
||||||
|
Links
|
||||||
|
=============================================================================*/
|
||||||
|
|
||||||
|
a
|
||||||
|
{
|
||||||
|
text-decoration: none; /* no underline */
|
||||||
|
}
|
||||||
|
|
||||||
|
a:hover
|
||||||
|
{
|
||||||
|
text-decoration: underline;
|
||||||
|
}
|
||||||
|
|
||||||
|
/*=============================================================================
|
||||||
|
Spirit style navigation
|
||||||
|
=============================================================================*/
|
||||||
|
|
||||||
|
.spirit-nav
|
||||||
|
{
|
||||||
|
text-align: right;
|
||||||
|
}
|
||||||
|
|
||||||
|
.spirit-nav a
|
||||||
|
{
|
||||||
|
color: white;
|
||||||
|
padding-left: 0.5em;
|
||||||
|
}
|
||||||
|
|
||||||
|
.spirit-nav img
|
||||||
|
{
|
||||||
|
border-width: 0px;
|
||||||
|
}
|
||||||
|
|
||||||
|
/*=============================================================================
|
||||||
|
Table of contents
|
||||||
|
=============================================================================*/
|
||||||
|
|
||||||
|
.toc
|
||||||
|
{
|
||||||
|
margin: 1pc 4% 0pc 4%;
|
||||||
|
padding: 0.5pc;
|
||||||
|
font-size: 11pt;
|
||||||
|
line-height: 1.3;
|
||||||
|
}
|
||||||
|
|
||||||
|
.boost-toc
|
||||||
|
{
|
||||||
|
float: right;
|
||||||
|
padding: 0.5pc;
|
||||||
|
}
|
||||||
|
|
||||||
|
/*=============================================================================
|
||||||
|
Tables
|
||||||
|
=============================================================================*/
|
||||||
|
|
||||||
|
.table-title,
|
||||||
|
div.table p.title
|
||||||
|
{
|
||||||
|
margin-left: 4%;
|
||||||
|
padding-right: 0.5em;
|
||||||
|
padding-left: 0.5em;
|
||||||
|
font-size: 120%;
|
||||||
|
}
|
||||||
|
|
||||||
|
.informaltable table,
|
||||||
|
.table table
|
||||||
|
{
|
||||||
|
width: 92%;
|
||||||
|
margin-left: 4%;
|
||||||
|
margin-right: 4%;
|
||||||
|
}
|
||||||
|
|
||||||
|
div.informaltable table,
|
||||||
|
div.table table
|
||||||
|
{
|
||||||
|
padding: 4px;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Table Cells */
|
||||||
|
div.informaltable table tr td,
|
||||||
|
div.table table tr td
|
||||||
|
{
|
||||||
|
padding: 0.5em;
|
||||||
|
text-align: justify;
|
||||||
|
font-size: 11pt;
|
||||||
|
}
|
||||||
|
|
||||||
|
div.informaltable table tr th,
|
||||||
|
div.table table tr th
|
||||||
|
{
|
||||||
|
padding: 0.5em 0.5em 0.5em 0.5em;
|
||||||
|
border: 1pt solid white;
|
||||||
|
}
|
||||||
|
|
||||||
|
/*=============================================================================
|
||||||
|
Blurbs
|
||||||
|
=============================================================================*/
|
||||||
|
|
||||||
|
div.informaltable table tr td.blurb
|
||||||
|
{
|
||||||
|
font-size: 10pt; /* A little bit smaller than the main text */
|
||||||
|
line-height: 1.2;
|
||||||
|
}
|
||||||
|
|
||||||
|
td.blurb img
|
||||||
|
{
|
||||||
|
padding: 1pt;
|
||||||
|
}
|
||||||
|
|
||||||
|
/*=============================================================================
|
||||||
|
Misc
|
||||||
|
=============================================================================*/
|
||||||
|
|
||||||
|
/* Tone down the title of Parameter lists */
|
||||||
|
div.variablelist p.title
|
||||||
|
{
|
||||||
|
font-weight: bold;
|
||||||
|
font-size: 100%;
|
||||||
|
text-align: left;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Tabularize parameter lists */
|
||||||
|
div.variablelist dl dt
|
||||||
|
{
|
||||||
|
float: left;
|
||||||
|
clear: left;
|
||||||
|
display: block;
|
||||||
|
font-style: italic;
|
||||||
|
}
|
||||||
|
|
||||||
|
div.variablelist dl dd
|
||||||
|
{
|
||||||
|
display: block;
|
||||||
|
clear: right;
|
||||||
|
padding-left: 8pc;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Title of books and articles in bibliographies */
|
||||||
|
span.title
|
||||||
|
{
|
||||||
|
font-style: italic;
|
||||||
|
}
|
||||||
|
|
||||||
|
span.underline
|
||||||
|
{
|
||||||
|
text-decoration: underline;
|
||||||
|
}
|
||||||
|
|
||||||
|
span.strikethrough
|
||||||
|
{
|
||||||
|
text-decoration: line-through;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Copyright, Legal Notice */
|
||||||
|
div div.legalnotice p
|
||||||
|
{
|
||||||
|
text-align: left
|
||||||
|
}
|
||||||
|
|
||||||
|
/*=============================================================================
|
||||||
|
Colors
|
||||||
|
=============================================================================*/
|
||||||
|
|
||||||
|
@media screen
|
||||||
|
{
|
||||||
|
/* Links */
|
||||||
|
a
|
||||||
|
{
|
||||||
|
color: #005a9c;
|
||||||
|
}
|
||||||
|
|
||||||
|
a:visited
|
||||||
|
{
|
||||||
|
color: #9c5a9c;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Syntax Highlighting */
|
||||||
|
.keyword { color: #0000AA; }
|
||||||
|
.identifier { color: #000000; }
|
||||||
|
.special { color: #707070; }
|
||||||
|
.preprocessor { color: #402080; }
|
||||||
|
.char { color: teal; }
|
||||||
|
.comment { color: #800000; }
|
||||||
|
.string { color: teal; }
|
||||||
|
.number { color: teal; }
|
||||||
|
.white_bkd { background-color: #FFFFFF; }
|
||||||
|
.dk_grey_bkd { background-color: #999999; }
|
||||||
|
|
||||||
|
/* Copyright, Legal Notice */
|
||||||
|
.copyright
|
||||||
|
{
|
||||||
|
color: #666666;
|
||||||
|
font-size: small;
|
||||||
|
}
|
||||||
|
|
||||||
|
div div.legalnotice p
|
||||||
|
{
|
||||||
|
color: #666666;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Program listing */
|
||||||
|
pre.synopsis
|
||||||
|
{
|
||||||
|
background-color: #F3F3F3;
|
||||||
|
border: 1pt solid #C0C0C0;
|
||||||
|
}
|
||||||
|
|
||||||
|
.programlisting,
|
||||||
|
.screen
|
||||||
|
{
|
||||||
|
background-color: #F3F3F3;
|
||||||
|
border: 1pt solid #C0C0C0;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Blurbs */
|
||||||
|
div.informaltable table tr td.blurb
|
||||||
|
{
|
||||||
|
background-color: #FFFFF0;
|
||||||
|
border: 1pt solid #707070;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Table of contents */
|
||||||
|
.toc
|
||||||
|
{
|
||||||
|
background-color: #F3F3F3;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Tables */
|
||||||
|
div.informaltable table tr td,
|
||||||
|
div.table table tr td
|
||||||
|
{
|
||||||
|
background-color: #F0F0F0;
|
||||||
|
}
|
||||||
|
|
||||||
|
div.informaltable table tr th,
|
||||||
|
div.table table tr th
|
||||||
|
{
|
||||||
|
background-color: #E4E4E4;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Misc */
|
||||||
|
span.highlight
|
||||||
|
{
|
||||||
|
color: #00A000;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@media print
|
||||||
|
{
|
||||||
|
/* Links */
|
||||||
|
a
|
||||||
|
{
|
||||||
|
color: black;
|
||||||
|
}
|
||||||
|
|
||||||
|
a:visited
|
||||||
|
{
|
||||||
|
color: black;
|
||||||
|
}
|
||||||
|
|
||||||
|
.spirit-nav
|
||||||
|
{
|
||||||
|
display: none;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Program listing */
|
||||||
|
pre.synopsis
|
||||||
|
{
|
||||||
|
border: 1px solid gray;
|
||||||
|
}
|
||||||
|
|
||||||
|
.programlisting,
|
||||||
|
.screen
|
||||||
|
{
|
||||||
|
border: 1px solid gray;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Table of contents */
|
||||||
|
.toc
|
||||||
|
{
|
||||||
|
border: 1px solid gray;
|
||||||
|
}
|
||||||
|
|
||||||
|
.informaltable table,
|
||||||
|
.table table
|
||||||
|
{
|
||||||
|
border: 1px solid gray;
|
||||||
|
border-collapse: collapse;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Tables */
|
||||||
|
div.informaltable table tr td,
|
||||||
|
div.table table tr td
|
||||||
|
{
|
||||||
|
border: 1px solid gray;
|
||||||
|
}
|
||||||
|
|
||||||
|
div.informaltable table tr th,
|
||||||
|
div.table table tr th
|
||||||
|
{
|
||||||
|
border: 1px solid gray;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Misc */
|
||||||
|
span.highlight
|
||||||
|
{
|
||||||
|
font-weight: bold;
|
||||||
|
}
|
||||||
|
}
|
||||||
BIN
doc/tutorial/doc/html/images/alert.png
Executable file
|
After Width: | Height: | Size: 603 B |
BIN
doc/tutorial/doc/html/images/home.png
Executable file
|
After Width: | Height: | Size: 358 B |
|
Before Width: | Height: | Size: 3.8 KiB After Width: | Height: | Size: 3.8 KiB |
BIN
doc/tutorial/doc/html/images/next.png
Executable file
|
After Width: | Height: | Size: 336 B |
BIN
doc/tutorial/doc/html/images/note.png
Executable file
|
After Width: | Height: | Size: 658 B |
BIN
doc/tutorial/doc/html/images/prev.png
Executable file
|
After Width: | Height: | Size: 334 B |
|
Before Width: | Height: | Size: 14 KiB After Width: | Height: | Size: 14 KiB |
BIN
doc/tutorial/doc/html/images/smiley.png
Normal file
|
After Width: | Height: | Size: 867 B |
BIN
doc/tutorial/doc/html/images/tip.png
Executable file
|
After Width: | Height: | Size: 640 B |
BIN
doc/tutorial/doc/html/images/up.png
Executable file
|
After Width: | Height: | Size: 370 B |
144
doc/tutorial/doc/html/index.html
Normal file
@@ -0,0 +1,144 @@
|
|||||||
|
<html>
|
||||||
|
<head>
|
||||||
|
<meta http-equiv="Content-Type" content="text/html; charset=ISO-8859-1">
|
||||||
|
<title>Chapter 1. python 1.0</title>
|
||||||
|
<link rel="stylesheet" href="boostbook.css" type="text/css">
|
||||||
|
<meta name="generator" content="DocBook XSL Stylesheets V1.66.1">
|
||||||
|
<link rel="start" href="index.html" title="Chapter 1. python 1.0">
|
||||||
|
<link rel="next" href="python/hello.html" title=" Building Hello World">
|
||||||
|
</head>
|
||||||
|
<body bgcolor="white" text="black" link="#0000FF" vlink="#840084" alink="#0000FF">
|
||||||
|
<table cellpadding="2" width="100%">
|
||||||
|
<td valign="top"><img alt="boost.png (6897 bytes)" width="277" height="86" src="../../../../../../boost.png"></td>
|
||||||
|
<td align="center"><a href="../../../../../../index.htm">Home</a></td>
|
||||||
|
<td align="center"><a href="../../../../../../libs/libraries.htm">Libraries</a></td>
|
||||||
|
<td align="center"><a href="../../../../../../people/people.htm">People</a></td>
|
||||||
|
<td align="center"><a href="../../../../../../more/faq.htm">FAQ</a></td>
|
||||||
|
<td align="center"><a href="../../../../../../more/index.htm">More</a></td>
|
||||||
|
</table>
|
||||||
|
<hr>
|
||||||
|
<div class="spirit-nav"><a accesskey="n" href="python/hello.html"><img src="images/next.png" alt="Next"></a></div>
|
||||||
|
<div class="chapter" lang="en">
|
||||||
|
<div class="titlepage"><div>
|
||||||
|
<div><h2 class="title">
|
||||||
|
<a name="python"></a>Chapter 1. python 1.0</h2></div>
|
||||||
|
<div><div class="author"><h3 class="author">
|
||||||
|
<span class="firstname">Joel</span> <span class="surname">de Guzman</span>
|
||||||
|
</h3></div></div>
|
||||||
|
<div><div class="author"><h3 class="author">
|
||||||
|
<span class="firstname">David</span> <span class="surname">Abrahams</span>
|
||||||
|
</h3></div></div>
|
||||||
|
<div><p class="copyright">Copyright © 2002-2005 Joel
|
||||||
|
de Guzman, David Abrahams</p></div>
|
||||||
|
<div><div class="legalnotice">
|
||||||
|
<a name="id427816"></a><p>
|
||||||
|
Distributed under the Boost Software License, Version 1.0. (See accompanying
|
||||||
|
file LICENSE_1_0.txt or copy at <a href="http://www.boost.org/LICENSE_1_0.txt" target="_top">
|
||||||
|
http://www.boost.org/LICENSE_1_0.txt </a>)
|
||||||
|
</p>
|
||||||
|
</div></div>
|
||||||
|
</div></div>
|
||||||
|
<div class="toc">
|
||||||
|
<p><b>Table of Contents</b></p>
|
||||||
|
<dl>
|
||||||
|
<dt><span class="section"><a href="index.html#python.quickstart">QuickStart</a></span></dt>
|
||||||
|
<dt><span class="section"><a href="python/hello.html"> Building Hello World</a></span></dt>
|
||||||
|
<dt><span class="section"><a href="python/exposing.html"> Exposing Classes</a></span></dt>
|
||||||
|
<dd><dl>
|
||||||
|
<dt><span class="section"><a href="python/exposing.html#python.constructors">Constructors</a></span></dt>
|
||||||
|
<dt><span class="section"><a href="python/exposing.html#python.class_data_members">Class Data Members</a></span></dt>
|
||||||
|
<dt><span class="section"><a href="python/exposing.html#python.class_properties">Class Properties</a></span></dt>
|
||||||
|
<dt><span class="section"><a href="python/exposing.html#python.inheritance">Inheritance</a></span></dt>
|
||||||
|
<dt><span class="section"><a href="python/exposing.html#python.class_virtual_functions">Class Virtual Functions</a></span></dt>
|
||||||
|
<dt><span class="section"><a href="python/exposing.html#python.virtual_functions_with_default_implementations">Virtual Functions with Default Implementations</a></span></dt>
|
||||||
|
<dt><span class="section"><a href="python/exposing.html#python.class_operators_special_functions">Class Operators/Special Functions</a></span></dt>
|
||||||
|
</dl></dd>
|
||||||
|
<dt><span class="section"><a href="python/functions.html">Functions</a></span></dt>
|
||||||
|
<dd><dl>
|
||||||
|
<dt><span class="section"><a href="python/functions.html#python.call_policies">Call Policies</a></span></dt>
|
||||||
|
<dt><span class="section"><a href="python/functions.html#python.overloading">Overloading</a></span></dt>
|
||||||
|
<dt><span class="section"><a href="python/functions.html#python.default_arguments">Default Arguments</a></span></dt>
|
||||||
|
<dt><span class="section"><a href="python/functions.html#python.auto_overloading">Auto-Overloading</a></span></dt>
|
||||||
|
</dl></dd>
|
||||||
|
<dt><span class="section"><a href="python/object.html"> Object Interface</a></span></dt>
|
||||||
|
<dd><dl>
|
||||||
|
<dt><span class="section"><a href="python/object.html#python.basic_interface">Basic Interface</a></span></dt>
|
||||||
|
<dt><span class="section"><a href="python/object.html#python.derived_object_types">Derived Object types</a></span></dt>
|
||||||
|
<dt><span class="section"><a href="python/object.html#python.extracting_c___objects">Extracting C++ objects</a></span></dt>
|
||||||
|
<dt><span class="section"><a href="python/object.html#python.enums">Enums</a></span></dt>
|
||||||
|
</dl></dd>
|
||||||
|
<dt><span class="section"><a href="python/embedding.html">Embedding</a></span></dt>
|
||||||
|
<dd><dl><dt><span class="section"><a href="python/embedding.html#python.using_the_interpreter">Using the interpreter</a></span></dt></dl></dd>
|
||||||
|
<dt><span class="section"><a href="python/iterators.html">Iterators</a></span></dt>
|
||||||
|
<dt><span class="section"><a href="python/exception.html"> Exception Translation</a></span></dt>
|
||||||
|
<dt><span class="section"><a href="python/techniques.html"> General Techniques</a></span></dt>
|
||||||
|
<dd><dl>
|
||||||
|
<dt><span class="section"><a href="python/techniques.html#python.creating_packages">Creating Packages</a></span></dt>
|
||||||
|
<dt><span class="section"><a href="python/techniques.html#python.extending_wrapped_objects_in_python">Extending Wrapped Objects in Python</a></span></dt>
|
||||||
|
<dt><span class="section"><a href="python/techniques.html#python.reducing_compiling_time">Reducing Compiling Time</a></span></dt>
|
||||||
|
</dl></dd>
|
||||||
|
</dl>
|
||||||
|
</div>
|
||||||
|
<div class="section" lang="en">
|
||||||
|
<div class="titlepage"><div><div><h2 class="title" style="clear: both">
|
||||||
|
<a name="python.quickstart"></a>QuickStart</h2></div></div></div>
|
||||||
|
<p>
|
||||||
|
QuickStartThe Boost Python Library is a framework for interfacing Python and
|
||||||
|
C++. It allows you to quickly and seamlessly expose C++ classes functions and
|
||||||
|
objects to Python, and vice-versa, using no special tools -- just your C++
|
||||||
|
compiler. It is designed to wrap C++ interfaces non-intrusively, so that you
|
||||||
|
should not have to change the C++ code at all in order to wrap it, making Boost.Python
|
||||||
|
ideal for exposing 3rd-party libraries to Python. The library's use of advanced
|
||||||
|
metaprogramming techniques simplifies its syntax for users, so that wrapping
|
||||||
|
code takes on the look of a kind of declarative interface definition language
|
||||||
|
(IDL).
|
||||||
|
</p>
|
||||||
|
<a name="quickstart.hello_world"></a><h2>
|
||||||
|
<a name="id372244"></a>
|
||||||
|
Hello World
|
||||||
|
</h2>
|
||||||
|
<p>
|
||||||
|
Following C/C++ tradition, let's start with the "hello, world". A
|
||||||
|
C++ Function:
|
||||||
|
</p>
|
||||||
|
<pre class="programlisting">
|
||||||
|
<span class="keyword">char</span> <span class="keyword">const</span><span class="special">*</span> <span class="identifier">greet</span><span class="special">()</span>
|
||||||
|
<span class="special">{</span>
|
||||||
|
<span class="keyword">return</span> <span class="string">"hello, world"</span><span class="special">;</span>
|
||||||
|
<span class="special">}</span>
|
||||||
|
</pre>
|
||||||
|
<p>
|
||||||
|
can be exposed to Python by writing a Boost.Python wrapper:
|
||||||
|
</p>
|
||||||
|
<pre class="programlisting">
|
||||||
|
<span class="preprocessor">#include</span> <span class="special"><</span><span class="identifier">boost</span><span class="special">/</span><span class="identifier">python</span><span class="special">.</span><span class="identifier">hpp</span><span class="special">></span>
|
||||||
|
<span class="keyword">using</span> <span class="keyword">namespace</span> <span class="identifier">boost</span><span class="special">::</span><span class="identifier">python</span><span class="special">;</span>
|
||||||
|
|
||||||
|
<span class="identifier">BOOST_PYTHON_MODULE</span><span class="special">(</span><span class="identifier">hello</span><span class="special">)</span>
|
||||||
|
<span class="special">{</span>
|
||||||
|
<span class="identifier">def</span><span class="special">(</span><span class="string">"greet"</span><span class="special">,</span> <span class="identifier">greet</span><span class="special">);</span>
|
||||||
|
<span class="special">}</span>
|
||||||
|
</pre>
|
||||||
|
<p>
|
||||||
|
That's it. We're done. We can now build this as a shared library. The resulting
|
||||||
|
DLL is now visible to Python. Here's a sample Python session:
|
||||||
|
</p>
|
||||||
|
<p></p>
|
||||||
|
<pre class="programlisting">
|
||||||
|
<span class="special">>>></span> <span class="keyword">import</span> <span class="identifier">hello</span>
|
||||||
|
<span class="special">>>></span> <span class="keyword">print</span> <span class="identifier">hello</span><span class="special">.</span><span class="identifier">greet</span><span class="special">()</span>
|
||||||
|
<span class="identifier">hello</span><span class="special">,</span> <span class="identifier">world</span>
|
||||||
|
</pre>
|
||||||
|
<p></p>
|
||||||
|
<div class="blockquote"><blockquote class="blockquote"><p><span class="emphasis"><em><span class="bold"><b>Next stop... Building your Hello World module
|
||||||
|
from start to finish...</b></span></em></span></p></blockquote></div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<table xmlns:rev="http://www.cs.rpi.edu/~gregod/boost/tools/doc/revision" width="100%"><tr>
|
||||||
|
<td align="left"><small><p>Last revised: October 31, 2005 at 18:46:06 GMT</p></small></td>
|
||||||
|
<td align="right"><small></small></td>
|
||||||
|
</tr></table>
|
||||||
|
<hr>
|
||||||
|
<div class="spirit-nav"><a accesskey="n" href="python/hello.html"><img src="images/next.png" alt="Next"></a></div>
|
||||||
|
</body>
|
||||||
|
</html>
|
||||||
422
doc/tutorial/doc/html/python/embedding.html
Normal file
@@ -0,0 +1,422 @@
|
|||||||
|
<html>
|
||||||
|
<head>
|
||||||
|
<meta http-equiv="Content-Type" content="text/html; charset=ISO-8859-1">
|
||||||
|
<title>Embedding</title>
|
||||||
|
<link rel="stylesheet" href="../boostbook.css" type="text/css">
|
||||||
|
<meta name="generator" content="DocBook XSL Stylesheets V1.66.1">
|
||||||
|
<link rel="start" href="../index.html" title="Chapter 1. python 1.0">
|
||||||
|
<link rel="up" href="../index.html" title="Chapter 1. python 1.0">
|
||||||
|
<link rel="prev" href="object.html" title=" Object Interface">
|
||||||
|
<link rel="next" href="iterators.html" title="Iterators">
|
||||||
|
</head>
|
||||||
|
<body bgcolor="white" text="black" link="#0000FF" vlink="#840084" alink="#0000FF">
|
||||||
|
<table cellpadding="2" width="100%">
|
||||||
|
<td valign="top"><img alt="boost.png (6897 bytes)" width="277" height="86" src="../../../../../../../boost.png"></td>
|
||||||
|
<td align="center"><a href="../../../../../../../index.htm">Home</a></td>
|
||||||
|
<td align="center"><a href="../../../../../../../libs/libraries.htm">Libraries</a></td>
|
||||||
|
<td align="center"><a href="../../../../../../../people/people.htm">People</a></td>
|
||||||
|
<td align="center"><a href="../../../../../../../more/faq.htm">FAQ</a></td>
|
||||||
|
<td align="center"><a href="../../../../../../../more/index.htm">More</a></td>
|
||||||
|
</table>
|
||||||
|
<hr>
|
||||||
|
<div class="spirit-nav">
|
||||||
|
<a accesskey="p" href="object.html"><img src="../images/prev.png" alt="Prev"></a><a accesskey="u" href="../index.html"><img src="../images/up.png" alt="Up"></a><a accesskey="h" href="../index.html"><img src="../images/home.png" alt="Home"></a><a accesskey="n" href="iterators.html"><img src="../images/next.png" alt="Next"></a>
|
||||||
|
</div>
|
||||||
|
<div class="section" lang="en">
|
||||||
|
<div class="titlepage"><div><div><h2 class="title" style="clear: both">
|
||||||
|
<a name="python.embedding"></a>Embedding</h2></div></div></div>
|
||||||
|
<div class="toc"><dl><dt><span class="section"><a href="embedding.html#python.using_the_interpreter">Using the interpreter</a></span></dt></dl></div>
|
||||||
|
<p>
|
||||||
|
EmbeddingBy 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 <span class="emphasis"><em>embed</em></span> the
|
||||||
|
Python interpreter into your C++ program.
|
||||||
|
</p>
|
||||||
|
<p>
|
||||||
|
Currently, Boost.Python does not directly support everything you'll need when
|
||||||
|
embedding. Therefore you'll need to use the <a href="http://www.python.org/doc/current/api/api.html" target="_top">Python/C
|
||||||
|
API</a> 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... <span class="inlinemediaobject"><img src="../images/smiley.png"></span></p>
|
||||||
|
<a name="embedding.building_embedded_programs"></a><h2>
|
||||||
|
<a name="id457321"></a>
|
||||||
|
Building embedded programs
|
||||||
|
</h2>
|
||||||
|
<p>
|
||||||
|
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.
|
||||||
|
</p>
|
||||||
|
<p>
|
||||||
|
Boost.Python's static link library comes in two variants. Both are located
|
||||||
|
in Boost's <tt class="literal">/libs/python/build/bin-stage</tt> subdirectory. On
|
||||||
|
Windows, the variants are called <tt class="literal">boost_python.lib</tt> (for release
|
||||||
|
builds) and <tt class="literal">boost_python_debug.lib</tt> (for debugging). If you
|
||||||
|
can't find the libraries, you probably haven't built Boost.Python yet. See
|
||||||
|
<a href="../../../../building.html" target="_top">Building and Testing</a> on how to
|
||||||
|
do this.
|
||||||
|
</p>
|
||||||
|
<p>
|
||||||
|
Python's static link library can be found in the <tt class="literal">/libs</tt> subdirectory
|
||||||
|
of your Python directory. On Windows it is called pythonXY.lib where X.Y is
|
||||||
|
your major Python version number.
|
||||||
|
</p>
|
||||||
|
<p>
|
||||||
|
Additionally, Python's <tt class="literal">/include</tt> subdirectory has to be added
|
||||||
|
to your include path.
|
||||||
|
</p>
|
||||||
|
<p>
|
||||||
|
In a Jamfile, all the above boils down to:
|
||||||
|
</p>
|
||||||
|
<pre class="programlisting">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) ;
|
||||||
|
</pre>
|
||||||
|
<a name="embedding.getting_started"></a><h2>
|
||||||
|
<a name="id457409"></a>
|
||||||
|
Getting started
|
||||||
|
</h2>
|
||||||
|
<p>
|
||||||
|
Being able to build is nice, but there is nothing to build yet. Embedding the
|
||||||
|
Python interpreter into one of your C++ programs requires these 4 steps:
|
||||||
|
</p>
|
||||||
|
<div class="orderedlist"><ol type="1">
|
||||||
|
<li>
|
||||||
|
#include <tt class="literal"><boost/python.hpp></tt><br><br>
|
||||||
|
</li>
|
||||||
|
<li>
|
||||||
|
Call <a href="http://www.python.org/doc/current/api/initialization.html#l2h-652" target="_top">Py_Initialize</a>()
|
||||||
|
to start the interpreter and create the <tt class="literal"><span class="underline">_main</span>_</tt>
|
||||||
|
module.<br><br>
|
||||||
|
</li>
|
||||||
|
<li>
|
||||||
|
Call other Python C API routines to use the interpreter.<br><br>
|
||||||
|
</li>
|
||||||
|
<li>
|
||||||
|
Call <a href="http://www.python.org/doc/current/api/initialization.html#l2h-656" target="_top">Py_Finalize</a>()
|
||||||
|
to stop the interpreter and release its resources.
|
||||||
|
</li>
|
||||||
|
</ol></div>
|
||||||
|
<p>
|
||||||
|
(Of course, there can be other C++ code between all of these steps.)
|
||||||
|
</p>
|
||||||
|
<div class="blockquote"><blockquote class="blockquote"><p><span class="emphasis"><em><span class="bold"><b>Now that we can embed the interpreter in
|
||||||
|
our programs, lets see how to put it to use...</b></span></em></span></p></blockquote></div>
|
||||||
|
<div class="section" lang="en">
|
||||||
|
<div class="titlepage"><div><div><h3 class="title">
|
||||||
|
<a name="python.using_the_interpreter"></a>Using the interpreter</h3></div></div></div>
|
||||||
|
<p>
|
||||||
|
Using the interpreterAs you probably already know, objects in Python are
|
||||||
|
reference-counted. Naturally, the <tt class="literal">PyObject</tt>s of the Python/C
|
||||||
|
API are also reference-counted. There is a difference however. While the
|
||||||
|
reference-counting is fully automatic in Python, the Python/C API requires
|
||||||
|
you to do it <a href="http://www.python.org/doc/current/api/refcounts.html" target="_top">by
|
||||||
|
hand</a>. This is messy and especially hard to get right in the presence
|
||||||
|
of C++ exceptions. Fortunately Boost.Python provides the <a href="../../../../v2/handle.html" target="_top">handle</a>
|
||||||
|
and <a href="../../../../v2/object.html" target="_top">object</a> class templates to
|
||||||
|
automate the process.
|
||||||
|
</p>
|
||||||
|
<a name="using_the_interpreter.reference_counting_handles_and_objects"></a><h2>
|
||||||
|
<a name="id457544"></a>
|
||||||
|
Reference-counting handles and objects
|
||||||
|
</h2>
|
||||||
|
<p>
|
||||||
|
There are two ways in which a function in the Python/C API can return a
|
||||||
|
<tt class="literal">PyObject*</tt>: as a <span class="emphasis"><em>borrowed reference</em></span>
|
||||||
|
or as a <span class="emphasis"><em>new reference</em></span>. 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.
|
||||||
|
</p>
|
||||||
|
<p>
|
||||||
|
For a function returning a <span class="emphasis"><em>borrowed reference</em></span> we'll
|
||||||
|
have to tell the <tt class="literal">handle</tt> that the <tt class="literal">PyObject*</tt>
|
||||||
|
is borrowed with the aptly named <a href="../../../../v2/handle.html#borrowed-spec" target="_top">borrowed</a>
|
||||||
|
function. Two functions returning borrowed references are <a href="http://www.python.org/doc/current/api/importing.html#l2h-125" target="_top">PyImport_AddModule</a>
|
||||||
|
and <a href="http://www.python.org/doc/current/api/moduleObjects.html#l2h-594" target="_top">PyModule_GetDict</a>.
|
||||||
|
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 <tt class="literal"><span class="underline">_main</span>_</tt>
|
||||||
|
module:
|
||||||
|
</p>
|
||||||
|
<pre class="programlisting">
|
||||||
|
<span class="identifier">object</span> <span class="identifier">main_module</span><span class="special">((</span>
|
||||||
|
<span class="identifier">handle</span><span class="special"><>(</span><span class="identifier">borrowed</span><span class="special">(</span><a href="http://www.python.org/doc/current/api/importing.html#l2h-125" target="_top">PyImport_AddModule</a><span class="special">(</span><span class="string">"__main__"</span><span class="special">)))));</span>
|
||||||
|
|
||||||
|
<span class="identifier">object</span> <span class="identifier">main_namespace</span> <span class="special">=</span> <span class="identifier">main_module</span><span class="special">.</span><span class="identifier">attr</span><span class="special">(</span><span class="string">"__dict__"</span><span class="special">);</span>
|
||||||
|
</pre>
|
||||||
|
<p>
|
||||||
|
For a function returning a <span class="emphasis"><em>new reference</em></span> we can just
|
||||||
|
create a <tt class="literal">handle</tt> out of the raw <tt class="literal">PyObject*</tt>
|
||||||
|
without wrapping it in a call to borrowed. One such function that returns
|
||||||
|
a new reference is <a href="http://www.python.org/doc/current/api/veryhigh.html#l2h-55" target="_top">PyRun_String</a>
|
||||||
|
which we'll discuss in the next section.
|
||||||
|
</p>
|
||||||
|
<div class="informaltable"><table class="table">
|
||||||
|
<colgroup><col></colgroup>
|
||||||
|
<tbody><tr><td class="blurb">
|
||||||
|
<span class="inlinemediaobject"><img src="../images/note.png"></span> <span class="bold"><b>Handle is a class <span class="emphasis"><em>template</em></span>, so why
|
||||||
|
haven't we been using any template parameters?</b></span><br><br><tt class="literal">handle</tt> has a single template parameter specifying
|
||||||
|
the type of the managed object. This type is <tt class="literal">PyObject</tt>
|
||||||
|
99% of the time, so the parameter was defaulted to <tt class="literal">PyObject</tt>
|
||||||
|
for convenience. Therefore we can use the shorthand <tt class="literal">handle<></tt>
|
||||||
|
instead of the longer, but equivalent, <tt class="literal">handle<PyObject></tt>.
|
||||||
|
</td></tr></tbody>
|
||||||
|
</table></div>
|
||||||
|
<a name="using_the_interpreter.running_python_code"></a><h2>
|
||||||
|
<a name="id457863"></a>
|
||||||
|
Running Python code
|
||||||
|
</h2>
|
||||||
|
<p>
|
||||||
|
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 <a href="http://www.python.org/doc/current/api/veryhigh.html" target="_top">here</a>. They
|
||||||
|
all work similarly so we will look at only one of them, namely:
|
||||||
|
</p>
|
||||||
|
<pre class="programlisting">
|
||||||
|
<span class="identifier">PyObject</span><span class="special">*</span> <a href="http://www.python.org/doc/current/api/veryhigh.html#l2h-55" target="_top">PyRun_String</a><span class="special">(</span><span class="keyword">char</span> <span class="special">*</span><span class="identifier">str</span><span class="special">,</span> <span class="keyword">int</span> <span class="identifier">start</span><span class="special">,</span> <span class="identifier">PyObject</span> <span class="special">*</span><span class="identifier">globals</span><span class="special">,</span> <span class="identifier">PyObject</span> <span class="special">*</span><span class="identifier">locals</span><span class="special">)</span>
|
||||||
|
</pre>
|
||||||
|
<p><a href="http://www.python.org/doc/current/api/veryhigh.html#l2h-55" target="_top">PyRun_String</a>
|
||||||
|
takes the code to execute as a null-terminated (C-style) string in its <tt class="literal">str</tt>
|
||||||
|
parameter. The function returns a new reference to a Python object. Which
|
||||||
|
object is returned depends on the <tt class="literal">start</tt> paramater.
|
||||||
|
</p>
|
||||||
|
<p>
|
||||||
|
The <tt class="literal">start</tt> parameter is the start symbol from the Python
|
||||||
|
grammar to use for interpreting the code. The possible values are:
|
||||||
|
</p>
|
||||||
|
<div class="informaltable">
|
||||||
|
<h4>
|
||||||
|
<a name="id458033"></a><span class="table-title">Start symbols</span>
|
||||||
|
</h4>
|
||||||
|
<table class="table">
|
||||||
|
<colgroup>
|
||||||
|
<col>
|
||||||
|
<col>
|
||||||
|
</colgroup>
|
||||||
|
<thead><tr>
|
||||||
|
<th><a href="http://www.python.org/doc/current/api/veryhigh.html#l2h-58" target="_top">Py_eval_input</a></th>
|
||||||
|
<th>for
|
||||||
|
interpreting isolated expressions</th>
|
||||||
|
</tr></thead>
|
||||||
|
<tbody>
|
||||||
|
<tr>
|
||||||
|
<td><a href="http://www.python.org/doc/current/api/veryhigh.html#l2h-59" target="_top">Py_file_input</a></td>
|
||||||
|
<td>for
|
||||||
|
interpreting sequences of statements</td>
|
||||||
|
</tr>
|
||||||
|
<tr>
|
||||||
|
<td><a href="http://www.python.org/doc/current/api/veryhigh.html#l2h-60" target="_top">Py_single_input</a></td>
|
||||||
|
<td>for
|
||||||
|
interpreting a single statement</td>
|
||||||
|
</tr>
|
||||||
|
</tbody>
|
||||||
|
</table>
|
||||||
|
</div>
|
||||||
|
<p>
|
||||||
|
When using <a href="http://www.python.org/doc/current/api/veryhigh.html#l2h-58" target="_top">Py_eval_input</a>,
|
||||||
|
the input string must contain a single expression and its result is returned.
|
||||||
|
When using <a href="http://www.python.org/doc/current/api/veryhigh.html#l2h-59" target="_top">Py_file_input</a>,
|
||||||
|
the string can contain an abitrary number of statements and None is returned.
|
||||||
|
<a href="http://www.python.org/doc/current/api/veryhigh.html#l2h-60" target="_top">Py_single_input</a>
|
||||||
|
works in the same way as <a href="http://www.python.org/doc/current/api/veryhigh.html#l2h-59" target="_top">Py_file_input</a>
|
||||||
|
but only accepts a single statement.
|
||||||
|
</p>
|
||||||
|
<p>
|
||||||
|
Lastly, the <tt class="literal">globals</tt> and <tt class="literal">locals</tt> parameters
|
||||||
|
are Python dictionaries containing the globals and locals of the context
|
||||||
|
in which to run the code. For most intents and purposes you can use the namespace
|
||||||
|
dictionary of the <tt class="literal"><span class="underline">_main</span>_</tt>
|
||||||
|
module for both parameters.
|
||||||
|
</p>
|
||||||
|
<p>
|
||||||
|
We have already seen how to get the <tt class="literal"><span class="underline">_main</span>_</tt>
|
||||||
|
module's namespace so let's run some Python code in it:
|
||||||
|
</p>
|
||||||
|
<pre class="programlisting">
|
||||||
|
<span class="identifier">object</span> <span class="identifier">main_module</span><span class="special">((</span>
|
||||||
|
<span class="identifier">handle</span><span class="special"><>(</span><span class="identifier">borrowed</span><span class="special">(</span><a href="http://www.python.org/doc/current/api/importing.html#l2h-125" target="_top">PyImport_AddModule</a><span class="special">(</span><span class="string">"__main__"</span><span class="special">)))));</span>
|
||||||
|
|
||||||
|
<span class="identifier">object</span> <span class="identifier">main_namespace</span> <span class="special">=</span> <span class="identifier">main_module</span><span class="special">.</span><span class="identifier">attr</span><span class="special">(</span><span class="string">"__dict__"</span><span class="special">);</span>
|
||||||
|
|
||||||
|
<span class="identifier">handle</span><span class="special"><></span> <span class="identifier">ignored</span><span class="special">((</span><a href="http://www.python.org/doc/current/api/veryhigh.html#l2h-55" target="_top">PyRun_String</a><span class="special">(</span>
|
||||||
|
|
||||||
|
<span class="string">"hello = file('hello.txt', 'w')\n"</span>
|
||||||
|
<span class="string">"hello.write('Hello world!')\n"</span>
|
||||||
|
<span class="string">"hello.close()"</span>
|
||||||
|
|
||||||
|
<span class="special">,</span> <a href="http://www.python.org/doc/current/api/veryhigh.html#l2h-59" target="_top">Py_file_input</a>
|
||||||
|
<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="special">,</span> <span class="identifier">main_namespace</span><span class="special">.</span><span class="identifier">ptr</span><span class="special">())</span>
|
||||||
|
<span class="special">));</span>
|
||||||
|
</pre>
|
||||||
|
<p>
|
||||||
|
Because the Python/C API doesn't know anything about <tt class="literal">object</tt>s,
|
||||||
|
we used the object's <tt class="literal">ptr</tt> member function to retrieve the
|
||||||
|
<tt class="literal">PyObject*</tt>.
|
||||||
|
</p>
|
||||||
|
<p>
|
||||||
|
This should create a file called 'hello.txt' in the current directory containing
|
||||||
|
a phrase that is well-known in programming circles.
|
||||||
|
</p>
|
||||||
|
<div class="informaltable"><table class="table">
|
||||||
|
<colgroup><col></colgroup>
|
||||||
|
<tbody><tr><td class="blurb">
|
||||||
|
<span class="inlinemediaobject"><img src="../images/note.png"></span> <span class="bold"><b>Note</b></span> that we wrap the return value of <a href="http://www.python.org/doc/current/api/veryhigh.html#l2h-55" target="_top">PyRun_String</a>
|
||||||
|
in a (nameless) <tt class="literal">handle</tt> 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 <tt class="literal">PyObject*</tt>s in <tt class="literal">handle</tt>s.
|
||||||
|
</td></tr></tbody>
|
||||||
|
</table></div>
|
||||||
|
<a name="using_the_interpreter.beyond_handles"></a><h2>
|
||||||
|
<a name="id458506"></a>
|
||||||
|
Beyond handles
|
||||||
|
</h2>
|
||||||
|
<p>
|
||||||
|
It's nice that <tt class="literal">handle</tt> 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 above, and in the <a href="object.html" target="_top">previous section</a>:
|
||||||
|
the aptly named <tt class="literal">object</tt> class and it's derivatives. We've
|
||||||
|
already seen that they can be constructed from a <tt class="literal">handle</tt>.
|
||||||
|
The following examples should further illustrate this fact:
|
||||||
|
</p>
|
||||||
|
<pre class="programlisting">
|
||||||
|
<span class="identifier">object</span> <span class="identifier">main_module</span><span class="special">((</span>
|
||||||
|
<span class="identifier">handle</span><span class="special"><>(</span><span class="identifier">borrowed</span><span class="special">(</span><a href="http://www.python.org/doc/current/api/importing.html#l2h-125" target="_top">PyImport_AddModule</a><span class="special">(</span><span class="string">"__main__"</span><span class="special">)))));</span>
|
||||||
|
|
||||||
|
<span class="identifier">object</span> <span class="identifier">main_namespace</span> <span class="special">=</span> <span class="identifier">main_module</span><span class="special">.</span><span class="identifier">attr</span><span class="special">(</span><span class="string">"__dict__"</span><span class="special">);</span>
|
||||||
|
|
||||||
|
<span class="identifier">handle</span><span class="special"><></span> <span class="identifier">ignored</span><span class="special">((</span><a href="http://www.python.org/doc/current/api/veryhigh.html#l2h-55" target="_top">PyRun_String</a><span class="special">(</span>
|
||||||
|
|
||||||
|
<span class="string">"result = 5 ** 2"</span>
|
||||||
|
|
||||||
|
<span class="special">,</span> <a href="http://www.python.org/doc/current/api/veryhigh.html#l2h-59" target="_top">Py_file_input</a>
|
||||||
|
<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="special">,</span> <span class="identifier">main_namespace</span><span class="special">.</span><span class="identifier">ptr</span><span class="special">())</span>
|
||||||
|
<span class="special">));</span>
|
||||||
|
|
||||||
|
<span class="keyword">int</span> <span class="identifier">five_squared</span> <span class="special">=</span> <span class="identifier">extract</span><span class="special"><</span><span class="keyword">int</span><span class="special">>(</span><span class="identifier">main_namespace</span><span class="special">[</span><span class="string">"result"</span><span class="special">]);</span>
|
||||||
|
</pre>
|
||||||
|
<p>
|
||||||
|
Here we create a dictionary object for the <tt class="literal"><span class="underline">_main</span>_</tt>
|
||||||
|
module's namespace. Then we assign 5 squared to the result variable and read
|
||||||
|
this variable from the dictionary. Another way to achieve the same result
|
||||||
|
is to let <a href="http://www.python.org/doc/current/api/veryhigh.html#l2h-55" target="_top">PyRun_String</a>
|
||||||
|
return the result directly with <a href="http://www.python.org/doc/current/api/veryhigh.html#l2h-58" target="_top">Py_eval_input</a>:
|
||||||
|
</p>
|
||||||
|
<pre class="programlisting">
|
||||||
|
<span class="identifier">object</span> <span class="identifier">result</span><span class="special">((</span><span class="identifier">handle</span><span class="special"><>(</span>
|
||||||
|
<a href="http://www.python.org/doc/current/api/veryhigh.html#l2h-55" target="_top">PyRun_String</a><span class="special">(</span><span class="string">"5 ** 2"</span>
|
||||||
|
<span class="special">,</span> <a href="http://www.python.org/doc/current/api/veryhigh.html#l2h-58" target="_top">Py_eval_input</a>
|
||||||
|
<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="special">,</span> <span class="identifier">main_namespace</span><span class="special">.</span><span class="identifier">ptr</span><span class="special">()))</span>
|
||||||
|
<span class="special">));</span>
|
||||||
|
|
||||||
|
<span class="keyword">int</span> <span class="identifier">five_squared</span> <span class="special">=</span> <span class="identifier">extract</span><span class="special"><</span><span class="keyword">int</span><span class="special">>(</span><span class="identifier">result</span><span class="special">);</span>
|
||||||
|
</pre>
|
||||||
|
<div class="informaltable"><table class="table">
|
||||||
|
<colgroup><col></colgroup>
|
||||||
|
<tbody><tr><td class="blurb">
|
||||||
|
<span class="inlinemediaobject"><img src="../images/note.png"></span> <span class="bold"><b>Note</b></span> that <tt class="literal">object</tt>'s member
|
||||||
|
function to return the wrapped <tt class="literal">PyObject*</tt> is called
|
||||||
|
<tt class="literal">ptr</tt> instead of <tt class="literal">get</tt>. This makes
|
||||||
|
sense if you take into account the different functions that <tt class="literal">object</tt>
|
||||||
|
and <tt class="literal">handle</tt> perform. </td></tr></tbody>
|
||||||
|
</table></div>
|
||||||
|
<a name="using_the_interpreter.exception_handling"></a><h2>
|
||||||
|
<a name="id459120"></a>
|
||||||
|
Exception handling
|
||||||
|
</h2>
|
||||||
|
<p>
|
||||||
|
If an exception occurs in the execution of some Python code, the <a href="http://www.python.org/doc/current/api/veryhigh.html#l2h-55" target="_top">PyRun_String</a>
|
||||||
|
function returns a null pointer. Constructing a <tt class="literal">handle</tt>
|
||||||
|
out of this null pointer throws <a href="../../../../v2/errors.html#error_already_set-spec" target="_top">error_already_set</a>,
|
||||||
|
so basically, the Python exception is automatically translated into a C++
|
||||||
|
exception when using <tt class="literal">handle</tt>:
|
||||||
|
</p>
|
||||||
|
<pre class="programlisting">
|
||||||
|
<span class="keyword">try</span>
|
||||||
|
<span class="special">{</span>
|
||||||
|
<span class="identifier">object</span> <span class="identifier">result</span><span class="special">((</span><span class="identifier">handle</span><span class="special"><>(</span><a href="http://www.python.org/doc/current/api/veryhigh.html#l2h-55" target="_top">PyRun_String</a><span class="special">(</span>
|
||||||
|
<span class="string">"5/0"</span>
|
||||||
|
<span class="special">,</span> <a href="http://www.python.org/doc/current/api/veryhigh.html#l2h-58" target="_top">Py_eval_input</a>
|
||||||
|
<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="special">,</span> <span class="identifier">main_namespace</span><span class="special">.</span><span class="identifier">ptr</span><span class="special">()))</span>
|
||||||
|
<span class="special">));</span>
|
||||||
|
|
||||||
|
<span class="comment">// execution will never get here:
|
||||||
|
</span> <span class="keyword">int</span> <span class="identifier">five_divided_by_zero</span> <span class="special">=</span> <span class="identifier">extract</span><span class="special"><</span><span class="keyword">int</span><span class="special">>(</span><span class="identifier">result</span><span class="special">);</span>
|
||||||
|
<span class="special">}</span>
|
||||||
|
<span class="keyword">catch</span><span class="special">(</span><span class="identifier">error_already_set</span><span class="special">)</span>
|
||||||
|
<span class="special">{</span>
|
||||||
|
<span class="comment">// handle the exception in some way
|
||||||
|
</span><span class="special">}</span>
|
||||||
|
</pre>
|
||||||
|
<p>
|
||||||
|
The <tt class="literal">error_already_set</tt> exception class doesn't carry any
|
||||||
|
information in itself. To find out more about the Python exception that occurred,
|
||||||
|
you need to use the <a href="http://www.python.org/doc/api/exceptionHandling.html" target="_top">exception
|
||||||
|
handling functions</a> of the Python/C API in your catch-statement. This
|
||||||
|
can be as simple as calling <a href="http://www.python.org/doc/api/exceptionHandling.html#l2h-70" target="_top">PyErr_Print()</a>
|
||||||
|
to print the exception's traceback to the console, or comparing the type
|
||||||
|
of the exception with those of the <a href="http://www.python.org/doc/api/standardExceptions.html" target="_top">standard
|
||||||
|
exceptions</a>:
|
||||||
|
</p>
|
||||||
|
<pre class="programlisting">
|
||||||
|
<span class="keyword">catch</span><span class="special">(</span><span class="identifier">error_already_set</span><span class="special">)</span>
|
||||||
|
<span class="special">{</span>
|
||||||
|
<span class="keyword">if</span> <span class="special">(</span><span class="identifier">PyErr_ExceptionMatches</span><span class="special">(</span><span class="identifier">PyExc_ZeroDivisionError</span><span class="special">))</span>
|
||||||
|
<span class="special">{</span>
|
||||||
|
<span class="comment">// handle ZeroDivisionError specially
|
||||||
|
</span> <span class="special">}</span>
|
||||||
|
<span class="keyword">else</span>
|
||||||
|
<span class="special">{</span>
|
||||||
|
<span class="comment">// print all other errors to stderr
|
||||||
|
</span> <span class="identifier">PyErr_Print</span><span class="special">();</span>
|
||||||
|
<span class="special">}</span>
|
||||||
|
<span class="special">}</span>
|
||||||
|
</pre>
|
||||||
|
<p>
|
||||||
|
(To retrieve even more information from the exception you can use some of
|
||||||
|
the other exception handling functions listed <a href="http://www.python.org/doc/api/exceptionHandling.html" target="_top">here</a>.)
|
||||||
|
</p>
|
||||||
|
<p>
|
||||||
|
If you'd rather not have <tt class="literal">handle</tt> throw a C++ exception
|
||||||
|
when it is constructed, you can use the <a href="../../../../v2/handle.html#allow_null-spec" target="_top">allow_null</a>
|
||||||
|
function in the same way you'd use borrowed:
|
||||||
|
</p>
|
||||||
|
<pre class="programlisting">
|
||||||
|
<span class="identifier">handle</span><span class="special"><></span> <span class="identifier">result</span><span class="special">((</span><span class="identifier">allow_null</span><span class="special">(</span><a href="http://www.python.org/doc/current/api/veryhigh.html#l2h-55" target="_top">PyRun_String</a><span class="special">(</span>
|
||||||
|
<span class="string">"5/0"</span>
|
||||||
|
<span class="special">,</span> <a href="http://www.python.org/doc/current/api/veryhigh.html#l2h-58" target="_top">Py_eval_input</a>
|
||||||
|
<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="special">,</span> <span class="identifier">main_namespace</span><span class="special">.</span><span class="identifier">ptr</span><span class="special">()))));</span>
|
||||||
|
|
||||||
|
<span class="keyword">if</span> <span class="special">(!</span><span class="identifier">result</span><span class="special">)</span>
|
||||||
|
<span class="comment">// Python exception occurred
|
||||||
|
</span><span class="keyword">else</span>
|
||||||
|
<span class="comment">// everything went okay, it's safe to use the result
|
||||||
|
</span></pre>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<table xmlns:rev="http://www.cs.rpi.edu/~gregod/boost/tools/doc/revision" width="100%"><tr>
|
||||||
|
<td align="left"></td>
|
||||||
|
<td align="right"><small>Copyright © 2002-2005 Joel
|
||||||
|
de Guzman, David Abrahams</small></td>
|
||||||
|
</tr></table>
|
||||||
|
<hr>
|
||||||
|
<div class="spirit-nav">
|
||||||
|
<a accesskey="p" href="object.html"><img src="../images/prev.png" alt="Prev"></a><a accesskey="u" href="../index.html"><img src="../images/up.png" alt="Up"></a><a accesskey="h" href="../index.html"><img src="../images/home.png" alt="Home"></a><a accesskey="n" href="iterators.html"><img src="../images/next.png" alt="Next"></a>
|
||||||
|
</div>
|
||||||
|
</body>
|
||||||
|
</html>
|
||||||
61
doc/tutorial/doc/html/python/exception.html
Normal file
@@ -0,0 +1,61 @@
|
|||||||
|
<html>
|
||||||
|
<head>
|
||||||
|
<meta http-equiv="Content-Type" content="text/html; charset=ISO-8859-1">
|
||||||
|
<title> Exception Translation</title>
|
||||||
|
<link rel="stylesheet" href="../boostbook.css" type="text/css">
|
||||||
|
<meta name="generator" content="DocBook XSL Stylesheets V1.66.1">
|
||||||
|
<link rel="start" href="../index.html" title="Chapter 1. python 1.0">
|
||||||
|
<link rel="up" href="../index.html" title="Chapter 1. python 1.0">
|
||||||
|
<link rel="prev" href="iterators.html" title="Iterators">
|
||||||
|
<link rel="next" href="techniques.html" title=" General Techniques">
|
||||||
|
</head>
|
||||||
|
<body bgcolor="white" text="black" link="#0000FF" vlink="#840084" alink="#0000FF">
|
||||||
|
<table cellpadding="2" width="100%">
|
||||||
|
<td valign="top"><img alt="boost.png (6897 bytes)" width="277" height="86" src="../../../../../../../boost.png"></td>
|
||||||
|
<td align="center"><a href="../../../../../../../index.htm">Home</a></td>
|
||||||
|
<td align="center"><a href="../../../../../../../libs/libraries.htm">Libraries</a></td>
|
||||||
|
<td align="center"><a href="../../../../../../../people/people.htm">People</a></td>
|
||||||
|
<td align="center"><a href="../../../../../../../more/faq.htm">FAQ</a></td>
|
||||||
|
<td align="center"><a href="../../../../../../../more/index.htm">More</a></td>
|
||||||
|
</table>
|
||||||
|
<hr>
|
||||||
|
<div class="spirit-nav">
|
||||||
|
<a accesskey="p" href="iterators.html"><img src="../images/prev.png" alt="Prev"></a><a accesskey="u" href="../index.html"><img src="../images/up.png" alt="Up"></a><a accesskey="h" href="../index.html"><img src="../images/home.png" alt="Home"></a><a accesskey="n" href="techniques.html"><img src="../images/next.png" alt="Next"></a>
|
||||||
|
</div>
|
||||||
|
<div class="section" lang="en">
|
||||||
|
<div class="titlepage"><div><div><h2 class="title" style="clear: both">
|
||||||
|
<a name="python.exception"></a> Exception Translation</h2></div></div></div>
|
||||||
|
<p>
|
||||||
|
Exception TranslationAll C++ exceptions must be caught at the boundary with
|
||||||
|
Python code. This boundary is the point where C++ meets Python. Boost.Python
|
||||||
|
provides a default exception handler that translates selected standard exceptions,
|
||||||
|
then gives up:
|
||||||
|
</p>
|
||||||
|
<pre class="programlisting">
|
||||||
|
<span class="keyword">raise</span> <span class="identifier">RuntimeError</span><span class="special">,</span> <span class="string">'unidentifiable C++ Exception'</span>
|
||||||
|
</pre>
|
||||||
|
<p>
|
||||||
|
Users may provide custom translation. Here's an example:
|
||||||
|
</p>
|
||||||
|
<pre class="programlisting">
|
||||||
|
<span class="identifier">struct</span> <span class="identifier">PodBayDoorException</span><span class="special">;</span>
|
||||||
|
<span class="identifier">void</span> <span class="identifier">translator</span><span class="special">(</span><span class="identifier">PodBayDoorException</span> <span class="identifier">const</span><span class="special">&</span> <span class="identifier">x</span><span class="special">)</span> <span class="special">{</span>
|
||||||
|
<span class="identifier">PyErr_SetString</span><span class="special">(</span><span class="identifier">PyExc_UserWarning</span><span class="special">,</span> <span class="string">"I'm sorry Dave..."</span><span class="special">);</span>
|
||||||
|
<span class="special">}</span>
|
||||||
|
<span class="identifier">BOOST_PYTHON_MODULE</span><span class="special">(</span><span class="identifier">kubrick</span><span class="special">)</span> <span class="special">{</span>
|
||||||
|
<span class="identifier">register_exception_translator</span><span class="special"><</span>
|
||||||
|
<span class="identifier">PodBayDoorException</span><span class="special">>(</span><span class="identifier">translator</span><span class="special">);</span>
|
||||||
|
<span class="special">...</span>
|
||||||
|
</pre>
|
||||||
|
</div>
|
||||||
|
<table xmlns:rev="http://www.cs.rpi.edu/~gregod/boost/tools/doc/revision" width="100%"><tr>
|
||||||
|
<td align="left"></td>
|
||||||
|
<td align="right"><small>Copyright © 2002-2005 Joel
|
||||||
|
de Guzman, David Abrahams</small></td>
|
||||||
|
</tr></table>
|
||||||
|
<hr>
|
||||||
|
<div class="spirit-nav">
|
||||||
|
<a accesskey="p" href="iterators.html"><img src="../images/prev.png" alt="Prev"></a><a accesskey="u" href="../index.html"><img src="../images/up.png" alt="Up"></a><a accesskey="h" href="../index.html"><img src="../images/home.png" alt="Home"></a><a accesskey="n" href="techniques.html"><img src="../images/next.png" alt="Next"></a>
|
||||||
|
</div>
|
||||||
|
</body>
|
||||||
|
</html>
|
||||||
608
doc/tutorial/doc/html/python/exposing.html
Normal file
@@ -0,0 +1,608 @@
|
|||||||
|
<html>
|
||||||
|
<head>
|
||||||
|
<meta http-equiv="Content-Type" content="text/html; charset=ISO-8859-1">
|
||||||
|
<title> Exposing Classes</title>
|
||||||
|
<link rel="stylesheet" href="../boostbook.css" type="text/css">
|
||||||
|
<meta name="generator" content="DocBook XSL Stylesheets V1.66.1">
|
||||||
|
<link rel="start" href="../index.html" title="Chapter 1. python 1.0">
|
||||||
|
<link rel="up" href="../index.html" title="Chapter 1. python 1.0">
|
||||||
|
<link rel="prev" href="hello.html" title=" Building Hello World">
|
||||||
|
<link rel="next" href="functions.html" title="Functions">
|
||||||
|
</head>
|
||||||
|
<body bgcolor="white" text="black" link="#0000FF" vlink="#840084" alink="#0000FF">
|
||||||
|
<table cellpadding="2" width="100%">
|
||||||
|
<td valign="top"><img alt="boost.png (6897 bytes)" width="277" height="86" src="../../../../../../../boost.png"></td>
|
||||||
|
<td align="center"><a href="../../../../../../../index.htm">Home</a></td>
|
||||||
|
<td align="center"><a href="../../../../../../../libs/libraries.htm">Libraries</a></td>
|
||||||
|
<td align="center"><a href="../../../../../../../people/people.htm">People</a></td>
|
||||||
|
<td align="center"><a href="../../../../../../../more/faq.htm">FAQ</a></td>
|
||||||
|
<td align="center"><a href="../../../../../../../more/index.htm">More</a></td>
|
||||||
|
</table>
|
||||||
|
<hr>
|
||||||
|
<div class="spirit-nav">
|
||||||
|
<a accesskey="p" href="hello.html"><img src="../images/prev.png" alt="Prev"></a><a accesskey="u" href="../index.html"><img src="../images/up.png" alt="Up"></a><a accesskey="h" href="../index.html"><img src="../images/home.png" alt="Home"></a><a accesskey="n" href="functions.html"><img src="../images/next.png" alt="Next"></a>
|
||||||
|
</div>
|
||||||
|
<div class="section" lang="en">
|
||||||
|
<div class="titlepage"><div><div><h2 class="title" style="clear: both">
|
||||||
|
<a name="python.exposing"></a> Exposing Classes</h2></div></div></div>
|
||||||
|
<div class="toc"><dl>
|
||||||
|
<dt><span class="section"><a href="exposing.html#python.constructors">Constructors</a></span></dt>
|
||||||
|
<dt><span class="section"><a href="exposing.html#python.class_data_members">Class Data Members</a></span></dt>
|
||||||
|
<dt><span class="section"><a href="exposing.html#python.class_properties">Class Properties</a></span></dt>
|
||||||
|
<dt><span class="section"><a href="exposing.html#python.inheritance">Inheritance</a></span></dt>
|
||||||
|
<dt><span class="section"><a href="exposing.html#python.class_virtual_functions">Class Virtual Functions</a></span></dt>
|
||||||
|
<dt><span class="section"><a href="exposing.html#python.virtual_functions_with_default_implementations">Virtual Functions with Default Implementations</a></span></dt>
|
||||||
|
<dt><span class="section"><a href="exposing.html#python.class_operators_special_functions">Class Operators/Special Functions</a></span></dt>
|
||||||
|
</dl></div>
|
||||||
|
<p>
|
||||||
|
Exposing ClassesNow let's expose a C++ class to Python.
|
||||||
|
</p>
|
||||||
|
<p>
|
||||||
|
Consider a C++ class/struct that we want to expose to Python:
|
||||||
|
</p>
|
||||||
|
<pre class="programlisting">
|
||||||
|
<span class="keyword">struct</span> <span class="identifier">World</span>
|
||||||
|
<span class="special">{</span>
|
||||||
|
<span class="keyword">void</span> <span class="identifier">set</span><span class="special">(</span><span class="identifier">std</span><span class="special">::</span><span class="identifier">string</span> <span class="identifier">msg</span><span class="special">)</span> <span class="special">{</span> <span class="keyword">this</span><span class="special">-></span><span class="identifier">msg</span> <span class="special">=</span> <span class="identifier">msg</span><span class="special">;</span> <span class="special">}</span>
|
||||||
|
<span class="identifier">std</span><span class="special">::</span><span class="identifier">string</span> <span class="identifier">greet</span><span class="special">()</span> <span class="special">{</span> <span class="keyword">return</span> <span class="identifier">msg</span><span class="special">;</span> <span class="special">}</span>
|
||||||
|
<span class="identifier">std</span><span class="special">::</span><span class="identifier">string</span> <span class="identifier">msg</span><span class="special">;</span>
|
||||||
|
<span class="special">};</span>
|
||||||
|
</pre>
|
||||||
|
<p>
|
||||||
|
We can expose this to Python by writing a corresponding Boost.Python C++ Wrapper:
|
||||||
|
</p>
|
||||||
|
<pre class="programlisting">
|
||||||
|
<span class="preprocessor">#include</span> <span class="special"><</span><span class="identifier">boost</span><span class="special">/</span><span class="identifier">python</span><span class="special">.</span><span class="identifier">hpp</span><span class="special">></span>
|
||||||
|
<span class="keyword">using</span> <span class="keyword">namespace</span> <span class="identifier">boost</span><span class="special">::</span><span class="identifier">python</span><span class="special">;</span>
|
||||||
|
|
||||||
|
<span class="identifier">BOOST_PYTHON_MODULE</span><span class="special">(</span><span class="identifier">hello</span><span class="special">)</span>
|
||||||
|
<span class="special">{</span>
|
||||||
|
<span class="identifier">class_</span><span class="special"><</span><span class="identifier">World</span><span class="special">>(</span><span class="string">"World"</span><span class="special">)</span>
|
||||||
|
<span class="special">.</span><span class="identifier">def</span><span class="special">(</span><span class="string">"greet"</span><span class="special">,</span> <span class="special">&</span><span class="identifier">World</span><span class="special">::</span><span class="identifier">greet</span><span class="special">)</span>
|
||||||
|
<span class="special">.</span><span class="identifier">def</span><span class="special">(</span><span class="string">"set"</span><span class="special">,</span> <span class="special">&</span><span class="identifier">World</span><span class="special">::</span><span class="identifier">set</span><span class="special">)</span>
|
||||||
|
<span class="special">;</span>
|
||||||
|
<span class="special">}</span>
|
||||||
|
</pre>
|
||||||
|
<p>
|
||||||
|
Here, we wrote a C++ class wrapper that exposes the member functions <tt class="literal">greet</tt>
|
||||||
|
and <tt class="literal">set</tt>. Now, after building our module as a shared library,
|
||||||
|
we may use our class <tt class="literal">World</tt> in Python. Here's a sample Python
|
||||||
|
session:
|
||||||
|
</p>
|
||||||
|
<p></p>
|
||||||
|
<pre class="programlisting">
|
||||||
|
<span class="special">>>></span> <span class="keyword">import</span> <span class="identifier">hello</span>
|
||||||
|
<span class="special">>>></span> <span class="identifier">planet</span> <span class="special">=</span> <span class="identifier">hello</span><span class="special">.</span><span class="identifier">World</span><span class="special">()</span>
|
||||||
|
<span class="special">>>></span> <span class="identifier">planet</span><span class="special">.</span><span class="identifier">set</span><span class="special">(</span><span class="string">'howdy'</span><span class="special">)</span>
|
||||||
|
<span class="special">>>></span> <span class="identifier">planet</span><span class="special">.</span><span class="identifier">greet</span><span class="special">()</span>
|
||||||
|
<span class="string">'howdy'</span>
|
||||||
|
</pre>
|
||||||
|
<div class="section" lang="en">
|
||||||
|
<div class="titlepage"><div><div><h3 class="title">
|
||||||
|
<a name="python.constructors"></a>Constructors</h3></div></div></div>
|
||||||
|
<p>
|
||||||
|
ConstructorsOur previous example didn't have any explicit constructors. Since
|
||||||
|
<tt class="literal">World</tt> is declared as a plain struct, it has an implicit
|
||||||
|
default constructor. Boost.Python exposes the default constructor by default,
|
||||||
|
which is why we were able to write
|
||||||
|
</p>
|
||||||
|
<pre class="programlisting">
|
||||||
|
<span class="special">>>></span> <span class="identifier">planet</span> <span class="special">=</span> <span class="identifier">hello</span><span class="special">.</span><span class="identifier">World</span><span class="special">()</span>
|
||||||
|
</pre>
|
||||||
|
<p>
|
||||||
|
We may wish to wrap a class with a non-default constructor. Let us build
|
||||||
|
on our previous example:
|
||||||
|
</p>
|
||||||
|
<p></p>
|
||||||
|
<pre class="programlisting">
|
||||||
|
<span class="keyword">struct</span> <span class="identifier">World</span>
|
||||||
|
<span class="special">{</span>
|
||||||
|
<span class="identifier">World</span><span class="special">(</span><span class="identifier">std</span><span class="special">::</span><span class="identifier">string</span> <span class="identifier">msg</span><span class="special">):</span> <span class="identifier">msg</span><span class="special">(</span><span class="identifier">msg</span><span class="special">)</span> <span class="special">{}</span> <span class="comment">// added constructor
|
||||||
|
</span> <span class="keyword">void</span> <span class="identifier">set</span><span class="special">(</span><span class="identifier">std</span><span class="special">::</span><span class="identifier">string</span> <span class="identifier">msg</span><span class="special">)</span> <span class="special">{</span> <span class="keyword">this</span><span class="special">-></span><span class="identifier">msg</span> <span class="special">=</span> <span class="identifier">msg</span><span class="special">;</span> <span class="special">}</span>
|
||||||
|
<span class="identifier">std</span><span class="special">::</span><span class="identifier">string</span> <span class="identifier">greet</span><span class="special">()</span> <span class="special">{</span> <span class="keyword">return</span> <span class="identifier">msg</span><span class="special">;</span> <span class="special">}</span>
|
||||||
|
<span class="identifier">std</span><span class="special">::</span><span class="identifier">string</span> <span class="identifier">msg</span><span class="special">;</span>
|
||||||
|
<span class="special">};</span>
|
||||||
|
</pre>
|
||||||
|
<p>
|
||||||
|
This time <tt class="literal">World</tt> has no default constructor; our previous
|
||||||
|
wrapping code would fail to compile when the library tried to expose it.
|
||||||
|
We have to tell <tt class="literal">class_<World></tt> about the constructor
|
||||||
|
we want to expose instead.
|
||||||
|
</p>
|
||||||
|
<pre class="programlisting">
|
||||||
|
<span class="preprocessor">#include</span> <span class="special"><</span><span class="identifier">boost</span><span class="special">/</span><span class="identifier">python</span><span class="special">.</span><span class="identifier">hpp</span><span class="special">></span>
|
||||||
|
<span class="keyword">using</span> <span class="keyword">namespace</span> <span class="identifier">boost</span><span class="special">::</span><span class="identifier">python</span><span class="special">;</span>
|
||||||
|
|
||||||
|
<span class="identifier">BOOST_PYTHON_MODULE</span><span class="special">(</span><span class="identifier">hello</span><span class="special">)</span>
|
||||||
|
<span class="special">{</span>
|
||||||
|
<span class="identifier">class_</span><span class="special"><</span><span class="identifier">World</span><span class="special">>(</span><span class="string">"World"</span><span class="special">,</span> <span class="identifier">init</span><span class="special"><</span><span class="identifier">std</span><span class="special">::</span><span class="identifier">string</span><span class="special">>())</span>
|
||||||
|
<span class="special">.</span><span class="identifier">def</span><span class="special">(</span><span class="string">"greet"</span><span class="special">,</span> <span class="special">&</span><span class="identifier">World</span><span class="special">::</span><span class="identifier">greet</span><span class="special">)</span>
|
||||||
|
<span class="special">.</span><span class="identifier">def</span><span class="special">(</span><span class="string">"set"</span><span class="special">,</span> <span class="special">&</span><span class="identifier">World</span><span class="special">::</span><span class="identifier">set</span><span class="special">)</span>
|
||||||
|
<span class="special">;</span>
|
||||||
|
<span class="special">}</span>
|
||||||
|
</pre>
|
||||||
|
<p><tt class="literal">init<std::string>()</tt> exposes the constructor taking
|
||||||
|
in a <tt class="literal">std::string</tt> (in Python, constructors are spelled
|
||||||
|
"<tt class="literal">"<span class="underline">_init</span>_"</tt>").
|
||||||
|
</p>
|
||||||
|
<p>
|
||||||
|
We can expose additional constructors by passing more <tt class="literal">init<...></tt>s
|
||||||
|
to the <tt class="literal">def()</tt> member function. Say for example we have
|
||||||
|
another World constructor taking in two doubles:
|
||||||
|
</p>
|
||||||
|
<pre class="programlisting">
|
||||||
|
<span class="identifier">class_</span><span class="special"><</span><span class="identifier">World</span><span class="special">>(</span><span class="string">"World"</span><span class="special">,</span> <span class="identifier">init</span><span class="special"><</span><span class="identifier">std</span><span class="special">::</span><span class="identifier">string</span><span class="special">>())</span>
|
||||||
|
<span class="special">.</span><span class="identifier">def</span><span class="special">(</span><span class="identifier">init</span><span class="special"><</span><span class="keyword">double</span><span class="special">,</span> <span class="keyword">double</span><span class="special">>())</span>
|
||||||
|
<span class="special">.</span><span class="identifier">def</span><span class="special">(</span><span class="string">"greet"</span><span class="special">,</span> <span class="special">&</span><span class="identifier">World</span><span class="special">::</span><span class="identifier">greet</span><span class="special">)</span>
|
||||||
|
<span class="special">.</span><span class="identifier">def</span><span class="special">(</span><span class="string">"set"</span><span class="special">,</span> <span class="special">&</span><span class="identifier">World</span><span class="special">::</span><span class="identifier">set</span><span class="special">)</span>
|
||||||
|
<span class="special">;</span>
|
||||||
|
</pre>
|
||||||
|
<p>
|
||||||
|
On the other hand, if we do not wish to expose any constructors at all, we
|
||||||
|
may use <tt class="literal">no_init</tt> instead:
|
||||||
|
</p>
|
||||||
|
<pre class="programlisting">
|
||||||
|
<span class="identifier">class_</span><span class="special"><</span><span class="identifier">Abstract</span><span class="special">>(</span><span class="string">"Abstract"</span><span class="special">,</span> <span class="identifier">no_init</span><span class="special">)</span>
|
||||||
|
</pre>
|
||||||
|
<p>
|
||||||
|
This actually adds an <tt class="literal"><span class="underline">_init</span>_</tt>
|
||||||
|
method which always raises a Python RuntimeError exception.
|
||||||
|
</p>
|
||||||
|
</div>
|
||||||
|
<div class="section" lang="en">
|
||||||
|
<div class="titlepage"><div><div><h3 class="title">
|
||||||
|
<a name="python.class_data_members"></a>Class Data Members</h3></div></div></div>
|
||||||
|
<p>
|
||||||
|
Class Data MembersData members may also be exposed to Python so that they
|
||||||
|
can be accessed as attributes of the corresponding Python class. Each data
|
||||||
|
member that we wish to be exposed may be regarded as <span class="bold"><b>read-only</b></span>
|
||||||
|
or <span class="bold"><b>read-write</b></span>. Consider this class <tt class="literal">Var</tt>:
|
||||||
|
</p>
|
||||||
|
<pre class="programlisting">
|
||||||
|
<span class="keyword">struct</span> <span class="identifier">Var</span>
|
||||||
|
<span class="special">{</span>
|
||||||
|
<span class="identifier">Var</span><span class="special">(</span><span class="identifier">std</span><span class="special">::</span><span class="identifier">string</span> <span class="identifier">name</span><span class="special">)</span> <span class="special">:</span> <span class="identifier">name</span><span class="special">(</span><span class="identifier">name</span><span class="special">),</span> <span class="identifier">value</span><span class="special">()</span> <span class="special">{}</span>
|
||||||
|
<span class="identifier">std</span><span class="special">::</span><span class="identifier">string</span> <span class="keyword">const</span> <span class="identifier">name</span><span class="special">;</span>
|
||||||
|
<span class="keyword">float</span> <span class="identifier">value</span><span class="special">;</span>
|
||||||
|
<span class="special">};</span>
|
||||||
|
</pre>
|
||||||
|
<p>
|
||||||
|
Our C++ <tt class="literal">Var</tt> class and its data members can be exposed
|
||||||
|
to Python:
|
||||||
|
</p>
|
||||||
|
<pre class="programlisting">
|
||||||
|
<span class="identifier">class_</span><span class="special"><</span><span class="identifier">Var</span><span class="special">>(</span><span class="string">"Var"</span><span class="special">,</span> <span class="identifier">init</span><span class="special"><</span><span class="identifier">std</span><span class="special">::</span><span class="identifier">string</span><span class="special">>())</span>
|
||||||
|
<span class="special">.</span><span class="identifier">def_readonly</span><span class="special">(</span><span class="string">"name"</span><span class="special">,</span> <span class="special">&</span><span class="identifier">Var</span><span class="special">::</span><span class="identifier">name</span><span class="special">)</span>
|
||||||
|
<span class="special">.</span><span class="identifier">def_readwrite</span><span class="special">(</span><span class="string">"value"</span><span class="special">,</span> <span class="special">&</span><span class="identifier">Var</span><span class="special">::</span><span class="identifier">value</span><span class="special">);</span>
|
||||||
|
</pre>
|
||||||
|
<p>
|
||||||
|
Then, in Python, assuming we have placed our Var class inside the namespace
|
||||||
|
hello as we did before:
|
||||||
|
</p>
|
||||||
|
<p></p>
|
||||||
|
<pre class="programlisting">
|
||||||
|
<span class="special">>>></span> <span class="identifier">x</span> <span class="special">=</span> <span class="identifier">hello</span><span class="special">.</span><span class="identifier">Var</span><span class="special">(</span><span class="string">'pi'</span><span class="special">)</span>
|
||||||
|
<span class="special">>>></span> <span class="identifier">x</span><span class="special">.</span><span class="identifier">value</span> <span class="special">=</span> <span class="number">3.14</span>
|
||||||
|
<span class="special">>>></span> <span class="keyword">print</span> <span class="identifier">x</span><span class="special">.</span><span class="identifier">name</span><span class="special">,</span> <span class="string">'is around'</span><span class="special">,</span> <span class="identifier">x</span><span class="special">.</span><span class="identifier">value</span>
|
||||||
|
<span class="identifier">pi</span> <span class="keyword">is</span> <span class="identifier">around</span> <span class="number">3.14</span>
|
||||||
|
</pre>
|
||||||
|
<p>
|
||||||
|
Note that <tt class="literal">name</tt> is exposed as <span class="bold"><b>read-only</b></span>
|
||||||
|
while <tt class="literal">value</tt> is exposed as <span class="bold"><b>read-write</b></span>.
|
||||||
|
</p>
|
||||||
|
<pre class="programlisting">
|
||||||
|
<span class="special">>>></span> <span class="identifier">x</span><span class="special">.</span><span class="identifier">name</span> <span class="special">=</span> <span class="string">'e'</span> <span class="comment"># can't change name
|
||||||
|
</span><span class="identifier">Traceback</span> <span class="special">(</span><span class="identifier">most</span> <span class="identifier">recent</span> <span class="identifier">call</span> <span class="identifier">last</span><span class="special">):</span>
|
||||||
|
<span class="identifier">File</span> <span class="string">"<stdin>"</span><span class="special">,</span> <span class="identifier">line</span> <span class="number">1</span><span class="special">,</span> <span class="keyword">in</span> #
|
||||||
|
<span class="identifier">AttributeError</span><span class="special">:</span> <span class="identifier">can</span>#<span class="identifier">t</span> <span class="identifier">set</span> <span class="identifier">attribute</span>
|
||||||
|
</pre>
|
||||||
|
</div>
|
||||||
|
<div class="section" lang="en">
|
||||||
|
<div class="titlepage"><div><div><h3 class="title">
|
||||||
|
<a name="python.class_properties"></a>Class Properties</h3></div></div></div>
|
||||||
|
<p>
|
||||||
|
Class PropertiesIn C++, classes with public data members are usually frowned
|
||||||
|
upon. Well designed classes that take advantage of encapsulation hide the
|
||||||
|
class' data members. The only way to access the class' data is through access
|
||||||
|
(getter/setter) functions. Access functions expose class properties. Here's
|
||||||
|
an example:
|
||||||
|
</p>
|
||||||
|
<p></p>
|
||||||
|
<pre class="programlisting">
|
||||||
|
<span class="keyword">struct</span> <span class="identifier">Num</span>
|
||||||
|
<span class="special">{</span>
|
||||||
|
<span class="identifier">Num</span><span class="special">();</span>
|
||||||
|
<span class="keyword">float</span> <span class="identifier">get</span><span class="special">()</span> <span class="keyword">const</span><span class="special">;</span>
|
||||||
|
<span class="keyword">void</span> <span class="identifier">set</span><span class="special">(</span><span class="keyword">float</span> <span class="identifier">value</span><span class="special">);</span>
|
||||||
|
<span class="special">...</span>
|
||||||
|
<span class="special">};</span>
|
||||||
|
</pre>
|
||||||
|
<p>
|
||||||
|
However, in Python attribute access is fine; it doesn't neccessarily break
|
||||||
|
encapsulation to let users handle attributes directly, because the attributes
|
||||||
|
can just be a different syntax for a method call. Wrapping our <tt class="literal">Num</tt>
|
||||||
|
class using Boost.Python:
|
||||||
|
</p>
|
||||||
|
<pre class="programlisting">
|
||||||
|
<span class="identifier">class_</span><span class="special"><</span><span class="identifier">Num</span><span class="special">>(</span><span class="string">"Num"</span><span class="special">)</span>
|
||||||
|
<span class="special">.</span><span class="identifier">add_property</span><span class="special">(</span><span class="string">"rovalue"</span><span class="special">,</span> <span class="special">&</span><span class="identifier">Num</span><span class="special">::</span><span class="identifier">get</span><span class="special">)</span>
|
||||||
|
<span class="special">.</span><span class="identifier">add_property</span><span class="special">(</span><span class="string">"value"</span><span class="special">,</span> <span class="special">&</span><span class="identifier">Num</span><span class="special">::</span><span class="identifier">get</span><span class="special">,</span> <span class="special">&</span><span class="identifier">Num</span><span class="special">::</span><span class="identifier">set</span><span class="special">);</span>
|
||||||
|
</pre>
|
||||||
|
<p>
|
||||||
|
And at last, in Python:
|
||||||
|
</p>
|
||||||
|
<p></p>
|
||||||
|
<pre class="programlisting">
|
||||||
|
<span class="special">>>></span> <span class="identifier">x</span> <span class="special">=</span> <span class="identifier">Num</span><span class="special">()</span>
|
||||||
|
<span class="special">>>></span> <span class="identifier">x</span><span class="special">.</span><span class="identifier">value</span> <span class="special">=</span> <span class="number">3.14</span>
|
||||||
|
<span class="special">>>></span> <span class="identifier">x</span><span class="special">.</span><span class="identifier">value</span><span class="special">,</span> <span class="identifier">x</span><span class="special">.</span><span class="identifier">rovalue</span>
|
||||||
|
<span class="special">(</span><span class="number">3.14</span><span class="special">,</span> <span class="number">3.14</span><span class="special">)</span>
|
||||||
|
<span class="special">>>></span> <span class="identifier">x</span><span class="special">.</span><span class="identifier">rovalue</span> <span class="special">=</span> <span class="number">2.17</span> <span class="comment"># error!
|
||||||
|
</span></pre>
|
||||||
|
<p>
|
||||||
|
Take note that the class property <tt class="literal">rovalue</tt> is exposed as
|
||||||
|
<span class="bold"><b>read-only</b></span> since the <tt class="literal">rovalue</tt>
|
||||||
|
setter member function is not passed in:
|
||||||
|
</p>
|
||||||
|
<p></p>
|
||||||
|
<pre class="programlisting">
|
||||||
|
<span class="special">.</span><span class="identifier">add_property</span><span class="special">(</span><span class="string">"rovalue"</span><span class="special">,</span> <span class="special">&</span><span class="identifier">Num</span><span class="special">::</span><span class="identifier">get</span><span class="special">)</span>
|
||||||
|
</pre>
|
||||||
|
</div>
|
||||||
|
<div class="section" lang="en">
|
||||||
|
<div class="titlepage"><div><div><h3 class="title">
|
||||||
|
<a name="python.inheritance"></a>Inheritance</h3></div></div></div>
|
||||||
|
<p>
|
||||||
|
InheritanceIn the previous examples, we dealt with classes that are not polymorphic.
|
||||||
|
This is not often the case. Much of the time, we will be wrapping polymorphic
|
||||||
|
classes and class hierarchies related by inheritance. We will often have
|
||||||
|
to write Boost.Python wrappers for classes that are derived from abstract
|
||||||
|
base classes.
|
||||||
|
</p>
|
||||||
|
<p>
|
||||||
|
Consider this trivial inheritance structure:
|
||||||
|
</p>
|
||||||
|
<pre class="programlisting">
|
||||||
|
<span class="keyword">struct</span> <span class="identifier">Base</span> <span class="special">{</span> <span class="keyword">virtual</span> <span class="special">~</span><span class="identifier">Base</span><span class="special">();</span> <span class="special">};</span>
|
||||||
|
<span class="keyword">struct</span> <span class="identifier">Derived</span> <span class="special">:</span> <span class="identifier">Base</span> <span class="special">{};</span>
|
||||||
|
</pre>
|
||||||
|
<p>
|
||||||
|
And a set of C++ functions operating on <tt class="literal">Base</tt> and <tt class="literal">Derived</tt>
|
||||||
|
object instances:
|
||||||
|
</p>
|
||||||
|
<pre class="programlisting">
|
||||||
|
<span class="keyword">void</span> <span class="identifier">b</span><span class="special">(</span><span class="identifier">Base</span><span class="special">*);</span>
|
||||||
|
<span class="keyword">void</span> <span class="identifier">d</span><span class="special">(</span><span class="identifier">Derived</span><span class="special">*);</span>
|
||||||
|
<span class="identifier">Base</span><span class="special">*</span> <span class="identifier">factory</span><span class="special">()</span> <span class="special">{</span> <span class="keyword">return</span> <span class="keyword">new</span> <span class="identifier">Derived</span><span class="special">;</span> <span class="special">}</span>
|
||||||
|
</pre>
|
||||||
|
<p>
|
||||||
|
We've seen how we can wrap the base class <tt class="literal">Base</tt>:
|
||||||
|
</p>
|
||||||
|
<pre class="programlisting">
|
||||||
|
<span class="identifier">class_</span><span class="special"><</span><span class="identifier">Base</span><span class="special">>(</span><span class="string">"Base"</span><span class="special">)</span>
|
||||||
|
<span class="comment">/*...*/</span>
|
||||||
|
<span class="special">;</span>
|
||||||
|
</pre>
|
||||||
|
<p>
|
||||||
|
Now we can inform Boost.Python of the inheritance relationship between <tt class="literal">Derived</tt>
|
||||||
|
and its base class <tt class="literal">Base</tt>. Thus:
|
||||||
|
</p>
|
||||||
|
<pre class="programlisting">
|
||||||
|
<span class="identifier">class_</span><span class="special"><</span><span class="identifier">Derived</span><span class="special">,</span> <span class="identifier">bases</span><span class="special"><</span><span class="identifier">Base</span><span class="special">></span> <span class="special">>(</span><span class="string">"Derived"</span><span class="special">)</span>
|
||||||
|
<span class="comment">/*...*/</span>
|
||||||
|
<span class="special">;</span>
|
||||||
|
</pre>
|
||||||
|
<p>
|
||||||
|
Doing so, we get some things for free:
|
||||||
|
</p>
|
||||||
|
<div class="orderedlist"><ol type="1">
|
||||||
|
<li>
|
||||||
|
Derived automatically inherits all of Base's Python methods (wrapped C++
|
||||||
|
member functions)
|
||||||
|
</li>
|
||||||
|
<li>
|
||||||
|
<span class="bold"><b>If</b></span> Base is polymorphic, <tt class="literal">Derived</tt>
|
||||||
|
objects which have been passed to Python via a pointer or reference to
|
||||||
|
<tt class="literal">Base</tt> can be passed where a pointer or reference to
|
||||||
|
<tt class="literal">Derived</tt> is expected.
|
||||||
|
</li>
|
||||||
|
</ol></div>
|
||||||
|
<p>
|
||||||
|
Now, we shall expose the C++ free functions <tt class="literal">b</tt> and <tt class="literal">d</tt>
|
||||||
|
and <tt class="literal">factory</tt>:
|
||||||
|
</p>
|
||||||
|
<pre class="programlisting">
|
||||||
|
<span class="identifier">def</span><span class="special">(</span><span class="string">"b"</span><span class="special">,</span> <span class="identifier">b</span><span class="special">);</span>
|
||||||
|
<span class="identifier">def</span><span class="special">(</span><span class="string">"d"</span><span class="special">,</span> <span class="identifier">d</span><span class="special">);</span>
|
||||||
|
<span class="identifier">def</span><span class="special">(</span><span class="string">"factory"</span><span class="special">,</span> <span class="identifier">factory</span><span class="special">);</span>
|
||||||
|
</pre>
|
||||||
|
<p>
|
||||||
|
Note that free function <tt class="literal">factory</tt> is being used to generate
|
||||||
|
new instances of class <tt class="literal">Derived</tt>. In such cases, we use
|
||||||
|
<tt class="literal">return_value_policy<manage_new_object></tt> to instruct
|
||||||
|
Python to adopt the pointer to <tt class="literal">Base</tt> and hold the instance
|
||||||
|
in a new Python <tt class="literal">Base</tt> object until the the Python object
|
||||||
|
is destroyed. We shall see more of Boost.Python <a href="functions.html#python.call_policies" title="Call Policies">call
|
||||||
|
policies</a> later.
|
||||||
|
</p>
|
||||||
|
<pre class="programlisting">
|
||||||
|
<span class="comment">// Tell Python to take ownership of factory's result
|
||||||
|
</span><span class="identifier">def</span><span class="special">(</span><span class="string">"factory"</span><span class="special">,</span> <span class="identifier">factory</span><span class="special">,</span>
|
||||||
|
<span class="identifier">return_value_policy</span><span class="special"><</span><span class="identifier">manage_new_object</span><span class="special">>());</span>
|
||||||
|
</pre>
|
||||||
|
</div>
|
||||||
|
<div class="section" lang="en">
|
||||||
|
<div class="titlepage"><div><div><h3 class="title">
|
||||||
|
<a name="python.class_virtual_functions"></a>Class Virtual Functions</h3></div></div></div>
|
||||||
|
<p>
|
||||||
|
Class Virtual FunctionsIn this section, we shall learn how to make functions
|
||||||
|
behave polymorphically through virtual functions. Continuing our example,
|
||||||
|
let us add a virtual function to our <tt class="literal">Base</tt> class:
|
||||||
|
</p>
|
||||||
|
<pre class="programlisting">
|
||||||
|
<span class="keyword">struct</span> <span class="identifier">Base</span>
|
||||||
|
<span class="special">{</span>
|
||||||
|
<span class="keyword">virtual</span> <span class="special">~</span><span class="identifier">Base</span><span class="special">()</span> <span class="special">{}</span>
|
||||||
|
<span class="keyword">virtual</span> <span class="keyword">int</span> <span class="identifier">f</span><span class="special">()</span> <span class="special">=</span> <span class="number">0</span><span class="special">;</span>
|
||||||
|
<span class="special">};</span>
|
||||||
|
</pre>
|
||||||
|
<p>
|
||||||
|
One of the goals of Boost.Python is to be minimally intrusive on an existing
|
||||||
|
C++ design. In principle, it should be possible to expose the interface for
|
||||||
|
a 3rd party library without changing it. It is not ideal to add anything
|
||||||
|
to our class <tt class="computeroutput"><span class="identifier">Base</span></tt>. Yet, when
|
||||||
|
you have a virtual function that's going to be overridden in Python and called
|
||||||
|
polymorphically <span class="bold"><b>from C++</b></span>, we'll need to
|
||||||
|
add some scaffoldings to make things work properly. What we'll do is write
|
||||||
|
a class wrapper that derives from <tt class="computeroutput"><span class="identifier">Base</span></tt>
|
||||||
|
that will unintrusively hook into the virtual functions so that a Python
|
||||||
|
override may be called:
|
||||||
|
</p>
|
||||||
|
<pre class="programlisting">
|
||||||
|
<span class="keyword">struct</span> <span class="identifier">BaseWrap</span> <span class="special">:</span> <span class="identifier">Base</span><span class="special">,</span> <span class="identifier">wrapper</span><span class="special"><</span><span class="identifier">Base</span><span class="special">></span>
|
||||||
|
<span class="special">{</span>
|
||||||
|
<span class="keyword">int</span> <span class="identifier">f</span><span class="special">()</span>
|
||||||
|
<span class="special">{</span>
|
||||||
|
<span class="keyword">return</span> <span class="keyword">this</span><span class="special">-></span><span class="identifier">get_override</span><span class="special">(</span><span class="string">"f"</span><span class="special">)();</span>
|
||||||
|
<span class="special">}</span>
|
||||||
|
<span class="special">};</span>
|
||||||
|
</pre>
|
||||||
|
<p>
|
||||||
|
Notice too that in addition to inheriting from <tt class="computeroutput"><span class="identifier">Base</span></tt>,
|
||||||
|
we also multiply- inherited <tt class="computeroutput"><span class="identifier">wrapper</span><span class="special"><</span><span class="identifier">Base</span><span class="special">></span></tt> (See <a href="../../../../v2/wrapper.html" target="_top">Wrapper</a>).
|
||||||
|
The <tt class="computeroutput"><span class="identifier">wrapper</span></tt> template makes
|
||||||
|
the job of wrapping classes that are meant to overridden in Python, easier.
|
||||||
|
</p>
|
||||||
|
<div class="informaltable"><table class="table">
|
||||||
|
<colgroup><col></colgroup>
|
||||||
|
<tbody><tr><td class="blurb">
|
||||||
|
<span class="inlinemediaobject"><img src="../images/alert.png"></span> <span class="bold"><b>MSVC6/7 Workaround</b></span><br><br> If you are using
|
||||||
|
Microsoft Visual C++ 6 or 7, you have to write <tt class="computeroutput"><span class="identifier">f</span></tt>
|
||||||
|
as:<br><br><tt class="computeroutput"><span class="keyword">return</span> <span class="identifier">call</span><span class="special"><</span><span class="keyword">int</span><span class="special">>(</span><span class="keyword">this</span><span class="special">-></span><span class="identifier">get_override</span><span class="special">(</span><span class="string">"f"</span><span class="special">).</span><span class="identifier">ptr</span><span class="special">());</span></tt>.</td></tr></tbody>
|
||||||
|
</table></div>
|
||||||
|
<p>
|
||||||
|
BaseWrap's overridden virtual member function <tt class="computeroutput"><span class="identifier">f</span></tt>
|
||||||
|
in effect calls the corresponding method of the Python object through <tt class="computeroutput"><span class="identifier">get_override</span></tt>.
|
||||||
|
</p>
|
||||||
|
<p>
|
||||||
|
Finally, exposing <tt class="computeroutput"><span class="identifier">Base</span></tt>:
|
||||||
|
</p>
|
||||||
|
<pre class="programlisting">
|
||||||
|
<span class="identifier">class_</span><span class="special"><</span><span class="identifier">BaseWrap</span><span class="special">,</span> <span class="identifier">boost</span><span class="special">::</span><span class="identifier">noncopyable</span><span class="special">>(</span><span class="string">"Base"</span><span class="special">)</span>
|
||||||
|
<span class="special">.</span><span class="identifier">def</span><span class="special">(</span><span class="string">"f"</span><span class="special">,</span> <span class="identifier">pure_virtual</span><span class="special">(&</span><span class="identifier">Base</span><span class="special">::</span><span class="identifier">f</span><span class="special">))</span>
|
||||||
|
<span class="special">;</span>
|
||||||
|
</pre>
|
||||||
|
<p><tt class="computeroutput"><span class="identifier">pure_virtual</span></tt> signals Boost.Python
|
||||||
|
that the function <tt class="computeroutput"><span class="identifier">f</span></tt> is a
|
||||||
|
pure virtual function.
|
||||||
|
</p>
|
||||||
|
<div class="informaltable"><table class="table">
|
||||||
|
<colgroup><col></colgroup>
|
||||||
|
<tbody><tr><td class="blurb">
|
||||||
|
<span class="inlinemediaobject"><img src="../images/note.png"></span> <span class="bold"><b>member function and methods</b></span><br><br> Python,
|
||||||
|
like many object oriented languages uses the term <span class="bold"><b>methods</b></span>.
|
||||||
|
Methods correspond roughly to C++'s <span class="bold"><b>member functions</b></span>
|
||||||
|
</td></tr></tbody>
|
||||||
|
</table></div>
|
||||||
|
</div>
|
||||||
|
<div class="section" lang="en">
|
||||||
|
<div class="titlepage"><div><div><h3 class="title">
|
||||||
|
<a name="python.virtual_functions_with_default_implementations"></a>Virtual Functions with Default Implementations</h3></div></div></div>
|
||||||
|
<p>
|
||||||
|
Virtual Functions with Default ImplementationsWe've seen in the previous
|
||||||
|
section how classes with pure virtual functions are wrapped using Boost.Python's
|
||||||
|
<a href="../../../../v2/wrapper.html" target="_top">class wrapper</a> facilities. If
|
||||||
|
we wish to wrap <span class="bold"><b>non</b></span>-pure-virtual functions
|
||||||
|
instead, the mechanism is a bit different.
|
||||||
|
</p>
|
||||||
|
<p>
|
||||||
|
Recall that in the <a href="exposing.html#python.class_virtual_functions" title="Class Virtual Functions">previous
|
||||||
|
section</a>, we wrapped a class with a pure virtual function that we then
|
||||||
|
implemented in C++, or Python classes derived from it. Our base class:
|
||||||
|
</p>
|
||||||
|
<pre class="programlisting">
|
||||||
|
<span class="keyword">struct</span> <span class="identifier">Base</span>
|
||||||
|
<span class="special">{</span>
|
||||||
|
<span class="keyword">virtual</span> <span class="keyword">int</span> <span class="identifier">f</span><span class="special">()</span> <span class="special">=</span> <span class="number">0</span><span class="special">;</span>
|
||||||
|
<span class="special">};</span>
|
||||||
|
</pre>
|
||||||
|
<p>
|
||||||
|
had a pure virtual function <tt class="literal">f</tt>. If, however, its member
|
||||||
|
function <tt class="literal">f</tt> was not declared as pure virtual:
|
||||||
|
</p>
|
||||||
|
<pre class="programlisting">
|
||||||
|
<span class="keyword">struct</span> <span class="identifier">Base</span>
|
||||||
|
<span class="special">{</span>
|
||||||
|
<span class="keyword">virtual</span> <span class="special">~</span><span class="identifier">Base</span><span class="special">()</span> <span class="special">{}</span>
|
||||||
|
<span class="keyword">virtual</span> <span class="keyword">int</span> <span class="identifier">f</span><span class="special">()</span> <span class="special">{</span> <span class="keyword">return</span> <span class="number">0</span><span class="special">;</span> <span class="special">}</span>
|
||||||
|
<span class="special">};</span>
|
||||||
|
</pre>
|
||||||
|
<p>
|
||||||
|
We wrap it this way:
|
||||||
|
</p>
|
||||||
|
<pre class="programlisting">
|
||||||
|
<span class="keyword">struct</span> <span class="identifier">BaseWrap</span> <span class="special">:</span> <span class="identifier">Base</span><span class="special">,</span> <span class="identifier">wrapper</span><span class="special"><</span><span class="identifier">Base</span><span class="special">></span>
|
||||||
|
<span class="special">{</span>
|
||||||
|
<span class="keyword">int</span> <span class="identifier">f</span><span class="special">()</span>
|
||||||
|
<span class="special">{</span>
|
||||||
|
<span class="keyword">if</span> <span class="special">(</span><span class="identifier">override</span> <span class="identifier">f</span> <span class="special">=</span> <span class="keyword">this</span><span class="special">-></span><span class="identifier">get_override</span><span class="special">(</span><span class="string">"f"</span><span class="special">))</span>
|
||||||
|
<span class="keyword">return</span> <span class="identifier">f</span><span class="special">();</span> <span class="comment">// *note*
|
||||||
|
</span> <span class="keyword">return</span> <span class="identifier">Base</span><span class="special">::</span><span class="identifier">f</span><span class="special">();</span>
|
||||||
|
<span class="special">}</span>
|
||||||
|
|
||||||
|
<span class="keyword">int</span> <span class="identifier">default_f</span><span class="special">()</span> <span class="special">{</span> <span class="keyword">return</span> <span class="keyword">this</span><span class="special">-></span><span class="identifier">Base</span><span class="special">::</span><span class="identifier">f</span><span class="special">();</span> <span class="special">}</span>
|
||||||
|
<span class="special">};</span>
|
||||||
|
</pre>
|
||||||
|
<p>
|
||||||
|
Notice how we implemented <tt class="computeroutput"><span class="identifier">BaseWrap</span><span class="special">::</span><span class="identifier">f</span></tt>. Now,
|
||||||
|
we have to check if there is an override for <tt class="computeroutput"><span class="identifier">f</span></tt>.
|
||||||
|
If none, then we call <tt class="computeroutput"><span class="identifier">Base</span><span class="special">::</span><span class="identifier">f</span><span class="special">()</span></tt>.
|
||||||
|
</p>
|
||||||
|
<div class="informaltable"><table class="table">
|
||||||
|
<colgroup><col></colgroup>
|
||||||
|
<tbody><tr><td class="blurb">
|
||||||
|
<span class="inlinemediaobject"><img src="../images/alert.png"></span> <span class="bold"><b>MSVC6/7 Workaround</b></span><br><br> If you are using
|
||||||
|
Microsoft Visual C++ 6 or 7, you have to rewrite the line with the
|
||||||
|
<tt class="computeroutput"><span class="special">*</span><span class="identifier">note</span><span class="special">*</span></tt> as:<br><br><tt class="computeroutput"><span class="keyword">return</span> <span class="identifier">call</span><span class="special"><</span><span class="keyword">char</span> <span class="keyword">const</span><span class="special">*>(</span><span class="identifier">f</span><span class="special">.</span><span class="identifier">ptr</span><span class="special">());</span></tt>.</td></tr></tbody>
|
||||||
|
</table></div>
|
||||||
|
<p>
|
||||||
|
Finally, exposing:
|
||||||
|
</p>
|
||||||
|
<pre class="programlisting">
|
||||||
|
<span class="identifier">class_</span><span class="special"><</span><span class="identifier">BaseWrap</span><span class="special">,</span> <span class="identifier">boost</span><span class="special">::</span><span class="identifier">noncopyable</span><span class="special">>(</span><span class="string">"Base"</span><span class="special">)</span>
|
||||||
|
<span class="special">.</span><span class="identifier">def</span><span class="special">(</span><span class="string">"f"</span><span class="special">,</span> <span class="special">&</span><span class="identifier">Base</span><span class="special">::</span><span class="identifier">f</span><span class="special">,</span> <span class="special">&</span><span class="identifier">BaseWrap</span><span class="special">::</span><span class="identifier">default_f</span><span class="special">)</span>
|
||||||
|
<span class="special">;</span>
|
||||||
|
</pre>
|
||||||
|
<p>
|
||||||
|
Take note that we expose both <tt class="computeroutput"><span class="special">&</span><span class="identifier">Base</span><span class="special">::</span><span class="identifier">f</span></tt> and <tt class="computeroutput"><span class="special">&</span><span class="identifier">BaseWrap</span><span class="special">::</span><span class="identifier">default_f</span></tt>. Boost.Python needs to keep track
|
||||||
|
of 1) the dispatch function <tt class="literal">f</tt> and 2) the forwarding function
|
||||||
|
to its default implementation <tt class="literal">default_f</tt>. There's a special
|
||||||
|
<tt class="literal">def</tt> function for this purpose.
|
||||||
|
</p>
|
||||||
|
<p>
|
||||||
|
In Python, the results would be as expected:
|
||||||
|
</p>
|
||||||
|
<p></p>
|
||||||
|
<pre class="programlisting">
|
||||||
|
<span class="special">>>></span> <span class="identifier">base</span> <span class="special">=</span> <span class="identifier">Base</span><span class="special">()</span>
|
||||||
|
<span class="special">>>></span> <span class="keyword">class</span> <span class="identifier">Derived</span><span class="special">(</span><span class="identifier">Base</span><span class="special">):</span>
|
||||||
|
<span class="special">...</span> <span class="keyword">def</span> <span class="identifier">f</span><span class="special">(</span><span class="identifier">self</span><span class="special">):</span>
|
||||||
|
<span class="special">...</span> <span class="keyword">return</span> <span class="number">42</span>
|
||||||
|
<span class="special">...</span>
|
||||||
|
<span class="special">>>></span> <span class="identifier">derived</span> <span class="special">=</span> <span class="identifier">Derived</span><span class="special">()</span>
|
||||||
|
</pre>
|
||||||
|
<p>
|
||||||
|
Calling <tt class="literal">base.f()</tt>:
|
||||||
|
</p>
|
||||||
|
<pre class="programlisting">
|
||||||
|
<span class="special">>>></span> <span class="identifier">base</span><span class="special">.</span><span class="identifier">f</span><span class="special">()</span>
|
||||||
|
<span class="number">0</span>
|
||||||
|
</pre>
|
||||||
|
<p>
|
||||||
|
Calling <tt class="literal">derived.f()</tt>:
|
||||||
|
</p>
|
||||||
|
<pre class="programlisting">
|
||||||
|
<span class="special">>>></span> <span class="identifier">derived</span><span class="special">.</span><span class="identifier">f</span><span class="special">()</span>
|
||||||
|
<span class="number">42</span>
|
||||||
|
</pre>
|
||||||
|
</div>
|
||||||
|
<div class="section" lang="en">
|
||||||
|
<div class="titlepage"><div><div><h3 class="title">
|
||||||
|
<a name="python.class_operators_special_functions"></a>Class Operators/Special Functions</h3></div></div></div>
|
||||||
|
<a name="class_operators_special_functions.class_operators_special_functionspython_operators"></a><h2>
|
||||||
|
<a name="id447955"></a>
|
||||||
|
Class Operators/Special FunctionsPython Operators
|
||||||
|
</h2>
|
||||||
|
<p>
|
||||||
|
C is well known for the abundance of operators. C++ extends this to the extremes
|
||||||
|
by allowing operator overloading. Boost.Python takes advantage of this and
|
||||||
|
makes it easy to wrap C++ operator-powered classes.
|
||||||
|
</p>
|
||||||
|
<p>
|
||||||
|
Consider a file position class <tt class="literal">FilePos</tt> and a set of operators
|
||||||
|
that take on FilePos instances:
|
||||||
|
</p>
|
||||||
|
<p></p>
|
||||||
|
<pre class="programlisting">
|
||||||
|
<span class="keyword">class</span> <span class="identifier">FilePos</span> <span class="special">{</span> <span class="comment">/*...*/</span> <span class="special">};</span>
|
||||||
|
|
||||||
|
<span class="identifier">FilePos</span> <span class="keyword">operator</span><span class="special">+(</span><span class="identifier">FilePos</span><span class="special">,</span> <span class="keyword">int</span><span class="special">);</span>
|
||||||
|
<span class="identifier">FilePos</span> <span class="keyword">operator</span><span class="special">+(</span><span class="keyword">int</span><span class="special">,</span> <span class="identifier">FilePos</span><span class="special">);</span>
|
||||||
|
<span class="keyword">int</span> <span class="keyword">operator</span><span class="special">-(</span><span class="identifier">FilePos</span><span class="special">,</span> <span class="identifier">FilePos</span><span class="special">);</span>
|
||||||
|
<span class="identifier">FilePos</span> <span class="keyword">operator</span><span class="special">-(</span><span class="identifier">FilePos</span><span class="special">,</span> <span class="keyword">int</span><span class="special">);</span>
|
||||||
|
<span class="identifier">FilePos</span><span class="special">&</span> <span class="keyword">operator</span><span class="special">+=(</span><span class="identifier">FilePos</span><span class="special">&,</span> <span class="keyword">int</span><span class="special">);</span>
|
||||||
|
<span class="identifier">FilePos</span><span class="special">&</span> <span class="keyword">operator</span><span class="special">-=(</span><span class="identifier">FilePos</span><span class="special">&,</span> <span class="keyword">int</span><span class="special">);</span>
|
||||||
|
<span class="keyword">bool</span> <span class="keyword">operator</span><span class="special"><(</span><span class="identifier">FilePos</span><span class="special">,</span> <span class="identifier">FilePos</span><span class="special">);</span>
|
||||||
|
</pre>
|
||||||
|
<p>
|
||||||
|
The class and the various operators can be mapped to Python rather easily
|
||||||
|
and intuitively:
|
||||||
|
</p>
|
||||||
|
<pre class="programlisting">
|
||||||
|
<span class="identifier">class_</span><span class="special"><</span><span class="identifier">FilePos</span><span class="special">>(</span><span class="string">"FilePos"</span><span class="special">)</span>
|
||||||
|
<span class="special">.</span><span class="identifier">def</span><span class="special">(</span><span class="identifier">self</span> <span class="special">+</span> <span class="keyword">int</span><span class="special">())</span> <span class="comment">// __add__
|
||||||
|
</span> <span class="special">.</span><span class="identifier">def</span><span class="special">(</span><span class="keyword">int</span><span class="special">()</span> <span class="special">+</span> <span class="identifier">self</span><span class="special">)</span> <span class="comment">// __radd__
|
||||||
|
</span> <span class="special">.</span><span class="identifier">def</span><span class="special">(</span><span class="identifier">self</span> <span class="special">-</span> <span class="identifier">self</span><span class="special">)</span> <span class="comment">// __sub__
|
||||||
|
</span> <span class="special">.</span><span class="identifier">def</span><span class="special">(</span><span class="identifier">self</span> <span class="special">-</span> <span class="keyword">int</span><span class="special">())</span> <span class="comment">// __sub__
|
||||||
|
</span> <span class="special">.</span><span class="identifier">def</span><span class="special">(</span><span class="identifier">self</span> <span class="special">+=</span> <span class="keyword">int</span><span class="special">())</span> <span class="comment">// __iadd__
|
||||||
|
</span> <span class="special">.</span><span class="identifier">def</span><span class="special">(</span><span class="identifier">self</span> <span class="special">-=</span> <span class="identifier">other</span><span class="special"><</span><span class="keyword">int</span><span class="special">>())</span>
|
||||||
|
<span class="special">.</span><span class="identifier">def</span><span class="special">(</span><span class="identifier">self</span> <span class="special"><</span> <span class="identifier">self</span><span class="special">);</span> <span class="comment">// __lt__
|
||||||
|
</span></pre>
|
||||||
|
<p>
|
||||||
|
The code snippet above is very clear and needs almost no explanation at all.
|
||||||
|
It is virtually the same as the operators' signatures. Just take note that
|
||||||
|
<tt class="literal">self</tt> refers to FilePos object. Also, not every class
|
||||||
|
<tt class="literal">T</tt> that you might need to interact with in an operator
|
||||||
|
expression is (cheaply) default-constructible. You can use <tt class="literal">other<T>()</tt>
|
||||||
|
in place of an actual <tt class="literal">T</tt> instance when writing "self
|
||||||
|
expressions".
|
||||||
|
</p>
|
||||||
|
<a name="class_operators_special_functions.special_methods"></a><h2>
|
||||||
|
<a name="id448698"></a>
|
||||||
|
Special Methods
|
||||||
|
</h2>
|
||||||
|
<p>
|
||||||
|
Python has a few more <span class="emphasis"><em>Special Methods</em></span>. Boost.Python
|
||||||
|
supports all of the standard special method names supported by real Python
|
||||||
|
class instances. A similar set of intuitive interfaces can also be used to
|
||||||
|
wrap C++ functions that correspond to these Python <span class="emphasis"><em>special functions</em></span>.
|
||||||
|
Example:
|
||||||
|
</p>
|
||||||
|
<pre class="programlisting">
|
||||||
|
<span class="keyword">class</span> <span class="identifier">Rational</span>
|
||||||
|
<span class="special">{</span> <span class="keyword">public</span><span class="special">:</span> <span class="keyword">operator</span> <span class="keyword">double</span><span class="special">()</span> <span class="keyword">const</span><span class="special">;</span> <span class="special">};</span>
|
||||||
|
|
||||||
|
<span class="identifier">Rational</span> <span class="identifier">pow</span><span class="special">(</span><span class="identifier">Rational</span><span class="special">,</span> <span class="identifier">Rational</span><span class="special">);</span>
|
||||||
|
<span class="identifier">Rational</span> <span class="identifier">abs</span><span class="special">(</span><span class="identifier">Rational</span><span class="special">);</span>
|
||||||
|
<span class="identifier">ostream</span><span class="special">&</span> <span class="keyword">operator</span><span class="special"><<(</span><span class="identifier">ostream</span><span class="special">&,</span><span class="identifier">Rational</span><span class="special">);</span>
|
||||||
|
|
||||||
|
<span class="identifier">class_</span><span class="special"><</span><span class="identifier">Rational</span><span class="special">>(</span><span class="string">"Rational"</span><span class="special">)</span>
|
||||||
|
<span class="special">.</span><span class="identifier">def</span><span class="special">(</span><span class="identifier">float_</span><span class="special">(</span><span class="identifier">self</span><span class="special">))</span> <span class="comment">// __float__
|
||||||
|
</span> <span class="special">.</span><span class="identifier">def</span><span class="special">(</span><span class="identifier">pow</span><span class="special">(</span><span class="identifier">self</span><span class="special">,</span> <span class="identifier">other</span><span class="special"><</span><span class="identifier">Rational</span><span class="special">>))</span> <span class="comment">// __pow__
|
||||||
|
</span> <span class="special">.</span><span class="identifier">def</span><span class="special">(</span><span class="identifier">abs</span><span class="special">(</span><span class="identifier">self</span><span class="special">))</span> <span class="comment">// __abs__
|
||||||
|
</span> <span class="special">.</span><span class="identifier">def</span><span class="special">(</span><span class="identifier">str</span><span class="special">(</span><span class="identifier">self</span><span class="special">))</span> <span class="comment">// __str__
|
||||||
|
</span> <span class="special">;</span>
|
||||||
|
</pre>
|
||||||
|
<p>
|
||||||
|
Need we say more?
|
||||||
|
</p>
|
||||||
|
<div class="informaltable"><table class="table">
|
||||||
|
<colgroup><col></colgroup>
|
||||||
|
<tbody><tr><td class="blurb">
|
||||||
|
<span class="inlinemediaobject"><img src="../images/note.png"></span>
|
||||||
|
What is the business of <tt class="computeroutput"><span class="keyword">operator</span><span class="special"><<</span></tt>? Well, the method <tt class="computeroutput"><span class="identifier">str</span></tt> requires the <tt class="computeroutput"><span class="keyword">operator</span><span class="special"><<</span></tt> to do its work (i.e. <tt class="computeroutput"><span class="keyword">operator</span><span class="special"><<</span></tt>
|
||||||
|
is used by the method defined by <tt class="computeroutput"><span class="identifier">def</span><span class="special">(</span><span class="identifier">str</span><span class="special">(</span><span class="identifier">self</span><span class="special">))</span></tt>.</td></tr></tbody>
|
||||||
|
</table></div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<table xmlns:rev="http://www.cs.rpi.edu/~gregod/boost/tools/doc/revision" width="100%"><tr>
|
||||||
|
<td align="left"></td>
|
||||||
|
<td align="right"><small>Copyright © 2002-2005 Joel
|
||||||
|
de Guzman, David Abrahams</small></td>
|
||||||
|
</tr></table>
|
||||||
|
<hr>
|
||||||
|
<div class="spirit-nav">
|
||||||
|
<a accesskey="p" href="hello.html"><img src="../images/prev.png" alt="Prev"></a><a accesskey="u" href="../index.html"><img src="../images/up.png" alt="Up"></a><a accesskey="h" href="../index.html"><img src="../images/home.png" alt="Home"></a><a accesskey="n" href="functions.html"><img src="../images/next.png" alt="Next"></a>
|
||||||
|
</div>
|
||||||
|
</body>
|
||||||
|
</html>
|
||||||
602
doc/tutorial/doc/html/python/functions.html
Normal file
@@ -0,0 +1,602 @@
|
|||||||
|
<html>
|
||||||
|
<head>
|
||||||
|
<meta http-equiv="Content-Type" content="text/html; charset=ISO-8859-1">
|
||||||
|
<title>Functions</title>
|
||||||
|
<link rel="stylesheet" href="../boostbook.css" type="text/css">
|
||||||
|
<meta name="generator" content="DocBook XSL Stylesheets V1.66.1">
|
||||||
|
<link rel="start" href="../index.html" title="Chapter 1. python 1.0">
|
||||||
|
<link rel="up" href="../index.html" title="Chapter 1. python 1.0">
|
||||||
|
<link rel="prev" href="exposing.html" title=" Exposing Classes">
|
||||||
|
<link rel="next" href="object.html" title=" Object Interface">
|
||||||
|
</head>
|
||||||
|
<body bgcolor="white" text="black" link="#0000FF" vlink="#840084" alink="#0000FF">
|
||||||
|
<table cellpadding="2" width="100%">
|
||||||
|
<td valign="top"><img alt="boost.png (6897 bytes)" width="277" height="86" src="../../../../../../../boost.png"></td>
|
||||||
|
<td align="center"><a href="../../../../../../../index.htm">Home</a></td>
|
||||||
|
<td align="center"><a href="../../../../../../../libs/libraries.htm">Libraries</a></td>
|
||||||
|
<td align="center"><a href="../../../../../../../people/people.htm">People</a></td>
|
||||||
|
<td align="center"><a href="../../../../../../../more/faq.htm">FAQ</a></td>
|
||||||
|
<td align="center"><a href="../../../../../../../more/index.htm">More</a></td>
|
||||||
|
</table>
|
||||||
|
<hr>
|
||||||
|
<div class="spirit-nav">
|
||||||
|
<a accesskey="p" href="exposing.html"><img src="../images/prev.png" alt="Prev"></a><a accesskey="u" href="../index.html"><img src="../images/up.png" alt="Up"></a><a accesskey="h" href="../index.html"><img src="../images/home.png" alt="Home"></a><a accesskey="n" href="object.html"><img src="../images/next.png" alt="Next"></a>
|
||||||
|
</div>
|
||||||
|
<div class="section" lang="en">
|
||||||
|
<div class="titlepage"><div><div><h2 class="title" style="clear: both">
|
||||||
|
<a name="python.functions"></a>Functions</h2></div></div></div>
|
||||||
|
<div class="toc"><dl>
|
||||||
|
<dt><span class="section"><a href="functions.html#python.call_policies">Call Policies</a></span></dt>
|
||||||
|
<dt><span class="section"><a href="functions.html#python.overloading">Overloading</a></span></dt>
|
||||||
|
<dt><span class="section"><a href="functions.html#python.default_arguments">Default Arguments</a></span></dt>
|
||||||
|
<dt><span class="section"><a href="functions.html#python.auto_overloading">Auto-Overloading</a></span></dt>
|
||||||
|
</dl></div>
|
||||||
|
<p>
|
||||||
|
FunctionsIn this chapter, we'll look at Boost.Python powered functions in closer
|
||||||
|
detail. We shall see some facilities to make exposing C++ functions to Python
|
||||||
|
safe from potential pifalls such as dangling pointers and references. We shall
|
||||||
|
also see facilities that will make it even easier for us to expose C++ functions
|
||||||
|
that take advantage of C++ features such as overloading and default arguments.
|
||||||
|
</p>
|
||||||
|
<div class="blockquote"><blockquote class="blockquote"><p><span class="emphasis"><em>Read on...</em></span></p></blockquote></div>
|
||||||
|
<p>
|
||||||
|
But before you do, you might want to fire up Python 2.2 or later and type
|
||||||
|
<tt class="literal">>>> import this</tt>.
|
||||||
|
</p>
|
||||||
|
<pre class="programlisting">>>> import this
|
||||||
|
The Zen of Python, by Tim Peters
|
||||||
|
Beautiful is better than ugly.
|
||||||
|
Explicit is better than implicit.
|
||||||
|
Simple is better than complex.
|
||||||
|
Complex is better than complicated.
|
||||||
|
Flat is better than nested.
|
||||||
|
Sparse is better than dense.
|
||||||
|
Readability counts.
|
||||||
|
Special cases aren't special enough to break the rules.
|
||||||
|
Although practicality beats purity.
|
||||||
|
Errors should never pass silently.
|
||||||
|
Unless explicitly silenced.
|
||||||
|
In the face of ambiguity, refuse the temptation to guess.
|
||||||
|
There should be one-- and preferably only one --obvious way to do it
|
||||||
|
Although that way may not be obvious at first unless you're Dutch.
|
||||||
|
Now is better than never.
|
||||||
|
Although never is often better than <span class="bold"><b>right</b></span> now.
|
||||||
|
If the implementation is hard to explain, it's a bad idea.
|
||||||
|
If the implementation is easy to explain, it may be a good idea.
|
||||||
|
Namespaces are one honking great idea -- let's do more of those!
|
||||||
|
</pre>
|
||||||
|
<div class="section" lang="en">
|
||||||
|
<div class="titlepage"><div><div><h3 class="title">
|
||||||
|
<a name="python.call_policies"></a>Call Policies</h3></div></div></div>
|
||||||
|
<p>
|
||||||
|
Call PoliciesIn C++, we often deal with arguments and return types such as
|
||||||
|
pointers and references. Such primitive types are rather, ummmm, low level
|
||||||
|
and they really don't tell us much. At the very least, we don't know the
|
||||||
|
owner of the pointer or the referenced object. No wonder languages such as
|
||||||
|
Java and Python never deal with such low level entities. In C++, it's usually
|
||||||
|
considered a good practice to use smart pointers which exactly describe ownership
|
||||||
|
semantics. Still, even good C++ interfaces use raw references and pointers
|
||||||
|
sometimes, so Boost.Python must deal with them. To do this, it may need your
|
||||||
|
help. Consider the following C++ function:
|
||||||
|
</p>
|
||||||
|
<pre class="programlisting">
|
||||||
|
<span class="identifier">X</span><span class="special">&</span> <span class="identifier">f</span><span class="special">(</span><span class="identifier">Y</span><span class="special">&</span> <span class="identifier">y</span><span class="special">,</span> <span class="identifier">Z</span><span class="special">*</span> <span class="identifier">z</span><span class="special">);</span>
|
||||||
|
</pre>
|
||||||
|
<p>
|
||||||
|
How should the library wrap this function? A naive approach builds a Python
|
||||||
|
X object around result reference. This strategy might or might not work out.
|
||||||
|
Here's an example where it didn't
|
||||||
|
</p>
|
||||||
|
<pre class="programlisting">
|
||||||
|
<span class="special">>>></span> <span class="identifier">x</span> <span class="special">=</span> <span class="identifier">f</span><span class="special">(</span><span class="identifier">y</span><span class="special">,</span> <span class="identifier">z</span><span class="special">)</span> # <span class="identifier">x</span> <span class="identifier">refers</span> <span class="identifier">to</span> <span class="identifier">some</span> <span class="identifier">C</span><span class="special">++</span> <span class="identifier">X</span>
|
||||||
|
<span class="special">>>></span> <span class="identifier">del</span> <span class="identifier">y</span>
|
||||||
|
<span class="special">>>></span> <span class="identifier">x</span><span class="special">.</span><span class="identifier">some_method</span><span class="special">()</span> # <span class="identifier">CRASH</span><span class="special">!</span>
|
||||||
|
</pre>
|
||||||
|
<p>
|
||||||
|
What's the problem?
|
||||||
|
</p>
|
||||||
|
<p>
|
||||||
|
Well, what if f() was implemented as shown below:
|
||||||
|
</p>
|
||||||
|
<pre class="programlisting">
|
||||||
|
<span class="identifier">X</span><span class="special">&</span> <span class="identifier">f</span><span class="special">(</span><span class="identifier">Y</span><span class="special">&</span> <span class="identifier">y</span><span class="special">,</span> <span class="identifier">Z</span><span class="special">*</span> <span class="identifier">z</span><span class="special">)</span>
|
||||||
|
<span class="special">{</span>
|
||||||
|
<span class="identifier">y</span><span class="special">.</span><span class="identifier">z</span> <span class="special">=</span> <span class="identifier">z</span><span class="special">;</span>
|
||||||
|
<span class="keyword">return</span> <span class="identifier">y</span><span class="special">.</span><span class="identifier">x</span><span class="special">;</span>
|
||||||
|
<span class="special">}</span>
|
||||||
|
</pre>
|
||||||
|
<p>
|
||||||
|
The problem is that the lifetime of result X& is tied to the lifetime
|
||||||
|
of y, because the f() returns a reference to a member of the y object. This
|
||||||
|
idiom is is not uncommon and perfectly acceptable in the context of C++.
|
||||||
|
However, Python users should not be able to crash the system just by using
|
||||||
|
our C++ interface. In this case deleting y will invalidate the reference
|
||||||
|
to X. We have a dangling reference.
|
||||||
|
</p>
|
||||||
|
<p>
|
||||||
|
Here's what's happening:
|
||||||
|
</p>
|
||||||
|
<div class="orderedlist"><ol type="1">
|
||||||
|
<li>
|
||||||
|
<tt class="literal">f</tt> is called passing in a reference to <tt class="literal">y</tt>
|
||||||
|
and a pointer to <tt class="literal">z</tt>
|
||||||
|
</li>
|
||||||
|
<li>
|
||||||
|
A reference to <tt class="literal">y.x</tt> is returned
|
||||||
|
</li>
|
||||||
|
<li>
|
||||||
|
<tt class="literal">y</tt> is deleted. <tt class="literal">x</tt> is a dangling reference
|
||||||
|
</li>
|
||||||
|
<li>
|
||||||
|
<tt class="literal">x.some_method()</tt> is called
|
||||||
|
</li>
|
||||||
|
<li><span class="bold"><b>BOOM!</b></span></li>
|
||||||
|
</ol></div>
|
||||||
|
<p>
|
||||||
|
We could copy result into a new object:
|
||||||
|
</p>
|
||||||
|
<p></p>
|
||||||
|
<pre class="programlisting">
|
||||||
|
<span class="special">>>></span> <span class="identifier">f</span><span class="special">(</span><span class="identifier">y</span><span class="special">,</span> <span class="identifier">z</span><span class="special">).</span><span class="identifier">set</span><span class="special">(</span><span class="number">42</span><span class="special">)</span> <span class="comment"># Result disappears
|
||||||
|
</span><span class="special">>>></span> <span class="identifier">y</span><span class="special">.</span><span class="identifier">x</span><span class="special">.</span><span class="identifier">get</span><span class="special">()</span> <span class="comment"># No crash, but still bad
|
||||||
|
</span><span class="number">3.14</span>
|
||||||
|
</pre>
|
||||||
|
<p>
|
||||||
|
This is not really our intent of our C++ interface. We've broken our promise
|
||||||
|
that the Python interface should reflect the C++ interface as closely as
|
||||||
|
possible.
|
||||||
|
</p>
|
||||||
|
<p>
|
||||||
|
Our problems do not end there. Suppose Y is implemented as follows:
|
||||||
|
</p>
|
||||||
|
<p></p>
|
||||||
|
<pre class="programlisting">
|
||||||
|
<span class="keyword">struct</span> <span class="identifier">Y</span>
|
||||||
|
<span class="special">{</span>
|
||||||
|
<span class="identifier">X</span> <span class="identifier">x</span><span class="special">;</span> <span class="identifier">Z</span><span class="special">*</span> <span class="identifier">z</span><span class="special">;</span>
|
||||||
|
<span class="keyword">int</span> <span class="identifier">z_value</span><span class="special">()</span> <span class="special">{</span> <span class="keyword">return</span> <span class="identifier">z</span><span class="special">-></span><span class="identifier">value</span><span class="special">();</span> <span class="special">}</span>
|
||||||
|
<span class="special">};</span>
|
||||||
|
</pre>
|
||||||
|
<p>
|
||||||
|
Notice that the data member <tt class="literal">z</tt> is held by class Y using
|
||||||
|
a raw pointer. Now we have a potential dangling pointer problem inside Y:
|
||||||
|
</p>
|
||||||
|
<pre class="programlisting">
|
||||||
|
<span class="special">>>></span> <span class="identifier">x</span> <span class="special">=</span> <span class="identifier">f</span><span class="special">(</span><span class="identifier">y</span><span class="special">,</span> <span class="identifier">z</span><span class="special">)</span> # <span class="identifier">y</span> <span class="identifier">refers</span> <span class="identifier">to</span> <span class="identifier">z</span>
|
||||||
|
<span class="special">>>></span> <span class="identifier">del</span> <span class="identifier">z</span> # <span class="identifier">Kill</span> <span class="identifier">the</span> <span class="identifier">z</span> <span class="identifier">object</span>
|
||||||
|
<span class="special">>>></span> <span class="identifier">y</span><span class="special">.</span><span class="identifier">z_value</span><span class="special">()</span> # <span class="identifier">CRASH</span><span class="special">!</span>
|
||||||
|
</pre>
|
||||||
|
<p>
|
||||||
|
For reference, here's the implementation of <tt class="literal">f</tt> again:
|
||||||
|
</p>
|
||||||
|
<pre class="programlisting">
|
||||||
|
<span class="identifier">X</span><span class="special">&</span> <span class="identifier">f</span><span class="special">(</span><span class="identifier">Y</span><span class="special">&</span> <span class="identifier">y</span><span class="special">,</span> <span class="identifier">Z</span><span class="special">*</span> <span class="identifier">z</span><span class="special">)</span>
|
||||||
|
<span class="special">{</span>
|
||||||
|
<span class="identifier">y</span><span class="special">.</span><span class="identifier">z</span> <span class="special">=</span> <span class="identifier">z</span><span class="special">;</span>
|
||||||
|
<span class="keyword">return</span> <span class="identifier">y</span><span class="special">.</span><span class="identifier">x</span><span class="special">;</span>
|
||||||
|
<span class="special">}</span>
|
||||||
|
</pre>
|
||||||
|
<p>
|
||||||
|
Here's what's happening:
|
||||||
|
</p>
|
||||||
|
<div class="orderedlist"><ol type="1">
|
||||||
|
<li>
|
||||||
|
<tt class="literal">f</tt> is called passing in a reference to <tt class="literal">y</tt>
|
||||||
|
and a pointer to <tt class="literal">z</tt>
|
||||||
|
</li>
|
||||||
|
<li>
|
||||||
|
A pointer to <tt class="literal">z</tt> is held by <tt class="literal">y</tt>
|
||||||
|
</li>
|
||||||
|
<li>
|
||||||
|
A reference to <tt class="literal">y.x</tt> is returned
|
||||||
|
</li>
|
||||||
|
<li>
|
||||||
|
<tt class="literal">z</tt> is deleted. <tt class="literal">y.z</tt> is a dangling pointer
|
||||||
|
</li>
|
||||||
|
<li>
|
||||||
|
<tt class="literal">y.z_value()</tt> is called
|
||||||
|
</li>
|
||||||
|
<li>
|
||||||
|
<tt class="literal">z->value()</tt> is called
|
||||||
|
</li>
|
||||||
|
<li><span class="bold"><b>BOOM!</b></span></li>
|
||||||
|
</ol></div>
|
||||||
|
<a name="call_policies.call_policies"></a><h2>
|
||||||
|
<a name="id450599"></a>
|
||||||
|
Call Policies
|
||||||
|
</h2>
|
||||||
|
<p>
|
||||||
|
Call Policies may be used in situations such as the example detailed above.
|
||||||
|
In our example, <tt class="literal">return_internal_reference</tt> and <tt class="literal">with_custodian_and_ward</tt>
|
||||||
|
are our friends:
|
||||||
|
</p>
|
||||||
|
<pre class="programlisting">
|
||||||
|
<span class="identifier">def</span><span class="special">(</span><span class="string">"f"</span><span class="special">,</span> <span class="identifier">f</span><span class="special">,</span>
|
||||||
|
<span class="identifier">return_internal_reference</span><span class="special"><</span><span class="number">1</span><span class="special">,</span>
|
||||||
|
<span class="identifier">with_custodian_and_ward</span><span class="special"><</span><span class="number">1</span><span class="special">,</span> <span class="number">2</span><span class="special">></span> <span class="special">>());</span>
|
||||||
|
</pre>
|
||||||
|
<p>
|
||||||
|
What are the <tt class="literal">1</tt> and <tt class="literal">2</tt> parameters, you
|
||||||
|
ask?
|
||||||
|
</p>
|
||||||
|
<pre class="programlisting">
|
||||||
|
<span class="identifier">return_internal_reference</span><span class="special"><</span><span class="number">1</span>
|
||||||
|
</pre>
|
||||||
|
<p>
|
||||||
|
Informs Boost.Python that the first argument, in our case <tt class="literal">Y&
|
||||||
|
y</tt>, is the owner of the returned reference: <tt class="literal">X&</tt>.
|
||||||
|
The "<tt class="literal">1</tt>" simply specifies the first argument.
|
||||||
|
In short: "return an internal reference <tt class="literal">X&</tt> owned
|
||||||
|
by the 1st argument <tt class="literal">Y& y</tt>".
|
||||||
|
</p>
|
||||||
|
<pre class="programlisting">
|
||||||
|
<span class="identifier">with_custodian_and_ward</span><span class="special"><</span><span class="number">1</span><span class="special">,</span> <span class="number">2</span><span class="special">></span>
|
||||||
|
</pre>
|
||||||
|
<p>
|
||||||
|
Informs Boost.Python that the lifetime of the argument indicated by ward
|
||||||
|
(i.e. the 2nd argument: <tt class="literal">Z* z</tt>) is dependent on the lifetime
|
||||||
|
of the argument indicated by custodian (i.e. the 1st argument: <tt class="literal">Y&
|
||||||
|
y</tt>).
|
||||||
|
</p>
|
||||||
|
<p>
|
||||||
|
It is also important to note that we have defined two policies above. Two
|
||||||
|
or more policies can be composed by chaining. Here's the general syntax:
|
||||||
|
</p>
|
||||||
|
<pre class="programlisting">
|
||||||
|
<span class="identifier">policy1</span><span class="special"><</span><span class="identifier">args</span><span class="special">...,</span>
|
||||||
|
<span class="identifier">policy2</span><span class="special"><</span><span class="identifier">args</span><span class="special">...,</span>
|
||||||
|
<span class="identifier">policy3</span><span class="special"><</span><span class="identifier">args</span><span class="special">...></span> <span class="special">></span> <span class="special">></span>
|
||||||
|
</pre>
|
||||||
|
<p>
|
||||||
|
Here is the list of predefined call policies. A complete reference detailing
|
||||||
|
these can be found <a href="../../../../v2/reference.html#models_of_call_policies" target="_top">here</a>.
|
||||||
|
</p>
|
||||||
|
<div class="itemizedlist"><ul type="disc">
|
||||||
|
<li>
|
||||||
|
<span class="bold"><b>with_custodian_and_ward</b></span><br> Ties lifetimes
|
||||||
|
of the arguments
|
||||||
|
</li>
|
||||||
|
<li>
|
||||||
|
<span class="bold"><b>with_custodian_and_ward_postcall</b></span><br>
|
||||||
|
Ties lifetimes of the arguments and results
|
||||||
|
</li>
|
||||||
|
<li>
|
||||||
|
<span class="bold"><b>return_internal_reference</b></span><br> Ties lifetime
|
||||||
|
of one argument to that of result
|
||||||
|
</li>
|
||||||
|
<li>
|
||||||
|
<span class="bold"><b>return_value_policy<T> with T one of:</b></span><br>
|
||||||
|
</li>
|
||||||
|
<li>
|
||||||
|
<span class="bold"><b>reference_existing_object</b></span><br> naive
|
||||||
|
(dangerous) approach
|
||||||
|
</li>
|
||||||
|
<li>
|
||||||
|
<span class="bold"><b>copy_const_reference</b></span><br> Boost.Python
|
||||||
|
v1 approach
|
||||||
|
</li>
|
||||||
|
<li>
|
||||||
|
<span class="bold"><b>copy_non_const_reference</b></span><br>
|
||||||
|
</li>
|
||||||
|
<li>
|
||||||
|
<span class="bold"><b>manage_new_object</b></span><br> Adopt a pointer
|
||||||
|
and hold the instance
|
||||||
|
</li>
|
||||||
|
</ul></div>
|
||||||
|
<div class="informaltable"><table class="table">
|
||||||
|
<colgroup><col></colgroup>
|
||||||
|
<tbody><tr><td class="blurb">
|
||||||
|
<span class="inlinemediaobject"><img src="../images/smiley.png"></span> <span class="bold"><b>Remember the Zen, Luke:</b></span><br><br> "Explicit
|
||||||
|
is better than implicit"<br> "In the face of ambiguity,
|
||||||
|
refuse the temptation to guess"<br>
|
||||||
|
</td></tr></tbody>
|
||||||
|
</table></div>
|
||||||
|
</div>
|
||||||
|
<div class="section" lang="en">
|
||||||
|
<div class="titlepage"><div><div><h3 class="title">
|
||||||
|
<a name="python.overloading"></a>Overloading</h3></div></div></div>
|
||||||
|
<p>
|
||||||
|
OverloadingThe following illustrates a scheme for manually wrapping an overloaded
|
||||||
|
member functions. Of course, the same technique can be applied to wrapping
|
||||||
|
overloaded non-member functions.
|
||||||
|
</p>
|
||||||
|
<p>
|
||||||
|
We have here our C++ class:
|
||||||
|
</p>
|
||||||
|
<pre class="programlisting">
|
||||||
|
<span class="keyword">struct</span> <span class="identifier">X</span>
|
||||||
|
<span class="special">{</span>
|
||||||
|
<span class="keyword">bool</span> <span class="identifier">f</span><span class="special">(</span><span class="keyword">int</span> <span class="identifier">a</span><span class="special">)</span>
|
||||||
|
<span class="special">{</span>
|
||||||
|
<span class="keyword">return</span> <span class="keyword">true</span><span class="special">;</span>
|
||||||
|
<span class="special">}</span>
|
||||||
|
|
||||||
|
<span class="keyword">bool</span> <span class="identifier">f</span><span class="special">(</span><span class="keyword">int</span> <span class="identifier">a</span><span class="special">,</span> <span class="keyword">double</span> <span class="identifier">b</span><span class="special">)</span>
|
||||||
|
<span class="special">{</span>
|
||||||
|
<span class="keyword">return</span> <span class="keyword">true</span><span class="special">;</span>
|
||||||
|
<span class="special">}</span>
|
||||||
|
|
||||||
|
<span class="keyword">bool</span> <span class="identifier">f</span><span class="special">(</span><span class="keyword">int</span> <span class="identifier">a</span><span class="special">,</span> <span class="keyword">double</span> <span class="identifier">b</span><span class="special">,</span> <span class="keyword">char</span> <span class="identifier">c</span><span class="special">)</span>
|
||||||
|
<span class="special">{</span>
|
||||||
|
<span class="keyword">return</span> <span class="keyword">true</span><span class="special">;</span>
|
||||||
|
<span class="special">}</span>
|
||||||
|
|
||||||
|
<span class="keyword">int</span> <span class="identifier">f</span><span class="special">(</span><span class="keyword">int</span> <span class="identifier">a</span><span class="special">,</span> <span class="keyword">int</span> <span class="identifier">b</span><span class="special">,</span> <span class="keyword">int</span> <span class="identifier">c</span><span class="special">)</span>
|
||||||
|
<span class="special">{</span>
|
||||||
|
<span class="keyword">return</span> <span class="identifier">a</span> <span class="special">+</span> <span class="identifier">b</span> <span class="special">+</span> <span class="identifier">c</span><span class="special">;</span>
|
||||||
|
<span class="special">};</span>
|
||||||
|
<span class="special">};</span>
|
||||||
|
</pre>
|
||||||
|
<p>
|
||||||
|
Class X has 4 overloaded functions. We shall start by introducing some member
|
||||||
|
function pointer variables:
|
||||||
|
</p>
|
||||||
|
<pre class="programlisting">
|
||||||
|
<span class="keyword">bool</span> <span class="special">(</span><span class="identifier">X</span><span class="special">::*</span><span class="identifier">fx1</span><span class="special">)(</span><span class="keyword">int</span><span class="special">)</span> <span class="special">=</span> <span class="special">&</span><span class="identifier">X</span><span class="special">::</span><span class="identifier">f</span><span class="special">;</span>
|
||||||
|
<span class="keyword">bool</span> <span class="special">(</span><span class="identifier">X</span><span class="special">::*</span><span class="identifier">fx2</span><span class="special">)(</span><span class="keyword">int</span><span class="special">,</span> <span class="keyword">double</span><span class="special">)</span> <span class="special">=</span> <span class="special">&</span><span class="identifier">X</span><span class="special">::</span><span class="identifier">f</span><span class="special">;</span>
|
||||||
|
<span class="keyword">bool</span> <span class="special">(</span><span class="identifier">X</span><span class="special">::*</span><span class="identifier">fx3</span><span class="special">)(</span><span class="keyword">int</span><span class="special">,</span> <span class="keyword">double</span><span class="special">,</span> <span class="keyword">char</span><span class="special">)=</span> <span class="special">&</span><span class="identifier">X</span><span class="special">::</span><span class="identifier">f</span><span class="special">;</span>
|
||||||
|
<span class="keyword">int</span> <span class="special">(</span><span class="identifier">X</span><span class="special">::*</span><span class="identifier">fx4</span><span class="special">)(</span><span class="keyword">int</span><span class="special">,</span> <span class="keyword">int</span><span class="special">,</span> <span class="keyword">int</span><span class="special">)</span> <span class="special">=</span> <span class="special">&</span><span class="identifier">X</span><span class="special">::</span><span class="identifier">f</span><span class="special">;</span>
|
||||||
|
</pre>
|
||||||
|
<p>
|
||||||
|
With these in hand, we can proceed to define and wrap this for Python:
|
||||||
|
</p>
|
||||||
|
<pre class="programlisting">
|
||||||
|
<span class="special">.</span><span class="identifier">def</span><span class="special">(</span><span class="string">"f"</span><span class="special">,</span> <span class="identifier">fx1</span><span class="special">)</span>
|
||||||
|
<span class="special">.</span><span class="identifier">def</span><span class="special">(</span><span class="string">"f"</span><span class="special">,</span> <span class="identifier">fx2</span><span class="special">)</span>
|
||||||
|
<span class="special">.</span><span class="identifier">def</span><span class="special">(</span><span class="string">"f"</span><span class="special">,</span> <span class="identifier">fx3</span><span class="special">)</span>
|
||||||
|
<span class="special">.</span><span class="identifier">def</span><span class="special">(</span><span class="string">"f"</span><span class="special">,</span> <span class="identifier">fx4</span><span class="special">)</span>
|
||||||
|
</pre>
|
||||||
|
</div>
|
||||||
|
<div class="section" lang="en">
|
||||||
|
<div class="titlepage"><div><div><h3 class="title">
|
||||||
|
<a name="python.default_arguments"></a>Default Arguments</h3></div></div></div>
|
||||||
|
<p>
|
||||||
|
Default ArgumentsBoost.Python wraps (member) function pointers. Unfortunately,
|
||||||
|
C++ function pointers carry no default argument info. Take a function <tt class="literal">f</tt>
|
||||||
|
with default arguments:
|
||||||
|
</p>
|
||||||
|
<pre class="programlisting">
|
||||||
|
<span class="keyword">int</span> <span class="identifier">f</span><span class="special">(</span><span class="keyword">int</span><span class="special">,</span> <span class="keyword">double</span> <span class="special">=</span> <span class="number">3.14</span><span class="special">,</span> <span class="keyword">char</span> <span class="keyword">const</span><span class="special">*</span> <span class="special">=</span> <span class="string">"hello"</span><span class="special">);</span>
|
||||||
|
</pre>
|
||||||
|
<p>
|
||||||
|
But the type of a pointer to the function <tt class="literal">f</tt> has no information
|
||||||
|
about its default arguments:
|
||||||
|
</p>
|
||||||
|
<pre class="programlisting">
|
||||||
|
<span class="keyword">int</span><span class="special">(*</span><span class="identifier">g</span><span class="special">)(</span><span class="keyword">int</span><span class="special">,</span><span class="keyword">double</span><span class="special">,</span><span class="keyword">char</span> <span class="keyword">const</span><span class="special">*)</span> <span class="special">=</span> <span class="identifier">f</span><span class="special">;</span> <span class="comment">// defaults lost!
|
||||||
|
</span></pre>
|
||||||
|
<p>
|
||||||
|
When we pass this function pointer to the <tt class="literal">def</tt> function,
|
||||||
|
there is no way to retrieve the default arguments:
|
||||||
|
</p>
|
||||||
|
<pre class="programlisting">
|
||||||
|
<span class="identifier">def</span><span class="special">(</span><span class="string">"f"</span><span class="special">,</span> <span class="identifier">f</span><span class="special">);</span> <span class="comment">// defaults lost!
|
||||||
|
</span></pre>
|
||||||
|
<p>
|
||||||
|
Because of this, when wrapping C++ code, we had to resort to manual wrapping
|
||||||
|
as outlined in the <a href="functions.html#python.overloading" title="Overloading">previous section</a>,
|
||||||
|
or writing thin wrappers:
|
||||||
|
</p>
|
||||||
|
<pre class="programlisting">
|
||||||
|
<span class="comment">// write "thin wrappers"
|
||||||
|
</span><span class="keyword">int</span> <span class="identifier">f1</span><span class="special">(</span><span class="keyword">int</span> <span class="identifier">x</span><span class="special">)</span> <span class="special">{</span> <span class="identifier">f</span><span class="special">(</span><span class="identifier">x</span><span class="special">);</span> <span class="special">}</span>
|
||||||
|
<span class="keyword">int</span> <span class="identifier">f2</span><span class="special">(</span><span class="keyword">int</span> <span class="identifier">x</span><span class="special">,</span> <span class="keyword">double</span> <span class="identifier">y</span><span class="special">)</span> <span class="special">{</span> <span class="identifier">f</span><span class="special">(</span><span class="identifier">x</span><span class="special">,</span><span class="identifier">y</span><span class="special">);</span> <span class="special">}</span>
|
||||||
|
|
||||||
|
<span class="comment">/*...*/</span>
|
||||||
|
|
||||||
|
<span class="comment">// in module init
|
||||||
|
</span> <span class="identifier">def</span><span class="special">(</span><span class="string">"f"</span><span class="special">,</span> <span class="identifier">f</span><span class="special">);</span> <span class="comment">// all arguments
|
||||||
|
</span> <span class="identifier">def</span><span class="special">(</span><span class="string">"f"</span><span class="special">,</span> <span class="identifier">f2</span><span class="special">);</span> <span class="comment">// two arguments
|
||||||
|
</span> <span class="identifier">def</span><span class="special">(</span><span class="string">"f"</span><span class="special">,</span> <span class="identifier">f1</span><span class="special">);</span> <span class="comment">// one argument
|
||||||
|
</span></pre>
|
||||||
|
<p>
|
||||||
|
When you want to wrap functions (or member functions) that either:
|
||||||
|
</p>
|
||||||
|
<div class="itemizedlist"><ul type="disc">
|
||||||
|
<li>
|
||||||
|
have default arguments, or
|
||||||
|
</li>
|
||||||
|
<li>
|
||||||
|
are overloaded with a common sequence of initial arguments
|
||||||
|
</li>
|
||||||
|
</ul></div>
|
||||||
|
<a name="default_arguments.boost_python_function_overloads"></a><h2>
|
||||||
|
<a name="id452559"></a>
|
||||||
|
BOOST_PYTHON_FUNCTION_OVERLOADS
|
||||||
|
</h2>
|
||||||
|
<p>
|
||||||
|
Boost.Python now has a way to make it easier. For instance, given a function:
|
||||||
|
</p>
|
||||||
|
<pre class="programlisting">
|
||||||
|
<span class="keyword">int</span> <span class="identifier">foo</span><span class="special">(</span><span class="keyword">int</span> <span class="identifier">a</span><span class="special">,</span> <span class="keyword">char</span> <span class="identifier">b</span> <span class="special">=</span> <span class="number">1</span><span class="special">,</span> <span class="keyword">unsigned</span> <span class="identifier">c</span> <span class="special">=</span> <span class="number">2</span><span class="special">,</span> <span class="keyword">double</span> <span class="identifier">d</span> <span class="special">=</span> <span class="number">3</span><span class="special">)</span>
|
||||||
|
<span class="special">{</span>
|
||||||
|
<span class="comment">/*...*/</span>
|
||||||
|
<span class="special">}</span>
|
||||||
|
</pre>
|
||||||
|
<p>
|
||||||
|
The macro invocation:
|
||||||
|
</p>
|
||||||
|
<pre class="programlisting">
|
||||||
|
<span class="identifier">BOOST_PYTHON_FUNCTION_OVERLOADS</span><span class="special">(</span><span class="identifier">foo_overloads</span><span class="special">,</span> <span class="identifier">foo</span><span class="special">,</span> <span class="number">1</span><span class="special">,</span> <span class="number">4</span><span class="special">)</span>
|
||||||
|
</pre>
|
||||||
|
<p>
|
||||||
|
will automatically create the thin wrappers for us. This macro will create
|
||||||
|
a class <tt class="literal">foo_overloads</tt> that can be passed on to <tt class="literal">def(...)</tt>.
|
||||||
|
The third and fourth macro argument are the minimum arguments and maximum
|
||||||
|
arguments, respectively. In our <tt class="literal">foo</tt> function the minimum
|
||||||
|
number of arguments is 1 and the maximum number of arguments is 4. The <tt class="literal">def(...)</tt>
|
||||||
|
function will automatically add all the foo variants for us:
|
||||||
|
</p>
|
||||||
|
<pre class="programlisting">
|
||||||
|
<span class="identifier">def</span><span class="special">(</span><span class="string">"foo"</span><span class="special">,</span> <span class="identifier">foo</span><span class="special">,</span> <span class="identifier">foo_overloads</span><span class="special">());</span>
|
||||||
|
</pre>
|
||||||
|
<a name="default_arguments.boost_python_member_function_overloads"></a><h2>
|
||||||
|
<a name="id452863"></a>
|
||||||
|
BOOST_PYTHON_MEMBER_FUNCTION_OVERLOADS
|
||||||
|
</h2>
|
||||||
|
<p>
|
||||||
|
Objects here, objects there, objects here there everywhere. More frequently
|
||||||
|
than anything else, we need to expose member functions of our classes to
|
||||||
|
Python. Then again, we have the same inconveniences as before when default
|
||||||
|
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 class="literal">BOOST_PYTHON_FUNCTION_OVERLOADS</tt>, <tt class="literal">BOOST_PYTHON_MEMBER_FUNCTION_OVERLOADS</tt>
|
||||||
|
may be used to automatically create the thin wrappers for wrapping member
|
||||||
|
functions. Let's have an example:
|
||||||
|
</p>
|
||||||
|
<pre class="programlisting">
|
||||||
|
<span class="keyword">struct</span> <span class="identifier">george</span>
|
||||||
|
<span class="special">{</span>
|
||||||
|
<span class="keyword">void</span>
|
||||||
|
<span class="identifier">wack_em</span><span class="special">(</span><span class="keyword">int</span> <span class="identifier">a</span><span class="special">,</span> <span class="keyword">int</span> <span class="identifier">b</span> <span class="special">=</span> <span class="number">0</span><span class="special">,</span> <span class="keyword">char</span> <span class="identifier">c</span> <span class="special">=</span> <span class="char">'x'</span><span class="special">)</span>
|
||||||
|
<span class="special">{</span>
|
||||||
|
<span class="comment">/*...*/</span>
|
||||||
|
<span class="special">}</span>
|
||||||
|
<span class="special">};</span>
|
||||||
|
</pre>
|
||||||
|
<p>
|
||||||
|
The macro invocation:
|
||||||
|
</p>
|
||||||
|
<pre class="programlisting">
|
||||||
|
<span class="identifier">BOOST_PYTHON_MEMBER_FUNCTION_OVERLOADS</span><span class="special">(</span><span class="identifier">george_overloads</span><span class="special">,</span> <span class="identifier">wack_em</span><span class="special">,</span> <span class="number">1</span><span class="special">,</span> <span class="number">3</span><span class="special">)</span>
|
||||||
|
</pre>
|
||||||
|
<p>
|
||||||
|
will generate a set of thin wrappers for george's <tt class="literal">wack_em</tt>
|
||||||
|
member function accepting a minimum of 1 and a maximum of 3 arguments (i.e.
|
||||||
|
the third and fourth macro argument). The thin wrappers are all enclosed
|
||||||
|
in a class named <tt class="literal">george_overloads</tt> that can then be used
|
||||||
|
as an argument to <tt class="literal">def(...)</tt>:
|
||||||
|
</p>
|
||||||
|
<pre class="programlisting">
|
||||||
|
<span class="special">.</span><span class="identifier">def</span><span class="special">(</span><span class="string">"wack_em"</span><span class="special">,</span> <span class="special">&</span><span class="identifier">george</span><span class="special">::</span><span class="identifier">wack_em</span><span class="special">,</span> <span class="identifier">george_overloads</span><span class="special">());</span>
|
||||||
|
</pre>
|
||||||
|
<p>
|
||||||
|
See the <a href="../../../../v2/overloads.html#BOOST_PYTHON_FUNCTION_OVERLOADS-spec" target="_top">overloads
|
||||||
|
reference</a> for details.
|
||||||
|
</p>
|
||||||
|
<a name="default_arguments.init_and_optional"></a><h2>
|
||||||
|
<a name="id453212"></a>
|
||||||
|
init and optional
|
||||||
|
</h2>
|
||||||
|
<p>
|
||||||
|
A similar facility is provided for class constructors, again, with default
|
||||||
|
arguments or a sequence of overloads. Remember <tt class="literal">init<...></tt>?
|
||||||
|
For example, given a class X with a constructor:
|
||||||
|
</p>
|
||||||
|
<pre class="programlisting">
|
||||||
|
<span class="keyword">struct</span> <span class="identifier">X</span>
|
||||||
|
<span class="special">{</span>
|
||||||
|
<span class="identifier">X</span><span class="special">(</span><span class="keyword">int</span> <span class="identifier">a</span><span class="special">,</span> <span class="keyword">char</span> <span class="identifier">b</span> <span class="special">=</span> <span class="char">'D'</span><span class="special">,</span> <span class="identifier">std</span><span class="special">::</span><span class="identifier">string</span> <span class="identifier">c</span> <span class="special">=</span> <span class="string">"constructor"</span><span class="special">,</span> <span class="keyword">double</span> <span class="identifier">d</span> <span class="special">=</span> <span class="number">0.0</span><span class="special">);</span>
|
||||||
|
<span class="comment">/*...*/</span>
|
||||||
|
<span class="special">}</span>
|
||||||
|
</pre>
|
||||||
|
<p>
|
||||||
|
You can easily add this constructor to Boost.Python in one shot:
|
||||||
|
</p>
|
||||||
|
<pre class="programlisting">
|
||||||
|
<span class="special">.</span><span class="identifier">def</span><span class="special">(</span><span class="identifier">init</span><span class="special"><</span><span class="keyword">int</span><span class="special">,</span> <span class="identifier">optional</span><span class="special"><</span><span class="keyword">char</span><span class="special">,</span> <span class="identifier">std</span><span class="special">::</span><span class="identifier">string</span><span class="special">,</span> <span class="keyword">double</span><span class="special">></span> <span class="special">>())</span>
|
||||||
|
</pre>
|
||||||
|
<p>
|
||||||
|
Notice the use of <tt class="literal">init<...></tt> and <tt class="literal">optional<...></tt>
|
||||||
|
to signify the default (optional arguments).
|
||||||
|
</p>
|
||||||
|
</div>
|
||||||
|
<div class="section" lang="en">
|
||||||
|
<div class="titlepage"><div><div><h3 class="title">
|
||||||
|
<a name="python.auto_overloading"></a>Auto-Overloading</h3></div></div></div>
|
||||||
|
<p>
|
||||||
|
Auto-OverloadingIt was mentioned in passing in the previous section that
|
||||||
|
<tt class="literal">BOOST_PYTHON_FUNCTION_OVERLOADS</tt> and <tt class="literal">BOOST_PYTHON_MEMBER_FUNCTION_OVERLOADS</tt>
|
||||||
|
can also be used for overloaded functions and member functions with a common
|
||||||
|
sequence of initial arguments. Here is an example:
|
||||||
|
</p>
|
||||||
|
<pre class="programlisting">
|
||||||
|
<span class="keyword">void</span> <span class="identifier">foo</span><span class="special">()</span>
|
||||||
|
<span class="special">{</span>
|
||||||
|
<span class="comment">/*...*/</span>
|
||||||
|
<span class="special">}</span>
|
||||||
|
|
||||||
|
<span class="keyword">void</span> <span class="identifier">foo</span><span class="special">(</span><span class="keyword">bool</span> <span class="identifier">a</span><span class="special">)</span>
|
||||||
|
<span class="special">{</span>
|
||||||
|
<span class="comment">/*...*/</span>
|
||||||
|
<span class="special">}</span>
|
||||||
|
|
||||||
|
<span class="keyword">void</span> <span class="identifier">foo</span><span class="special">(</span><span class="keyword">bool</span> <span class="identifier">a</span><span class="special">,</span> <span class="keyword">int</span> <span class="identifier">b</span><span class="special">)</span>
|
||||||
|
<span class="special">{</span>
|
||||||
|
<span class="comment">/*...*/</span>
|
||||||
|
<span class="special">}</span>
|
||||||
|
|
||||||
|
<span class="keyword">void</span> <span class="identifier">foo</span><span class="special">(</span><span class="keyword">bool</span> <span class="identifier">a</span><span class="special">,</span> <span class="keyword">int</span> <span class="identifier">b</span><span class="special">,</span> <span class="keyword">char</span> <span class="identifier">c</span><span class="special">)</span>
|
||||||
|
<span class="special">{</span>
|
||||||
|
<span class="comment">/*...*/</span>
|
||||||
|
<span class="special">}</span>
|
||||||
|
</pre>
|
||||||
|
<p>
|
||||||
|
Like in the previous section, we can generate thin wrappers for these overloaded
|
||||||
|
functions in one-shot:
|
||||||
|
</p>
|
||||||
|
<pre class="programlisting">
|
||||||
|
<span class="identifier">BOOST_PYTHON_FUNCTION_OVERLOADS</span><span class="special">(</span><span class="identifier">foo_overloads</span><span class="special">,</span> <span class="identifier">foo</span><span class="special">,</span> <span class="number">0</span><span class="special">,</span> <span class="number">3</span><span class="special">)</span>
|
||||||
|
</pre>
|
||||||
|
<p>
|
||||||
|
Then...
|
||||||
|
</p>
|
||||||
|
<pre class="programlisting">
|
||||||
|
<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>
|
||||||
|
</pre>
|
||||||
|
<p>
|
||||||
|
Notice though that we have a situation now where we have a minimum of zero
|
||||||
|
(0) arguments and a maximum of 3 arguments.
|
||||||
|
</p>
|
||||||
|
<a name="auto_overloading.manual_wrapping"></a><h2>
|
||||||
|
<a name="id453917"></a>
|
||||||
|
Manual Wrapping
|
||||||
|
</h2>
|
||||||
|
<p>
|
||||||
|
It is important to emphasize however that <span class="bold"><b>the overloaded
|
||||||
|
functions must have a common sequence of initial arguments</b></span>. Otherwise,
|
||||||
|
our scheme above will not work. If this is not the case, we have to wrap
|
||||||
|
our functions <a href="functions.html#python.overloading" title="Overloading">manually</a>.
|
||||||
|
</p>
|
||||||
|
<p>
|
||||||
|
Actually, we can mix and match manual wrapping of overloaded functions and
|
||||||
|
automatic wrapping through <tt class="literal">BOOST_PYTHON_MEMBER_FUNCTION_OVERLOADS</tt>
|
||||||
|
and its sister, <tt class="literal">BOOST_PYTHON_FUNCTION_OVERLOADS</tt>. Following
|
||||||
|
up on our example presented in the section <a href="functions.html#python.overloading" title="Overloading">on
|
||||||
|
overloading</a>, since the first 4 overload functins have a common sequence
|
||||||
|
of initial arguments, we can use <tt class="literal">BOOST_PYTHON_MEMBER_FUNCTION_OVERLOADS</tt>
|
||||||
|
to automatically wrap the first three of the <tt class="literal">def</tt>s and
|
||||||
|
manually wrap just the last. Here's how we'll do this:
|
||||||
|
</p>
|
||||||
|
<pre class="programlisting">
|
||||||
|
<span class="identifier">BOOST_PYTHON_MEMBER_FUNCTION_OVERLOADS</span><span class="special">(</span><span class="identifier">xf_overloads</span><span class="special">,</span> <span class="identifier">f</span><span class="special">,</span> <span class="number">1</span><span class="special">,</span> <span class="number">4</span><span class="special">)</span>
|
||||||
|
</pre>
|
||||||
|
<p>
|
||||||
|
Create a member function pointers as above for both X::f overloads:
|
||||||
|
</p>
|
||||||
|
<pre class="programlisting">
|
||||||
|
<span class="keyword">bool</span> <span class="special">(</span><span class="identifier">X</span><span class="special">::*</span><span class="identifier">fx1</span><span class="special">)(</span><span class="keyword">int</span><span class="special">,</span> <span class="keyword">double</span><span class="special">,</span> <span class="keyword">char</span><span class="special">)</span> <span class="special">=</span> <span class="special">&</span><span class="identifier">X</span><span class="special">::</span><span class="identifier">f</span><span class="special">;</span>
|
||||||
|
<span class="keyword">int</span> <span class="special">(</span><span class="identifier">X</span><span class="special">::*</span><span class="identifier">fx2</span><span class="special">)(</span><span class="keyword">int</span><span class="special">,</span> <span class="keyword">int</span><span class="special">,</span> <span class="keyword">int</span><span class="special">)</span> <span class="special">=</span> <span class="special">&</span><span class="identifier">X</span><span class="special">::</span><span class="identifier">f</span><span class="special">;</span>
|
||||||
|
</pre>
|
||||||
|
<p>
|
||||||
|
Then...
|
||||||
|
</p>
|
||||||
|
<pre class="programlisting">
|
||||||
|
<span class="special">.</span><span class="identifier">def</span><span class="special">(</span><span class="string">"f"</span><span class="special">,</span> <span class="identifier">fx1</span><span class="special">,</span> <span class="identifier">xf_overloads</span><span class="special">());</span>
|
||||||
|
<span class="special">.</span><span class="identifier">def</span><span class="special">(</span><span class="string">"f"</span><span class="special">,</span> <span class="identifier">fx2</span><span class="special">)</span>
|
||||||
|
</pre>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<table xmlns:rev="http://www.cs.rpi.edu/~gregod/boost/tools/doc/revision" width="100%"><tr>
|
||||||
|
<td align="left"></td>
|
||||||
|
<td align="right"><small>Copyright © 2002-2005 Joel
|
||||||
|
de Guzman, David Abrahams</small></td>
|
||||||
|
</tr></table>
|
||||||
|
<hr>
|
||||||
|
<div class="spirit-nav">
|
||||||
|
<a accesskey="p" href="exposing.html"><img src="../images/prev.png" alt="Prev"></a><a accesskey="u" href="../index.html"><img src="../images/up.png" alt="Up"></a><a accesskey="h" href="../index.html"><img src="../images/home.png" alt="Home"></a><a accesskey="n" href="object.html"><img src="../images/next.png" alt="Next"></a>
|
||||||
|
</div>
|
||||||
|
</body>
|
||||||
|
</html>
|
||||||
282
doc/tutorial/doc/html/python/hello.html
Normal file
@@ -0,0 +1,282 @@
|
|||||||
|
<html>
|
||||||
|
<head>
|
||||||
|
<meta http-equiv="Content-Type" content="text/html; charset=ISO-8859-1">
|
||||||
|
<title> Building Hello World</title>
|
||||||
|
<link rel="stylesheet" href="../boostbook.css" type="text/css">
|
||||||
|
<meta name="generator" content="DocBook XSL Stylesheets V1.66.1">
|
||||||
|
<link rel="start" href="../index.html" title="Chapter 1. python 1.0">
|
||||||
|
<link rel="up" href="../index.html" title="Chapter 1. python 1.0">
|
||||||
|
<link rel="prev" href="../index.html" title="Chapter 1. python 1.0">
|
||||||
|
<link rel="next" href="exposing.html" title=" Exposing Classes">
|
||||||
|
</head>
|
||||||
|
<body bgcolor="white" text="black" link="#0000FF" vlink="#840084" alink="#0000FF">
|
||||||
|
<table cellpadding="2" width="100%">
|
||||||
|
<td valign="top"><img alt="boost.png (6897 bytes)" width="277" height="86" src="../../../../../../../boost.png"></td>
|
||||||
|
<td align="center"><a href="../../../../../../../index.htm">Home</a></td>
|
||||||
|
<td align="center"><a href="../../../../../../../libs/libraries.htm">Libraries</a></td>
|
||||||
|
<td align="center"><a href="../../../../../../../people/people.htm">People</a></td>
|
||||||
|
<td align="center"><a href="../../../../../../../more/faq.htm">FAQ</a></td>
|
||||||
|
<td align="center"><a href="../../../../../../../more/index.htm">More</a></td>
|
||||||
|
</table>
|
||||||
|
<hr>
|
||||||
|
<div class="spirit-nav">
|
||||||
|
<a accesskey="p" href="../index.html"><img src="../images/prev.png" alt="Prev"></a><a accesskey="u" href="../index.html"><img src="../images/up.png" alt="Up"></a><a accesskey="h" href="../index.html"><img src="../images/home.png" alt="Home"></a><a accesskey="n" href="exposing.html"><img src="../images/next.png" alt="Next"></a>
|
||||||
|
</div>
|
||||||
|
<div class="section" lang="en">
|
||||||
|
<div class="titlepage"><div><div><h2 class="title" style="clear: both">
|
||||||
|
<a name="python.hello"></a> Building Hello World</h2></div></div></div>
|
||||||
|
<a name="hello._building_hello_worldfrom_start_to_finish"></a><h2>
|
||||||
|
<a name="id442456"></a>
|
||||||
|
Building Hello WorldFrom Start To Finish
|
||||||
|
</h2>
|
||||||
|
<p>
|
||||||
|
Now the first thing you'd want to do is to build the Hello World module and
|
||||||
|
try it for yourself in Python. In this section, we shall outline the steps
|
||||||
|
necessary to achieve that. We shall use the build tool that comes bundled with
|
||||||
|
every boost distribution: <span class="bold"><b>bjam</b></span>.
|
||||||
|
</p>
|
||||||
|
<div class="informaltable"><table class="table">
|
||||||
|
<colgroup><col></colgroup>
|
||||||
|
<tbody><tr><td class="blurb">
|
||||||
|
<span class="inlinemediaobject"><img src="../images/note.png"></span> <span class="bold"><b>Building without bjam</b></span><br><br> Besides bjam,
|
||||||
|
there are of course other ways to get your module built. What's written
|
||||||
|
here should not be taken as "the one and only way". There are
|
||||||
|
of course other build tools apart from <tt class="literal">bjam</tt>.<br><br> Take note however that the preferred build tool for Boost.Python
|
||||||
|
is bjam. There are so many ways to set up the build incorrectly. Experience
|
||||||
|
shows that 90% of the "I can't build Boost.Python" problems
|
||||||
|
come from people who had to use a different tool. </td></tr></tbody>
|
||||||
|
</table></div>
|
||||||
|
<p>
|
||||||
|
We shall skip over the details. Our objective will be to simply create the
|
||||||
|
hello world module and run it in Python. For a complete reference to building
|
||||||
|
Boost.Python, check out: <a href="../../../../building.html" target="_top">building.html</a>.
|
||||||
|
After this brief <span class="emphasis"><em>bjam</em></span> tutorial, we should have built two
|
||||||
|
DLLs:
|
||||||
|
</p>
|
||||||
|
<div class="itemizedlist"><ul type="disc">
|
||||||
|
<li>
|
||||||
|
boost_python.dll
|
||||||
|
</li>
|
||||||
|
<li>
|
||||||
|
hello.pyd
|
||||||
|
</li>
|
||||||
|
</ul></div>
|
||||||
|
<p>
|
||||||
|
if you are on Windows, and
|
||||||
|
</p>
|
||||||
|
<div class="itemizedlist"><ul type="disc">
|
||||||
|
<li>
|
||||||
|
libboost_python.so
|
||||||
|
</li>
|
||||||
|
<li>
|
||||||
|
hello.so
|
||||||
|
</li>
|
||||||
|
</ul></div>
|
||||||
|
<p>
|
||||||
|
if you are on Unix.
|
||||||
|
</p>
|
||||||
|
<p>
|
||||||
|
The tutorial example can be found in the directory: <tt class="literal">libs/python/example/tutorial</tt>.
|
||||||
|
There, you can find:
|
||||||
|
</p>
|
||||||
|
<div class="itemizedlist"><ul type="disc">
|
||||||
|
<li>
|
||||||
|
hello.cpp
|
||||||
|
</li>
|
||||||
|
<li>
|
||||||
|
Jamfile
|
||||||
|
</li>
|
||||||
|
</ul></div>
|
||||||
|
<p>
|
||||||
|
The <tt class="literal">hello.cpp</tt> file is our C++ hello world example. The
|
||||||
|
<tt class="literal">Jamfile</tt> is a minimalist <span class="emphasis"><em>bjam</em></span> script
|
||||||
|
that builds the DLLs for us.
|
||||||
|
</p>
|
||||||
|
<p>
|
||||||
|
Before anything else, you should have the bjam executable in your boost directory
|
||||||
|
or somewhere in your path such that <tt class="literal">bjam</tt> can be executed
|
||||||
|
in the command line. Pre-built Boost.Jam executables are available for most
|
||||||
|
platforms. The complete list of Bjam executables can be found <a href="http://sourceforge.net/project/showfiles.php?group_id=7586" target="_top">here</a>.
|
||||||
|
</p>
|
||||||
|
<a name="hello.let_s_jam_"></a><h2>
|
||||||
|
<a name="id373799"></a>
|
||||||
|
Let's Jam!
|
||||||
|
</h2>
|
||||||
|
<p><span class="inlinemediaobject"><img src="../images/jam.png"></span></p>
|
||||||
|
<p>
|
||||||
|
Here is our minimalist Jamfile:
|
||||||
|
</p>
|
||||||
|
<pre class="programlisting"># This is the top of our own project tree
|
||||||
|
project-root ;
|
||||||
|
|
||||||
|
import python ;
|
||||||
|
|
||||||
|
extension hello # Declare a Python extension called hello
|
||||||
|
: hello.cpp # source
|
||||||
|
# requirements and dependencies for Boost.Python extensions
|
||||||
|
<template>@boost/libs/python/build/extension
|
||||||
|
;
|
||||||
|
</pre>
|
||||||
|
<p>
|
||||||
|
First, we need to specify our location. You may place your project anywhere.
|
||||||
|
<tt class="literal">project-root</tt> allows you to do that.
|
||||||
|
</p>
|
||||||
|
<pre class="programlisting">project-root ;
|
||||||
|
</pre>
|
||||||
|
<p>
|
||||||
|
By doing so, you'll need a Jamrules file. Simply copy the one in the <a href="../../../../../example/tutorial/Jamrules" target="_top">example/tutorial directory</a>
|
||||||
|
and tweak the <tt class="literal">path-global BOOST_ROOT</tt> to where your boost
|
||||||
|
root directory is. The file has <a href="../../../../../example/tutorial/Jamrules" target="_top">detailed
|
||||||
|
instructions</a> you can follow.
|
||||||
|
</p>
|
||||||
|
<p>
|
||||||
|
Then we will import the definitions needed by Python modules:
|
||||||
|
</p>
|
||||||
|
<pre class="programlisting">import python ;
|
||||||
|
</pre>
|
||||||
|
<p>
|
||||||
|
Finally we declare our <tt class="literal">hello</tt> extension:
|
||||||
|
</p>
|
||||||
|
<pre class="programlisting">extension hello # Declare a Python extension called hello
|
||||||
|
: hello.cpp # source
|
||||||
|
|
||||||
|
# requirements and dependencies for Boost.Python extensions
|
||||||
|
<template>@boost/libs/python/build/extension
|
||||||
|
;
|
||||||
|
</pre>
|
||||||
|
<p>
|
||||||
|
The last part tells BJam that we are depending on the Boost Python Library.
|
||||||
|
</p>
|
||||||
|
<a name="hello.running_bjam"></a><h2>
|
||||||
|
<a name="id373910"></a>
|
||||||
|
Running bjam
|
||||||
|
</h2>
|
||||||
|
<p><span class="emphasis"><em>bjam</em></span> is run using your operating system's command line
|
||||||
|
interpreter.
|
||||||
|
</p>
|
||||||
|
<div class="blockquote"><blockquote class="blockquote"><p>
|
||||||
|
Start it up.
|
||||||
|
</p></blockquote></div>
|
||||||
|
<p>
|
||||||
|
Make sure that the environment is set so that we can invoke the C++ compiler.
|
||||||
|
With MSVC, that would mean running the <tt class="literal">Vcvars32.bat</tt> batch
|
||||||
|
file. For instance:
|
||||||
|
</p>
|
||||||
|
<pre class="programlisting">C:\Program Files\Microsoft Visual Studio .NET 2003\Common7\Tools\vsvars32.bat
|
||||||
|
</pre>
|
||||||
|
<p>
|
||||||
|
Some environment variables will have to be setup for proper building of our
|
||||||
|
Python modules. Example:
|
||||||
|
</p>
|
||||||
|
<pre class="programlisting">set PYTHON_ROOT=c:/dev/tools/python
|
||||||
|
set PYTHON_VERSION=2.2
|
||||||
|
</pre>
|
||||||
|
<p>
|
||||||
|
The above assumes that the Python installation is in <tt class="literal">c:/dev/tools/python</tt>
|
||||||
|
and that we are using Python version 2.2. You'll have to tweak these appropriately.
|
||||||
|
</p>
|
||||||
|
<div class="informaltable"><table class="table">
|
||||||
|
<colgroup><col></colgroup>
|
||||||
|
<tbody><tr><td class="blurb">
|
||||||
|
<span class="inlinemediaobject"><img src="../images/tip.png"></span>
|
||||||
|
Be sure not to include a third number, e.g. <span class="bold"><b>not</b></span>
|
||||||
|
"2.2.1", even if that's the version you have.</td></tr></tbody>
|
||||||
|
</table></div>
|
||||||
|
<p>
|
||||||
|
Take note that you may also do that through the Jamrules file we put in our
|
||||||
|
project as detailed above. The file has <a href="../../../../../example/tutorial/Jamrules" target="_top">detailed
|
||||||
|
instructions</a> you can follow.
|
||||||
|
</p>
|
||||||
|
<p>
|
||||||
|
Now we are ready... Be sure to <tt class="literal">cd</tt> to <tt class="literal">libs/python/example/tutorial</tt>
|
||||||
|
where the tutorial <tt class="literal">"hello.cpp"</tt> and the <tt class="literal">"Jamfile"</tt>
|
||||||
|
is situated.
|
||||||
|
</p>
|
||||||
|
<p>
|
||||||
|
Finally:
|
||||||
|
</p>
|
||||||
|
<pre class="programlisting">
|
||||||
|
<span class="identifier">bjam</span> <span class="special">-</span><span class="identifier">sTOOLS</span><span class="special">=</span><span class="identifier">vc</span><span class="special">-</span><span class="number">7</span><span class="identifier">_1</span>
|
||||||
|
</pre>
|
||||||
|
<p>
|
||||||
|
We are again assuming that we are using Microsoft Visual C++ version 7.1. If
|
||||||
|
not, then you will have to specify the appropriate tool. See <a href="../../../../../../../tools/build/index.html" target="_top">Building
|
||||||
|
Boost Libraries</a> for further details.
|
||||||
|
</p>
|
||||||
|
<p>
|
||||||
|
It should be building now:
|
||||||
|
</p>
|
||||||
|
<pre class="programlisting">cd C:\dev\boost\libs\python\example\tutorial
|
||||||
|
bjam -sTOOLS=msvc
|
||||||
|
...patience...
|
||||||
|
...found 1703 targets...
|
||||||
|
...updating 40 targets...
|
||||||
|
</pre>
|
||||||
|
<p>
|
||||||
|
And so on... Finally:
|
||||||
|
</p>
|
||||||
|
<pre class="programlisting">Creating library bin\boost\libs\python\build\boost_python.dll\vc-7_1\debug\th
|
||||||
|
reading-multi\boost_python.lib and object bin\boost\libs\python\build\boost_pyth
|
||||||
|
on.dll\vc-7_1\debug\threading-multi\boost_python.exp
|
||||||
|
vc-C++ bin\tutorial\hello.pyd\vc-7_1\debug\threading-multi\hello.obj
|
||||||
|
hello.cpp
|
||||||
|
vc-Link bin\tutorial\hello.pyd\vc-7_1\debug\threading-multi\hello.pyd bin\tutori
|
||||||
|
al\hello.pyd\vc-7_1\debug\threading-multi\hello.lib
|
||||||
|
Creating library bin\tutorial\hello.pyd\vc-7_1\debug\threading-multi\hello.li
|
||||||
|
b and object bin\tutorial\hello.pyd\vc-7_1\debug\threading-multi\hello.exp
|
||||||
|
...updated 31 targets...
|
||||||
|
</pre>
|
||||||
|
<p>
|
||||||
|
If all is well, you should now have:
|
||||||
|
</p>
|
||||||
|
<div class="itemizedlist"><ul type="disc">
|
||||||
|
<li>
|
||||||
|
boost_python.dll
|
||||||
|
</li>
|
||||||
|
<li>
|
||||||
|
hello.pyd
|
||||||
|
</li>
|
||||||
|
</ul></div>
|
||||||
|
<p>
|
||||||
|
if you are on Windows, and
|
||||||
|
</p>
|
||||||
|
<div class="itemizedlist"><ul type="disc">
|
||||||
|
<li>
|
||||||
|
libboost_python.so
|
||||||
|
</li>
|
||||||
|
<li>
|
||||||
|
hello.so
|
||||||
|
</li>
|
||||||
|
</ul></div>
|
||||||
|
<p>
|
||||||
|
if you are on Unix.
|
||||||
|
</p>
|
||||||
|
<p><tt class="literal">boost_python.dll</tt> and <tt class="literal">hello.pyd</tt> can be
|
||||||
|
found somewhere in your project's <tt class="literal">bin</tt> directory. After a
|
||||||
|
successful build, you can just link in these DLLs with the Python interpreter.
|
||||||
|
In Windows for example, you can simply put these libraries inside the directory
|
||||||
|
where the Python executable is.
|
||||||
|
</p>
|
||||||
|
<p>
|
||||||
|
You may now fire up Python and run our hello module:
|
||||||
|
</p>
|
||||||
|
<p></p>
|
||||||
|
<pre class="programlisting">
|
||||||
|
<span class="special">>>></span> <span class="keyword">import</span> <span class="identifier">hello</span>
|
||||||
|
<span class="special">>>></span> <span class="keyword">print</span> <span class="identifier">hello</span><span class="special">.</span><span class="identifier">greet</span><span class="special">()</span>
|
||||||
|
<span class="identifier">hello</span><span class="special">,</span> <span class="identifier">world</span>
|
||||||
|
</pre>
|
||||||
|
<p></p>
|
||||||
|
<div class="blockquote"><blockquote class="blockquote"><p><span class="bold"><b>There you go... Have fun!</b></span></p></blockquote></div>
|
||||||
|
</div>
|
||||||
|
<table xmlns:rev="http://www.cs.rpi.edu/~gregod/boost/tools/doc/revision" width="100%"><tr>
|
||||||
|
<td align="left"></td>
|
||||||
|
<td align="right"><small>Copyright © 2002-2005 Joel
|
||||||
|
de Guzman, David Abrahams</small></td>
|
||||||
|
</tr></table>
|
||||||
|
<hr>
|
||||||
|
<div class="spirit-nav">
|
||||||
|
<a accesskey="p" href="../index.html"><img src="../images/prev.png" alt="Prev"></a><a accesskey="u" href="../index.html"><img src="../images/up.png" alt="Up"></a><a accesskey="h" href="../index.html"><img src="../images/home.png" alt="Home"></a><a accesskey="n" href="exposing.html"><img src="../images/next.png" alt="Next"></a>
|
||||||
|
</div>
|
||||||
|
</body>
|
||||||
|
</html>
|
||||||
185
doc/tutorial/doc/html/python/iterators.html
Normal file
@@ -0,0 +1,185 @@
|
|||||||
|
<html>
|
||||||
|
<head>
|
||||||
|
<meta http-equiv="Content-Type" content="text/html; charset=ISO-8859-1">
|
||||||
|
<title>Iterators</title>
|
||||||
|
<link rel="stylesheet" href="../boostbook.css" type="text/css">
|
||||||
|
<meta name="generator" content="DocBook XSL Stylesheets V1.66.1">
|
||||||
|
<link rel="start" href="../index.html" title="Chapter 1. python 1.0">
|
||||||
|
<link rel="up" href="../index.html" title="Chapter 1. python 1.0">
|
||||||
|
<link rel="prev" href="embedding.html" title="Embedding">
|
||||||
|
<link rel="next" href="exception.html" title=" Exception Translation">
|
||||||
|
</head>
|
||||||
|
<body bgcolor="white" text="black" link="#0000FF" vlink="#840084" alink="#0000FF">
|
||||||
|
<table cellpadding="2" width="100%">
|
||||||
|
<td valign="top"><img alt="boost.png (6897 bytes)" width="277" height="86" src="../../../../../../../boost.png"></td>
|
||||||
|
<td align="center"><a href="../../../../../../../index.htm">Home</a></td>
|
||||||
|
<td align="center"><a href="../../../../../../../libs/libraries.htm">Libraries</a></td>
|
||||||
|
<td align="center"><a href="../../../../../../../people/people.htm">People</a></td>
|
||||||
|
<td align="center"><a href="../../../../../../../more/faq.htm">FAQ</a></td>
|
||||||
|
<td align="center"><a href="../../../../../../../more/index.htm">More</a></td>
|
||||||
|
</table>
|
||||||
|
<hr>
|
||||||
|
<div class="spirit-nav">
|
||||||
|
<a accesskey="p" href="embedding.html"><img src="../images/prev.png" alt="Prev"></a><a accesskey="u" href="../index.html"><img src="../images/up.png" alt="Up"></a><a accesskey="h" href="../index.html"><img src="../images/home.png" alt="Home"></a><a accesskey="n" href="exception.html"><img src="../images/next.png" alt="Next"></a>
|
||||||
|
</div>
|
||||||
|
<div class="section" lang="en">
|
||||||
|
<div class="titlepage"><div><div><h2 class="title" style="clear: both">
|
||||||
|
<a name="python.iterators"></a>Iterators</h2></div></div></div>
|
||||||
|
<p>
|
||||||
|
IteratorsIn C++, and STL in particular, we see iterators everywhere. Python
|
||||||
|
also has iterators, but these are two very different beasts.
|
||||||
|
</p>
|
||||||
|
<p><span class="bold"><b>C++ iterators:</b></span></p>
|
||||||
|
<div class="itemizedlist"><ul type="disc">
|
||||||
|
<li>
|
||||||
|
C++ has 5 type categories (random-access, bidirectional, forward, input,
|
||||||
|
output)
|
||||||
|
</li>
|
||||||
|
<li>
|
||||||
|
There are 2 Operation categories: reposition, access
|
||||||
|
</li>
|
||||||
|
<li>
|
||||||
|
A pair of iterators is needed to represent a (first/last) range.
|
||||||
|
</li>
|
||||||
|
</ul></div>
|
||||||
|
<p><span class="bold"><b>Python Iterators:</b></span></p>
|
||||||
|
<div class="itemizedlist"><ul type="disc">
|
||||||
|
<li>
|
||||||
|
1 category (forward)
|
||||||
|
</li>
|
||||||
|
<li>
|
||||||
|
1 operation category (next())
|
||||||
|
</li>
|
||||||
|
<li>
|
||||||
|
Raises StopIteration exception at end
|
||||||
|
</li>
|
||||||
|
</ul></div>
|
||||||
|
<p>
|
||||||
|
The typical Python iteration protocol: <tt class="literal"><span class="bold"><b>for y
|
||||||
|
in x...</b></span></tt> is as follows:
|
||||||
|
</p>
|
||||||
|
<p></p>
|
||||||
|
<pre class="programlisting">
|
||||||
|
<span class="identifier">iter</span> <span class="special">=</span> <span class="identifier">x</span><span class="special">.</span><span class="identifier">__iter__</span><span class="special">()</span> <span class="comment"># get iterator
|
||||||
|
</span><span class="keyword">try</span><span class="special">:</span>
|
||||||
|
<span class="keyword">while</span> <span class="number">1</span><span class="special">:</span>
|
||||||
|
<span class="identifier">y</span> <span class="special">=</span> <span class="identifier">iter</span><span class="special">.</span><span class="identifier">next</span><span class="special">()</span> <span class="comment"># get each item
|
||||||
|
</span> <span class="special">...</span> <span class="comment"># process y
|
||||||
|
</span><span class="keyword">except</span> <span class="identifier">StopIteration</span><span class="special">:</span> <span class="keyword">pass</span> <span class="comment"># iterator exhausted
|
||||||
|
</span></pre>
|
||||||
|
<p>
|
||||||
|
Boost.Python provides some mechanisms to make C++ iterators play along nicely
|
||||||
|
as Python iterators. What we need to do is to produce appropriate <tt class="computeroutput"><span class="identifier">__iter__</span></tt> function from C++ iterators that
|
||||||
|
is compatible with the Python iteration protocol. For example:
|
||||||
|
</p>
|
||||||
|
<p></p>
|
||||||
|
<pre class="programlisting">
|
||||||
|
<span class="identifier">object</span> <span class="identifier">get_iterator</span> <span class="special">=</span> <span class="identifier">iterator</span><span class="special"><</span><span class="identifier">vector</span><span class="special"><</span><span class="keyword">int</span><span class="special">></span> <span class="special">>();</span>
|
||||||
|
<span class="identifier">object</span> <span class="identifier">iter</span> <span class="special">=</span> <span class="identifier">get_iterator</span><span class="special">(</span><span class="identifier">v</span><span class="special">);</span>
|
||||||
|
<span class="identifier">object</span> <span class="identifier">first</span> <span class="special">=</span> <span class="identifier">iter</span><span class="special">.</span><span class="identifier">next</span><span class="special">();</span>
|
||||||
|
</pre>
|
||||||
|
<p>
|
||||||
|
Or for use in class_<>:
|
||||||
|
</p>
|
||||||
|
<pre class="programlisting">
|
||||||
|
<span class="special">.</span><span class="identifier">def</span><span class="special">(</span><span class="string">"__iter__"</span><span class="special">,</span> <span class="identifier">iterator</span><span class="special"><</span><span class="identifier">vector</span><span class="special"><</span><span class="keyword">int</span><span class="special">></span> <span class="special">>())</span>
|
||||||
|
</pre>
|
||||||
|
<p><span class="bold"><b>range</b></span></p>
|
||||||
|
<p>
|
||||||
|
We can create a Python savvy iterator using the range function:
|
||||||
|
</p>
|
||||||
|
<div class="itemizedlist"><ul type="disc">
|
||||||
|
<li>
|
||||||
|
range(start, finish)
|
||||||
|
</li>
|
||||||
|
<li>
|
||||||
|
range<Policies,Target>(start, finish)
|
||||||
|
</li>
|
||||||
|
</ul></div>
|
||||||
|
<p>
|
||||||
|
Here, start/finish may be one of:
|
||||||
|
</p>
|
||||||
|
<div class="itemizedlist"><ul type="disc">
|
||||||
|
<li>
|
||||||
|
member data pointers
|
||||||
|
</li>
|
||||||
|
<li>
|
||||||
|
member function pointers
|
||||||
|
</li>
|
||||||
|
<li>
|
||||||
|
adaptable function object (use Target parameter)
|
||||||
|
</li>
|
||||||
|
</ul></div>
|
||||||
|
<p><span class="bold"><b>iterator</b></span></p>
|
||||||
|
<div class="itemizedlist"><ul type="disc"><li>
|
||||||
|
iterator<T, Policies>()
|
||||||
|
</li></ul></div>
|
||||||
|
<p>
|
||||||
|
Given a container <tt class="literal">T</tt>, iterator is a shortcut that simply
|
||||||
|
calls <tt class="literal">range</tt> with &T::begin, &T::end.
|
||||||
|
</p>
|
||||||
|
<p>
|
||||||
|
Let's put this into action... Here's an example from some hypothetical bogon
|
||||||
|
Particle accelerator code:
|
||||||
|
</p>
|
||||||
|
<p></p>
|
||||||
|
<pre class="programlisting">
|
||||||
|
<span class="identifier">f</span> <span class="special">=</span> <span class="identifier">Field</span><span class="special">()</span>
|
||||||
|
<span class="keyword">for</span> <span class="identifier">x</span> <span class="keyword">in</span> <span class="identifier">f</span><span class="special">.</span><span class="identifier">pions</span><span class="special">:</span>
|
||||||
|
<span class="identifier">smash</span><span class="special">(</span><span class="identifier">x</span><span class="special">)</span>
|
||||||
|
<span class="keyword">for</span> <span class="identifier">y</span> <span class="keyword">in</span> <span class="identifier">f</span><span class="special">.</span><span class="identifier">bogons</span><span class="special">:</span>
|
||||||
|
<span class="identifier">count</span><span class="special">(</span><span class="identifier">y</span><span class="special">)</span>
|
||||||
|
</pre>
|
||||||
|
<p>
|
||||||
|
Now, our C++ Wrapper:
|
||||||
|
</p>
|
||||||
|
<p></p>
|
||||||
|
<pre class="programlisting">
|
||||||
|
<span class="identifier">class_</span><span class="special"><</span><span class="identifier">F</span><span class="special">>(</span><span class="string">"Field"</span><span class="special">)</span>
|
||||||
|
<span class="special">.</span><span class="identifier">property</span><span class="special">(</span><span class="string">"pions"</span><span class="special">,</span> <span class="identifier">range</span><span class="special">(&</span><span class="identifier">F</span><span class="special">::</span><span class="identifier">p_begin</span><span class="special">,</span> <span class="special">&</span><span class="identifier">F</span><span class="special">::</span><span class="identifier">p_end</span><span class="special">))</span>
|
||||||
|
<span class="special">.</span><span class="identifier">property</span><span class="special">(</span><span class="string">"bogons"</span><span class="special">,</span> <span class="identifier">range</span><span class="special">(&</span><span class="identifier">F</span><span class="special">::</span><span class="identifier">b_begin</span><span class="special">,</span> <span class="special">&</span><span class="identifier">F</span><span class="special">::</span><span class="identifier">b_end</span><span class="special">));</span>
|
||||||
|
</pre>
|
||||||
|
<p><span class="bold"><b>stl_input_iterator</b></span></p>
|
||||||
|
<p>
|
||||||
|
So far, we have seen how to expose C++ iterators and ranges to Python. Sometimes
|
||||||
|
we wish to go the other way, though: we'd like to pass a Python sequence to
|
||||||
|
an STL algorithm or use it to initialize an STL container. We need to make
|
||||||
|
a Python iterator look like an STL iterator. For that, we use <tt class="computeroutput"><span class="identifier">stl_input_iterator</span><span class="special"><></span></tt>.
|
||||||
|
Consider how we might implement a function that exposes <tt class="computeroutput"><span class="identifier">std</span><span class="special">::</span><span class="identifier">list</span><span class="special"><</span><span class="keyword">int</span><span class="special">>::</span><span class="identifier">assign</span><span class="special">()</span></tt> to Python:
|
||||||
|
</p>
|
||||||
|
<p></p>
|
||||||
|
<pre class="programlisting">
|
||||||
|
<span class="keyword">template</span><span class="special"><</span><span class="keyword">typename</span> <span class="identifier">T</span><span class="special">></span>
|
||||||
|
<span class="keyword">void</span> <span class="identifier">list_assign</span><span class="special">(</span><span class="identifier">std</span><span class="special">::</span><span class="identifier">list</span><span class="special"><</span><span class="identifier">T</span><span class="special">>&</span> <span class="identifier">l</span><span class="special">,</span> <span class="identifier">object</span> <span class="identifier">o</span><span class="special">)</span> <span class="special">{</span>
|
||||||
|
<span class="comment">// Turn a Python sequence into an STL input range
|
||||||
|
</span> <span class="identifier">stl_input_iterator</span><span class="special"><</span><span class="identifier">T</span><span class="special">></span> <span class="identifier">begin</span><span class="special">(</span><span class="identifier">o</span><span class="special">),</span> <span class="identifier">end</span><span class="special">;</span>
|
||||||
|
<span class="identifier">l</span><span class="special">.</span><span class="identifier">assign</span><span class="special">(</span><span class="identifier">begin</span><span class="special">,</span> <span class="identifier">end</span><span class="special">);</span>
|
||||||
|
<span class="special">}</span>
|
||||||
|
|
||||||
|
<span class="comment">// Part of the wrapper for list<int>
|
||||||
|
</span><span class="identifier">class_</span><span class="special"><</span><span class="identifier">std</span><span class="special">::</span><span class="identifier">list</span><span class="special"><</span><span class="keyword">int</span><span class="special">></span> <span class="special">>(</span><span class="string">"list_int"</span><span class="special">)</span>
|
||||||
|
<span class="special">.</span><span class="identifier">def</span><span class="special">(</span><span class="string">"assign"</span><span class="special">,</span> <span class="special">&</span><span class="identifier">list_assign</span><span class="special"><</span><span class="keyword">int</span><span class="special">>)</span>
|
||||||
|
<span class="comment">// ...
|
||||||
|
</span> <span class="special">;</span>
|
||||||
|
</pre>
|
||||||
|
<p>
|
||||||
|
Now in Python, we can assign any integer sequence to <tt class="computeroutput"><span class="identifier">list_int</span></tt>
|
||||||
|
objects:
|
||||||
|
</p>
|
||||||
|
<p></p>
|
||||||
|
<pre class="programlisting">
|
||||||
|
<span class="identifier">x</span> <span class="special">=</span> <span class="identifier">list_int</span><span class="special">();</span>
|
||||||
|
<span class="identifier">x</span><span class="special">.</span><span class="identifier">assign</span><span class="special">([</span><span class="number">1</span><span class="special">,</span><span class="number">2</span><span class="special">,</span><span class="number">3</span><span class="special">,</span><span class="number">4</span><span class="special">,</span><span class="number">5</span><span class="special">])</span>
|
||||||
|
</pre>
|
||||||
|
</div>
|
||||||
|
<table xmlns:rev="http://www.cs.rpi.edu/~gregod/boost/tools/doc/revision" width="100%"><tr>
|
||||||
|
<td align="left"></td>
|
||||||
|
<td align="right"><small>Copyright © 2002-2005 Joel
|
||||||
|
de Guzman, David Abrahams</small></td>
|
||||||
|
</tr></table>
|
||||||
|
<hr>
|
||||||
|
<div class="spirit-nav">
|
||||||
|
<a accesskey="p" href="embedding.html"><img src="../images/prev.png" alt="Prev"></a><a accesskey="u" href="../index.html"><img src="../images/up.png" alt="Up"></a><a accesskey="h" href="../index.html"><img src="../images/home.png" alt="Home"></a><a accesskey="n" href="exception.html"><img src="../images/next.png" alt="Next"></a>
|
||||||
|
</div>
|
||||||
|
</body>
|
||||||
|
</html>
|
||||||
339
doc/tutorial/doc/html/python/object.html
Normal file
@@ -0,0 +1,339 @@
|
|||||||
|
<html>
|
||||||
|
<head>
|
||||||
|
<meta http-equiv="Content-Type" content="text/html; charset=ISO-8859-1">
|
||||||
|
<title> Object Interface</title>
|
||||||
|
<link rel="stylesheet" href="../boostbook.css" type="text/css">
|
||||||
|
<meta name="generator" content="DocBook XSL Stylesheets V1.66.1">
|
||||||
|
<link rel="start" href="../index.html" title="Chapter 1. python 1.0">
|
||||||
|
<link rel="up" href="../index.html" title="Chapter 1. python 1.0">
|
||||||
|
<link rel="prev" href="functions.html" title="Functions">
|
||||||
|
<link rel="next" href="embedding.html" title="Embedding">
|
||||||
|
</head>
|
||||||
|
<body bgcolor="white" text="black" link="#0000FF" vlink="#840084" alink="#0000FF">
|
||||||
|
<table cellpadding="2" width="100%">
|
||||||
|
<td valign="top"><img alt="boost.png (6897 bytes)" width="277" height="86" src="../../../../../../../boost.png"></td>
|
||||||
|
<td align="center"><a href="../../../../../../../index.htm">Home</a></td>
|
||||||
|
<td align="center"><a href="../../../../../../../libs/libraries.htm">Libraries</a></td>
|
||||||
|
<td align="center"><a href="../../../../../../../people/people.htm">People</a></td>
|
||||||
|
<td align="center"><a href="../../../../../../../more/faq.htm">FAQ</a></td>
|
||||||
|
<td align="center"><a href="../../../../../../../more/index.htm">More</a></td>
|
||||||
|
</table>
|
||||||
|
<hr>
|
||||||
|
<div class="spirit-nav">
|
||||||
|
<a accesskey="p" href="functions.html"><img src="../images/prev.png" alt="Prev"></a><a accesskey="u" href="../index.html"><img src="../images/up.png" alt="Up"></a><a accesskey="h" href="../index.html"><img src="../images/home.png" alt="Home"></a><a accesskey="n" href="embedding.html"><img src="../images/next.png" alt="Next"></a>
|
||||||
|
</div>
|
||||||
|
<div class="section" lang="en">
|
||||||
|
<div class="titlepage"><div><div><h2 class="title" style="clear: both">
|
||||||
|
<a name="python.object"></a> Object Interface</h2></div></div></div>
|
||||||
|
<div class="toc"><dl>
|
||||||
|
<dt><span class="section"><a href="object.html#python.basic_interface">Basic Interface</a></span></dt>
|
||||||
|
<dt><span class="section"><a href="object.html#python.derived_object_types">Derived Object types</a></span></dt>
|
||||||
|
<dt><span class="section"><a href="object.html#python.extracting_c___objects">Extracting C++ objects</a></span></dt>
|
||||||
|
<dt><span class="section"><a href="object.html#python.enums">Enums</a></span></dt>
|
||||||
|
</dl></div>
|
||||||
|
<p>
|
||||||
|
Object InterfacePython is dynamically typed, unlike C++ which is statically
|
||||||
|
typed. Python variables may hold an integer, a float, list, dict, tuple, str,
|
||||||
|
long etc., among other things. In the viewpoint of Boost.Python and C++, these
|
||||||
|
Pythonic variables are just instances of class <tt class="literal">object</tt>. We
|
||||||
|
shall see in this chapter how to deal with Python objects.
|
||||||
|
</p>
|
||||||
|
<p>
|
||||||
|
As mentioned, one of the goals of Boost.Python is to provide a bidirectional
|
||||||
|
mapping between C++ and Python while maintaining the Python feel. Boost.Python
|
||||||
|
C++ <tt class="literal">object</tt>s are as close as possible to Python. This should
|
||||||
|
minimize the learning curve significantly.
|
||||||
|
</p>
|
||||||
|
<p><span class="inlinemediaobject"><img src="../images/python.png"></span></p>
|
||||||
|
<div class="section" lang="en">
|
||||||
|
<div class="titlepage"><div><div><h3 class="title">
|
||||||
|
<a name="python.basic_interface"></a>Basic Interface</h3></div></div></div>
|
||||||
|
<p>
|
||||||
|
Basic InterfaceClass <tt class="literal">object</tt> wraps <tt class="literal">PyObject*</tt>.
|
||||||
|
All the intricacies of dealing with <tt class="literal">PyObject</tt>s such as
|
||||||
|
managing reference counting are handled by the <tt class="literal">object</tt>
|
||||||
|
class. C++ object interoperability is seamless. Boost.Python C++ <tt class="literal">object</tt>s
|
||||||
|
can in fact be explicitly constructed from any C++ object.
|
||||||
|
</p>
|
||||||
|
<p>
|
||||||
|
To illustrate, this Python code snippet:
|
||||||
|
</p>
|
||||||
|
<p></p>
|
||||||
|
<pre class="programlisting">
|
||||||
|
<span class="keyword">def</span> <span class="identifier">f</span><span class="special">(</span><span class="identifier">x</span><span class="special">,</span> <span class="identifier">y</span><span class="special">):</span>
|
||||||
|
<span class="keyword">if</span> <span class="special">(</span><span class="identifier">y</span> <span class="special">==</span> <span class="string">'foo'</span><span class="special">):</span>
|
||||||
|
<span class="identifier">x</span><span class="special">[</span><span class="number">3</span><span class="special">:</span><span class="number">7</span><span class="special">]</span> <span class="special">=</span> <span class="string">'bar'</span>
|
||||||
|
<span class="keyword">else</span><span class="special">:</span>
|
||||||
|
<span class="identifier">x</span><span class="special">.</span><span class="identifier">items</span> <span class="special">+=</span> <span class="identifier">y</span><span class="special">(</span><span class="number">3</span><span class="special">,</span> <span class="identifier">x</span><span class="special">)</span>
|
||||||
|
<span class="keyword">return</span> <span class="identifier">x</span>
|
||||||
|
|
||||||
|
<span class="keyword">def</span> <span class="identifier">getfunc</span><span class="special">():</span>
|
||||||
|
<span class="keyword">return</span> <span class="identifier">f</span><span class="special">;</span>
|
||||||
|
</pre>
|
||||||
|
<p>
|
||||||
|
Can be rewritten in C++ using Boost.Python facilities this way:
|
||||||
|
</p>
|
||||||
|
<p></p>
|
||||||
|
<pre class="programlisting">
|
||||||
|
<span class="identifier">object</span> <span class="identifier">f</span><span class="special">(</span><span class="identifier">object</span> <span class="identifier">x</span><span class="special">,</span> <span class="identifier">object</span> <span class="identifier">y</span><span class="special">)</span> <span class="special">{</span>
|
||||||
|
<span class="keyword">if</span> <span class="special">(</span><span class="identifier">y</span> <span class="special">==</span> <span class="string">"foo"</span><span class="special">)</span>
|
||||||
|
<span class="identifier">x</span><span class="special">.</span><span class="identifier">slice</span><span class="special">(</span><span class="number">3</span><span class="special">,</span><span class="number">7</span><span class="special">)</span> <span class="special">=</span> <span class="string">"bar"</span><span class="special">;</span>
|
||||||
|
<span class="keyword">else</span>
|
||||||
|
<span class="identifier">x</span><span class="special">.</span><span class="identifier">attr</span><span class="special">(</span><span class="string">"items"</span><span class="special">)</span> <span class="special">+=</span> <span class="identifier">y</span><span class="special">(</span><span class="number">3</span><span class="special">,</span> <span class="identifier">x</span><span class="special">);</span>
|
||||||
|
<span class="keyword">return</span> <span class="identifier">x</span><span class="special">;</span>
|
||||||
|
<span class="special">}</span>
|
||||||
|
<span class="identifier">object</span> <span class="identifier">getfunc</span><span class="special">()</span> <span class="special">{</span>
|
||||||
|
<span class="keyword">return</span> <span class="identifier">object</span><span class="special">(</span><span class="identifier">f</span><span class="special">);</span>
|
||||||
|
<span class="special">}</span>
|
||||||
|
</pre>
|
||||||
|
<p>
|
||||||
|
Apart from cosmetic differences due to the fact that we are writing the code
|
||||||
|
in C++, the look and feel should be immediately apparent to the Python coder.
|
||||||
|
</p>
|
||||||
|
</div>
|
||||||
|
<div class="section" lang="en">
|
||||||
|
<div class="titlepage"><div><div><h3 class="title">
|
||||||
|
<a name="python.derived_object_types"></a>Derived Object types</h3></div></div></div>
|
||||||
|
<p>
|
||||||
|
Derived Object typesBoost.Python comes with a set of derived <tt class="literal">object</tt>
|
||||||
|
types corresponding to that of Python's:
|
||||||
|
</p>
|
||||||
|
<div class="itemizedlist"><ul type="disc">
|
||||||
|
<li>
|
||||||
|
list
|
||||||
|
</li>
|
||||||
|
<li>
|
||||||
|
dict
|
||||||
|
</li>
|
||||||
|
<li>
|
||||||
|
tuple
|
||||||
|
</li>
|
||||||
|
<li>
|
||||||
|
str
|
||||||
|
</li>
|
||||||
|
<li>
|
||||||
|
long_
|
||||||
|
</li>
|
||||||
|
<li>
|
||||||
|
enum
|
||||||
|
</li>
|
||||||
|
</ul></div>
|
||||||
|
<p>
|
||||||
|
These derived <tt class="literal">object</tt> types act like real Python types.
|
||||||
|
For instance:
|
||||||
|
</p>
|
||||||
|
<pre class="programlisting">
|
||||||
|
<span class="identifier">str</span><span class="special">(</span><span class="number">1</span><span class="special">)</span> <span class="special">==></span> <span class="string">"1"</span>
|
||||||
|
</pre>
|
||||||
|
<p>
|
||||||
|
Wherever appropriate, a particular derived <tt class="literal">object</tt> has
|
||||||
|
corresponding Python type's methods. For instance, <tt class="literal">dict</tt>
|
||||||
|
has a <tt class="literal">keys()</tt> method:
|
||||||
|
</p>
|
||||||
|
<pre class="programlisting">
|
||||||
|
<span class="identifier">d</span><span class="special">.</span><span class="identifier">keys</span><span class="special">()</span>
|
||||||
|
</pre>
|
||||||
|
<p><tt class="literal">make_tuple</tt> is provided for declaring <span class="emphasis"><em>tuple literals</em></span>.
|
||||||
|
Example:
|
||||||
|
</p>
|
||||||
|
<pre class="programlisting">
|
||||||
|
<span class="identifier">make_tuple</span><span class="special">(</span><span class="number">123</span><span class="special">,</span> <span class="char">'D'</span><span class="special">,</span> <span class="string">"Hello, World"</span><span class="special">,</span> <span class="number">0.0</span><span class="special">);</span>
|
||||||
|
</pre>
|
||||||
|
<p>
|
||||||
|
In C++, when Boost.Python <tt class="literal">object</tt>s are used as arguments
|
||||||
|
to functions, subtype matching is required. For example, when a function
|
||||||
|
<tt class="literal">f</tt>, as declared below, is wrapped, it will only accept
|
||||||
|
instances of Python's <tt class="literal">str</tt> type and subtypes.
|
||||||
|
</p>
|
||||||
|
<pre class="programlisting">
|
||||||
|
<span class="keyword">void</span> <span class="identifier">f</span><span class="special">(</span><span class="identifier">str</span> <span class="identifier">name</span><span class="special">)</span>
|
||||||
|
<span class="special">{</span>
|
||||||
|
<span class="identifier">object</span> <span class="identifier">n2</span> <span class="special">=</span> <span class="identifier">name</span><span class="special">.</span><span class="identifier">attr</span><span class="special">(</span><span class="string">"upper"</span><span class="special">)();</span> <span class="comment">// NAME = name.upper()
|
||||||
|
</span> <span class="identifier">str</span> <span class="identifier">NAME</span> <span class="special">=</span> <span class="identifier">name</span><span class="special">.</span><span class="identifier">upper</span><span class="special">();</span> <span class="comment">// better
|
||||||
|
</span> <span class="identifier">object</span> <span class="identifier">msg</span> <span class="special">=</span> <span class="string">"%s is bigger than %s"</span> <span class="special">%</span> <span class="identifier">make_tuple</span><span class="special">(</span><span class="identifier">NAME</span><span class="special">,</span><span class="identifier">name</span><span class="special">);</span>
|
||||||
|
<span class="special">}</span>
|
||||||
|
</pre>
|
||||||
|
<p>
|
||||||
|
In finer detail:
|
||||||
|
</p>
|
||||||
|
<pre class="programlisting">
|
||||||
|
<span class="identifier">str</span> <span class="identifier">NAME</span> <span class="special">=</span> <span class="identifier">name</span><span class="special">.</span><span class="identifier">upper</span><span class="special">();</span>
|
||||||
|
</pre>
|
||||||
|
<p>
|
||||||
|
Illustrates that we provide versions of the str type's methods as C++ member
|
||||||
|
functions.
|
||||||
|
</p>
|
||||||
|
<pre class="programlisting">
|
||||||
|
<span class="identifier">object</span> <span class="identifier">msg</span> <span class="special">=</span> <span class="string">"%s is bigger than %s"</span> <span class="special">%</span> <span class="identifier">make_tuple</span><span class="special">(</span><span class="identifier">NAME</span><span class="special">,</span><span class="identifier">name</span><span class="special">);</span>
|
||||||
|
</pre>
|
||||||
|
<p>
|
||||||
|
Demonstrates that you can write the C++ equivalent of <tt class="literal">"format"
|
||||||
|
% x,y,z</tt> in Python, which is useful since there's no easy way to
|
||||||
|
do that in std C++.
|
||||||
|
</p>
|
||||||
|
<div class="informaltable"><table class="table">
|
||||||
|
<colgroup><col></colgroup>
|
||||||
|
<tbody><tr><td class="blurb">
|
||||||
|
<span class="inlinemediaobject"><img src="../images/alert.png"></span> <span class="bold"><b>Beware</b></span> the common pitfall of forgetting that
|
||||||
|
the constructors of most of Python's mutable types make copies, just
|
||||||
|
as in Python. </td></tr></tbody>
|
||||||
|
</table></div>
|
||||||
|
<p>
|
||||||
|
Python:
|
||||||
|
</p>
|
||||||
|
<pre class="programlisting">
|
||||||
|
<span class="special">>>></span> <span class="identifier">d</span> <span class="special">=</span> <span class="identifier">dict</span><span class="special">(</span><span class="identifier">x</span><span class="special">.</span><span class="identifier">__dict__</span><span class="special">)</span> <span class="comment"># copies x.__dict__
|
||||||
|
</span><span class="special">>>></span> <span class="identifier">d</span><span class="special">[</span><span class="string">'whatever'</span><span class="special">]</span> <span class="special">=</span> <span class="number">3</span> <span class="comment"># modifies the copy
|
||||||
|
</span></pre>
|
||||||
|
<p>
|
||||||
|
C++:
|
||||||
|
</p>
|
||||||
|
<pre class="programlisting">
|
||||||
|
<span class="identifier">dict</span> <span class="identifier">d</span><span class="special">(</span><span class="identifier">x</span><span class="special">.</span><span class="identifier">attr</span><span class="special">(</span><span class="string">"__dict__"</span><span class="special">));</span> <span class="comment">// copies x.__dict__
|
||||||
|
</span><span class="identifier">d</span><span class="special">[</span><span class="char">'whatever'</span><span class="special">]</span> <span class="special">=</span> <span class="number">3</span><span class="special">;</span> <span class="comment">// modifies the copy
|
||||||
|
</span></pre>
|
||||||
|
<a name="derived_object_types.class__lt_t_gt__as_objects"></a><h2>
|
||||||
|
<a name="id455806"></a>
|
||||||
|
class_<T> as objects
|
||||||
|
</h2>
|
||||||
|
<p>
|
||||||
|
Due to the dynamic nature of Boost.Python objects, any <tt class="literal">class_<T></tt>
|
||||||
|
may also be one of these types! The following code snippet wraps the class
|
||||||
|
(type) object.
|
||||||
|
</p>
|
||||||
|
<p>
|
||||||
|
We can use this to create wrapped instances. Example:
|
||||||
|
</p>
|
||||||
|
<pre class="programlisting">
|
||||||
|
<span class="identifier">object</span> <span class="identifier">vec345</span> <span class="special">=</span> <span class="special">(</span>
|
||||||
|
<span class="identifier">class_</span><span class="special"><</span><span class="identifier">Vec2</span><span class="special">>(</span><span class="string">"Vec2"</span><span class="special">,</span> <span class="identifier">init</span><span class="special"><</span><span class="keyword">double</span><span class="special">,</span> <span class="keyword">double</span><span class="special">>())</span>
|
||||||
|
<span class="special">.</span><span class="identifier">def_readonly</span><span class="special">(</span><span class="string">"length"</span><span class="special">,</span> <span class="special">&</span><span class="identifier">Point</span><span class="special">::</span><span class="identifier">length</span><span class="special">)</span>
|
||||||
|
<span class="special">.</span><span class="identifier">def_readonly</span><span class="special">(</span><span class="string">"angle"</span><span class="special">,</span> <span class="special">&</span><span class="identifier">Point</span><span class="special">::</span><span class="identifier">angle</span><span class="special">)</span>
|
||||||
|
<span class="special">)(</span><span class="number">3.0</span><span class="special">,</span> <span class="number">4.0</span><span class="special">);</span>
|
||||||
|
|
||||||
|
<span class="identifier">assert</span><span class="special">(</span><span class="identifier">vec345</span><span class="special">.</span><span class="identifier">attr</span><span class="special">(</span><span class="string">"length"</span><span class="special">)</span> <span class="special">==</span> <span class="number">5.0</span><span class="special">);</span>
|
||||||
|
</pre>
|
||||||
|
</div>
|
||||||
|
<div class="section" lang="en">
|
||||||
|
<div class="titlepage"><div><div><h3 class="title">
|
||||||
|
<a name="python.extracting_c___objects"></a>Extracting C++ objects</h3></div></div></div>
|
||||||
|
<p>
|
||||||
|
Extracting C++ objectsAt some point, we will need to get C++ values out of
|
||||||
|
object instances. This can be achieved with the <tt class="literal">extract<T></tt>
|
||||||
|
function. Consider the following:
|
||||||
|
</p>
|
||||||
|
<pre class="programlisting">
|
||||||
|
<span class="keyword">double</span> <span class="identifier">x</span> <span class="special">=</span> <span class="identifier">o</span><span class="special">.</span><span class="identifier">attr</span><span class="special">(</span><span class="string">"length"</span><span class="special">);</span> <span class="comment">// compile error
|
||||||
|
</span></pre>
|
||||||
|
<p>
|
||||||
|
In the code above, we got a compiler error because Boost.Python <tt class="literal">object</tt>
|
||||||
|
can't be implicitly converted to <tt class="literal">double</tt>s. Instead, what
|
||||||
|
we wanted to do above can be achieved by writing:
|
||||||
|
</p>
|
||||||
|
<pre class="programlisting">
|
||||||
|
<span class="keyword">double</span> <span class="identifier">l</span> <span class="special">=</span> <span class="identifier">extract</span><span class="special"><</span><span class="keyword">double</span><span class="special">>(</span><span class="identifier">o</span><span class="special">.</span><span class="identifier">attr</span><span class="special">(</span><span class="string">"length"</span><span class="special">));</span>
|
||||||
|
<span class="identifier">Vec2</span><span class="special">&</span> <span class="identifier">v</span> <span class="special">=</span> <span class="identifier">extract</span><span class="special"><</span><span class="identifier">Vec2</span><span class="special">&>(</span><span class="identifier">o</span><span class="special">);</span>
|
||||||
|
<span class="identifier">assert</span><span class="special">(</span><span class="identifier">l</span> <span class="special">==</span> <span class="identifier">v</span><span class="special">.</span><span class="identifier">length</span><span class="special">());</span>
|
||||||
|
</pre>
|
||||||
|
<p>
|
||||||
|
The first line attempts to extract the "length" attribute of the
|
||||||
|
Boost.Python <tt class="literal">object</tt>. The second line attempts to <span class="emphasis"><em>extract</em></span>
|
||||||
|
the <tt class="literal">Vec2</tt> object from held by the Boost.Python <tt class="literal">object</tt>.
|
||||||
|
</p>
|
||||||
|
<p>
|
||||||
|
Take note that we said "attempt to" above. What if the Boost.Python
|
||||||
|
<tt class="literal">object</tt> does not really hold a <tt class="literal">Vec2</tt>
|
||||||
|
type? This is certainly a possibility considering the dynamic nature of Python
|
||||||
|
<tt class="literal">object</tt>s. To be on the safe side, if the C++ type can't
|
||||||
|
be extracted, an appropriate exception is thrown. To avoid an exception,
|
||||||
|
we need to test for extractibility:
|
||||||
|
</p>
|
||||||
|
<pre class="programlisting">
|
||||||
|
<span class="identifier">extract</span><span class="special"><</span><span class="identifier">Vec2</span><span class="special">&></span> <span class="identifier">x</span><span class="special">(</span><span class="identifier">o</span><span class="special">);</span>
|
||||||
|
<span class="keyword">if</span> <span class="special">(</span><span class="identifier">x</span><span class="special">.</span><span class="identifier">check</span><span class="special">())</span> <span class="special">{</span>
|
||||||
|
<span class="identifier">Vec2</span><span class="special">&</span> <span class="identifier">v</span> <span class="special">=</span> <span class="identifier">x</span><span class="special">();</span> <span class="special">...</span>
|
||||||
|
</pre>
|
||||||
|
<p><span class="inlinemediaobject"><img src="../images/tip.png"></span>
|
||||||
|
The astute reader might have noticed that the <tt class="literal">extract<T></tt>
|
||||||
|
facility in fact solves the mutable copying problem:
|
||||||
|
</p>
|
||||||
|
<pre class="programlisting">
|
||||||
|
<span class="identifier">dict</span> <span class="identifier">d</span> <span class="special">=</span> <span class="identifier">extract</span><span class="special"><</span><span class="identifier">dict</span><span class="special">>(</span><span class="identifier">x</span><span class="special">.</span><span class="identifier">attr</span><span class="special">(</span><span class="string">"__dict__"</span><span class="special">));</span>
|
||||||
|
<span class="identifier">d</span><span class="special">[</span><span class="string">"whatever"</span><span class="special">]</span> <span class="special">=</span> <span class="number">3</span><span class="special">;</span> <span class="comment">// modifies x.__dict__ !
|
||||||
|
</span></pre>
|
||||||
|
</div>
|
||||||
|
<div class="section" lang="en">
|
||||||
|
<div class="titlepage"><div><div><h3 class="title">
|
||||||
|
<a name="python.enums"></a>Enums</h3></div></div></div>
|
||||||
|
<p>
|
||||||
|
EnumsBoost.Python has a nifty facility to capture and wrap C++ enums. While
|
||||||
|
Python has no <tt class="literal">enum</tt> type, we'll often want to expose our
|
||||||
|
C++ enums to Python as an <tt class="literal">int</tt>. Boost.Python's enum facility
|
||||||
|
makes this easy while taking care of the proper conversions from Python's
|
||||||
|
dynamic typing to C++'s strong static typing (in C++, ints cannot be implicitly
|
||||||
|
converted to enums). To illustrate, given a C++ enum:
|
||||||
|
</p>
|
||||||
|
<pre class="programlisting">
|
||||||
|
<span class="keyword">enum</span> <span class="identifier">choice</span> <span class="special">{</span> <span class="identifier">red</span><span class="special">,</span> <span class="identifier">blue</span> <span class="special">};</span>
|
||||||
|
</pre>
|
||||||
|
<p>
|
||||||
|
the construct:
|
||||||
|
</p>
|
||||||
|
<pre class="programlisting">
|
||||||
|
<span class="identifier">enum_</span><span class="special"><</span><span class="identifier">choice</span><span class="special">>(</span><span class="string">"choice"</span><span class="special">)</span>
|
||||||
|
<span class="special">.</span><span class="identifier">value</span><span class="special">(</span><span class="string">"red"</span><span class="special">,</span> <span class="identifier">red</span><span class="special">)</span>
|
||||||
|
<span class="special">.</span><span class="identifier">value</span><span class="special">(</span><span class="string">"blue"</span><span class="special">,</span> <span class="identifier">blue</span><span class="special">)</span>
|
||||||
|
<span class="special">;</span>
|
||||||
|
</pre>
|
||||||
|
<p>
|
||||||
|
can be used to expose to Python. The new enum type is created in the current
|
||||||
|
<tt class="literal">scope()</tt>, which is usually the current module. The snippet
|
||||||
|
above creates a Python class derived from Python's <tt class="literal">int</tt>
|
||||||
|
type which is associated with the C++ type passed as its first parameter.
|
||||||
|
</p>
|
||||||
|
<div class="informaltable"><table class="table">
|
||||||
|
<colgroup><col></colgroup>
|
||||||
|
<tbody><tr><td class="blurb">
|
||||||
|
<span class="inlinemediaobject"><img src="../images/note.png"></span> <span class="bold"><b>what is a scope?</b></span><br><br> The scope is a
|
||||||
|
class that has an associated global Python object which controls the
|
||||||
|
Python namespace in which new extension classes and wrapped functions
|
||||||
|
will be defined as attributes. Details can be found <a href="../../../../v2/scope.html" target="_top">here</a>.</td></tr></tbody>
|
||||||
|
</table></div>
|
||||||
|
<p>
|
||||||
|
You can access those values in Python as
|
||||||
|
</p>
|
||||||
|
<p></p>
|
||||||
|
<pre class="programlisting">
|
||||||
|
<span class="special">>>></span> <span class="identifier">my_module</span><span class="special">.</span><span class="identifier">choice</span><span class="special">.</span><span class="identifier">red</span>
|
||||||
|
<span class="identifier">my_module</span><span class="special">.</span><span class="identifier">choice</span><span class="special">.</span><span class="identifier">red</span>
|
||||||
|
</pre>
|
||||||
|
<p>
|
||||||
|
where my_module is the module where the enum is declared. You can also create
|
||||||
|
a new scope around a class:
|
||||||
|
</p>
|
||||||
|
<p></p>
|
||||||
|
<pre class="programlisting">
|
||||||
|
<span class="identifier">scope</span> <span class="identifier">in_X</span> <span class="special">=</span> <span class="identifier">class_</span><span class="special"><</span><span class="identifier">X</span><span class="special">>(</span><span class="string">"X"</span><span class="special">)</span>
|
||||||
|
<span class="special">.</span><span class="identifier">def</span><span class="special">(</span> <span class="special">...</span> <span class="special">)</span>
|
||||||
|
<span class="special">.</span><span class="identifier">def</span><span class="special">(</span> <span class="special">...</span> <span class="special">)</span>
|
||||||
|
<span class="special">;</span>
|
||||||
|
|
||||||
|
<span class="comment">// Expose X::nested as X.nested
|
||||||
|
</span><span class="identifier">enum_</span><span class="special"><</span><span class="identifier">X</span><span class="special">::</span><span class="identifier">nested</span><span class="special">>(</span><span class="string">"nested"</span><span class="special">)</span>
|
||||||
|
<span class="special">.</span><span class="identifier">value</span><span class="special">(</span><span class="string">"red"</span><span class="special">,</span> <span class="identifier">red</span><span class="special">)</span>
|
||||||
|
<span class="special">.</span><span class="identifier">value</span><span class="special">(</span><span class="string">"blue"</span><span class="special">,</span> <span class="identifier">blue</span><span class="special">)</span>
|
||||||
|
<span class="special">;</span>
|
||||||
|
</pre>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<table xmlns:rev="http://www.cs.rpi.edu/~gregod/boost/tools/doc/revision" width="100%"><tr>
|
||||||
|
<td align="left"></td>
|
||||||
|
<td align="right"><small>Copyright © 2002-2005 Joel
|
||||||
|
de Guzman, David Abrahams</small></td>
|
||||||
|
</tr></table>
|
||||||
|
<hr>
|
||||||
|
<div class="spirit-nav">
|
||||||
|
<a accesskey="p" href="functions.html"><img src="../images/prev.png" alt="Prev"></a><a accesskey="u" href="../index.html"><img src="../images/up.png" alt="Up"></a><a accesskey="h" href="../index.html"><img src="../images/home.png" alt="Home"></a><a accesskey="n" href="embedding.html"><img src="../images/next.png" alt="Next"></a>
|
||||||
|
</div>
|
||||||
|
</body>
|
||||||
|
</html>
|
||||||
450
doc/tutorial/doc/html/python/techniques.html
Normal file
@@ -0,0 +1,450 @@
|
|||||||
|
<html>
|
||||||
|
<head>
|
||||||
|
<meta http-equiv="Content-Type" content="text/html; charset=ISO-8859-1">
|
||||||
|
<title> General Techniques</title>
|
||||||
|
<link rel="stylesheet" href="../boostbook.css" type="text/css">
|
||||||
|
<meta name="generator" content="DocBook XSL Stylesheets V1.66.1">
|
||||||
|
<link rel="start" href="../index.html" title="Chapter 1. python 1.0">
|
||||||
|
<link rel="up" href="../index.html" title="Chapter 1. python 1.0">
|
||||||
|
<link rel="prev" href="exception.html" title=" Exception Translation">
|
||||||
|
</head>
|
||||||
|
<body bgcolor="white" text="black" link="#0000FF" vlink="#840084" alink="#0000FF">
|
||||||
|
<table cellpadding="2" width="100%">
|
||||||
|
<td valign="top"><img alt="boost.png (6897 bytes)" width="277" height="86" src="../../../../../../../boost.png"></td>
|
||||||
|
<td align="center"><a href="../../../../../../../index.htm">Home</a></td>
|
||||||
|
<td align="center"><a href="../../../../../../../libs/libraries.htm">Libraries</a></td>
|
||||||
|
<td align="center"><a href="../../../../../../../people/people.htm">People</a></td>
|
||||||
|
<td align="center"><a href="../../../../../../../more/faq.htm">FAQ</a></td>
|
||||||
|
<td align="center"><a href="../../../../../../../more/index.htm">More</a></td>
|
||||||
|
</table>
|
||||||
|
<hr>
|
||||||
|
<div class="spirit-nav">
|
||||||
|
<a accesskey="p" href="exception.html"><img src="../images/prev.png" alt="Prev"></a><a accesskey="u" href="../index.html"><img src="../images/up.png" alt="Up"></a><a accesskey="h" href="../index.html"><img src="../images/home.png" alt="Home"></a>
|
||||||
|
</div>
|
||||||
|
<div class="section" lang="en">
|
||||||
|
<div class="titlepage"><div><div><h2 class="title" style="clear: both">
|
||||||
|
<a name="python.techniques"></a> General Techniques</h2></div></div></div>
|
||||||
|
<div class="toc"><dl>
|
||||||
|
<dt><span class="section"><a href="techniques.html#python.creating_packages">Creating Packages</a></span></dt>
|
||||||
|
<dt><span class="section"><a href="techniques.html#python.extending_wrapped_objects_in_python">Extending Wrapped Objects in Python</a></span></dt>
|
||||||
|
<dt><span class="section"><a href="techniques.html#python.reducing_compiling_time">Reducing Compiling Time</a></span></dt>
|
||||||
|
</dl></div>
|
||||||
|
<p>
|
||||||
|
General TechniquesHere are presented some useful techniques that you can use
|
||||||
|
while wrapping code with Boost.Python.
|
||||||
|
</p>
|
||||||
|
<div class="section" lang="en">
|
||||||
|
<div class="titlepage"><div><div><h3 class="title">
|
||||||
|
<a name="python.creating_packages"></a>Creating Packages</h3></div></div></div>
|
||||||
|
<p>
|
||||||
|
Creating PackagesA 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" target="_top">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 class="literal">sounds</tt>. Our library already has a neat C++ namespace hierarchy,
|
||||||
|
like so:
|
||||||
|
</p>
|
||||||
|
<pre class="programlisting">
|
||||||
|
<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>
|
||||||
|
<p>
|
||||||
|
We would like to present this same hierarchy to the Python user, allowing
|
||||||
|
him to write code like this:
|
||||||
|
</p>
|
||||||
|
<pre class="programlisting">
|
||||||
|
<span class="keyword">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="comment"># echo is a C++ function
|
||||||
|
</span></pre>
|
||||||
|
<p>
|
||||||
|
The first step is to write the wrapping code. We have to export each module
|
||||||
|
separately with Boost.Python, like this:
|
||||||
|
</p>
|
||||||
|
<pre class="programlisting">
|
||||||
|
<span class="special">/*</span> <span class="identifier">file</span> <span class="identifier">core</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">core</span><span class="special">)</span>
|
||||||
|
<span class="special">{</span>
|
||||||
|
<span class="special">/*</span> <span class="identifier">export</span> <span class="identifier">everything</span> <span class="keyword">in</span> <span class="identifier">the</span> <span class="identifier">sounds</span><span class="special">::</span><span class="identifier">core</span> <span class="identifier">namespace</span> <span class="special">*/</span>
|
||||||
|
<span class="special">...</span>
|
||||||
|
<span class="special">}</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="special">{</span>
|
||||||
|
<span class="special">/*</span> <span class="identifier">export</span> <span class="identifier">everything</span> <span class="keyword">in</span> <span class="identifier">the</span> <span class="identifier">sounds</span><span class="special">::</span><span class="identifier">io</span> <span class="identifier">namespace</span> <span class="special">*/</span>
|
||||||
|
<span class="special">...</span>
|
||||||
|
<span class="special">}</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="special">{</span>
|
||||||
|
<span class="special">/*</span> <span class="identifier">export</span> <span class="identifier">everything</span> <span class="keyword">in</span> <span class="identifier">the</span> <span class="identifier">sounds</span><span class="special">::</span><span class="identifier">filters</span> <span class="identifier">namespace</span> <span class="special">*/</span>
|
||||||
|
<span class="special">...</span>
|
||||||
|
<span class="special">}</span>
|
||||||
|
</pre>
|
||||||
|
<p>
|
||||||
|
Compiling these files will generate the following Python extensions: <tt class="literal">core.pyd</tt>,
|
||||||
|
<tt class="literal">io.pyd</tt> and <tt class="literal">filters.pyd</tt>.
|
||||||
|
</p>
|
||||||
|
<div class="informaltable"><table class="table">
|
||||||
|
<colgroup><col></colgroup>
|
||||||
|
<tbody><tr><td class="blurb">
|
||||||
|
<span class="inlinemediaobject"><img src="../images/note.png"></span>
|
||||||
|
The extension <tt class="literal">.pyd</tt> is used for python extension
|
||||||
|
modules, which are just shared libraries. Using the default for your
|
||||||
|
system, like <tt class="literal">.so</tt> for Unix and <tt class="literal">.dll</tt>
|
||||||
|
for Windows, works just as well.</td></tr></tbody>
|
||||||
|
</table></div>
|
||||||
|
<p>
|
||||||
|
Now, we create this directory structure for our Python package:
|
||||||
|
</p>
|
||||||
|
<pre class="programlisting">sounds/
|
||||||
|
__init__.py
|
||||||
|
core.pyd
|
||||||
|
filters.pyd
|
||||||
|
io.pyd
|
||||||
|
</pre>
|
||||||
|
<p>
|
||||||
|
The file <tt class="literal">__init__.py</tt> is what tells Python that the directory
|
||||||
|
<tt class="literal">sounds/</tt> is actually a Python package. It can be a empty
|
||||||
|
file, but can also perform some magic, that will be shown later.
|
||||||
|
</p>
|
||||||
|
<p>
|
||||||
|
Now our package is ready. All the user has to do is put <tt class="literal">sounds</tt>
|
||||||
|
into his <a href="http://www.python.org/doc/current/tut/node8.html#SECTION008110000000000000000" target="_top">PYTHONPATH</a>
|
||||||
|
and fire up the interpreter:
|
||||||
|
</p>
|
||||||
|
<p></p>
|
||||||
|
<pre class="programlisting">
|
||||||
|
<span class="special">>>></span> <span class="keyword">import</span> <span class="identifier">sounds</span><span class="special">.</span><span class="identifier">io</span>
|
||||||
|
<span class="special">>>></span> <span class="keyword">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="string">'file.mp3'</span><span class="special">)</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>
|
||||||
|
<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 <span class="emphasis"><em>pure</em></span> 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>
|
||||||
|
<p></p>
|
||||||
|
<pre class="programlisting">
|
||||||
|
<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="special">{</span>
|
||||||
|
<span class="special">...</span>
|
||||||
|
<span class="comment">/* export everything in the sounds::core namespace */</span>
|
||||||
|
<span class="special">}</span>
|
||||||
|
</pre>
|
||||||
|
<p>
|
||||||
|
Note that we added an underscore to the module name. The filename will have
|
||||||
|
to be changed to <tt class="literal">_core.pyd</tt> as well, and we do the same
|
||||||
|
to the other extension modules. Now, we change our package hierarchy like
|
||||||
|
so:
|
||||||
|
</p>
|
||||||
|
<pre class="programlisting">sounds/
|
||||||
|
__init__.py
|
||||||
|
core/
|
||||||
|
__init__.py
|
||||||
|
_core.pyd
|
||||||
|
filters/
|
||||||
|
__init__.py
|
||||||
|
_filters.pyd
|
||||||
|
io/
|
||||||
|
__init__.py
|
||||||
|
_io.pyd
|
||||||
|
</pre>
|
||||||
|
<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>
|
||||||
|
<p></p>
|
||||||
|
<pre class="programlisting">
|
||||||
|
<span class="special">>>></span> <span class="keyword">import</span> <span class="identifier">sounds</span><span class="special">.</span><span class="identifier">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>
|
||||||
|
<p>
|
||||||
|
which is not what we want. But here enters the <tt class="literal">__init__.py</tt>
|
||||||
|
magic: everything that is brought to the <tt class="literal">__init__.py</tt> namespace
|
||||||
|
can be accessed directly by the user. So, all we have to do is bring the
|
||||||
|
entire namespace from <tt class="literal">_core.pyd</tt> to <tt class="literal">core/__init__.py</tt>.
|
||||||
|
So add this line of code to <tt class="literal">sounds<span class="emphasis"><em>core</em></span>__init__.py</tt>:
|
||||||
|
</p>
|
||||||
|
<pre class="programlisting">
|
||||||
|
<span class="keyword">from</span> <span class="identifier">_core</span> <span class="keyword">import</span> <span class="special">*</span>
|
||||||
|
</pre>
|
||||||
|
<p>
|
||||||
|
We do the same for the other packages. Now the user accesses the functions
|
||||||
|
and classes in the extension modules like before:
|
||||||
|
</p>
|
||||||
|
<pre class="programlisting">
|
||||||
|
<span class="special">>>></span> <span class="keyword">import</span> <span class="identifier">sounds</span><span class="special">.</span><span class="identifier">filters</span>
|
||||||
|
<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>
|
||||||
|
<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 <span class="emphasis"><em>pure</em></span>
|
||||||
|
Python function, <tt class="literal">echo_noise</tt>, to the <tt class="literal">filters</tt>
|
||||||
|
package. This function applies both the <tt class="literal">echo</tt> and <tt class="literal">noise</tt>
|
||||||
|
filters in sequence in the given <tt class="literal">sound</tt> object. We create
|
||||||
|
a file named <tt class="literal">sounds/filters/echo_noise.py</tt> and code our
|
||||||
|
function:
|
||||||
|
</p>
|
||||||
|
<pre class="programlisting">
|
||||||
|
<span class="keyword">import</span> <span class="identifier">_filters</span>
|
||||||
|
<span class="keyword">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>
|
||||||
|
<p>
|
||||||
|
Next, we add this line to <tt class="literal">sounds<span class="emphasis"><em>filters</em></span>__init__.py</tt>:
|
||||||
|
</p>
|
||||||
|
<pre class="programlisting">
|
||||||
|
<span class="keyword">from</span> <span class="identifier">echo_noise</span> <span class="keyword">import</span> <span class="identifier">echo_noise</span>
|
||||||
|
</pre>
|
||||||
|
<p>
|
||||||
|
And that's it. The user now accesses this function like any other function
|
||||||
|
from the <tt class="literal">filters</tt> package:
|
||||||
|
</p>
|
||||||
|
<pre class="programlisting">
|
||||||
|
<span class="special">>>></span> <span class="keyword">import</span> <span class="identifier">sounds</span><span class="special">.</span><span class="identifier">filters</span>
|
||||||
|
<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>
|
||||||
|
</div>
|
||||||
|
<div class="section" lang="en">
|
||||||
|
<div class="titlepage"><div><div><h3 class="title">
|
||||||
|
<a name="python.extending_wrapped_objects_in_python"></a>Extending Wrapped Objects in Python</h3></div></div></div>
|
||||||
|
<p>
|
||||||
|
Extending Wrapped Objects in PythonThanks to Python's flexibility, you can
|
||||||
|
easily add new methods to a class, even after it was already created:
|
||||||
|
</p>
|
||||||
|
<pre class="programlisting">
|
||||||
|
<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="keyword">pass</span>
|
||||||
|
<span class="special">>>></span>
|
||||||
|
<span class="special">>>></span> <span class="comment"># a regular function
|
||||||
|
</span><span class="special">>>></span> <span class="keyword">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="string">'A C instance!'</span>
|
||||||
|
<span class="special">>>></span>
|
||||||
|
<span class="special">>>></span> <span class="comment"># now we turn it in a member 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="special">>>></span> <span class="identifier">c</span> <span class="special">=</span> <span class="identifier">C</span><span class="special">()</span>
|
||||||
|
<span class="special">>>></span> <span class="keyword">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="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>
|
||||||
|
<p>
|
||||||
|
Yes, Python rox. <span class="inlinemediaobject"><img src="../images/smiley.png"></span></p>
|
||||||
|
<p>
|
||||||
|
We can do the same with classes that were wrapped with Boost.Python. Suppose
|
||||||
|
we have a class <tt class="literal">point</tt> in C++:
|
||||||
|
</p>
|
||||||
|
<p></p>
|
||||||
|
<pre class="programlisting">
|
||||||
|
<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="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="special">}</span>
|
||||||
|
</pre>
|
||||||
|
<p>
|
||||||
|
If we are using the technique from the previous session, <a href="techniques.html#python.creating_packages" title="Creating Packages">Creating
|
||||||
|
Packages</a>, we can code directly into <tt class="literal">geom/__init__.py</tt>:
|
||||||
|
</p>
|
||||||
|
<p></p>
|
||||||
|
<pre class="programlisting">
|
||||||
|
<span class="keyword">from</span> <span class="identifier">_geom</span> <span class="keyword">import</span> <span class="special">*</span>
|
||||||
|
|
||||||
|
<span class="comment"># a regular function
|
||||||
|
</span><span class="keyword">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="comment"># now we turn it into a member 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>
|
||||||
|
<p><span class="bold"><b>All</b></span> point instances created from C++ will
|
||||||
|
also have this member function! This technique has several advantages:
|
||||||
|
</p>
|
||||||
|
<div class="itemizedlist"><ul type="disc">
|
||||||
|
<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></div>
|
||||||
|
<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>
|
||||||
|
<pre class="programlisting">
|
||||||
|
<span class="comment"># The one Boost.Python uses for all wrapped classes.
|
||||||
|
</span><span class="comment"># You can use here any class exported by Boost instead of "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="keyword">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="keyword">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="keyword">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="keyword">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="comment"># inject some methods in the point 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="keyword">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="string">'Point(x=%s, y=%s)'</span> <span class="special">%</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="keyword">def</span> <span class="identifier">foo</span><span class="special">(</span><span class="identifier">self</span><span class="special">):</span>
|
||||||
|
<span class="keyword">print</span> <span class="string">'foo!'</span>
|
||||||
|
</pre>
|
||||||
|
<p>
|
||||||
|
Now let's see how it got:
|
||||||
|
</p>
|
||||||
|
<pre class="programlisting">
|
||||||
|
<span class="special">>>></span> <span class="keyword">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="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>
|
||||||
|
<p>
|
||||||
|
Another useful idea is to replace constructors with factory functions:
|
||||||
|
</p>
|
||||||
|
<pre class="programlisting">
|
||||||
|
<span class="identifier">_point</span> <span class="special">=</span> <span class="identifier">point</span>
|
||||||
|
|
||||||
|
<span class="keyword">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>
|
||||||
|
<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>
|
||||||
|
</div>
|
||||||
|
<div class="section" lang="en">
|
||||||
|
<div class="titlepage"><div><div><h3 class="title">
|
||||||
|
<a name="python.reducing_compiling_time"></a>Reducing Compiling Time</h3></div></div></div>
|
||||||
|
<p>
|
||||||
|
Reducing Compiling TimeIf 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>
|
||||||
|
<p></p>
|
||||||
|
<pre class="programlisting">
|
||||||
|
<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="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="special">}</span>
|
||||||
|
|
||||||
|
<span class="comment">/* file triangle.cpp */</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="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>
|
||||||
|
<span class="special">}</span>
|
||||||
|
</pre>
|
||||||
|
<p>
|
||||||
|
Now you create a file <tt class="literal">main.cpp</tt>, which contains the <tt class="literal">BOOST_PYTHON_MODULE</tt>
|
||||||
|
macro, and call the various export functions inside it.
|
||||||
|
</p>
|
||||||
|
<pre class="programlisting">
|
||||||
|
<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="special">{</span>
|
||||||
|
<span class="identifier">export_point</span><span class="special">();</span>
|
||||||
|
<span class="identifier">export_triangle</span><span class="special">();</span>
|
||||||
|
<span class="special">}</span>
|
||||||
|
</pre>
|
||||||
|
<p>
|
||||||
|
Compiling and linking together all this files produces the same result as
|
||||||
|
the usual approach:
|
||||||
|
</p>
|
||||||
|
<pre class="programlisting">
|
||||||
|
<span class="preprocessor">#include</span> <span class="special"><</span><span class="identifier">boost</span><span class="special">/</span><span class="identifier">python</span><span class="special">.</span><span class="identifier">hpp</span><span class="special">></span>
|
||||||
|
<span class="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="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>
|
||||||
|
<span class="special">}</span>
|
||||||
|
</pre>
|
||||||
|
<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>
|
||||||
|
<div class="informaltable"><table class="table">
|
||||||
|
<colgroup><col></colgroup>
|
||||||
|
<tbody><tr><td class="blurb">
|
||||||
|
<span class="inlinemediaobject"><img src="../images/note.png"></span>
|
||||||
|
If you're exporting your classes with <a href="../../../../../pyste/index.html" target="_top">Pyste</a>,
|
||||||
|
take a look at the <tt class="literal">--multiple</tt> option, that generates
|
||||||
|
the wrappers in various files as demonstrated here.</td></tr></tbody>
|
||||||
|
</table></div>
|
||||||
|
<div class="informaltable"><table class="table">
|
||||||
|
<colgroup><col></colgroup>
|
||||||
|
<tbody><tr><td class="blurb">
|
||||||
|
<span class="inlinemediaobject"><img src="../images/note.png"></span>
|
||||||
|
This method is useful too if you are getting the error message <span class="emphasis"><em>"fatal
|
||||||
|
error C1204:Compiler limit:internal structure overflow"</em></span>
|
||||||
|
when compiling a large source file, as explained in the <a href="../../../../v2/faq.html#c1204" target="_top">FAQ</a>.</td></tr></tbody>
|
||||||
|
</table></div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<table xmlns:rev="http://www.cs.rpi.edu/~gregod/boost/tools/doc/revision" width="100%"><tr>
|
||||||
|
<td align="left"></td>
|
||||||
|
<td align="right"><small>Copyright © 2002-2005 Joel
|
||||||
|
de Guzman, David Abrahams</small></td>
|
||||||
|
</tr></table>
|
||||||
|
<hr>
|
||||||
|
<div class="spirit-nav">
|
||||||
|
<a accesskey="p" href="exception.html"><img src="../images/prev.png" alt="Prev"></a><a accesskey="u" href="../index.html"><img src="../images/up.png" alt="Up"></a><a accesskey="h" href="../index.html"><img src="../images/home.png" alt="Home"></a>
|
||||||
|
</div>
|
||||||
|
</body>
|
||||||
|
</html>
|
||||||
@@ -1,98 +0,0 @@
|
|||||||
<html>
|
|
||||||
<head>
|
|
||||||
<!-- Generated by the Spirit (http://spirit.sf.net) QuickDoc -->
|
|
||||||
<title>Inheritance</title>
|
|
||||||
<link rel="stylesheet" href="theme/style.css" type="text/css">
|
|
||||||
<link rel="prev" href="class_properties.html">
|
|
||||||
<link rel="next" href="class_virtual_functions.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>Inheritance</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="class_properties.html"><img src="theme/l_arr.gif" border="0"></a></td>
|
|
||||||
<td width="20"><a href="class_virtual_functions.html"><img src="theme/r_arr.gif" border="0"></a></td>
|
|
||||||
</tr>
|
|
||||||
</table>
|
|
||||||
<p>
|
|
||||||
In the previous examples, we dealt with classes that are not polymorphic.
|
|
||||||
This is not often the case. Much of the time, we will be wrapping
|
|
||||||
polymorphic classes and class hierarchies related by inheritance. We will
|
|
||||||
often have to write Boost.Python wrappers for classes that are derived from
|
|
||||||
abstract base classes.</p>
|
|
||||||
<p>
|
|
||||||
Consider this trivial inheritance structure:</p>
|
|
||||||
<code><pre>
|
|
||||||
<span class=keyword>struct </span><span class=identifier>Base </span><span class=special>{ </span><span class=keyword>virtual </span><span class=special>~</span><span class=identifier>Base</span><span class=special>(); };
|
|
||||||
</span><span class=keyword>struct </span><span class=identifier>Derived </span><span class=special>: </span><span class=identifier>Base </span><span class=special>{};
|
|
||||||
</span></pre></code>
|
|
||||||
<p>
|
|
||||||
And a set of C++ functions operating on <tt>Base</tt> and <tt>Derived</tt> object
|
|
||||||
instances:</p>
|
|
||||||
<code><pre>
|
|
||||||
<span class=keyword>void </span><span class=identifier>b</span><span class=special>(</span><span class=identifier>Base</span><span class=special>*);
|
|
||||||
</span><span class=keyword>void </span><span class=identifier>d</span><span class=special>(</span><span class=identifier>Derived</span><span class=special>*);
|
|
||||||
</span><span class=identifier>Base</span><span class=special>* </span><span class=identifier>factory</span><span class=special>() { </span><span class=keyword>return </span><span class=keyword>new </span><span class=identifier>Derived</span><span class=special>; }
|
|
||||||
</span></pre></code>
|
|
||||||
<p>
|
|
||||||
We've seen how we can wrap the base class <tt>Base</tt>:</p>
|
|
||||||
<code><pre>
|
|
||||||
<span class=identifier>class_</span><span class=special><</span><span class=identifier>Base</span><span class=special>>(</span><span class=string>"Base"</span><span class=special>)
|
|
||||||
/*...*/
|
|
||||||
;
|
|
||||||
</span></pre></code>
|
|
||||||
<p>
|
|
||||||
Now we can inform Boost.Python of the inheritance relationship between
|
|
||||||
<tt>Derived</tt> and its base class <tt>Base</tt>. Thus:</p>
|
|
||||||
<code><pre>
|
|
||||||
<span class=identifier>class_</span><span class=special><</span><span class=identifier>Derived</span><span class=special>, </span><span class=identifier>bases</span><span class=special><</span><span class=identifier>Base</span><span class=special>> >(</span><span class=string>"Derived"</span><span class=special>)
|
|
||||||
/*...*/
|
|
||||||
;
|
|
||||||
</span></pre></code>
|
|
||||||
<p>
|
|
||||||
Doing so, we get some things for free:</p>
|
|
||||||
<ol><li>Derived automatically inherits all of Base's Python methods (wrapped C++ member functions)</li><li><b>If</b> Base is polymorphic, <tt>Derived</tt> objects which have been passed to Python via a pointer or reference to <tt>Base</tt> can be passed where a pointer or reference to <tt>Derived</tt> is expected.</li></ol><p>
|
|
||||||
Now, we shall expose the C++ free functions <tt>b</tt> and <tt>d</tt> and <tt>factory</tt>:</p>
|
|
||||||
<code><pre>
|
|
||||||
<span class=identifier>def</span><span class=special>(</span><span class=string>"b"</span><span class=special>, </span><span class=identifier>b</span><span class=special>);
|
|
||||||
</span><span class=identifier>def</span><span class=special>(</span><span class=string>"d"</span><span class=special>, </span><span class=identifier>d</span><span class=special>);
|
|
||||||
</span><span class=identifier>def</span><span class=special>(</span><span class=string>"factory"</span><span class=special>, </span><span class=identifier>factory</span><span class=special>);
|
|
||||||
</span></pre></code>
|
|
||||||
<p>
|
|
||||||
Note that free function <tt>factory</tt> is being used to generate new
|
|
||||||
instances of class <tt>Derived</tt>. In such cases, we use
|
|
||||||
<tt>return_value_policy<manage_new_object></tt> to instruct Python to adopt
|
|
||||||
the pointer to <tt>Base</tt> and hold the instance in a new Python <tt>Base</tt>
|
|
||||||
object until the the Python object is destroyed. We shall see more of
|
|
||||||
Boost.Python <a href="call_policies.html">
|
|
||||||
call policies</a> later.</p>
|
|
||||||
<code><pre>
|
|
||||||
<span class=comment>// Tell Python to take ownership of factory's result
|
|
||||||
</span><span class=identifier>def</span><span class=special>(</span><span class=string>"factory"</span><span class=special>, </span><span class=identifier>factory</span><span class=special>,
|
|
||||||
</span><span class=identifier>return_value_policy</span><span class=special><</span><span class=identifier>manage_new_object</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="class_properties.html"><img src="theme/l_arr.gif" border="0"></a></td>
|
|
||||||
<td width="20"><a href="class_virtual_functions.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>
|
|
||||||
@@ -1,101 +0,0 @@
|
|||||||
<html>
|
|
||||||
<head>
|
|
||||||
<!-- Generated by the Spirit (http://spirit.sf.net) QuickDoc -->
|
|
||||||
<title>Iterators</title>
|
|
||||||
<link rel="stylesheet" href="theme/style.css" type="text/css">
|
|
||||||
<link rel="prev" href="using_the_interpreter.html">
|
|
||||||
<link rel="next" href="exception_translation.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>Iterators</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="using_the_interpreter.html"><img src="theme/l_arr.gif" border="0"></a></td>
|
|
||||||
<td width="20"><a href="exception_translation.html"><img src="theme/r_arr.gif" border="0"></a></td>
|
|
||||||
</tr>
|
|
||||||
</table>
|
|
||||||
<p>
|
|
||||||
In C++, and STL in particular, we see iterators everywhere. Python also has
|
|
||||||
iterators, but these are two very different beasts.</p>
|
|
||||||
<p>
|
|
||||||
<b>C++ iterators:</b></p>
|
|
||||||
<ul><li>C++ has 5 type categories (random-access, bidirectional, forward, input, output)</li><li>There are 2 Operation categories: reposition, access</li><li>A pair of iterators is needed to represent a (first/last) range.</li></ul><p>
|
|
||||||
<b>Python Iterators:</b></p>
|
|
||||||
<ul><li>1 category (forward)</li><li>1 operation category (next())</li><li>Raises StopIteration exception at end</li></ul><p>
|
|
||||||
The typical Python iteration protocol: <tt><b>for y in x...</b></tt> is as follows:</p>
|
|
||||||
<code><pre>
|
|
||||||
<span class=identifier>iter </span><span class=special>= </span><span class=identifier>x</span><span class=special>.</span><span class=identifier>__iter__</span><span class=special>() </span>##<span class=identifier>get </span><span class=identifier>iterator
|
|
||||||
</span><span class=keyword>try</span><span class=special>:
|
|
||||||
</span><span class=keyword>while </span><span class=number>1</span><span class=special>:
|
|
||||||
</span><span class=identifier>y </span><span class=special>= </span><span class=identifier>iter</span><span class=special>.</span><span class=identifier>next</span><span class=special>() </span>##<span class=identifier>get </span><span class=identifier>each </span><span class=identifier>item
|
|
||||||
</span><span class=special>... </span>##<span class=identifier>process </span><span class=identifier>y
|
|
||||||
</span><span class=identifier>except </span><span class=identifier>StopIteration</span><span class=special>: </span><span class=identifier>pass </span>##<span class=identifier>iterator </span><span class=identifier>exhausted
|
|
||||||
</span></pre></code>
|
|
||||||
<p>
|
|
||||||
Boost.Python provides some mechanisms to make C++ iterators play along
|
|
||||||
nicely as Python iterators. What we need to do is to produce
|
|
||||||
appropriate __iter__ function from C++ iterators that is compatible
|
|
||||||
with the Python iteration protocol. For example:</p>
|
|
||||||
<code><pre>
|
|
||||||
<span class=identifier>object </span><span class=identifier>get_iterator </span><span class=special>= </span><span class=identifier>iterator</span><span class=special><</span><span class=identifier>vector</span><span class=special><</span><span class=keyword>int</span><span class=special>> >();
|
|
||||||
</span><span class=identifier>object </span><span class=identifier>iter </span><span class=special>= </span><span class=identifier>get_iterator</span><span class=special>(</span><span class=identifier>v</span><span class=special>);
|
|
||||||
</span><span class=identifier>object </span><span class=identifier>first </span><span class=special>= </span><span class=identifier>iter</span><span class=special>.</span><span class=identifier>next</span><span class=special>();
|
|
||||||
</span></pre></code>
|
|
||||||
<p>
|
|
||||||
Or for use in class_<>:</p>
|
|
||||||
<code><pre>
|
|
||||||
<span class=special>.</span><span class=identifier>def</span><span class=special>(</span><span class=string>"__iter__"</span><span class=special>, </span><span class=identifier>iterator</span><span class=special><</span><span class=identifier>vector</span><span class=special><</span><span class=keyword>int</span><span class=special>> >())
|
|
||||||
</span></pre></code>
|
|
||||||
<p>
|
|
||||||
<b>range</b></p>
|
|
||||||
<p>
|
|
||||||
We can create a Python savvy iterator using the range function:</p>
|
|
||||||
<ul><li>range(start, finish)</li><li>range<Policies,Target>(start, finish)</li></ul><p>
|
|
||||||
Here, start/finish may be one of:</p>
|
|
||||||
<ul><li>member data pointers</li><li>member function pointers</li><li>adaptable function object (use Target parameter)</li></ul><p>
|
|
||||||
<b>iterator</b></p>
|
|
||||||
<ul><li>iterator<T, Policies>()</li></ul><p>
|
|
||||||
Given a container <tt>T</tt>, iterator is a shortcut that simply calls <tt>range</tt>
|
|
||||||
with &T::begin, &T::end.</p>
|
|
||||||
<p>
|
|
||||||
Let's put this into action... Here's an example from some hypothetical
|
|
||||||
bogon Particle accelerator code:</p>
|
|
||||||
<code><pre>
|
|
||||||
<span class=identifier>f </span><span class=special>= </span><span class=identifier>Field</span><span class=special>()
|
|
||||||
</span><span class=keyword>for </span><span class=identifier>x </span><span class=identifier>in </span><span class=identifier>f</span><span class=special>.</span><span class=identifier>pions</span><span class=special>:
|
|
||||||
</span><span class=identifier>smash</span><span class=special>(</span><span class=identifier>x</span><span class=special>)
|
|
||||||
</span><span class=keyword>for </span><span class=identifier>y </span><span class=identifier>in </span><span class=identifier>f</span><span class=special>.</span><span class=identifier>bogons</span><span class=special>:
|
|
||||||
</span><span class=identifier>count</span><span class=special>(</span><span class=identifier>y</span><span class=special>)
|
|
||||||
</span></pre></code>
|
|
||||||
<p>
|
|
||||||
Now, our C++ Wrapper:</p>
|
|
||||||
<code><pre>
|
|
||||||
<span class=identifier>class_</span><span class=special><</span><span class=identifier>F</span><span class=special>>(</span><span class=string>"Field"</span><span class=special>)
|
|
||||||
.</span><span class=identifier>property</span><span class=special>(</span><span class=string>"pions"</span><span class=special>, </span><span class=identifier>range</span><span class=special>(&</span><span class=identifier>F</span><span class=special>::</span><span class=identifier>p_begin</span><span class=special>, &</span><span class=identifier>F</span><span class=special>::</span><span class=identifier>p_end</span><span class=special>))
|
|
||||||
.</span><span class=identifier>property</span><span class=special>(</span><span class=string>"bogons"</span><span class=special>, </span><span class=identifier>range</span><span class=special>(&</span><span class=identifier>F</span><span class=special>::</span><span class=identifier>b_begin</span><span class=special>, &</span><span class=identifier>F</span><span class=special>::</span><span class=identifier>b_end</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="using_the_interpreter.html"><img src="theme/l_arr.gif" border="0"></a></td>
|
|
||||||
<td width="20"><a href="exception_translation.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>
|
|
||||||
@@ -1,54 +0,0 @@
|
|||||||
<html>
|
|
||||||
<head>
|
|
||||||
<!-- Generated by the Spirit (http://spirit.sf.net) QuickDoc -->
|
|
||||||
<title>Object Interface</title>
|
|
||||||
<link rel="stylesheet" href="theme/style.css" type="text/css">
|
|
||||||
<link rel="prev" href="auto_overloading.html">
|
|
||||||
<link rel="next" href="basic_interface.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>Object Interface</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="auto_overloading.html"><img src="theme/l_arr.gif" border="0"></a></td>
|
|
||||||
<td width="20"><a href="basic_interface.html"><img src="theme/r_arr.gif" border="0"></a></td>
|
|
||||||
</tr>
|
|
||||||
</table>
|
|
||||||
<p>
|
|
||||||
Python is dynamically typed, unlike C++ which is statically typed. Python
|
|
||||||
variables may hold an integer, a float, list, dict, tuple, str, long etc.,
|
|
||||||
among other things. In the viewpoint of Boost.Python and C++, these
|
|
||||||
Pythonic variables are just instances of class <tt>object</tt>. We shall see in
|
|
||||||
this chapter how to deal with Python objects.</p>
|
|
||||||
<p>
|
|
||||||
As mentioned, one of the goals of Boost.Python is to provide a
|
|
||||||
bidirectional mapping between C++ and Python while maintaining the Python
|
|
||||||
feel. Boost.Python C++ <tt>object</tt>s are as close as possible to Python. This
|
|
||||||
should minimize the learning curve significantly.</p>
|
|
||||||
<p>
|
|
||||||
<img src="theme/python.png"></img></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="auto_overloading.html"><img src="theme/l_arr.gif" border="0"></a></td>
|
|
||||||
<td width="20"><a href="basic_interface.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>
|
|
||||||
@@ -1,88 +0,0 @@
|
|||||||
<html>
|
|
||||||
<head>
|
|
||||||
<!-- Generated by the Spirit (http://spirit.sf.net) QuickDoc -->
|
|
||||||
<title>Overloading</title>
|
|
||||||
<link rel="stylesheet" href="theme/style.css" type="text/css">
|
|
||||||
<link rel="prev" href="call_policies.html">
|
|
||||||
<link rel="next" href="default_arguments.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>Overloading</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="call_policies.html"><img src="theme/l_arr.gif" border="0"></a></td>
|
|
||||||
<td width="20"><a href="default_arguments.html"><img src="theme/r_arr.gif" border="0"></a></td>
|
|
||||||
</tr>
|
|
||||||
</table>
|
|
||||||
<p>
|
|
||||||
The following illustrates a scheme for manually wrapping an overloaded
|
|
||||||
member functions. Of course, the same technique can be applied to wrapping
|
|
||||||
overloaded non-member functions.</p>
|
|
||||||
<p>
|
|
||||||
We have here our C++ class:</p>
|
|
||||||
<code><pre>
|
|
||||||
<span class=keyword>struct </span><span class=identifier>X
|
|
||||||
</span><span class=special>{
|
|
||||||
</span><span class=keyword>bool </span><span class=identifier>f</span><span class=special>(</span><span class=keyword>int </span><span class=identifier>a</span><span class=special>)
|
|
||||||
{
|
|
||||||
</span><span class=keyword>return </span><span class=keyword>true</span><span class=special>;
|
|
||||||
}
|
|
||||||
|
|
||||||
</span><span class=keyword>bool </span><span class=identifier>f</span><span class=special>(</span><span class=keyword>int </span><span class=identifier>a</span><span class=special>, </span><span class=keyword>double </span><span class=identifier>b</span><span class=special>)
|
|
||||||
{
|
|
||||||
</span><span class=keyword>return </span><span class=keyword>true</span><span class=special>;
|
|
||||||
}
|
|
||||||
|
|
||||||
</span><span class=keyword>bool </span><span class=identifier>f</span><span class=special>(</span><span class=keyword>int </span><span class=identifier>a</span><span class=special>, </span><span class=keyword>double </span><span class=identifier>b</span><span class=special>, </span><span class=keyword>char </span><span class=identifier>c</span><span class=special>)
|
|
||||||
{
|
|
||||||
</span><span class=keyword>return </span><span class=keyword>true</span><span class=special>;
|
|
||||||
}
|
|
||||||
|
|
||||||
</span><span class=keyword>int </span><span class=identifier>f</span><span class=special>(</span><span class=keyword>int </span><span class=identifier>a</span><span class=special>, </span><span class=keyword>int </span><span class=identifier>b</span><span class=special>, </span><span class=keyword>int </span><span class=identifier>c</span><span class=special>)
|
|
||||||
{
|
|
||||||
</span><span class=keyword>return </span><span class=identifier>a </span><span class=special>+ </span><span class=identifier>b </span><span class=special>+ </span><span class=identifier>c</span><span class=special>;
|
|
||||||
};
|
|
||||||
};
|
|
||||||
</span></pre></code>
|
|
||||||
<p>
|
|
||||||
Class X has 4 overloaded functions. We shall start by introducing some
|
|
||||||
member function pointer variables:</p>
|
|
||||||
<code><pre>
|
|
||||||
<span class=keyword>bool </span><span class=special>(</span><span class=identifier>X</span><span class=special>::*</span><span class=identifier>fx1</span><span class=special>)(</span><span class=keyword>int</span><span class=special>) = &</span><span class=identifier>X</span><span class=special>::</span><span class=identifier>f</span><span class=special>;
|
|
||||||
</span><span class=keyword>bool </span><span class=special>(</span><span class=identifier>X</span><span class=special>::*</span><span class=identifier>fx2</span><span class=special>)(</span><span class=keyword>int</span><span class=special>, </span><span class=keyword>double</span><span class=special>) = &</span><span class=identifier>X</span><span class=special>::</span><span class=identifier>f</span><span class=special>;
|
|
||||||
</span><span class=keyword>bool </span><span class=special>(</span><span class=identifier>X</span><span class=special>::*</span><span class=identifier>fx3</span><span class=special>)(</span><span class=keyword>int</span><span class=special>, </span><span class=keyword>double</span><span class=special>, </span><span class=keyword>char</span><span class=special>)= &</span><span class=identifier>X</span><span class=special>::</span><span class=identifier>f</span><span class=special>;
|
|
||||||
</span><span class=keyword>int </span><span class=special>(</span><span class=identifier>X</span><span class=special>::*</span><span class=identifier>fx4</span><span class=special>)(</span><span class=keyword>int</span><span class=special>, </span><span class=keyword>int</span><span class=special>, </span><span class=keyword>int</span><span class=special>) = &</span><span class=identifier>X</span><span class=special>::</span><span class=identifier>f</span><span class=special>;
|
|
||||||
</span></pre></code>
|
|
||||||
<p>
|
|
||||||
With these in hand, we can proceed to define and wrap this for Python:</p>
|
|
||||||
<code><pre>
|
|
||||||
<span class=special>.</span><span class=identifier>def</span><span class=special>(</span><span class=string>"f"</span><span class=special>, </span><span class=identifier>fx1</span><span class=special>)
|
|
||||||
.</span><span class=identifier>def</span><span class=special>(</span><span class=string>"f"</span><span class=special>, </span><span class=identifier>fx2</span><span class=special>)
|
|
||||||
.</span><span class=identifier>def</span><span class=special>(</span><span class=string>"f"</span><span class=special>, </span><span class=identifier>fx3</span><span class=special>)
|
|
||||||
.</span><span class=identifier>def</span><span class=special>(</span><span class=string>"f"</span><span class=special>, </span><span class=identifier>fx4</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="call_policies.html"><img src="theme/l_arr.gif" border="0"></a></td>
|
|
||||||
<td width="20"><a href="default_arguments.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>
|
|
||||||
@@ -1,79 +0,0 @@
|
|||||||
<html>
|
|
||||||
<head>
|
|
||||||
<!-- Generated by the Spirit (http://spirit.sf.net) QuickDoc -->
|
|
||||||
<title>QuickStart</title>
|
|
||||||
<link rel="stylesheet" href="theme/style.css" type="text/css">
|
|
||||||
<link rel="next" href="building_hello_world.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>QuickStart</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"><img src="theme/l_arr_disabled.gif" border="0"></td>
|
|
||||||
<td width="20"><a href="building_hello_world.html"><img src="theme/r_arr.gif" border="0"></a></td>
|
|
||||||
</tr>
|
|
||||||
</table>
|
|
||||||
<p>
|
|
||||||
The Boost Python Library is a framework for interfacing Python and
|
|
||||||
C++. It allows you to quickly and seamlessly expose C++ classes
|
|
||||||
functions and objects to Python, and vice-versa, using no special
|
|
||||||
tools -- just your C++ compiler. It is designed to wrap C++ interfaces
|
|
||||||
non-intrusively, so that you should not have to change the C++ code at
|
|
||||||
all in order to wrap it, making Boost.Python ideal for exposing
|
|
||||||
3rd-party libraries to Python. The library's use of advanced
|
|
||||||
metaprogramming techniques simplifies its syntax for users, so that
|
|
||||||
wrapping code takes on the look of a kind of declarative interface
|
|
||||||
definition language (IDL).</p>
|
|
||||||
<a name="hello_world"></a><h2>Hello World</h2><p>
|
|
||||||
Following C/C++ tradition, let's start with the "hello, world". A C++
|
|
||||||
Function:</p>
|
|
||||||
<code><pre>
|
|
||||||
<span class=keyword>char </span><span class=keyword>const</span><span class=special>* </span><span class=identifier>greet</span><span class=special>()
|
|
||||||
{
|
|
||||||
</span><span class=keyword>return </span><span class=string>"hello, world"</span><span class=special>;
|
|
||||||
}
|
|
||||||
</span></pre></code>
|
|
||||||
<p>
|
|
||||||
can be exposed to Python by writing a Boost.Python wrapper:</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=keyword>using </span><span class=keyword>namespace </span><span class=identifier>boost</span><span class=special>::</span><span class=identifier>python</span><span class=special>;
|
|
||||||
|
|
||||||
</span><span class=identifier>BOOST_PYTHON_MODULE</span><span class=special>(</span><span class=identifier>hello</span><span class=special>)
|
|
||||||
{
|
|
||||||
</span><span class=identifier>def</span><span class=special>(</span><span class=string>"greet"</span><span class=special>, </span><span class=identifier>greet</span><span class=special>);
|
|
||||||
}
|
|
||||||
</span></pre></code>
|
|
||||||
<p>
|
|
||||||
That's it. We're done. We can now build this as a shared library. The
|
|
||||||
resulting DLL is now visible to Python. Here's a sample Python session:</p>
|
|
||||||
<code><pre>
|
|
||||||
<span class=special>>>> </span><span class=identifier>import </span><span class=identifier>hello
|
|
||||||
</span><span class=special>>>> </span><span class=identifier>print </span><span class=identifier>hello</span><span class=special>.</span><span class=identifier>greet</span><span class=special>()
|
|
||||||
</span><span class=identifier>hello</span><span class=special>, </span><span class=identifier>world
|
|
||||||
</span></pre></code>
|
|
||||||
<blockquote><p><i><b>Next stop... Building your Hello World module from start to finish...</b></i></p></blockquote><table border="0">
|
|
||||||
<tr>
|
|
||||||
<td width="30"><a href="../index.html"><img src="theme/u_arr.gif" border="0"></a></td>
|
|
||||||
<td width="30"><img src="theme/l_arr_disabled.gif" border="0"></td>
|
|
||||||
<td width="20"><a href="building_hello_world.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>
|
|
||||||
BIN
doc/tutorial/doc/theme/alert.gif
vendored
|
Before Width: | Height: | Size: 577 B |
BIN
doc/tutorial/doc/theme/arrow.gif
vendored
|
Before Width: | Height: | Size: 70 B |
BIN
doc/tutorial/doc/theme/bkd.gif
vendored
|
Before Width: | Height: | Size: 1.3 KiB |
BIN
doc/tutorial/doc/theme/bkd2.gif
vendored
|
Before Width: | Height: | Size: 2.5 KiB |
BIN
doc/tutorial/doc/theme/bulb.gif
vendored
|
Before Width: | Height: | Size: 944 B |
BIN
doc/tutorial/doc/theme/bullet.gif
vendored
|
Before Width: | Height: | Size: 152 B |
BIN
doc/tutorial/doc/theme/c++boost.gif
vendored
|
Before Width: | Height: | Size: 8.6 KiB |
BIN
doc/tutorial/doc/theme/l_arr.gif
vendored
|
Before Width: | Height: | Size: 147 B |
BIN
doc/tutorial/doc/theme/l_arr_disabled.gif
vendored
|
Before Width: | Height: | Size: 91 B |
BIN
doc/tutorial/doc/theme/lens.gif
vendored
|
Before Width: | Height: | Size: 897 B |
BIN
doc/tutorial/doc/theme/note.gif
vendored
|
Before Width: | Height: | Size: 151 B |
BIN
doc/tutorial/doc/theme/r_arr.gif
vendored
|
Before Width: | Height: | Size: 147 B |
BIN
doc/tutorial/doc/theme/r_arr_disabled.gif
vendored
|
Before Width: | Height: | Size: 91 B |
BIN
doc/tutorial/doc/theme/smiley.gif
vendored
|
Before Width: | Height: | Size: 879 B |
170
doc/tutorial/doc/theme/style.css
vendored
@@ -1,170 +0,0 @@
|
|||||||
body
|
|
||||||
{
|
|
||||||
background-image: url(bkd.gif);
|
|
||||||
background-color: #FFFFFF;
|
|
||||||
margin: 1em 2em 1em 2em;
|
|
||||||
}
|
|
||||||
|
|
||||||
h1 { font-family: Verdana, Arial, Helvetica, sans-serif; font-weight: bold; text-align: left; }
|
|
||||||
h2 { font: 140% sans-serif; font-weight: bold; text-align: left; }
|
|
||||||
h3 { font: 120% sans-serif; font-weight: bold; text-align: left; }
|
|
||||||
h4 { font: bold 100% sans-serif; font-weight: bold; text-align: left; }
|
|
||||||
h5 { font: italic 100% sans-serif; font-weight: bold; text-align: left; }
|
|
||||||
h6 { font: small-caps 100% sans-serif; font-weight: bold; text-align: left; }
|
|
||||||
|
|
||||||
pre
|
|
||||||
{
|
|
||||||
border-top: gray 1pt solid;
|
|
||||||
border-right: gray 1pt solid;
|
|
||||||
border-left: gray 1pt solid;
|
|
||||||
border-bottom: gray 1pt solid;
|
|
||||||
|
|
||||||
padding-top: 2pt;
|
|
||||||
padding-right: 2pt;
|
|
||||||
padding-left: 2pt;
|
|
||||||
padding-bottom: 2pt;
|
|
||||||
|
|
||||||
display: block;
|
|
||||||
font-family: "courier new", courier, mono;
|
|
||||||
background-color: #eeeeee; font-size: small
|
|
||||||
}
|
|
||||||
|
|
||||||
code
|
|
||||||
{
|
|
||||||
font-family: "Courier New", Courier, mono;
|
|
||||||
font-size: small
|
|
||||||
}
|
|
||||||
|
|
||||||
tt
|
|
||||||
{
|
|
||||||
display: inline;
|
|
||||||
font-family: "Courier New", Courier, mono;
|
|
||||||
color: #000099;
|
|
||||||
font-size: small
|
|
||||||
}
|
|
||||||
|
|
||||||
p
|
|
||||||
{
|
|
||||||
text-align: justify;
|
|
||||||
font-family: Georgia, "Times New Roman", Times, serif
|
|
||||||
}
|
|
||||||
|
|
||||||
ul
|
|
||||||
{
|
|
||||||
list-style-image: url(bullet.gif);
|
|
||||||
font-family: Georgia, "Times New Roman", Times, serif
|
|
||||||
}
|
|
||||||
|
|
||||||
ol
|
|
||||||
{
|
|
||||||
font-family: Georgia, "Times New Roman", Times, serif
|
|
||||||
}
|
|
||||||
|
|
||||||
a
|
|
||||||
{
|
|
||||||
font-weight: bold;
|
|
||||||
color: #003366;
|
|
||||||
text-decoration: none;
|
|
||||||
}
|
|
||||||
|
|
||||||
a:hover { color: #8080FF; }
|
|
||||||
|
|
||||||
.literal { color: #666666; font-style: italic}
|
|
||||||
.keyword { color: #000099}
|
|
||||||
.identifier {}
|
|
||||||
.comment { font-style: italic; color: #990000}
|
|
||||||
.special { color: #800040}
|
|
||||||
.preprocessor { color: #FF0000}
|
|
||||||
.string { font-style: italic; color: #666666}
|
|
||||||
.copyright { color: #666666; font-size: small}
|
|
||||||
.white_bkd { background-color: #FFFFFF}
|
|
||||||
.dk_grey_bkd { background-color: #999999}
|
|
||||||
.quotes { color: #666666; font-style: italic; font-weight: bold}
|
|
||||||
|
|
||||||
.note_box
|
|
||||||
{
|
|
||||||
display: block;
|
|
||||||
|
|
||||||
border-top: gray 1pt solid;
|
|
||||||
border-right: gray 1pt solid;
|
|
||||||
border-left: gray 1pt solid;
|
|
||||||
border-bottom: gray 1pt solid;
|
|
||||||
|
|
||||||
padding-right: 12pt;
|
|
||||||
padding-left: 12pt;
|
|
||||||
padding-bottom: 12pt;
|
|
||||||
padding-top: 12pt;
|
|
||||||
|
|
||||||
font-family: Arial, Helvetica, sans-serif;
|
|
||||||
background-color: #E2E9EF;
|
|
||||||
font-size: small; text-align: justify
|
|
||||||
}
|
|
||||||
|
|
||||||
.table_title
|
|
||||||
{
|
|
||||||
background-color: #648CCA;
|
|
||||||
|
|
||||||
font-family: Verdana, Arial, Helvetica, sans-serif; color: #FFFFFF;
|
|
||||||
font-weight: bold
|
|
||||||
; padding-top: 4px; padding-right: 4px; padding-bottom: 4px; padding-left: 4px
|
|
||||||
}
|
|
||||||
|
|
||||||
.table_cells
|
|
||||||
{
|
|
||||||
background-color: #E2E9EF;
|
|
||||||
|
|
||||||
font-family: Geneva, Arial, Helvetica, san-serif;
|
|
||||||
font-size: small
|
|
||||||
; padding-top: 4px; padding-right: 4px; padding-bottom: 4px; padding-left: 4px
|
|
||||||
}
|
|
||||||
|
|
||||||
.toc
|
|
||||||
{
|
|
||||||
DISPLAY: block;
|
|
||||||
background-color: #E2E9EF
|
|
||||||
font-family: Arial, Helvetica, sans-serif;
|
|
||||||
|
|
||||||
border-top: gray 1pt solid;
|
|
||||||
border-left: gray 1pt solid;
|
|
||||||
border-bottom: gray 1pt solid;
|
|
||||||
border-right: gray 1pt solid;
|
|
||||||
|
|
||||||
padding-top: 24pt;
|
|
||||||
padding-right: 24pt;
|
|
||||||
padding-left: 24pt;
|
|
||||||
padding-bottom: 24pt;
|
|
||||||
}
|
|
||||||
|
|
||||||
.toc_title
|
|
||||||
{
|
|
||||||
background-color: #648CCA;
|
|
||||||
padding-top: 4px;
|
|
||||||
padding-right: 4px;
|
|
||||||
padding-bottom: 4px;
|
|
||||||
padding-left: 4px;
|
|
||||||
font-family: Geneva, Arial, Helvetica, san-serif;
|
|
||||||
color: #FFFFFF;
|
|
||||||
font-weight: bold
|
|
||||||
}
|
|
||||||
|
|
||||||
.toc_cells
|
|
||||||
{
|
|
||||||
background-color: #E2E9EF;
|
|
||||||
padding-top: 4px;
|
|
||||||
padding-right: 4px;
|
|
||||||
padding-bottom: 4px;
|
|
||||||
padding-left: 4px;
|
|
||||||
font-family: Geneva, Arial, Helvetica, san-serif;
|
|
||||||
font-size: small
|
|
||||||
}
|
|
||||||
|
|
||||||
div.logo
|
|
||||||
{
|
|
||||||
float: right;
|
|
||||||
}
|
|
||||||
|
|
||||||
.toc_cells_L0 { background-color: #E2E9EF; padding-top: 4px; padding-right: 4px; padding-bottom: 4px; padding-left: 4px; font-family: Geneva, Arial, Helvetica, san-serif; font-size: small }
|
|
||||||
.toc_cells_L1 { background-color: #E2E9EF; padding-top: 4px; padding-right: 4px; padding-bottom: 4px; padding-left: 44px; font-family: Geneva, Arial, Helvetica, san-serif; font-size: small }
|
|
||||||
.toc_cells_L2 { background-color: #E2E9EF; padding-top: 4px; padding-right: 4px; padding-bottom: 4px; padding-left: 88px; font-family: Geneva, Arial, Helvetica, san-serif; font-size: small }
|
|
||||||
.toc_cells_L3 { background-color: #E2E9EF; padding-top: 4px; padding-right: 4px; padding-bottom: 4px; padding-left: 122px; font-family: Geneva, Arial, Helvetica, san-serif; font-size: small }
|
|
||||||
.toc_cells_L4 { background-color: #E2E9EF; padding-top: 4px; padding-right: 4px; padding-bottom: 4px; padding-left: 166px; font-family: Geneva, Arial, Helvetica, san-serif; font-size: small }
|
|
||||||
BIN
doc/tutorial/doc/theme/u_arr.gif
vendored
|
Before Width: | Height: | Size: 170 B |
@@ -1,238 +0,0 @@
|
|||||||
<html>
|
|
||||||
<head>
|
|
||||||
<!-- Generated by the Spirit (http://spirit.sf.net) QuickDoc -->
|
|
||||||
<title>Using the interpreter</title>
|
|
||||||
<link rel="stylesheet" href="theme/style.css" type="text/css">
|
|
||||||
<link rel="prev" href="embedding.html">
|
|
||||||
<link rel="next" href="iterators.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>Using the interpreter</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="embedding.html"><img src="theme/l_arr.gif" border="0"></a></td>
|
|
||||||
<td width="20"><a href="iterators.html"><img src="theme/r_arr.gif" border="0"></a></td>
|
|
||||||
</tr>
|
|
||||||
</table>
|
|
||||||
<p>
|
|
||||||
As you probably already know, objects in Python are reference-counted.
|
|
||||||
Naturally, the <tt>PyObject</tt>s of the Python/C API are also reference-counted.
|
|
||||||
There is a difference however. While the reference-counting is fully
|
|
||||||
automatic in Python, the Python/C API requires you to do it
|
|
||||||
<a href="http://www.python.org/doc/current/api/refcounts.html">
|
|
||||||
by hand</a>. This is
|
|
||||||
messy and especially hard to get right in the presence of C++ exceptions.
|
|
||||||
Fortunately Boost.Python provides the <a href="../../v2/handle.html">
|
|
||||||
handle</a> class
|
|
||||||
template to automate the process.</p>
|
|
||||||
<a name="reference_counting_handles"></a><h2>Reference-counting handles</h2><p>
|
|
||||||
There are two ways in which a function in the Python/C API can return a
|
|
||||||
<tt>PyObject*</tt>: as a <i>borrowed reference</i> or as a <i>new reference</i>. 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.</p>
|
|
||||||
<p>
|
|
||||||
For a function returning a <i>borrowed reference</i> we'll have to tell the
|
|
||||||
<tt>handle</tt> that the <tt>PyObject*</tt> is borrowed with the aptly named
|
|
||||||
<a href="../../v2/handle.html#borrowed-spec">
|
|
||||||
borrowed</a> function. Two functions
|
|
||||||
returning borrowed references are <a href="http://www.python.org/doc/current/api/importing.html#l2h-125">
|
|
||||||
PyImport_AddModule</a> and <a href="http://www.python.org/doc/current/api/moduleObjects.html#l2h-594">
|
|
||||||
PyModule_GetDict</a>.
|
|
||||||
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 <tt>__main__</tt> module:</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>handle</span><span class=special><> </span><span class=identifier>main_namespace</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></pre></code>
|
|
||||||
<p>
|
|
||||||
Because the Python/C API doesn't know anything about <tt>handle</tt>s, we used
|
|
||||||
the <a href="../../v2/handle.html#handle-spec-observers">
|
|
||||||
get</a> member function to
|
|
||||||
retrieve the <tt>PyObject*</tt> from which the <tt>handle</tt> was constructed.</p>
|
|
||||||
<p>
|
|
||||||
For a function returning a <i>new reference</i> we can just create a <tt>handle</tt>
|
|
||||||
out of the raw <tt>PyObject*</tt> without wrapping it in a call to borrowed. One
|
|
||||||
such function that returns a new reference is <a href="http://www.python.org/doc/current/api/veryhigh.html#l2h-55">
|
|
||||||
PyRun_String</a> which we'll
|
|
||||||
discuss in the next section.</p>
|
|
||||||
<table width="80%" border="0" align="center">
|
|
||||||
<tr>
|
|
||||||
<td class="note_box">
|
|
||||||
<img src="theme/lens.gif"></img> <b>Handle is a class <i>template</i>, so why haven't we been using any template parameters?</b><br>
|
|
||||||
<br>
|
|
||||||
<tt>handle</tt> has a single template parameter specifying the type of the managed object. This type is <tt>PyObject</tt> 99% of the time, so the parameter was defaulted to <tt>PyObject</tt> for convenience. Therefore we can use the shorthand <tt>handle<></tt> instead of the longer, but equivalent, <tt>handle<PyObject></tt>.
|
|
||||||
</td>
|
|
||||||
</tr>
|
|
||||||
</table>
|
|
||||||
<a name="running_python_code"></a><h2>Running Python code</h2><p>
|
|
||||||
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 <a href="http://www.python.org/doc/current/api/veryhigh.html">
|
|
||||||
here</a>. They
|
|
||||||
all work similarly so we will look at only one of them, namely:</p>
|
|
||||||
<code><pre>
|
|
||||||
<span class=identifier>PyObject</span><span class=special>* </span><span class=identifier>PyRun_String</span><span class=special>(</span><span class=keyword>char </span><span class=special>*</span><span class=identifier>str</span><span class=special>, </span><span class=keyword>int </span><span class=identifier>start</span><span class=special>, </span><span class=identifier>PyObject </span><span class=special>*</span><span class=identifier>globals</span><span class=special>, </span><span class=identifier>PyObject </span><span class=special>*</span><span class=identifier>locals</span><span class=special>)
|
|
||||||
</span></pre></code>
|
|
||||||
<p>
|
|
||||||
<a href="http://www.python.org/doc/current/api/veryhigh.html#l2h-55">
|
|
||||||
PyRun_String</a> takes the code to execute as a null-terminated (C-style)
|
|
||||||
string in its <tt>str</tt> parameter. The function returns a new reference to a
|
|
||||||
Python object. Which object is returned depends on the <tt>start</tt> paramater.</p>
|
|
||||||
<p>
|
|
||||||
The <tt>start</tt> parameter is the start symbol from the Python grammar to use
|
|
||||||
for interpreting the code. The possible values are:</p>
|
|
||||||
<table width="90%" border="0" align="center"> <tr>
|
|
||||||
<td class="table_title" colspan="6">
|
|
||||||
Start symbols </td>
|
|
||||||
</tr>
|
|
||||||
<tr><tr><td class="table_cells"><a href="http://www.python.org/doc/current/api/veryhigh.html#l2h-58">
|
|
||||||
Py_eval_input</a></td><td class="table_cells">for interpreting isolated expressions</td></tr><td class="table_cells"><a href="http://www.python.org/doc/current/api/veryhigh.html#l2h-59">
|
|
||||||
Py_file_input</a></td><td class="table_cells">for interpreting sequences of statements</td></tr><td class="table_cells"><a href="http://www.python.org/doc/current/api/veryhigh.html#l2h-60">
|
|
||||||
Py_single_input</a></td><td class="table_cells">for interpreting a single statement</td></tr></table>
|
|
||||||
<p>
|
|
||||||
When using <a href="http://www.python.org/doc/current/api/veryhigh.html#l2h-58">
|
|
||||||
Py_eval_input</a>, the input string must contain a single expression
|
|
||||||
and its result is returned. When using <a href="http://www.python.org/doc/current/api/veryhigh.html#l2h-59">
|
|
||||||
Py_file_input</a>, the string can
|
|
||||||
contain an abitrary number of statements and None is returned.
|
|
||||||
<a href="http://www.python.org/doc/current/api/veryhigh.html#l2h-60">
|
|
||||||
Py_single_input</a> works in the same way as <a href="http://www.python.org/doc/current/api/veryhigh.html#l2h-59">
|
|
||||||
Py_file_input</a> but only accepts a
|
|
||||||
single statement.</p>
|
|
||||||
<p>
|
|
||||||
Lastly, the <tt>globals</tt> and <tt>locals</tt> parameters are Python dictionaries
|
|
||||||
containing the globals and locals of the context in which to run the code.
|
|
||||||
For most intents and purposes you can use the namespace dictionary of the
|
|
||||||
<tt>__main__</tt> module for both parameters.</p>
|
|
||||||
<p>
|
|
||||||
We have already seen how to get the <tt>__main__</tt> module's namespace so let's
|
|
||||||
run some Python code in it:</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>handle</span><span class=special><> </span><span class=identifier>main_namespace</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>"hello = file('hello.txt', 'w')\n"
|
|
||||||
</span><span class=string>"hello.write('Hello world!')\n"
|
|
||||||
</span><span class=string>"hello.close()"</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>get</span><span class=special>(), </span><span class=identifier>main_namespace</span><span class=special>.</span><span class=identifier>get</span><span class=special>()) );
|
|
||||||
</span></pre></code>
|
|
||||||
<p>
|
|
||||||
This should create a file called 'hello.txt' in the current directory
|
|
||||||
containing a phrase that is well-known in programming circles.</p>
|
|
||||||
<p>
|
|
||||||
<img src="theme/note.gif"></img> <b>Note</b> that we wrap the return value of <a href="http://www.python.org/doc/current/api/veryhigh.html#l2h-55">
|
|
||||||
PyRun_String</a> in a
|
|
||||||
(nameless) <tt>handle</tt> 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 <tt>PyObject*</tt>s in <tt>handle</tt>s.</p>
|
|
||||||
<a name="beyond_handles"></a><h2>Beyond handles</h2><p>
|
|
||||||
It's nice that <tt>handle</tt> 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 <a href="object_interface.html">
|
|
||||||
previous section</a>: the aptly named <tt>object</tt>
|
|
||||||
class and it's derivatives. What we haven't seen, is that they can be
|
|
||||||
constructed from a <tt>handle</tt>. The following examples should illustrate this
|
|
||||||
fact:</p>
|
|
||||||
<code>
|
|
||||||
<pre>
|
|
||||||
<span class=identifier>handle</span><span class=special><> </span><span class=identifier>main_module</span><span class=special>(</span><span class=identifier>borrowed</span><span class=special>( </span><span class=identifier>PyImport_AddModule</span><span class=special>(</span><span class=string>"__main__"</span><span class=special>) ));
|
|
||||||
</span><span class=identifier>dict </span><span class=identifier>main_namespace</span><span class=special>(</span><span class=identifier>handle</span><span class=special><>(</span><span class=identifier>borrowed</span><span class=special>( </span><span class=identifier>PyModule_GetDict</span><span class=special>(</span><span class=identifier>main_module</span><span class=special>.</span><span class=identifier>get</span><span class=special>()) )));
|
|
||||||
</span><span class=identifier>handle</span><span class=special><>( </span><span class=identifier>PyRun_String</span><span class=special>(</span><span class=string>"result = 5 ** 2"</span><span class=special>, </span><span class=identifier>Py_file_input</span><span class=special>,
|
|
||||||
</span><span class=identifier>main_namespace</span><span class=special>.</span><span class=identifier>ptr</span><span class=special>(), </span><span class=identifier>main_namespace</span><span class=special>.</span><span class=identifier>ptr</span><span class=special>()) );
|
|
||||||
</span><span class=keyword>int </span><span class=identifier>five_squared </span><span class=special>= </span><span class=identifier>extract</span><span class=special><</span><span class=keyword>int</span><span class=special>>( </span><span class=identifier>main_namespace</span><span class=special>[</span><span class=string>"result"</span><span class=special>] );
|
|
||||||
</span></pre>
|
|
||||||
</code>
|
|
||||||
<p>
|
|
||||||
Here we create a dictionary object for the <tt>__main__</tt> module's namespace.
|
|
||||||
Then we assign 5 squared to the result variable and read this variable from
|
|
||||||
the dictionary. Another way to achieve the same result is to let
|
|
||||||
<a href="http://www.python.org/doc/current/api/veryhigh.html#l2h-55">
|
|
||||||
PyRun_String</a> return the result directly with <a href="http://www.python.org/doc/current/api/veryhigh.html#l2h-58">
|
|
||||||
Py_eval_input</a>:</p>
|
|
||||||
<code><pre>
|
|
||||||
<span class=identifier>object </span><span class=identifier>result</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>"5 ** 2"</span><span class=special>, </span><span class=identifier>Py_eval_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>result</span><span class=special>);
|
|
||||||
</span></pre></code>
|
|
||||||
<p>
|
|
||||||
<img src="theme/note.gif"></img> <b>Note</b> that <tt>object</tt>'s member function to return the wrapped
|
|
||||||
<tt>PyObject*</tt> is called <tt>ptr</tt> instead of <tt>get</tt>. This makes sense if you
|
|
||||||
take into account the different functions that <tt>object</tt> and <tt>handle</tt>
|
|
||||||
perform.</p>
|
|
||||||
<a name="exception_handling"></a><h2>Exception handling</h2><p>
|
|
||||||
If an exception occurs in the execution of some Python code, the <a href="http://www.python.org/doc/current/api/veryhigh.html#l2h-55">
|
|
||||||
PyRun_String</a> function returns a null pointer. Constructing a <tt>handle</tt> out of this null pointer throws <a href="../../v2/errors.html#error_already_set-spec">
|
|
||||||
error_already_set</a>, so basically, the Python exception is automatically translated into a C++ exception when using <tt>handle</tt>:</p>
|
|
||||||
<code><pre>
|
|
||||||
<span class=keyword>try
|
|
||||||
</span><span class=special>{
|
|
||||||
</span><span class=identifier>object </span><span class=identifier>result</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>"5/0"</span><span class=special>, </span><span class=identifier>Py_eval_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=identifier>execution </span><span class=identifier>will </span><span class=identifier>never </span><span class=identifier>get </span><span class=identifier>here</span><span class=special>:
|
|
||||||
</span><span class=keyword>int </span><span class=identifier>five_divided_by_zero </span><span class=special>= </span><span class=identifier>extract</span><span class=special><</span><span class=keyword>int</span><span class=special>>(</span><span class=identifier>result</span><span class=special>);
|
|
||||||
}
|
|
||||||
</span><span class=keyword>catch</span><span class=special>(</span><span class=identifier>error_already_set</span><span class=special>)
|
|
||||||
{
|
|
||||||
// </span><span class=identifier>handle </span><span class=identifier>the </span><span class=identifier>exception </span><span class=identifier>in </span><span class=identifier>some </span><span class=identifier>way
|
|
||||||
</span><span class=special>}
|
|
||||||
</span></pre></code>
|
|
||||||
<p>
|
|
||||||
The <tt>error_already_set</tt> exception class doesn't carry any information in itself. To find out more about the Python exception that occurred, you need to use the <a href="http://www.python.org/doc/api/exceptionHandling.html">
|
|
||||||
exception handling functions</a> of the Python/C API in your catch-statement. This can be as simple as calling <a href="http://www.python.org/doc/api/exceptionHandling.html#l2h-70">
|
|
||||||
PyErr_Print()</a> to print the exception's traceback to the console, or comparing the type of the exception with those of the <a href="http://www.python.org/doc/api/standardExceptions.html">
|
|
||||||
standard exceptions</a>:</p>
|
|
||||||
<code><pre>
|
|
||||||
<span class=keyword>catch</span><span class=special>(</span><span class=identifier>error_already_set</span><span class=special>)
|
|
||||||
{
|
|
||||||
</span><span class=keyword>if </span><span class=special>(</span><span class=identifier>PyErr_ExceptionMatches</span><span class=special>(</span><span class=identifier>PyExc_ZeroDivisionError</span><span class=special>))
|
|
||||||
{
|
|
||||||
// </span><span class=identifier>handle </span><span class=identifier>ZeroDivisionError </span><span class=identifier>specially
|
|
||||||
</span><span class=special>}
|
|
||||||
</span><span class=keyword>else
|
|
||||||
</span><span class=special>{
|
|
||||||
// </span><span class=identifier>print </span><span class=identifier>all </span><span class=identifier>other </span><span class=identifier>errors </span><span class=identifier>to </span><span class=identifier>stderr
|
|
||||||
</span><span class=identifier>PyErr_Print</span><span class=special>();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
</span></pre></code>
|
|
||||||
<p>
|
|
||||||
(To retrieve even more information from the exception you can use some of the other exception handling functions listed <a href="http://www.python.org/doc/api/exceptionHandling.html">
|
|
||||||
here</a>.)</p>
|
|
||||||
<p>
|
|
||||||
If you'd rather not have <tt>handle</tt> throw a C++ exception when it is constructed, you can use the <a href="../../v2/handle.html#allow_null-spec">
|
|
||||||
allow_null</a> function in the same way you'd use borrowed:</p>
|
|
||||||
<code><pre>
|
|
||||||
<span class=identifier>handle</span><span class=special><> </span><span class=identifier>result</span><span class=special>(</span><span class=identifier>allow_null</span><span class=special>( </span><span class=identifier>PyRun_String</span><span class=special>(</span><span class=string>"5/0"</span><span class=special>, </span><span class=identifier>Py_eval_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>if </span><span class=special>(!</span><span class=identifier>result</span><span class=special>)
|
|
||||||
// </span><span class=identifier>Python </span><span class=identifier>exception </span><span class=identifier>occurred
|
|
||||||
</span><span class=keyword>else
|
|
||||||
</span><span class=comment>// everything went okay, it's safe to use the result
|
|
||||||
</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="embedding.html"><img src="theme/l_arr.gif" border="0"></a></td>
|
|
||||||
<td width="20"><a href="iterators.html"><img src="theme/r_arr.gif" border="0"></a></td>
|
|
||||||
</tr>
|
|
||||||
</table>
|
|
||||||
<br>
|
|
||||||
<hr size="1"><p class="copyright">Copyright © 2002-2003 Dirk Gerrits<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>
|
|
||||||
@@ -1,122 +0,0 @@
|
|||||||
<html>
|
|
||||||
<head>
|
|
||||||
<!-- Generated by the Spirit (http://spirit.sf.net) QuickDoc -->
|
|
||||||
<title>Virtual Functions with Default Implementations</title>
|
|
||||||
<link rel="stylesheet" href="theme/style.css" type="text/css">
|
|
||||||
<link rel="prev" href="deriving_a_python_class.html">
|
|
||||||
<link rel="next" href="class_operators_special_functions.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>Virtual Functions with Default Implementations</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="deriving_a_python_class.html"><img src="theme/l_arr.gif" border="0"></a></td>
|
|
||||||
<td width="20"><a href="class_operators_special_functions.html"><img src="theme/r_arr.gif" border="0"></a></td>
|
|
||||||
</tr>
|
|
||||||
</table>
|
|
||||||
<p>
|
|
||||||
Recall that in the <a href="class_virtual_functions.html">
|
|
||||||
previous section</a>, we
|
|
||||||
wrapped a class with a pure virtual function that we then implemented in
|
|
||||||
C++ or Python classes derived from it. Our base class:</p>
|
|
||||||
<code><pre>
|
|
||||||
<span class=keyword>struct </span><span class=identifier>Base
|
|
||||||
</span><span class=special>{
|
|
||||||
</span><span class=keyword>virtual </span><span class=keyword>int </span><span class=identifier>f</span><span class=special>() = </span><span class=number>0</span><span class=special>;
|
|
||||||
};
|
|
||||||
</span></pre></code>
|
|
||||||
<p>
|
|
||||||
had a pure virtual function <tt>f</tt>. If, however, its member function <tt>f</tt> was
|
|
||||||
not declared as pure virtual:</p>
|
|
||||||
<code><pre>
|
|
||||||
<span class=keyword>struct </span><span class=identifier>Base
|
|
||||||
</span><span class=special>{
|
|
||||||
</span><span class=keyword>virtual </span><span class=keyword>int </span><span class=identifier>f</span><span class=special>() { </span><span class=keyword>return </span><span class=number>0</span><span class=special>; }
|
|
||||||
};
|
|
||||||
</span></pre></code>
|
|
||||||
<p>
|
|
||||||
and instead had a default implementation that returns <tt>0</tt>, as shown above,
|
|
||||||
we need to add a forwarding function that calls the <tt>Base</tt> default virtual
|
|
||||||
function <tt>f</tt> implementation:</p>
|
|
||||||
<code><pre>
|
|
||||||
<span class=keyword>struct </span><span class=identifier>BaseWrap </span><span class=special>: </span><span class=identifier>Base
|
|
||||||
</span><span class=special>{
|
|
||||||
</span><span class=identifier>BaseWrap</span><span class=special>(</span><span class=identifier>PyObject</span><span class=special>* </span><span class=identifier>self_</span><span class=special>)
|
|
||||||
: </span><span class=identifier>self</span><span class=special>(</span><span class=identifier>self_</span><span class=special>) {}
|
|
||||||
</span><span class=keyword>int </span><span class=identifier>f</span><span class=special>() { </span><span class=keyword>return </span><span class=identifier>call_method</span><span class=special><</span><span class=keyword>int</span><span class=special>>(</span><span class=identifier>self</span><span class=special>, </span><span class=string>"f"</span><span class=special>); }
|
|
||||||
</span><span class=keyword>int </span><span class=identifier>default_f</span><span class=special>() { </span><span class=keyword>return </span><span class=identifier>Base</span><span class=special>::</span><span class=identifier>f</span><span class=special>(); } // <<=== ***</span><span class=identifier>ADDED</span><span class=special>***
|
|
||||||
</span><span class=identifier>PyObject</span><span class=special>* </span><span class=identifier>self</span><span class=special>;
|
|
||||||
};
|
|
||||||
</span></pre></code>
|
|
||||||
<p>
|
|
||||||
Then, Boost.Python needs to keep track of 1) the dispatch function <tt>f</tt> and
|
|
||||||
2) the forwarding function to its default implementation <tt>default_f</tt>.
|
|
||||||
There's a special <tt>def</tt> function for this purpose. Here's how it is
|
|
||||||
applied to our example above:</p>
|
|
||||||
<code><pre>
|
|
||||||
<span class=identifier>class_</span><span class=special><</span><span class=identifier>Base</span><span class=special>, </span><span class=identifier>BaseWrap</span><span class=special>>(</span><span class=string>"Base"</span><span class=special>)
|
|
||||||
.</span><span class=identifier>def</span><span class=special>(</span><span class=string>"f"</span><span class=special>, &</span><span class=identifier>Base</span><span class=special>::</span><span class=identifier>f</span><span class=special>, &</span><span class=identifier>BaseWrap</span><span class=special>::</span><span class=identifier>default_f</span><span class=special>)
|
|
||||||
</span></pre></code>
|
|
||||||
<p>
|
|
||||||
Note that we are allowing <tt>Base</tt> objects to be instantiated this time,
|
|
||||||
unlike before where we specifically defined the <tt>class_<Base></tt> with
|
|
||||||
<tt>no_init</tt>.</p>
|
|
||||||
<p>
|
|
||||||
In Python, the results would be as expected:</p>
|
|
||||||
<code><pre>
|
|
||||||
<span class=special>>>> </span><span class=identifier>base </span><span class=special>= </span><span class=identifier>Base</span><span class=special>()
|
|
||||||
>>> </span><span class=keyword>class </span><span class=identifier>Derived</span><span class=special>(</span><span class=identifier>Base</span><span class=special>):
|
|
||||||
... </span><span class=identifier>def </span><span class=identifier>f</span><span class=special>(</span><span class=identifier>self</span><span class=special>):
|
|
||||||
... </span><span class=keyword>return </span><span class=number>42
|
|
||||||
</span><span class=special>...
|
|
||||||
>>> </span><span class=identifier>derived </span><span class=special>= </span><span class=identifier>Derived</span><span class=special>()
|
|
||||||
</span></pre></code>
|
|
||||||
<p>
|
|
||||||
Calling <tt>base.f()</tt>:</p>
|
|
||||||
<code><pre>
|
|
||||||
<span class=special>>>> </span><span class=identifier>base</span><span class=special>.</span><span class=identifier>f</span><span class=special>()
|
|
||||||
</span><span class=number>0
|
|
||||||
</span></pre></code>
|
|
||||||
<p>
|
|
||||||
Calling <tt>derived.f()</tt>:</p>
|
|
||||||
<code><pre>
|
|
||||||
<span class=special>>>> </span><span class=identifier>derived</span><span class=special>.</span><span class=identifier>f</span><span class=special>()
|
|
||||||
</span><span class=number>42
|
|
||||||
</span></pre></code>
|
|
||||||
<p>
|
|
||||||
Calling <tt>call_f</tt>, passing in a <tt>base</tt> object:</p>
|
|
||||||
<code><pre>
|
|
||||||
<span class=special>>>> </span><span class=identifier>call_f</span><span class=special>(</span><span class=identifier>base</span><span class=special>)
|
|
||||||
</span><span class=number>0
|
|
||||||
</span></pre></code>
|
|
||||||
<p>
|
|
||||||
Calling <tt>call_f</tt>, passing in a <tt>derived</tt> object:</p>
|
|
||||||
<code><pre>
|
|
||||||
<span class=special>>>> </span><span class=identifier>call_f</span><span class=special>(</span><span class=identifier>derived</span><span class=special>)
|
|
||||||
</span><span class=number>42
|
|
||||||
</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="deriving_a_python_class.html"><img src="theme/l_arr.gif" border="0"></a></td>
|
|
||||||
<td width="20"><a href="class_operators_special_functions.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>
|
|
||||||
@@ -1,156 +1,10 @@
|
|||||||
|
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN">
|
||||||
<html>
|
<html>
|
||||||
<head>
|
<head>
|
||||||
<!-- Generated by the Spirit (http://spirit.sf.net) QuickDoc -->
|
<meta http-equiv="refresh" content="0; URL=doc/html/index.html">
|
||||||
<title>Boost Python Tutorial</title>
|
</head>
|
||||||
<link rel="stylesheet" href="doc/theme/style.css" type="text/css">
|
<body>
|
||||||
<link rel="next" href="quickstart.html">
|
Automatic redirection failed, click this
|
||||||
</head>
|
<a href="doc/html/index.html">link</a>
|
||||||
<body>
|
</body>
|
||||||
<table width="100%" height="48" border="0" cellspacing="2">
|
|
||||||
<tr>
|
|
||||||
<td><img src="doc/theme/c%2B%2Bboost.gif">
|
|
||||||
</td>
|
|
||||||
<td width="85%">
|
|
||||||
<font size="6" face="Verdana, Arial, Helvetica, sans-serif"><b>Boost Python Tutorial</b></font>
|
|
||||||
</td>
|
|
||||||
</tr>
|
|
||||||
</table>
|
|
||||||
<br>
|
|
||||||
<table width="80%" border="0" align="center">
|
|
||||||
<tr>
|
|
||||||
<td class="toc_title">Table of contents</td>
|
|
||||||
</tr>
|
|
||||||
<tr>
|
|
||||||
<td class="toc_cells_L0">
|
|
||||||
<a href="doc/quickstart.html">QuickStart</a>
|
|
||||||
</td>
|
|
||||||
</tr>
|
|
||||||
<tr>
|
|
||||||
<td class="toc_cells_L0">
|
|
||||||
<a href="doc/building_hello_world.html">Building Hello World</a>
|
|
||||||
</td>
|
|
||||||
</tr>
|
|
||||||
<tr>
|
|
||||||
<td class="toc_cells_L0">
|
|
||||||
<a href="doc/exposing_classes.html">Exposing Classes</a>
|
|
||||||
</td>
|
|
||||||
</tr>
|
|
||||||
<tr>
|
|
||||||
<td class="toc_cells_L1">
|
|
||||||
<a href="doc/constructors.html">Constructors</a>
|
|
||||||
</td>
|
|
||||||
</tr>
|
|
||||||
<tr>
|
|
||||||
<td class="toc_cells_L1">
|
|
||||||
<a href="doc/class_data_members.html">Class Data Members</a>
|
|
||||||
</td>
|
|
||||||
</tr>
|
|
||||||
<tr>
|
|
||||||
<td class="toc_cells_L1">
|
|
||||||
<a href="doc/class_properties.html">Class Properties</a>
|
|
||||||
</td>
|
|
||||||
</tr>
|
|
||||||
<tr>
|
|
||||||
<td class="toc_cells_L1">
|
|
||||||
<a href="doc/inheritance.html">Inheritance</a>
|
|
||||||
</td>
|
|
||||||
</tr>
|
|
||||||
<tr>
|
|
||||||
<td class="toc_cells_L1">
|
|
||||||
<a href="doc/class_virtual_functions.html">Class Virtual Functions</a>
|
|
||||||
</td>
|
|
||||||
</tr>
|
|
||||||
<tr>
|
|
||||||
<td class="toc_cells_L1">
|
|
||||||
<a href="doc/deriving_a_python_class.html">Deriving a Python Class</a>
|
|
||||||
</td>
|
|
||||||
</tr>
|
|
||||||
<tr>
|
|
||||||
<td class="toc_cells_L1">
|
|
||||||
<a href="doc/virtual_functions_with_default_implementations.html">Virtual Functions with Default Implementations</a>
|
|
||||||
</td>
|
|
||||||
</tr>
|
|
||||||
<tr>
|
|
||||||
<td class="toc_cells_L1">
|
|
||||||
<a href="doc/class_operators_special_functions.html">Class Operators/Special Functions</a>
|
|
||||||
</td>
|
|
||||||
</tr>
|
|
||||||
<tr>
|
|
||||||
<td class="toc_cells_L0">
|
|
||||||
<a href="doc/functions.html">Functions</a>
|
|
||||||
</td>
|
|
||||||
</tr>
|
|
||||||
<tr>
|
|
||||||
<td class="toc_cells_L1">
|
|
||||||
<a href="doc/call_policies.html">Call Policies</a>
|
|
||||||
</td>
|
|
||||||
</tr>
|
|
||||||
<tr>
|
|
||||||
<td class="toc_cells_L1">
|
|
||||||
<a href="doc/overloading.html">Overloading</a>
|
|
||||||
</td>
|
|
||||||
</tr>
|
|
||||||
<tr>
|
|
||||||
<td class="toc_cells_L1">
|
|
||||||
<a href="doc/default_arguments.html">Default Arguments</a>
|
|
||||||
</td>
|
|
||||||
</tr>
|
|
||||||
<tr>
|
|
||||||
<td class="toc_cells_L1">
|
|
||||||
<a href="doc/auto_overloading.html">Auto-Overloading</a>
|
|
||||||
</td>
|
|
||||||
</tr>
|
|
||||||
<tr>
|
|
||||||
<td class="toc_cells_L0">
|
|
||||||
<a href="doc/object_interface.html">Object Interface</a>
|
|
||||||
</td>
|
|
||||||
</tr>
|
|
||||||
<tr>
|
|
||||||
<td class="toc_cells_L1">
|
|
||||||
<a href="doc/basic_interface.html">Basic Interface</a>
|
|
||||||
</td>
|
|
||||||
</tr>
|
|
||||||
<tr>
|
|
||||||
<td class="toc_cells_L1">
|
|
||||||
<a href="doc/derived_object_types.html">Derived Object types</a>
|
|
||||||
</td>
|
|
||||||
</tr>
|
|
||||||
<tr>
|
|
||||||
<td class="toc_cells_L1">
|
|
||||||
<a href="doc/extracting_c___objects.html">Extracting C++ objects</a>
|
|
||||||
</td>
|
|
||||||
</tr>
|
|
||||||
<tr>
|
|
||||||
<td class="toc_cells_L1">
|
|
||||||
<a href="doc/enums.html">Enums</a>
|
|
||||||
</td>
|
|
||||||
</tr>
|
|
||||||
<tr>
|
|
||||||
<td class="toc_cells_L0">
|
|
||||||
<a href="doc/embedding.html">Embedding</a>
|
|
||||||
</td>
|
|
||||||
</tr>
|
|
||||||
<tr>
|
|
||||||
<td class="toc_cells_L1">
|
|
||||||
<a href="doc/using_the_interpreter.html">Using the interpreter</a>
|
|
||||||
</td>
|
|
||||||
</tr>
|
|
||||||
<tr>
|
|
||||||
<td class="toc_cells_L0">
|
|
||||||
<a href="doc/iterators.html">Iterators</a>
|
|
||||||
</td>
|
|
||||||
</tr>
|
|
||||||
<tr>
|
|
||||||
<td class="toc_cells_L0">
|
|
||||||
<a href="doc/exception_translation.html">Exception Translation</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>
|
</html>
|
||||||
|
|||||||
@@ -10,7 +10,7 @@
|
|||||||
<tr>
|
<tr>
|
||||||
<td valign="top" width="300">
|
<td valign="top" width="300">
|
||||||
<h3><a href="../../../../index.htm"><img height="86" width="277" alt=
|
<h3><a href="../../../../index.htm"><img height="86" width="277" alt=
|
||||||
"C++ Boost" src="../../../../c++boost.gif" border="0"></a></h3>
|
"C++ Boost" src="../../../../boost.png" border="0"></a></h3>
|
||||||
</td>
|
</td>
|
||||||
<td valign="top">
|
<td valign="top">
|
||||||
<h1 align="center"><a href="../index.html">Boost.Python</a></h1>
|
<h1 align="center"><a href="../index.html">Boost.Python</a></h1>
|
||||||
@@ -45,7 +45,7 @@ of work got done...
|
|||||||
<h3><a name="arity">Arbitrary Arity Support</a></h3>
|
<h3><a name="arity">Arbitrary Arity Support</a></h3>
|
||||||
|
|
||||||
I began using the <a
|
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
|
metaprogramming library to generate support for functions and member
|
||||||
functions of arbitrary arity, which was, to say the least, quite an
|
functions of arbitrary arity, which was, to say the least, quite an
|
||||||
adventure. The feedback cycle resulting from my foray into
|
adventure. The feedback cycle resulting from my foray into
|
||||||
@@ -158,6 +158,6 @@ documentation).
|
|||||||
<!--webbot bot="Timestamp" endspan i-checksum="39359" -->
|
<!--webbot bot="Timestamp" endspan i-checksum="39359" -->
|
||||||
</p>
|
</p>
|
||||||
<p><i>© Copyright <a href="../../../../people/dave_abrahams.htm">Dave Abrahams</a>
|
<p><i>© Copyright <a href="../../../../people/dave_abrahams.htm">Dave Abrahams</a>
|
||||||
2002. All Rights Reserved.</i></p>
|
2002. </i></p>
|
||||||
</body>
|
</body>
|
||||||
</html>
|
</html>
|
||||||
|
|||||||
@@ -16,7 +16,7 @@
|
|||||||
<tr>
|
<tr>
|
||||||
<td valign="top" width="300">
|
<td valign="top" width="300">
|
||||||
<h3><a href="../../../../index.htm"><img height="86" width="277"
|
<h3><a href="../../../../index.htm"><img height="86" width="277"
|
||||||
alt="C++ Boost" src="../../../../c++boost.gif" border="0"></a></h3>
|
alt="C++ Boost" src="../../../../boost.png" border="0"></a></h3>
|
||||||
</td>
|
</td>
|
||||||
|
|
||||||
<td valign="top">
|
<td valign="top">
|
||||||
@@ -113,7 +113,7 @@
|
|||||||
"ResultConverter.html#ResultConverterGenerator-concept">ResultConverterGenerator</a>.</td>
|
"ResultConverter.html#ResultConverterGenerator-concept">ResultConverterGenerator</a>.</td>
|
||||||
|
|
||||||
<td>An MPL unary <a href=
|
<td>An MPL unary <a href=
|
||||||
"../../../mpl/doc/paper/html/usage.html#metafunctions.classes">Metafunction
|
"../../../mpl/doc/refmanual/metafunction-class.html">Metafunction
|
||||||
Class</a> used produce the "preliminary" result object.</td>
|
Class</a> used produce the "preliminary" result object.</td>
|
||||||
</tr>
|
</tr>
|
||||||
|
|
||||||
@@ -141,8 +141,7 @@
|
|||||||
</p>
|
</p>
|
||||||
|
|
||||||
<p><i>© Copyright <a href=
|
<p><i>© Copyright <a href=
|
||||||
"../../../../people/dave_abrahams.htm">Dave Abrahams</a> 2002. All Rights
|
"../../../../people/dave_abrahams.htm">Dave Abrahams</a> 2002.</i></p>
|
||||||
Reserved.</i></p>
|
|
||||||
|
|
||||||
<p>Permission to copy, use, modify, sell and distribute this software is
|
<p>Permission to copy, use, modify, sell and distribute this software is
|
||||||
granted provided this copyright notice appears in all copies. This
|
granted provided this copyright notice appears in all copies. This
|
||||||
|
|||||||
@@ -9,7 +9,7 @@
|
|||||||
"header">
|
"header">
|
||||||
<tr>
|
<tr>
|
||||||
<td valign="top" width="300">
|
<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>
|
<h3><a href="../../../../index.htm"><img height="86" width="277" alt="C++ Boost" src="../../../../boost.png" border="0"></a></h3>
|
||||||
</td>
|
</td>
|
||||||
<td valign="top">
|
<td valign="top">
|
||||||
<h1 align="center"><a href="../index.html">Boost.Python</a></h1>
|
<h1 align="center"><a href="../index.html">Boost.Python</a></h1>
|
||||||
@@ -28,50 +28,40 @@
|
|||||||
|
|
||||||
<h2><a name="introduction"></a>Introduction</h2>
|
<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>
|
<h2><a name="concept-requirements"></a>Concept Requirements</h2>
|
||||||
<h3><a name="Dereferenceable-concept"></a>Dereferenceable Concept</h3>
|
<h3><a name="Dereferenceable-concept"></a>Dereferenceable Concept</h3>
|
||||||
|
|
||||||
<p>In the table below, <code><b>x</b></code> denotes an object whose
|
<p>In the table below, <code><b>T</b></code> is a model of
|
||||||
type is a model of Dereferenceable.
|
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>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:
|
|
||||||
|
|
||||||
<table summary="Dereferenceable expressions" border="1" cellpadding="5">
|
<table summary="Dereferenceable expressions" border="1" cellpadding="5">
|
||||||
|
|
||||||
<tr>
|
<tr>
|
||||||
<td><b>Expression</b></td>
|
<td><b>Expression</b></td>
|
||||||
|
<td><b>Result</b></td>
|
||||||
<td><b>Operational Semantics</b></td>
|
<td><b>Operational Semantics</b></td>
|
||||||
</tr>
|
</tr>
|
||||||
|
|
||||||
<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
|
<td><code>&*x</code>, or a null pointer
|
||||||
</tr>
|
</tr>
|
||||||
|
<tr>
|
||||||
|
|
||||||
</table>
|
</table>
|
||||||
|
|
||||||
<hr>
|
<hr>
|
||||||
<p>Revised
|
<p>Revised
|
||||||
<!--webbot bot="Timestamp" S-Type="EDITED" S-Format="%d %B, %Y" startspan -->
|
<!--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" -->
|
<!--webbot bot="Timestamp" endspan i-checksum="39359" -->
|
||||||
</p>
|
</p>
|
||||||
<p><i>© Copyright <a href="../../../../people/dave_abrahams.htm">Dave
|
<p><i>© Copyright <a href="../../../../people/dave_abrahams.htm">Dave
|
||||||
Abrahams</a> 2002. All Rights Reserved.</i>
|
Abrahams</a> 2002-2003. </i>
|
||||||
|
|
||||||
<p>Permission to copy, use, modify, sell
|
<p>Permission to copy, use, modify, sell
|
||||||
and distribute this software is granted provided this copyright notice appears
|
and distribute this software is granted provided this copyright notice appears
|
||||||
|
|||||||
@@ -9,7 +9,7 @@
|
|||||||
"header">
|
"header">
|
||||||
<tr>
|
<tr>
|
||||||
<td valign="top" width="300">
|
<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>
|
<h3><a href="../../../../index.htm"><img height="86" width="277" alt="C++ Boost" src="../../../../boost.png" border="0"></a></h3>
|
||||||
</td>
|
</td>
|
||||||
<td valign="top">
|
<td valign="top">
|
||||||
<h1 align="center"><a href="../index.html">Boost.Python</a></h1>
|
<h1 align="center"><a href="../index.html">Boost.Python</a></h1>
|
||||||
@@ -83,7 +83,7 @@ are layout-compatible with PyObject.
|
|||||||
<!--webbot bot="Timestamp" endspan i-checksum="39359" -->
|
<!--webbot bot="Timestamp" endspan i-checksum="39359" -->
|
||||||
</p>
|
</p>
|
||||||
<p><i>© Copyright <a href="../../../../people/dave_abrahams.htm">Dave
|
<p><i>© Copyright <a href="../../../../people/dave_abrahams.htm">Dave
|
||||||
Abrahams</a> 2002. All Rights Reserved.</i>
|
Abrahams</a> 2002. </i>
|
||||||
|
|
||||||
<p>Permission to copy, use, modify, sell
|
<p>Permission to copy, use, modify, sell
|
||||||
and distribute this software is granted provided this copyright notice appears
|
and distribute this software is granted provided this copyright notice appears
|
||||||
|
|||||||
@@ -9,7 +9,7 @@
|
|||||||
"header">
|
"header">
|
||||||
<tr>
|
<tr>
|
||||||
<td valign="top" width="300">
|
<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>
|
<h3><a href="../../../../index.htm"><img height="86" width="277" alt="C++ Boost" src="../../../../boost.png" border="0"></a></h3>
|
||||||
</td>
|
</td>
|
||||||
<td valign="top">
|
<td valign="top">
|
||||||
<h1 align="center"><a href="../index.html">Boost.Python</a></h1>
|
<h1 align="center"><a href="../index.html">Boost.Python</a></h1>
|
||||||
@@ -61,7 +61,7 @@ type.
|
|||||||
<!--webbot bot="Timestamp" endspan i-checksum="39359" -->
|
<!--webbot bot="Timestamp" endspan i-checksum="39359" -->
|
||||||
</p>
|
</p>
|
||||||
<p><i>© Copyright <a href="../../../../people/dave_abrahams.htm">Dave
|
<p><i>© Copyright <a href="../../../../people/dave_abrahams.htm">Dave
|
||||||
Abrahams</a> 2002. All Rights Reserved.</i>
|
Abrahams</a> 2002. </i>
|
||||||
|
|
||||||
<p>Permission to copy, use, modify, sell
|
<p>Permission to copy, use, modify, sell
|
||||||
and distribute this software is granted provided this copyright notice appears
|
and distribute this software is granted provided this copyright notice appears
|
||||||
|
|||||||
@@ -10,7 +10,7 @@
|
|||||||
<tr>
|
<tr>
|
||||||
<td valign="top" width="300">
|
<td valign="top" width="300">
|
||||||
<h3><a href="../../../../index.htm"><img height="86" width="277" alt=
|
<h3><a href="../../../../index.htm"><img height="86" width="277" alt=
|
||||||
"C++ Boost" src="../../../../c++boost.gif" border="0"></a></h3>
|
"C++ Boost" src="../../../../boost.png" border="0"></a></h3>
|
||||||
</td>
|
</td>
|
||||||
<td valign="top">
|
<td valign="top">
|
||||||
<h1 align="center"><a href="../index.html">Boost.Python</a></h1>
|
<h1 align="center"><a href="../index.html">Boost.Python</a></h1>
|
||||||
@@ -221,6 +221,6 @@ you'll just have to wait till next month (hopefully the beginning).
|
|||||||
<!--webbot bot="Timestamp" endspan i-checksum="39359" -->
|
<!--webbot bot="Timestamp" endspan i-checksum="39359" -->
|
||||||
</p>
|
</p>
|
||||||
<p><i>© Copyright <a href="../../../../people/dave_abrahams.htm">Dave Abrahams</a>
|
<p><i>© Copyright <a href="../../../../people/dave_abrahams.htm">Dave Abrahams</a>
|
||||||
2002. All Rights Reserved.</i></p>
|
2002. </i></p>
|
||||||
</body>
|
</body>
|
||||||
</html>
|
</html>
|
||||||
|
|||||||
@@ -10,7 +10,7 @@
|
|||||||
<tr>
|
<tr>
|
||||||
<td valign="top" width="300">
|
<td valign="top" width="300">
|
||||||
<h3><a href="../../../../index.htm"><img height="86" width="277" alt=
|
<h3><a href="../../../../index.htm"><img height="86" width="277" alt=
|
||||||
"C++ Boost" src="../../../../c++boost.gif" border="0"></a></h3>
|
"C++ Boost" src="../../../../boost.png" border="0"></a></h3>
|
||||||
</td>
|
</td>
|
||||||
<td valign="top">
|
<td valign="top">
|
||||||
<h1 align="center"><a href="../index.html">Boost.Python</a></h1>
|
<h1 align="center"><a href="../index.html">Boost.Python</a></h1>
|
||||||
@@ -229,6 +229,6 @@ worth doing anything about it.
|
|||||||
<!--webbot bot="Timestamp" endspan i-checksum="39359" -->
|
<!--webbot bot="Timestamp" endspan i-checksum="39359" -->
|
||||||
</p>
|
</p>
|
||||||
<p><i>© Copyright <a href="../../../../people/dave_abrahams.htm">Dave Abrahams</a>
|
<p><i>© Copyright <a href="../../../../people/dave_abrahams.htm">Dave Abrahams</a>
|
||||||
2002. All Rights Reserved.</i></p>
|
2002. </i></p>
|
||||||
</body>
|
</body>
|
||||||
</html>
|
</html>
|
||||||
|
|||||||
@@ -10,7 +10,7 @@
|
|||||||
<tr>
|
<tr>
|
||||||
<td valign="top" width="300">
|
<td valign="top" width="300">
|
||||||
<h3><a href="../../../../index.htm"><img height="86" width="277" alt=
|
<h3><a href="../../../../index.htm"><img height="86" width="277" alt=
|
||||||
"C++ Boost" src="../../../../c++boost.gif" border="0"></a></h3>
|
"C++ Boost" src="../../../../boost.png" border="0"></a></h3>
|
||||||
</td>
|
</td>
|
||||||
<td valign="top">
|
<td valign="top">
|
||||||
<h1 align="center"><a href="../index.html">Boost.Python</a></h1>
|
<h1 align="center"><a href="../index.html">Boost.Python</a></h1>
|
||||||
@@ -54,7 +54,7 @@ focused on reducing the support burden. In recent weeks, responding to
|
|||||||
requests for support, espcially surrounding building the library, had
|
requests for support, espcially surrounding building the library, had
|
||||||
begun to impede progress on development. There was a major push to
|
begun to impede progress on development. There was a major push to
|
||||||
release a stable 1.28.0 of Boost, including documentation of <a
|
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
|
<a href="../building.html">instructions</a> for building Boost.Python
|
||||||
v1. The documentation for Boost.Python v2 was also updated as
|
v1. The documentation for Boost.Python v2 was also updated as
|
||||||
described <a href="#documentation">here</a>.
|
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
|
Martin Casado which uncovered the key mechanism required to allow
|
||||||
shared libraries to use functions from the Python executable. The
|
shared libraries to use functions from the Python executable. The
|
||||||
current solution used in Boost.Build relies on a <a
|
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
|
Script</a> as part of the build process. This is not a problem for
|
||||||
Boost.Python, as Python will be available. However, the commands
|
Boost.Python, as Python will be available. However, the commands
|
||||||
issued by the script are so simple that a 100%-pure-Boost.Jam
|
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
|
Support for exposing C++ operators and functions as the corresponding
|
||||||
Python special methods was added. Thinking that the Boost.Python
|
Python special methods was added. Thinking that the Boost.Python
|
||||||
<a href="../special.html#numeric">v1 interface</a> was a little too
|
v1 interface was a little too esoteric (especially the use of
|
||||||
esoteric (especially the use of
|
|
||||||
<code>left_operand<...>/right_operand<...></code> for
|
<code>left_operand<...>/right_operand<...></code> for
|
||||||
asymmetric operands), I introduced a simple form of <a
|
asymmetric operands), I introduced a simple form of <a
|
||||||
href="http://osl.iu.edu/~tveldhui/papers/Expression-Templates/exprtmpl.html">expression
|
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>
|
href="http://www.python.org/2.2/descrintro.html#property"><code>property</code></a>
|
||||||
interface used internally to implement the data member exposure
|
interface used internally to implement the data member exposure
|
||||||
facility described in <a
|
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
|
incredibly useful idiom, so it's good to be able to provide them
|
||||||
at little new development cost.
|
at little new development cost.
|
||||||
|
|
||||||
@@ -212,7 +211,7 @@ Major updates were made to the following pages:
|
|||||||
|
|
||||||
<blockquote>
|
<blockquote>
|
||||||
<dl>
|
<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="class.html">class.html</a><dd>
|
||||||
<dt><a href="reference.html">reference.html</a><dd>
|
<dt><a href="reference.html">reference.html</a><dd>
|
||||||
</dl>
|
</dl>
|
||||||
@@ -304,6 +303,6 @@ to these issues will probably have to be formalized before long.
|
|||||||
<!--webbot bot="Timestamp" endspan i-checksum="39359" -->
|
<!--webbot bot="Timestamp" endspan i-checksum="39359" -->
|
||||||
</p>
|
</p>
|
||||||
<p><i>© Copyright <a href="../../../../people/dave_abrahams.htm">Dave Abrahams</a>
|
<p><i>© Copyright <a href="../../../../people/dave_abrahams.htm">Dave Abrahams</a>
|
||||||
2002. All Rights Reserved.</i></p>
|
2002. </i></p>
|
||||||
</body>
|
</body>
|
||||||
</html>
|
</html>
|
||||||
|
|||||||
@@ -16,7 +16,7 @@
|
|||||||
<tr>
|
<tr>
|
||||||
<td valign="top" width="300">
|
<td valign="top" width="300">
|
||||||
<h3><a href="../../../../index.htm"><img height="86" width="277"
|
<h3><a href="../../../../index.htm"><img height="86" width="277"
|
||||||
alt="C++ Boost" src="../../../../c++boost.gif" border="0"></a></h3>
|
alt="C++ Boost" src="../../../../boost.png" border="0"></a></h3>
|
||||||
</td>
|
</td>
|
||||||
|
|
||||||
<td valign="top">
|
<td valign="top">
|
||||||
@@ -144,13 +144,7 @@ instances of the associated Python type will be considered a match.
|
|||||||
</p>
|
</p>
|
||||||
|
|
||||||
<p><i>© Copyright <a href=
|
<p><i>© Copyright <a href=
|
||||||
"../../../../people/dave_abrahams.htm">Dave Abrahams</a> 2002. All Rights
|
"../../../../people/dave_abrahams.htm">Dave Abrahams</a> 2002.</i></p>
|
||||||
Reserved.</i></p>
|
|
||||||
|
|
||||||
<p>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.</p>
|
|
||||||
</body>
|
</body>
|
||||||
</html>
|
</html>
|
||||||
|
|
||||||
|
|||||||
@@ -9,7 +9,7 @@
|
|||||||
"header">
|
"header">
|
||||||
<tr>
|
<tr>
|
||||||
<td valign="top" width="300">
|
<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>
|
<h3><a href="../../../../index.htm"><img height="86" width="277" alt="C++ Boost" src="../../../../boost.png" border="0"></a></h3>
|
||||||
</td>
|
</td>
|
||||||
<td valign="top">
|
<td valign="top">
|
||||||
<h1 align="center"><a href="../index.html">Boost.Python</a></h1>
|
<h1 align="center"><a href="../index.html">Boost.Python</a></h1>
|
||||||
@@ -100,7 +100,7 @@ C++ function return type.
|
|||||||
<!--webbot bot="Timestamp" endspan i-checksum="39359" -->
|
<!--webbot bot="Timestamp" endspan i-checksum="39359" -->
|
||||||
</p>
|
</p>
|
||||||
<p><i>© Copyright <a href="../../../../people/dave_abrahams.htm">Dave
|
<p><i>© Copyright <a href="../../../../people/dave_abrahams.htm">Dave
|
||||||
Abrahams</a> 2002. All Rights Reserved.</i>
|
Abrahams</a> 2002. </i>
|
||||||
|
|
||||||
<p>Permission to copy, use, modify, sell
|
<p>Permission to copy, use, modify, sell
|
||||||
and distribute this software is granted provided this copyright notice appears
|
and distribute this software is granted provided this copyright notice appears
|
||||||
|
|||||||
@@ -16,7 +16,7 @@
|
|||||||
<tr>
|
<tr>
|
||||||
<td valign="top" width="300">
|
<td valign="top" width="300">
|
||||||
<h3><a href="../../../../index.htm"><img height="86" width="277"
|
<h3><a href="../../../../index.htm"><img height="86" width="277"
|
||||||
alt="C++ Boost" src="../../../../c++boost.gif" border="0"></a></h3>
|
alt="C++ Boost" src="../../../../boost.png" border="0"></a></h3>
|
||||||
</td>
|
</td>
|
||||||
|
|
||||||
<td valign="top">
|
<td valign="top">
|
||||||
@@ -72,7 +72,7 @@
|
|||||||
use the new preproccessor metaprogramming constructs and helping us to
|
use the new preproccessor metaprogramming constructs and helping us to
|
||||||
work around buggy and slow C++ preprocessors.</p>
|
work around buggy and slow C++ preprocessors.</p>
|
||||||
|
|
||||||
<p><a href="nicodemus-at-globalite.com.br">Bruno da Silva de
|
<p><a href="mailto:nicodemus-at-globalite.com.br">Bruno da Silva de
|
||||||
Oliveira</a> contributed the ingenious <a
|
Oliveira</a> contributed the ingenious <a
|
||||||
href="../../pyste/index.html">Pyste</a> ("Pie-Steh")
|
href="../../pyste/index.html">Pyste</a> ("Pie-Steh")
|
||||||
code generator.
|
code generator.
|
||||||
@@ -126,8 +126,7 @@
|
|||||||
</p>
|
</p>
|
||||||
|
|
||||||
<p><i>© Copyright <a href=
|
<p><i>© Copyright <a href=
|
||||||
"../../../../people/dave_abrahams.htm">Dave Abrahams</a> 2002. All Rights
|
"../../../../people/dave_abrahams.htm">Dave Abrahams</a> 2002.</i></p>
|
||||||
Reserved.</i></p>
|
|
||||||
</body>
|
</body>
|
||||||
</html>
|
</html>
|
||||||
|
|
||||||
|
|||||||
@@ -16,7 +16,7 @@
|
|||||||
<tr>
|
<tr>
|
||||||
<td valign="top" width="300">
|
<td valign="top" width="300">
|
||||||
<h3><a href="../../../../index.htm"><img height="86" width="277"
|
<h3><a href="../../../../index.htm"><img height="86" width="277"
|
||||||
alt="C++ Boost" src="../../../../c++boost.gif" border="0"></a></h3>
|
alt="C++ Boost" src="../../../../boost.png" border="0"></a></h3>
|
||||||
</td>
|
</td>
|
||||||
|
|
||||||
<td valign="top">
|
<td valign="top">
|
||||||
@@ -190,8 +190,7 @@ BOOST_PYTHON_MODULE(xxx)
|
|||||||
<p>Revised 01 August, 2003</p>
|
<p>Revised 01 August, 2003</p>
|
||||||
|
|
||||||
<p><i>© Copyright <a href=
|
<p><i>© Copyright <a href=
|
||||||
"../../../../people/dave_abrahams.htm">Dave Abrahams</a> 2002-2003. All
|
"../../../../people/dave_abrahams.htm">Dave Abrahams</a> 2002-2003.</i></p>
|
||||||
Rights Reserved.</i></p>
|
|
||||||
</body>
|
</body>
|
||||||
</html>
|
</html>
|
||||||
|
|
||||||
|
|||||||
@@ -1,32 +0,0 @@
|
|||||||
<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 - Bibliography</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">Bibliography</h2>
|
|
||||||
</td>
|
|
||||||
</tr>
|
|
||||||
</table>
|
|
||||||
<hr>
|
|
||||||
{{bibliographical information}}
|
|
||||||
<hr>
|
|
||||||
<p>Revised
|
|
||||||
<!--webbot bot="Timestamp" S-Type="EDITED" S-Format="%d %B, %Y" startspan -->
|
|
||||||
13 November, 2002
|
|
||||||
<!--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>
|
|
||||||
@@ -10,7 +10,7 @@
|
|||||||
<tr>
|
<tr>
|
||||||
<td valign="top" width="300">
|
<td valign="top" width="300">
|
||||||
<h3><a href="../../../../index.htm"><img height="86" width="277" alt=
|
<h3><a href="../../../../index.htm"><img height="86" width="277" alt=
|
||||||
"C++ Boost" src="../../../../c++boost.gif" border="0"></a></h3>
|
"C++ Boost" src="../../../../boost.png" border="0"></a></h3>
|
||||||
</td>
|
</td>
|
||||||
<td valign="top">
|
<td valign="top">
|
||||||
<h1 align="center"><a href="../index.html">Boost.Python</a></h1>
|
<h1 align="center"><a href="../index.html">Boost.Python</a></h1>
|
||||||
@@ -77,6 +77,6 @@ double apply2(PyObject* func, double x, double y)
|
|||||||
<!--webbot bot="Timestamp" endspan i-checksum="39359" -->
|
<!--webbot bot="Timestamp" endspan i-checksum="39359" -->
|
||||||
</p>
|
</p>
|
||||||
<p><i>© Copyright <a href="../../../../people/dave_abrahams.htm">Dave Abrahams</a>
|
<p><i>© Copyright <a href="../../../../people/dave_abrahams.htm">Dave Abrahams</a>
|
||||||
2002. All Rights Reserved.</i></p>
|
2002. </i></p>
|
||||||
</body>
|
</body>
|
||||||
</html>
|
</html>
|
||||||
|
|||||||
@@ -16,7 +16,7 @@
|
|||||||
<tr>
|
<tr>
|
||||||
<td valign="top" width="300">
|
<td valign="top" width="300">
|
||||||
<h3><a href="../../../../index.htm"><img height="86" width="277"
|
<h3><a href="../../../../index.htm"><img height="86" width="277"
|
||||||
alt="C++ Boost" src="../../../../c++boost.gif" border="0"></a></h3>
|
alt="C++ Boost" src="../../../../boost.png" border="0"></a></h3>
|
||||||
</td>
|
</td>
|
||||||
|
|
||||||
<td valign="top">
|
<td valign="top">
|
||||||
@@ -152,8 +152,7 @@ BOOST_PYTHON_MODULE(my_module)
|
|||||||
</p>
|
</p>
|
||||||
|
|
||||||
<p><i>© Copyright <a href=
|
<p><i>© Copyright <a href=
|
||||||
"../../../../people/dave_abrahams.htm">Dave Abrahams</a> 2002. All Rights
|
"../../../../people/dave_abrahams.htm">Dave Abrahams</a> 2002.</i></p>
|
||||||
Reserved.</i></p>
|
|
||||||
</body>
|
</body>
|
||||||
</html>
|
</html>
|
||||||
|
|
||||||
|
|||||||
@@ -16,7 +16,7 @@
|
|||||||
<tr>
|
<tr>
|
||||||
<td valign="top" width="300">
|
<td valign="top" width="300">
|
||||||
<h3><a href="../../../../index.htm"><img height="86" width="277"
|
<h3><a href="../../../../index.htm"><img height="86" width="277"
|
||||||
alt="C++ Boost" src="../../../../c++boost.gif" border="0"></a></h3>
|
alt="C++ Boost" src="../../../../boost.png" border="0"></a></h3>
|
||||||
</td>
|
</td>
|
||||||
|
|
||||||
<td valign="top">
|
<td valign="top">
|
||||||
@@ -79,7 +79,7 @@ call_method<ResultType>(self_object, "<i>method-name</i>", a1, a2... a<i>N
|
|||||||
the arguments <code>a1</code>...<code>a<i>N</i></code> are copied into
|
the arguments <code>a1</code>...<code>a<i>N</i></code> are copied into
|
||||||
new Python objects, but this behavior can be overridden by the use of
|
new Python objects, but this behavior can be overridden by the use of
|
||||||
<code><a href="ptr.html#ptr-spec">ptr()</a></code> and <a href=
|
<code><a href="ptr.html#ptr-spec">ptr()</a></code> and <a href=
|
||||||
"../../../bind/ref.html#reference_wrapper">ref()</a>:</p>
|
"../../../bind/ref.html">ref()</a>:</p>
|
||||||
<pre>
|
<pre>
|
||||||
class X : boost::noncopyable
|
class X : boost::noncopyable
|
||||||
{
|
{
|
||||||
@@ -128,7 +128,7 @@ void apply(PyObject* callable, X& x)
|
|||||||
|
|
||||||
<tr>
|
<tr>
|
||||||
<td><code><a href=
|
<td><code><a href=
|
||||||
"../../../bind/ref.html#reference_wrapper">boost::reference_wrapper</a><T></code></td>
|
"../../../bind/ref.html">boost::reference_wrapper</a><T></code></td>
|
||||||
|
|
||||||
<td>The Python argument contains a pointer to, rather than a copy of,
|
<td>The Python argument contains a pointer to, rather than a copy of,
|
||||||
<code>x.get()</code>. Note: failure to ensure that no Python code
|
<code>x.get()</code>. Note: failure to ensure that no Python code
|
||||||
@@ -245,8 +245,7 @@ void apply(PyObject* callable, X& x)
|
|||||||
</p>
|
</p>
|
||||||
|
|
||||||
<p><i>© Copyright <a href=
|
<p><i>© Copyright <a href=
|
||||||
"../../../../people/dave_abrahams.htm">Dave Abrahams</a> 2002. All Rights
|
"../../../../people/dave_abrahams.htm">Dave Abrahams</a> 2002.</i></p>
|
||||||
Reserved.</i></p>
|
|
||||||
</body>
|
</body>
|
||||||
</html>
|
</html>
|
||||||
|
|
||||||
|
|||||||
1008
doc/v2/class.html
@@ -16,7 +16,7 @@
|
|||||||
<tr>
|
<tr>
|
||||||
<td valign="top" width="300">
|
<td valign="top" width="300">
|
||||||
<h3><a href="../../../../index.htm"><img height="86" width="277"
|
<h3><a href="../../../../index.htm"><img height="86" width="277"
|
||||||
alt="C++ Boost" src="../../../../c++boost.gif" border="0"></a></h3>
|
alt="C++ Boost" src="../../../../boost.png" border="0"></a></h3>
|
||||||
</td>
|
</td>
|
||||||
|
|
||||||
<td valign="top">
|
<td valign="top">
|
||||||
@@ -146,8 +146,7 @@
|
|||||||
</p>
|
</p>
|
||||||
|
|
||||||
<p><i>© Copyright <a href=
|
<p><i>© Copyright <a href=
|
||||||
"../../../../people/dave_abrahams.htm">Dave Abrahams</a> 2002. All Rights
|
"../../../../people/dave_abrahams.htm">Dave Abrahams</a> 2002.</i></p>
|
||||||
Reserved.</i></p>
|
|
||||||
</body>
|
</body>
|
||||||
</html>
|
</html>
|
||||||
|
|
||||||
|
|||||||
@@ -17,7 +17,7 @@
|
|||||||
<tr>
|
<tr>
|
||||||
<td valign="top" width="300">
|
<td valign="top" width="300">
|
||||||
<h3><a href="../../../../index.htm"><img height="86" width="277"
|
<h3><a href="../../../../index.htm"><img height="86" width="277"
|
||||||
alt="C++ Boost" src="../../../../c++boost.gif" border="0"></a></h3>
|
alt="C++ Boost" src="../../../../boost.png" border="0"></a></h3>
|
||||||
</td>
|
</td>
|
||||||
|
|
||||||
<td valign="top">
|
<td valign="top">
|
||||||
@@ -140,8 +140,7 @@ BOOST_PYTHON_MODULE(my_module)
|
|||||||
</p>
|
</p>
|
||||||
|
|
||||||
<p><i>© Copyright <a href=
|
<p><i>© Copyright <a href=
|
||||||
"../../../../people/dave_abrahams.htm">Dave Abrahams</a> 2002. All Rights
|
"../../../../people/dave_abrahams.htm">Dave Abrahams</a> 2002.</i></p>
|
||||||
Reserved.</i></p>
|
|
||||||
</body>
|
</body>
|
||||||
</html>
|
</html>
|
||||||
|
|
||||||
|
|||||||
@@ -17,7 +17,7 @@
|
|||||||
<tr>
|
<tr>
|
||||||
<td valign="top" width="300">
|
<td valign="top" width="300">
|
||||||
<h3><a href="../../../../index.htm"><img height="86" width="277"
|
<h3><a href="../../../../index.htm"><img height="86" width="277"
|
||||||
alt="C++ Boost" src="../../../../c++boost.gif" border="0"></a></h3>
|
alt="C++ Boost" src="../../../../boost.png" border="0"></a></h3>
|
||||||
</td>
|
</td>
|
||||||
|
|
||||||
<td valign="top">
|
<td valign="top">
|
||||||
@@ -140,8 +140,7 @@ BOOST_PYTHON_MODULE(my_module)
|
|||||||
</p>
|
</p>
|
||||||
|
|
||||||
<p><i>© Copyright <a href=
|
<p><i>© Copyright <a href=
|
||||||
"../../../../people/dave_abrahams.htm">Dave Abrahams</a> 2002. All Rights
|
"../../../../people/dave_abrahams.htm">Dave Abrahams</a> 2002.</i></p>
|
||||||
Reserved.</i></p>
|
|
||||||
</body>
|
</body>
|
||||||
</html>
|
</html>
|
||||||
|
|
||||||
|
|||||||