mirror of
https://github.com/boostorg/python.git
synced 2026-01-20 04:42:28 +00:00
Compare commits
690 Commits
svn-branch
...
svn-branch
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
6b96eca21b | ||
|
|
f355be8ac5 | ||
|
|
60634d39e1 | ||
|
|
ada55bd9e2 | ||
|
|
5113de875e | ||
|
|
e079006a4b | ||
|
|
07561794e9 | ||
|
|
75a0da31fb | ||
|
|
33ee2a43c5 | ||
|
|
dcb6a88c63 | ||
|
|
eeda822196 | ||
|
|
060f59daa8 | ||
|
|
4117614861 | ||
|
|
e76440e940 | ||
|
|
f8490a8850 | ||
|
|
ee1cc99c65 | ||
|
|
dcf7e7cf0c | ||
|
|
4c8bcd918b | ||
|
|
a26bb0390d | ||
|
|
26a0df8253 | ||
|
|
526d99f832 | ||
|
|
acbb5be6ab | ||
|
|
522a29241b | ||
|
|
b8d3c84d3c | ||
|
|
9d520877d1 | ||
|
|
5cda0581cd | ||
|
|
ce2e9de6fb | ||
|
|
4d53fb97b6 | ||
|
|
d274a8395b | ||
|
|
ba86f516d8 | ||
|
|
ac02c763c7 | ||
|
|
7407a6b144 | ||
|
|
0453e05bb2 | ||
|
|
946a93164a | ||
|
|
fe02cae4f7 | ||
|
|
5762eb9b33 | ||
|
|
73ffc4a13f | ||
|
|
865ef2ab7f | ||
|
|
7d35ed4eda | ||
|
|
ec3cc6abe8 | ||
|
|
6f7957fd40 | ||
|
|
ec4de3326e | ||
|
|
f030618d19 | ||
|
|
5bcb9010f6 | ||
|
|
780fff70c4 | ||
|
|
1d94d7e604 | ||
|
|
a6cac2886b | ||
|
|
2566b8732e | ||
|
|
d4c50383af | ||
|
|
1ee7bd2a60 | ||
|
|
0bbfa9b483 | ||
|
|
2cad1b3d93 | ||
|
|
bcaa1043ea | ||
|
|
0b33d1800d | ||
|
|
946942214f | ||
|
|
cd6476e487 | ||
|
|
0b02fd4e99 | ||
|
|
d779a94cfb | ||
|
|
2f89a8eb58 | ||
|
|
26d3375900 | ||
|
|
b06e8c3022 | ||
|
|
8a20f8b2da | ||
|
|
e1099e9370 | ||
|
|
68c8901c2a | ||
|
|
cfb1aebf66 | ||
|
|
e4f54bd53a | ||
|
|
30ea4dd46e | ||
|
|
d5c33a203d | ||
|
|
087c09cc65 | ||
|
|
a9bb2a017e | ||
|
|
8a049b8ee7 | ||
|
|
37efd93725 | ||
|
|
3e61803e89 | ||
|
|
3173d88f3f | ||
|
|
f96a898c51 | ||
|
|
d66b79f468 | ||
|
|
b7e300d155 | ||
|
|
4bd680cec8 | ||
|
|
78ae892db6 | ||
|
|
d748e371e5 | ||
|
|
6bdc89252e | ||
|
|
c104f0167f | ||
|
|
6e3c6d1ba8 | ||
|
|
b77262ba13 | ||
|
|
960ebb13db | ||
|
|
1a7b331a4b | ||
|
|
3092e07281 | ||
|
|
a5d53d1ac8 | ||
|
|
3c5df28101 | ||
|
|
49e071d363 | ||
|
|
6e06ff048d | ||
|
|
c5ee39f54b | ||
|
|
f7b1e4ec09 | ||
|
|
e6830b2c19 | ||
|
|
fe3cf386c3 | ||
|
|
0a6a213891 | ||
|
|
2103e691db | ||
|
|
cf15a99730 | ||
|
|
a3102b552c | ||
|
|
bd0257cbe5 | ||
|
|
56e7b2a592 | ||
|
|
61d030748c | ||
|
|
f59ed991fe | ||
|
|
2bdf958663 | ||
|
|
bd8b6a2a64 | ||
|
|
88528e338b | ||
|
|
88b3bf1887 | ||
|
|
6907df1457 | ||
|
|
19036c14f5 | ||
|
|
ddb1236f2f | ||
|
|
30ef9c6418 | ||
|
|
8763fd1c53 | ||
|
|
5976005c4a | ||
|
|
63eed8994a | ||
|
|
f458dbdbcb | ||
|
|
b7421fd5cd | ||
|
|
a2feb04509 | ||
|
|
e25fee71a2 | ||
|
|
bfe2a6656c | ||
|
|
e15ca5c642 | ||
|
|
3232c5be86 | ||
|
|
1c5a50d4cb | ||
|
|
4ef5f77161 | ||
|
|
d27e5a5e1d | ||
|
|
7ecf76490c | ||
|
|
12120413f9 | ||
|
|
c0eea6e667 | ||
|
|
5c54aecdda | ||
|
|
5cfc0cce14 | ||
|
|
d9a58ef830 | ||
|
|
dfd85da9d7 | ||
|
|
94edc13393 | ||
|
|
a9baa519f3 | ||
|
|
a6c859c9cc | ||
|
|
f9a67b34b2 | ||
|
|
6ac5735d14 | ||
|
|
9d5e8b9ad8 | ||
|
|
bd72ee9cd1 | ||
|
|
c2e115b6a5 | ||
|
|
61ba4cd1ce | ||
|
|
244e0fa5e6 | ||
|
|
134bc44c45 | ||
|
|
1d2dc98f50 | ||
|
|
7a05b89a93 | ||
|
|
2bfeb20550 | ||
|
|
fa779034b5 | ||
|
|
ea5cfdcdce | ||
|
|
ba1eab1bf0 | ||
|
|
149c60bd2e | ||
|
|
9795a27482 | ||
|
|
baccdba75c | ||
|
|
93b4c6291a | ||
|
|
815edf1ba5 | ||
|
|
df7b4d81c7 | ||
|
|
3e07ba1012 | ||
|
|
32c6906750 | ||
|
|
3ebe4c47ba | ||
|
|
5b803f00e1 | ||
|
|
9a0118d991 | ||
|
|
093aae1f46 | ||
|
|
e431318dc0 | ||
|
|
c15812add2 | ||
|
|
3375cdbb49 | ||
|
|
559b564714 | ||
|
|
3ac4cfb9a7 | ||
|
|
a4d651ce9a | ||
|
|
d3bbc0eaa5 | ||
|
|
9ff90c98cd | ||
|
|
b8aaf7d7b1 | ||
|
|
c0ecde90bc | ||
|
|
83719a6f48 | ||
|
|
28011bbf55 | ||
|
|
88170f6dc4 | ||
|
|
931aab22bb | ||
|
|
6cb4fbb1c4 | ||
|
|
54a551e488 | ||
|
|
5a0d84f185 | ||
|
|
222396759b | ||
|
|
128c0ed5a1 | ||
|
|
ea74e34446 | ||
|
|
c7225a059f | ||
|
|
c1f8ae662f | ||
|
|
7d3227128c | ||
|
|
182b6755f5 | ||
|
|
0945f79ced | ||
|
|
8b611322e5 | ||
|
|
b255796b33 | ||
|
|
2ae7c60780 | ||
|
|
279ad90a3c | ||
|
|
bed7a7d29c | ||
|
|
f02a3c5b47 | ||
|
|
d7df5126ce | ||
|
|
97ecfe7e03 | ||
|
|
f30fde3a52 | ||
|
|
d7273dee1c | ||
|
|
55dff4d512 | ||
|
|
693b21188c | ||
|
|
220734ccac | ||
|
|
bf84024d6b | ||
|
|
7bb39ae541 | ||
|
|
d250057a7c | ||
|
|
d07454659a | ||
|
|
913d2984ce | ||
|
|
e2d75c0b76 | ||
|
|
8aba486295 | ||
|
|
66f2cd81a8 | ||
|
|
87bda9e124 | ||
|
|
954d019895 | ||
|
|
41132af773 | ||
|
|
9a5b89da59 | ||
|
|
c12ffa21da | ||
|
|
0b5937a396 | ||
|
|
773bb0651e | ||
|
|
8817b1e2af | ||
|
|
366ee6d24b | ||
|
|
0d58869d6e | ||
|
|
52ba3c7f80 | ||
|
|
14d2bae238 | ||
|
|
e331512473 | ||
|
|
1de6a21f3a | ||
|
|
43d8c81104 | ||
|
|
89930f34d7 | ||
|
|
59ea6b120c | ||
|
|
7c312d358b | ||
|
|
ac2746f680 | ||
|
|
e2b4178f42 | ||
|
|
266954be99 | ||
|
|
2e3ae9decb | ||
|
|
6741698f71 | ||
|
|
ccae1cc430 | ||
|
|
241a5bf4e5 | ||
|
|
e36aba8c66 | ||
|
|
1a0baef147 | ||
|
|
9a49d267eb | ||
|
|
7a832f1fdb | ||
|
|
16c391c78c | ||
|
|
92aae63af2 | ||
|
|
b042644c85 | ||
|
|
97afc4bd0c | ||
|
|
a67b29a576 | ||
|
|
97c87d0a99 | ||
|
|
fedf8d9935 | ||
|
|
23bfb84e38 | ||
|
|
c7d16fbf9e | ||
|
|
033a3dd620 | ||
|
|
f5a0b2fed8 | ||
|
|
b03dcfb7de | ||
|
|
502094439c | ||
|
|
c15f812366 | ||
|
|
dd1b102282 | ||
|
|
67b3cdc7b7 | ||
|
|
051994bdf4 | ||
|
|
0f7c12b517 | ||
|
|
aa2b0090d3 | ||
|
|
00b27c20da | ||
|
|
7ecd7e84d9 | ||
|
|
49c2dbd4a7 | ||
|
|
cf46535b66 | ||
|
|
91e2e6f207 | ||
|
|
b63434ce2e | ||
|
|
dde6c42421 | ||
|
|
beb6cca88d | ||
|
|
ba2f18ce21 | ||
|
|
c928eded74 | ||
|
|
9baefc2e56 | ||
|
|
313fe2c76c | ||
|
|
53c69e7ad5 | ||
|
|
3ff935d4c4 | ||
|
|
9fa89e8596 | ||
|
|
6c20af07f7 | ||
|
|
56abd7ba70 | ||
|
|
dc1769b28a | ||
|
|
97b863101b | ||
|
|
0a1b62a760 | ||
|
|
f2fa852f1a | ||
|
|
59f4ddf5af | ||
|
|
673d857bd8 | ||
|
|
36be16b3e9 | ||
|
|
390bb1988d | ||
|
|
63deae3ab2 | ||
|
|
710374ed1e | ||
|
|
8f1dc2522a | ||
|
|
9c3dd76e25 | ||
|
|
3328087de1 | ||
|
|
ec3f5ff40b | ||
|
|
3b000f080e | ||
|
|
09046c53ef | ||
|
|
13331d3eab | ||
|
|
a2a1a557f5 | ||
|
|
fff4cc8b0d | ||
|
|
aa0fc6dfe7 | ||
|
|
c639ac0c5a | ||
|
|
45aa77079d | ||
|
|
8e57090a75 | ||
|
|
e7cb8c8b4f | ||
|
|
57002aca36 | ||
|
|
5956d3ec77 | ||
|
|
2d522de701 | ||
|
|
aef987d832 | ||
|
|
c5d90745a0 | ||
|
|
1d160762b5 | ||
|
|
b45b9e5ccf | ||
|
|
4b9931c417 | ||
|
|
34424d7a00 | ||
|
|
7cd32fc4eb | ||
|
|
c9097566e2 | ||
|
|
e26556c631 | ||
|
|
bd32dce19a | ||
|
|
152a3f2e5f | ||
|
|
4fe6815062 | ||
|
|
525979afaa | ||
|
|
93a10f33d5 | ||
|
|
c9b4fb418a | ||
|
|
2151bf8f9a | ||
|
|
fa64ef6f00 | ||
|
|
a31c0e9082 | ||
|
|
365ce29761 | ||
|
|
93ca98d3a8 | ||
|
|
6e86a498ad | ||
|
|
94cfe30b77 | ||
|
|
cca3acc035 | ||
|
|
f0e3fd9e72 | ||
|
|
8388163aaf | ||
|
|
a203214ef9 | ||
|
|
4250893d2f | ||
|
|
0c1e2a7347 | ||
|
|
d5c35a1d83 | ||
|
|
722036f10e | ||
|
|
8eab74ea81 | ||
|
|
473d38c846 | ||
|
|
a9fb1b25a8 | ||
|
|
360dbd9e5e | ||
|
|
8c4f9d913d | ||
|
|
e4b1377b0e | ||
|
|
fc5e0fb012 | ||
|
|
9a140643c8 | ||
|
|
5fbba7bc01 | ||
|
|
4cf7ab3425 | ||
|
|
b7f93bd4ea | ||
|
|
962a08700e | ||
|
|
d23daf225d | ||
|
|
e5f2b0c0a9 | ||
|
|
6aa80b07e7 | ||
|
|
be0ae2389c | ||
|
|
7d8b6d149e | ||
|
|
a47fbc18f7 | ||
|
|
47ad802ab6 | ||
|
|
8a3e786294 | ||
|
|
4018b284e3 | ||
|
|
b704d42fe4 | ||
|
|
5dab2802b3 | ||
|
|
377fbed517 | ||
|
|
eab0a73f53 | ||
|
|
558170582a | ||
|
|
10ffaec730 | ||
|
|
f17876969d | ||
|
|
81777a29d5 | ||
|
|
3944786c13 | ||
|
|
af939fad66 | ||
|
|
79f8f3eb14 | ||
|
|
9137b38fb9 | ||
|
|
4bb5ee4b17 | ||
|
|
022c8502c0 | ||
|
|
b601ba55d0 | ||
|
|
8de3571aa8 | ||
|
|
5a6bc4404a | ||
|
|
17eb4a2660 | ||
|
|
81124780d0 | ||
|
|
aed7e14d4b | ||
|
|
6835c344eb | ||
|
|
0b965d1ee4 | ||
|
|
ed184acb40 | ||
|
|
7d7eac5030 | ||
|
|
68dbb13084 | ||
|
|
27d335ebe1 | ||
|
|
900e035412 | ||
|
|
bc552d326c | ||
|
|
7ffc983edd | ||
|
|
4a81d366bb | ||
|
|
383a51dde8 | ||
|
|
2a6060e425 | ||
|
|
576269dae9 | ||
|
|
ac34e0e108 | ||
|
|
11bd4c3223 | ||
|
|
8d88a92fe4 | ||
|
|
6004a35e23 | ||
|
|
a3a633242f | ||
|
|
4ad579d4ad | ||
|
|
2666c7312f | ||
|
|
516f30a307 | ||
|
|
9d3d50c654 | ||
|
|
453fbbed1b | ||
|
|
0ce8ab7bce | ||
|
|
d72128107e | ||
|
|
3b8dc924c3 | ||
|
|
08ac287726 | ||
|
|
a8d6f40794 | ||
|
|
a2071feeb1 | ||
|
|
aa705b07f3 | ||
|
|
fbbc1981ca | ||
|
|
6528bd0e4f | ||
|
|
81a07899ae | ||
|
|
c18d8fa967 | ||
|
|
3caa91cc36 | ||
|
|
0bdf3542e4 | ||
|
|
23769371bc | ||
|
|
bccd854676 | ||
|
|
2fa0910547 | ||
|
|
c170b1b83e | ||
|
|
be6016a972 | ||
|
|
a56f66e721 | ||
|
|
e589d7f1e1 | ||
|
|
948cde1a31 | ||
|
|
3447aaa8c6 | ||
|
|
688c64ce21 | ||
|
|
7eb42dc36b | ||
|
|
ae1c1b3a47 | ||
|
|
74078552df | ||
|
|
5da8206915 | ||
|
|
f271726cd8 | ||
|
|
22f6612354 | ||
|
|
74fe5bc4dd | ||
|
|
69d7011baf | ||
|
|
0301d4462b | ||
|
|
7c009e2443 | ||
|
|
a16d9f91ee | ||
|
|
7e76c85535 | ||
|
|
3054694726 | ||
|
|
a25021d215 | ||
|
|
532833ff70 | ||
|
|
e79a66851c | ||
|
|
97825fb2c7 | ||
|
|
bd9df7e619 | ||
|
|
087f09e9a6 | ||
|
|
1257b32464 | ||
|
|
a437af44f8 | ||
|
|
9644610e04 | ||
|
|
71cbe1cf50 | ||
|
|
edad2a1ee5 | ||
|
|
0e597f5768 | ||
|
|
b28dc55237 | ||
|
|
a2dec7a05d | ||
|
|
db9fb22cf4 | ||
|
|
412a00249f | ||
|
|
ccb7a8f94f | ||
|
|
ee26e13bea | ||
|
|
493ff9c685 | ||
|
|
bbc49e1ba3 | ||
|
|
0ef39e4440 | ||
|
|
8a956bcdf6 | ||
|
|
a16ff29638 | ||
|
|
f6381e7e5e | ||
|
|
e014765797 | ||
|
|
3899684686 | ||
|
|
e11b457b79 | ||
|
|
a04cbd111c | ||
|
|
6c7d3e1eab | ||
|
|
d965b41bdd | ||
|
|
d660c12a74 | ||
|
|
43bcbf771e | ||
|
|
7f420361b1 | ||
|
|
361455678a | ||
|
|
47c1c6288c | ||
|
|
07abc9fac4 | ||
|
|
266923d9e8 | ||
|
|
622ff9d764 | ||
|
|
b75d11da3a | ||
|
|
8af49161fb | ||
|
|
ca872af3c8 | ||
|
|
aeccf45d4e | ||
|
|
dcae0eadd5 | ||
|
|
80effaa541 | ||
|
|
edd93c80a1 | ||
|
|
39646acf5b | ||
|
|
f697d2daa1 | ||
|
|
607631604f | ||
|
|
09d012a10b | ||
|
|
b303d49634 | ||
|
|
371723a5d4 | ||
|
|
4481c3bada | ||
|
|
70bb30b95a | ||
|
|
ebc641440e | ||
|
|
586b4db968 | ||
|
|
12c7981450 | ||
|
|
08c909fd41 | ||
|
|
44e43d3b47 | ||
|
|
9e8273c7f7 | ||
|
|
93735c7bf1 | ||
|
|
e37a97e2d5 | ||
|
|
8ff5450ece | ||
|
|
5d30ddac22 | ||
|
|
80f697ef2a | ||
|
|
47c7748707 | ||
|
|
9f33aa2afc | ||
|
|
1dc6600b59 | ||
|
|
1ec58c1161 | ||
|
|
d023d577b2 | ||
|
|
21d65ca0bf | ||
|
|
bcf4401858 | ||
|
|
262396d48b | ||
|
|
0a9d5f680f | ||
|
|
64239f1c04 | ||
|
|
7590d546f1 | ||
|
|
021070f066 | ||
|
|
55a4318839 | ||
|
|
90647f30f8 | ||
|
|
8cc9080d36 | ||
|
|
6e5fc91885 | ||
|
|
71de2b5ec5 | ||
|
|
7703f91ee2 | ||
|
|
ecc8abcc50 | ||
|
|
14917c9791 | ||
|
|
25c56164b0 | ||
|
|
12988b879e | ||
|
|
684e391a9a | ||
|
|
7a16cd4c37 | ||
|
|
b3117c2b02 | ||
|
|
6a75fa83b5 | ||
|
|
88a8721b89 | ||
|
|
1f12857551 | ||
|
|
71032f6c4c | ||
|
|
088b1cab83 | ||
|
|
f40a534bfb | ||
|
|
f278530239 | ||
|
|
0389aab0a3 | ||
|
|
51a66a3202 | ||
|
|
248985e51a | ||
|
|
996d83eae0 | ||
|
|
98a1329dd7 | ||
|
|
ed2ebc7d3d | ||
|
|
41634f9998 | ||
|
|
93501af046 | ||
|
|
078585db28 | ||
|
|
03e9e4c1d9 | ||
|
|
4a1d077238 | ||
|
|
f7a5e6deb8 | ||
|
|
dabb22bb6a | ||
|
|
3d03ca3d10 | ||
|
|
386992c3b8 | ||
|
|
a48f252cfa | ||
|
|
c3a311ab85 | ||
|
|
7926e1bc3c | ||
|
|
b796db648a | ||
|
|
0964ecac8c | ||
|
|
dd1ac7952b | ||
|
|
7d1cbcb0c1 | ||
|
|
98c9e67625 | ||
|
|
aeef66ce35 | ||
|
|
8cff66e8c6 | ||
|
|
10a04acf41 | ||
|
|
9923a4c4ff | ||
|
|
0dafa9e229 | ||
|
|
e83e8a8f1c | ||
|
|
72aa768235 | ||
|
|
65c74e3976 | ||
|
|
cdac34efea | ||
|
|
03fef3106d | ||
|
|
d598d0a4db | ||
|
|
ab22e1b3a9 | ||
|
|
26d520af3c | ||
|
|
fb333f3641 | ||
|
|
1cc65a47eb | ||
|
|
8d56c52991 | ||
|
|
4b88b9eed1 | ||
|
|
462b91fb08 | ||
|
|
b65f4ff963 | ||
|
|
8d27b48225 | ||
|
|
e2623c5e82 | ||
|
|
acdae42fc5 | ||
|
|
451aac806e | ||
|
|
586e6178b4 | ||
|
|
1201761ff3 | ||
|
|
bdf68f092e | ||
|
|
a179f87d54 | ||
|
|
b2944a12de | ||
|
|
bfcb36927c | ||
|
|
ccd21d5254 | ||
|
|
a7b8448107 | ||
|
|
e934be2d99 | ||
|
|
015b875a9e | ||
|
|
1247ff2543 | ||
|
|
dc831fb3f6 | ||
|
|
94c0e947f5 | ||
|
|
ed9bc835a2 | ||
|
|
2eb2e52a79 | ||
|
|
14f6f88526 | ||
|
|
1f78c74085 | ||
|
|
c494649dde | ||
|
|
460f3aebe9 | ||
|
|
d4b215a66b | ||
|
|
1a13387012 | ||
|
|
291c36df05 | ||
|
|
bed2c8a371 | ||
|
|
e65ca4ccac | ||
|
|
f9e6933840 | ||
|
|
5134fb2ec1 | ||
|
|
3a86a69964 | ||
|
|
c6fd3c47a4 | ||
|
|
a365fa6109 | ||
|
|
160451b210 | ||
|
|
2f6e3cc09d | ||
|
|
d05cc7ccec | ||
|
|
ccfd4acbda | ||
|
|
6a6084ed0e | ||
|
|
0dbb780a2f | ||
|
|
e6efa6e13e | ||
|
|
76768120d4 | ||
|
|
7d6ff83760 | ||
|
|
5bec0d2d98 | ||
|
|
aad05325a6 | ||
|
|
6e7f1bc257 | ||
|
|
634d0848c8 | ||
|
|
b7e1059227 | ||
|
|
e7904fa67a | ||
|
|
e38bc7cbce | ||
|
|
b211f8a096 | ||
|
|
b4a1a6c688 | ||
|
|
6cb4b790b9 | ||
|
|
a245bdbc2a | ||
|
|
e63451a9e7 | ||
|
|
e552607c95 | ||
|
|
c7f1c5e29c | ||
|
|
37b6e22321 | ||
|
|
6e6ae18aab | ||
|
|
9f3cda0ac3 | ||
|
|
f646975c36 | ||
|
|
801cae13ac | ||
|
|
f1ae502b1f | ||
|
|
f2e34d4836 | ||
|
|
3c6a8d718f | ||
|
|
08eb28f7b8 | ||
|
|
24509a21d4 | ||
|
|
4f41a10fef | ||
|
|
26aa8b69f9 | ||
|
|
819db1524f | ||
|
|
8ad7d06ec6 | ||
|
|
606898f569 | ||
|
|
76c6adf1cf | ||
|
|
e504c3cd46 | ||
|
|
884b59a0b3 | ||
|
|
a32dedd16c | ||
|
|
ff2b37f6e3 | ||
|
|
4328ae1d8d | ||
|
|
88372000b5 | ||
|
|
081150b477 | ||
|
|
1364b97b88 | ||
|
|
7c33a46a76 | ||
|
|
8b88e9f727 | ||
|
|
91f0728b55 | ||
|
|
7a71cea92a | ||
|
|
29a855813d | ||
|
|
66da2339d4 | ||
|
|
294254efbb | ||
|
|
188597ecaf | ||
|
|
d04f613c41 | ||
|
|
25320cd0e0 | ||
|
|
00b4f09e8a | ||
|
|
fb8d9edfdf | ||
|
|
349b9bb2bf | ||
|
|
cbff11296b | ||
|
|
dc462cdc1f | ||
|
|
22024e7c1f | ||
|
|
ebb0145256 | ||
|
|
c3215d0ba5 | ||
|
|
da83f20a28 | ||
|
|
ad4b0fff56 | ||
|
|
62b90206e8 | ||
|
|
38ac4fe849 | ||
|
|
fa7b6591cf | ||
|
|
fde432601a | ||
|
|
0c954dde27 | ||
|
|
b5a86a9045 | ||
|
|
ef7c437957 | ||
|
|
8158a509c9 | ||
|
|
dc520c6c32 | ||
|
|
907033f725 | ||
|
|
533a005764 | ||
|
|
9ee563b864 | ||
|
|
748c118ea8 | ||
|
|
69e69a77d8 | ||
|
|
5a40cec1ed | ||
|
|
01bcd460da | ||
|
|
2a96c9f9ee | ||
|
|
f610e31a87 | ||
|
|
4ec0b61de5 | ||
|
|
c7d7cec281 | ||
|
|
c4775a581e | ||
|
|
591eaeaafb | ||
|
|
1f45a846c6 | ||
|
|
db943b4109 |
@@ -1,241 +0,0 @@
|
||||
# Microsoft Developer Studio Project File - Name="bpl_static" - Package Owner=<4>
|
||||
# Microsoft Developer Studio Generated Build File, Format Version 6.00
|
||||
# ** DO NOT EDIT **
|
||||
|
||||
# TARGTYPE "Win32 (x86) Static Library" 0x0104
|
||||
|
||||
CFG=bpl_static - Win32 DebugPython
|
||||
!MESSAGE This is not a valid makefile. To build this project using NMAKE,
|
||||
!MESSAGE use the Export Makefile command and run
|
||||
!MESSAGE
|
||||
!MESSAGE NMAKE /f "bpl_static.mak".
|
||||
!MESSAGE
|
||||
!MESSAGE You can specify a configuration when running NMAKE
|
||||
!MESSAGE by defining the macro CFG on the command line. For example:
|
||||
!MESSAGE
|
||||
!MESSAGE NMAKE /f "bpl_static.mak" CFG="bpl_static - Win32 DebugPython"
|
||||
!MESSAGE
|
||||
!MESSAGE Possible choices for configuration are:
|
||||
!MESSAGE
|
||||
!MESSAGE "bpl_static - Win32 Release" (based on "Win32 (x86) Static Library")
|
||||
!MESSAGE "bpl_static - Win32 Debug" (based on "Win32 (x86) Static Library")
|
||||
!MESSAGE "bpl_static - Win32 DebugPython" (based on "Win32 (x86) Static Library")
|
||||
!MESSAGE
|
||||
|
||||
# Begin Project
|
||||
# PROP AllowPerConfigDependencies 0
|
||||
# PROP Scc_ProjName ""
|
||||
# PROP Scc_LocalPath ""
|
||||
CPP=cl.exe
|
||||
RSC=rc.exe
|
||||
|
||||
!IF "$(CFG)" == "bpl_static - Win32 Release"
|
||||
|
||||
# PROP BASE Use_MFC 0
|
||||
# PROP BASE Use_Debug_Libraries 0
|
||||
# PROP BASE Output_Dir "Release"
|
||||
# PROP BASE Intermediate_Dir "Release"
|
||||
# PROP BASE Target_Dir ""
|
||||
# PROP Use_MFC 0
|
||||
# PROP Use_Debug_Libraries 0
|
||||
# PROP Output_Dir "Release"
|
||||
# PROP Intermediate_Dir "Release"
|
||||
# PROP Target_Dir ""
|
||||
# ADD BASE CPP /nologo /W3 /GX /O2 /D "WIN32" /D "NDEBUG" /D "_MBCS" /D "_LIB" /YX /FD /c
|
||||
# ADD CPP /nologo /MD /W4 /WX /GR /GX /O2 /I "..\..\.." /I "c:\tools\python\include" /D "WIN32" /D "NDEBUG" /D "_MBCS" /D "_LIB" /FR /YX /FD /c
|
||||
# ADD BASE RSC /l 0x409 /d "NDEBUG"
|
||||
# ADD RSC /l 0x409 /d "NDEBUG"
|
||||
BSC32=bscmake.exe
|
||||
# ADD BASE BSC32 /nologo
|
||||
# ADD BSC32 /nologo
|
||||
LIB32=link.exe -lib
|
||||
# ADD BASE LIB32 /nologo
|
||||
# ADD LIB32 /nologo
|
||||
|
||||
!ELSEIF "$(CFG)" == "bpl_static - Win32 Debug"
|
||||
|
||||
# PROP BASE Use_MFC 0
|
||||
# PROP BASE Use_Debug_Libraries 1
|
||||
# PROP BASE Output_Dir "Debug"
|
||||
# PROP BASE Intermediate_Dir "Debug"
|
||||
# PROP BASE Target_Dir ""
|
||||
# PROP Use_MFC 0
|
||||
# PROP Use_Debug_Libraries 1
|
||||
# PROP Output_Dir "Debug"
|
||||
# PROP Intermediate_Dir "Debug"
|
||||
# PROP Target_Dir ""
|
||||
# ADD BASE CPP /nologo /W3 /Gm /GX /ZI /Od /D "WIN32" /D "_DEBUG" /D "_MBCS" /D "_LIB" /YX /FD /GZ /c
|
||||
# ADD CPP /nologo /MDd /W4 /WX /Gm- /GR /GX /Zi /Od /I "..\..\.." /I "c:\tools\python\include" /D "WIN32" /D "_DEBUG" /D "_MBCS" /D "_LIB" /FR /YX /FD /GZ /c
|
||||
# ADD BASE RSC /l 0x409 /d "_DEBUG"
|
||||
# ADD RSC /l 0x409 /d "_DEBUG"
|
||||
BSC32=bscmake.exe
|
||||
# ADD BASE BSC32 /nologo
|
||||
# ADD BSC32 /nologo
|
||||
LIB32=link.exe -lib
|
||||
# ADD BASE LIB32 /nologo
|
||||
# ADD LIB32 /nologo
|
||||
|
||||
!ELSEIF "$(CFG)" == "bpl_static - Win32 DebugPython"
|
||||
|
||||
# PROP BASE Use_MFC 0
|
||||
# PROP BASE Use_Debug_Libraries 1
|
||||
# PROP BASE Output_Dir "bpl_static___Win32_DebugPython"
|
||||
# PROP BASE Intermediate_Dir "bpl_static___Win32_DebugPython"
|
||||
# PROP BASE Target_Dir ""
|
||||
# PROP Use_MFC 0
|
||||
# PROP Use_Debug_Libraries 1
|
||||
# PROP Output_Dir "DebugPython"
|
||||
# PROP Intermediate_Dir "DebugPython"
|
||||
# PROP Target_Dir ""
|
||||
# ADD BASE CPP /nologo /MDd /W4 /WX /Gm /GR /GX /Zi /Od /I "..\..\.." /I "c:\tools\python\include" /D "WIN32" /D "_DEBUG" /D "_MBCS" /D "_LIB" /FR /YX /FD /GZ /c
|
||||
# ADD CPP /nologo /MDd /W4 /WX /Gm- /GR /GX /Zi /Od /I "..\..\.." /I "c:\tools\python\include" /D "WIN32" /D "_DEBUG" /D "_MBCS" /D "_LIB" /D "BOOST_DEBUG_PYTHON" /FR /YX /FD /GZ /EHs /c
|
||||
# ADD BASE RSC /l 0x409 /d "_DEBUG"
|
||||
# ADD RSC /l 0x409 /d "_DEBUG"
|
||||
BSC32=bscmake.exe
|
||||
# ADD BASE BSC32 /nologo
|
||||
# ADD BSC32 /nologo
|
||||
LIB32=link.exe -lib
|
||||
# ADD BASE LIB32 /nologo
|
||||
# ADD LIB32 /nologo
|
||||
|
||||
!ENDIF
|
||||
|
||||
# Begin Target
|
||||
|
||||
# Name "bpl_static - Win32 Release"
|
||||
# Name "bpl_static - Win32 Debug"
|
||||
# Name "bpl_static - Win32 DebugPython"
|
||||
# Begin Group "Source Files"
|
||||
|
||||
# PROP Default_Filter "cpp;c;cxx;rc;def;r;odl;idl;hpj;bat"
|
||||
# Begin Source File
|
||||
|
||||
SOURCE=..\src\classes.cpp
|
||||
# ADD CPP /W3
|
||||
# End Source File
|
||||
# Begin Source File
|
||||
|
||||
SOURCE=..\src\conversions.cpp
|
||||
# ADD CPP /W3
|
||||
# End Source File
|
||||
# Begin Source File
|
||||
|
||||
SOURCE=..\src\extension_class.cpp
|
||||
# ADD CPP /W3
|
||||
# End Source File
|
||||
# Begin Source File
|
||||
|
||||
SOURCE=..\src\functions.cpp
|
||||
# ADD CPP /W3
|
||||
# End Source File
|
||||
# Begin Source File
|
||||
|
||||
SOURCE=..\src\init_function.cpp
|
||||
# ADD CPP /W3
|
||||
# End Source File
|
||||
# Begin Source File
|
||||
|
||||
SOURCE=..\src\module_builder.cpp
|
||||
# ADD CPP /W3
|
||||
# End Source File
|
||||
# Begin Source File
|
||||
|
||||
SOURCE=..\src\objects.cpp
|
||||
# ADD CPP /W3
|
||||
# End Source File
|
||||
# Begin Source File
|
||||
|
||||
SOURCE=..\src\types.cpp
|
||||
# ADD CPP /W3
|
||||
# End Source File
|
||||
# End Group
|
||||
# Begin Group "Header Files"
|
||||
|
||||
# PROP Default_Filter "h;hpp;hxx;hm;inl"
|
||||
# Begin Source File
|
||||
|
||||
SOURCE=..\..\..\boost\python\detail\base_object.hpp
|
||||
# End Source File
|
||||
# Begin Source File
|
||||
|
||||
SOURCE=..\..\..\boost\python\callback.hpp
|
||||
# End Source File
|
||||
# Begin Source File
|
||||
|
||||
SOURCE=..\..\..\boost\python\caller.hpp
|
||||
# End Source File
|
||||
# Begin Source File
|
||||
|
||||
SOURCE=..\..\..\boost\python\detail\cast.hpp
|
||||
# End Source File
|
||||
# Begin Source File
|
||||
|
||||
SOURCE=..\..\..\boost\python\class_builder.hpp
|
||||
# End Source File
|
||||
# Begin Source File
|
||||
|
||||
SOURCE=..\..\..\boost\python\classes.hpp
|
||||
# End Source File
|
||||
# Begin Source File
|
||||
|
||||
SOURCE=..\..\..\boost\python\detail\config.hpp
|
||||
# End Source File
|
||||
# Begin Source File
|
||||
|
||||
SOURCE=..\..\..\boost\python\conversions.hpp
|
||||
# End Source File
|
||||
# Begin Source File
|
||||
|
||||
SOURCE=..\..\..\boost\python\errors.hpp
|
||||
# End Source File
|
||||
# Begin Source File
|
||||
|
||||
SOURCE=..\..\..\boost\python\detail\extension_class.hpp
|
||||
# End Source File
|
||||
# Begin Source File
|
||||
|
||||
SOURCE=..\..\..\boost\python\detail\functions.hpp
|
||||
# End Source File
|
||||
# Begin Source File
|
||||
|
||||
SOURCE=..\..\..\boost\python\detail\init_function.hpp
|
||||
# End Source File
|
||||
# Begin Source File
|
||||
|
||||
SOURCE=..\..\..\boost\python\module_builder.hpp
|
||||
# End Source File
|
||||
# Begin Source File
|
||||
|
||||
SOURCE=..\..\..\boost\python\detail\none.hpp
|
||||
# End Source File
|
||||
# Begin Source File
|
||||
|
||||
SOURCE=..\..\..\boost\python\objects.hpp
|
||||
# End Source File
|
||||
# Begin Source File
|
||||
|
||||
SOURCE=..\..\..\boost\python\operators.hpp
|
||||
# End Source File
|
||||
# Begin Source File
|
||||
|
||||
SOURCE=..\..\..\boost\python\reference.hpp
|
||||
# End Source File
|
||||
# Begin Source File
|
||||
|
||||
SOURCE=..\..\..\boost\python\detail\signatures.hpp
|
||||
# End Source File
|
||||
# Begin Source File
|
||||
|
||||
SOURCE=..\..\..\boost\python\detail\singleton.hpp
|
||||
# End Source File
|
||||
# Begin Source File
|
||||
|
||||
SOURCE=..\..\..\boost\python\detail\types.hpp
|
||||
# End Source File
|
||||
# Begin Source File
|
||||
|
||||
SOURCE=..\..\..\boost\python\detail\wrap_python.hpp
|
||||
# End Source File
|
||||
# End Group
|
||||
# End Target
|
||||
# End Project
|
||||
108
build/build.dsw
108
build/build.dsw
@@ -1,108 +0,0 @@
|
||||
Microsoft Developer Studio Workspace File, Format Version 6.00
|
||||
# WARNING: DO NOT EDIT OR DELETE THIS WORKSPACE FILE!
|
||||
|
||||
###############################################################################
|
||||
|
||||
Project: "bpl_static"=.\bpl_static.dsp - Package Owner=<4>
|
||||
|
||||
Package=<5>
|
||||
{{{
|
||||
}}}
|
||||
|
||||
Package=<4>
|
||||
{{{
|
||||
}}}
|
||||
|
||||
###############################################################################
|
||||
|
||||
Project: "example1"=.\example1\example1.dsp - Package Owner=<4>
|
||||
|
||||
Package=<5>
|
||||
{{{
|
||||
}}}
|
||||
|
||||
Package=<4>
|
||||
{{{
|
||||
Begin Project Dependency
|
||||
Project_Dep_Name bpl_static
|
||||
End Project Dependency
|
||||
}}}
|
||||
|
||||
###############################################################################
|
||||
|
||||
Project: "getting_started1"=.\getting_started1\getting_started1.dsp - Package Owner=<4>
|
||||
|
||||
Package=<5>
|
||||
{{{
|
||||
}}}
|
||||
|
||||
Package=<4>
|
||||
{{{
|
||||
Begin Project Dependency
|
||||
Project_Dep_Name bpl_static
|
||||
End Project Dependency
|
||||
}}}
|
||||
|
||||
###############################################################################
|
||||
|
||||
Project: "getting_started2"=.\getting_started2\getting_started2.dsp - Package Owner=<4>
|
||||
|
||||
Package=<5>
|
||||
{{{
|
||||
begin source code control
|
||||
getting_started2
|
||||
.\getting_started2
|
||||
end source code control
|
||||
}}}
|
||||
|
||||
Package=<4>
|
||||
{{{
|
||||
Begin Project Dependency
|
||||
Project_Dep_Name bpl_static
|
||||
End Project Dependency
|
||||
}}}
|
||||
|
||||
###############################################################################
|
||||
|
||||
Project: "rwgk1"=.\rwgk1\rwgk1.dsp - Package Owner=<4>
|
||||
|
||||
Package=<5>
|
||||
{{{
|
||||
}}}
|
||||
|
||||
Package=<4>
|
||||
{{{
|
||||
Begin Project Dependency
|
||||
Project_Dep_Name bpl_static
|
||||
End Project Dependency
|
||||
}}}
|
||||
|
||||
###############################################################################
|
||||
|
||||
Project: "test"=.\test\test.dsp - Package Owner=<4>
|
||||
|
||||
Package=<5>
|
||||
{{{
|
||||
}}}
|
||||
|
||||
Package=<4>
|
||||
{{{
|
||||
Begin Project Dependency
|
||||
Project_Dep_Name bpl_static
|
||||
End Project Dependency
|
||||
}}}
|
||||
|
||||
###############################################################################
|
||||
|
||||
Global:
|
||||
|
||||
Package=<5>
|
||||
{{{
|
||||
}}}
|
||||
|
||||
Package=<3>
|
||||
{{{
|
||||
}}}
|
||||
|
||||
###############################################################################
|
||||
|
||||
BIN
build/build.opt
BIN
build/build.opt
Binary file not shown.
@@ -1,55 +0,0 @@
|
||||
# Revision History:
|
||||
# 06 Mar 01 Fixed typo in use of "PYTHON_LIB" (Dave Abrahams)
|
||||
# 04 Mar 01 Changed library name to libboost_python.a (David Abrahams)
|
||||
|
||||
LIBSRC = \
|
||||
classes.cpp \
|
||||
conversions.cpp \
|
||||
extension_class.cpp \
|
||||
functions.cpp \
|
||||
init_function.cpp \
|
||||
module_builder.cpp \
|
||||
objects.cpp \
|
||||
types.cpp
|
||||
|
||||
LIBOBJ = $(LIBSRC:.cpp=.o)
|
||||
OBJ = $(LIBOBJ)
|
||||
|
||||
|
||||
ifeq "$(OS)" "Windows_NT"
|
||||
PYTHON_LIB=c:/tools/python/libs/python15.lib
|
||||
INC = -Ic:/cygnus/usr/include/g++-3 -Ic:/cygnus/usr/include -Ic:/boost -Ic:/tools/python/include
|
||||
MODULE_EXTENSION=dll
|
||||
else
|
||||
INC = -I/usr/local/include/python1.5
|
||||
MODULE_EXTENSION=so
|
||||
endif
|
||||
|
||||
%.o: ../src/%.cpp
|
||||
como --pic $(INC) -o $*.o -c $<
|
||||
|
||||
%.d: ../src/%.cpp
|
||||
@echo creating $@
|
||||
@set -e; como -M $(INC) -c $< \
|
||||
| sed 's/\($*\)\.o[ :]*/\1.o $@ : /g' > $@; \
|
||||
[ -s $@ ] || rm -f $@
|
||||
|
||||
example1: example1.o libboost_python.a
|
||||
como-dyn-link -o ../example/hellomodule.$(MODULE_EXTENSION) $(PYTHON_LIB) example1.o -L. -lboost_python
|
||||
python ../example/test_example1.py
|
||||
|
||||
example1.o: ../example/example1.cpp
|
||||
como --pic $(INC) -o $*.o -c $<
|
||||
|
||||
clean:
|
||||
rm -rf *.o *.$(MODULE_EXTENSION) *.a *.d *.pyc *.bak a.out
|
||||
|
||||
libboost_python.a: $(LIBOBJ)
|
||||
rm -f libboost_python.a
|
||||
ar cq libboost_python.a $(LIBOBJ)
|
||||
|
||||
DEP = $(OBJ:.o=.d)
|
||||
|
||||
ifneq "$(MAKECMDGOALS)" "clean"
|
||||
include $(DEP)
|
||||
endif
|
||||
@@ -1,136 +0,0 @@
|
||||
# Microsoft Developer Studio Project File - Name="example1" - Package Owner=<4>
|
||||
# Microsoft Developer Studio Generated Build File, Format Version 6.00
|
||||
# ** DO NOT EDIT **
|
||||
|
||||
# TARGTYPE "Win32 (x86) Dynamic-Link Library" 0x0102
|
||||
|
||||
CFG=example1 - Win32 DebugPython
|
||||
!MESSAGE This is not a valid makefile. To build this project using NMAKE,
|
||||
!MESSAGE use the Export Makefile command and run
|
||||
!MESSAGE
|
||||
!MESSAGE NMAKE /f "example1.mak".
|
||||
!MESSAGE
|
||||
!MESSAGE You can specify a configuration when running NMAKE
|
||||
!MESSAGE by defining the macro CFG on the command line. For example:
|
||||
!MESSAGE
|
||||
!MESSAGE NMAKE /f "example1.mak" CFG="example1 - Win32 DebugPython"
|
||||
!MESSAGE
|
||||
!MESSAGE Possible choices for configuration are:
|
||||
!MESSAGE
|
||||
!MESSAGE "example1 - Win32 Release" (based on "Win32 (x86) Dynamic-Link Library")
|
||||
!MESSAGE "example1 - Win32 Debug" (based on "Win32 (x86) Dynamic-Link Library")
|
||||
!MESSAGE "example1 - Win32 DebugPython" (based on "Win32 (x86) Dynamic-Link Library")
|
||||
!MESSAGE
|
||||
|
||||
# Begin Project
|
||||
# PROP AllowPerConfigDependencies 0
|
||||
# PROP Scc_ProjName ""
|
||||
# PROP Scc_LocalPath ""
|
||||
CPP=cl.exe
|
||||
MTL=midl.exe
|
||||
RSC=rc.exe
|
||||
|
||||
!IF "$(CFG)" == "example1 - Win32 Release"
|
||||
|
||||
# PROP BASE Use_MFC 0
|
||||
# PROP BASE Use_Debug_Libraries 0
|
||||
# PROP BASE Output_Dir "Release"
|
||||
# PROP BASE Intermediate_Dir "Release"
|
||||
# PROP BASE Target_Dir ""
|
||||
# PROP Use_MFC 0
|
||||
# PROP Use_Debug_Libraries 0
|
||||
# PROP Output_Dir "Release"
|
||||
# PROP Intermediate_Dir "Release"
|
||||
# PROP Ignore_Export_Lib 0
|
||||
# PROP Target_Dir ""
|
||||
# ADD BASE CPP /nologo /MT /W3 /GX /O2 /D "WIN32" /D "NDEBUG" /D "_WINDOWS" /D "_MBCS" /D "_USRDLL" /D "EXAMPLE1_EXPORTS" /YX /FD /c
|
||||
# ADD CPP /nologo /MD /W3 /GX /O2 /I "..\..\..\.." /I "c:\tools\python\include" /D "WIN32" /D "NDEBUG" /D "_WINDOWS" /D "_MBCS" /D "_USRDLL" /D "EXAMPLE1_EXPORTS" /YX /FD /c
|
||||
# ADD BASE MTL /nologo /D "NDEBUG" /mktyplib203 /win32
|
||||
# ADD MTL /nologo /D "NDEBUG" /mktyplib203 /win32
|
||||
# ADD BASE RSC /l 0x409 /d "NDEBUG"
|
||||
# ADD RSC /l 0x409 /d "NDEBUG"
|
||||
BSC32=bscmake.exe
|
||||
# ADD BASE BSC32 /nologo
|
||||
# ADD BSC32 /nologo
|
||||
LINK32=link.exe
|
||||
# ADD BASE LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /dll /machine:I386
|
||||
# ADD LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /dll /machine:I386 /out:"Release/hello.dll" /libpath:"c:\tools\python\libs"
|
||||
|
||||
!ELSEIF "$(CFG)" == "example1 - Win32 Debug"
|
||||
|
||||
# PROP BASE Use_MFC 0
|
||||
# PROP BASE Use_Debug_Libraries 1
|
||||
# PROP BASE Output_Dir "Debug"
|
||||
# PROP BASE Intermediate_Dir "Debug"
|
||||
# PROP BASE Target_Dir ""
|
||||
# PROP Use_MFC 0
|
||||
# PROP Use_Debug_Libraries 1
|
||||
# PROP Output_Dir "Debug"
|
||||
# PROP Intermediate_Dir "Debug"
|
||||
# PROP Ignore_Export_Lib 0
|
||||
# PROP Target_Dir ""
|
||||
# ADD BASE CPP /nologo /MTd /W3 /Gm /GX /ZI /Od /D "WIN32" /D "_DEBUG" /D "_WINDOWS" /D "_MBCS" /D "_USRDLL" /D "EXAMPLE1_EXPORTS" /YX /FD /GZ /c
|
||||
# ADD CPP /nologo /MDd /W3 /Gm- /GR /GX /Zi /Od /I "..\..\..\.." /I "c:\tools\python\include" /D "WIN32" /D "_DEBUG" /D "_WINDOWS" /D "_MBCS" /D "_USRDLL" /D "EXAMPLE1_EXPORTS" /YX /FD /GZ /c
|
||||
# ADD BASE MTL /nologo /D "_DEBUG" /mktyplib203 /win32
|
||||
# ADD MTL /nologo /D "_DEBUG" /mktyplib203 /win32
|
||||
# ADD BASE RSC /l 0x409 /d "_DEBUG"
|
||||
# ADD RSC /l 0x409 /d "_DEBUG"
|
||||
BSC32=bscmake.exe
|
||||
# ADD BASE BSC32 /nologo
|
||||
# ADD BSC32 /nologo
|
||||
LINK32=link.exe
|
||||
# ADD BASE LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /dll /debug /machine:I386 /pdbtype:sept
|
||||
# ADD LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /dll /incremental:no /debug /machine:I386 /out:"Debug/hello.dll" /pdbtype:sept /libpath:"c:\tools\python\libs"
|
||||
|
||||
!ELSEIF "$(CFG)" == "example1 - Win32 DebugPython"
|
||||
|
||||
# PROP BASE Use_MFC 0
|
||||
# PROP BASE Use_Debug_Libraries 1
|
||||
# PROP BASE Output_Dir "example1___Win32_DebugPython"
|
||||
# PROP BASE Intermediate_Dir "example1___Win32_DebugPython"
|
||||
# PROP BASE Ignore_Export_Lib 0
|
||||
# PROP BASE Target_Dir ""
|
||||
# PROP Use_MFC 0
|
||||
# PROP Use_Debug_Libraries 1
|
||||
# PROP Output_Dir "DebugPython"
|
||||
# PROP Intermediate_Dir "DebugPython"
|
||||
# PROP Ignore_Export_Lib 1
|
||||
# PROP Target_Dir ""
|
||||
# ADD BASE CPP /nologo /MDd /W3 /Gm /GR /GX /Zi /Od /I "..\..\..\.." /I "c:\tools\python\include" /D "WIN32" /D "_DEBUG" /D "_WINDOWS" /D "_MBCS" /D "_USRDLL" /D "EXAMPLE1_EXPORTS" /YX /FD /GZ /c
|
||||
# ADD CPP /nologo /MDd /W3 /Gm- /GR /GX /Zi /Od /I "..\..\..\.." /I "c:\tools\python\include" /D "WIN32" /D "_DEBUG" /D "_WINDOWS" /D "_MBCS" /D "_USRDLL" /D "EXAMPLE1_EXPORTS" /D "BOOST_DEBUG_PYTHON" /YX /FD /GZ /EHs /c
|
||||
# ADD BASE MTL /nologo /D "_DEBUG" /mktyplib203 /win32
|
||||
# ADD MTL /nologo /D "_DEBUG" /mktyplib203 /win32
|
||||
# ADD BASE RSC /l 0x409 /d "_DEBUG"
|
||||
# ADD RSC /l 0x409 /d "_DEBUG"
|
||||
BSC32=bscmake.exe
|
||||
# ADD BASE BSC32 /nologo
|
||||
# ADD BSC32 /nologo
|
||||
LINK32=link.exe
|
||||
# ADD BASE LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /dll /incremental:no /debug /machine:I386 /out:"Debug/hello.dll" /pdbtype:sept /libpath:"c:\tools\python\libs"
|
||||
# ADD LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /dll /incremental:no /debug /machine:I386 /out:"DebugPython/hello_d.dll" /pdbtype:sept /libpath:"c:\tools\python\src\PCbuild"
|
||||
|
||||
!ENDIF
|
||||
|
||||
# Begin Target
|
||||
|
||||
# Name "example1 - Win32 Release"
|
||||
# Name "example1 - Win32 Debug"
|
||||
# Name "example1 - Win32 DebugPython"
|
||||
# Begin Group "Source Files"
|
||||
|
||||
# PROP Default_Filter "cpp;c;cxx;rc;def;r;odl;idl;hpj;bat"
|
||||
# Begin Source File
|
||||
|
||||
SOURCE=..\..\example\example1.cpp
|
||||
# End Source File
|
||||
# End Group
|
||||
# Begin Group "Header Files"
|
||||
|
||||
# PROP Default_Filter "h;hpp;hxx;hm;inl"
|
||||
# End Group
|
||||
# Begin Group "Resource Files"
|
||||
|
||||
# PROP Default_Filter "ico;cur;bmp;dlg;rc2;rct;bin;rgs;gif;jpg;jpeg;jpe"
|
||||
# End Group
|
||||
# End Target
|
||||
# End Project
|
||||
@@ -1,73 +0,0 @@
|
||||
# Revision History
|
||||
|
||||
# 04 Mar 01 Changed library name to libboost_python.a, various cleanups,
|
||||
# attempted Cygwin compatibility. Still needs testing on Linux
|
||||
# (David Abrahams)
|
||||
|
||||
|
||||
LIBSRC = \
|
||||
classes.cpp \
|
||||
conversions.cpp \
|
||||
extension_class.cpp \
|
||||
functions.cpp \
|
||||
init_function.cpp \
|
||||
module_builder.cpp \
|
||||
objects.cpp \
|
||||
types.cpp
|
||||
|
||||
LIBOBJ = $(LIBSRC:.cpp=.o)
|
||||
OBJ = $(LIBOBJ)
|
||||
|
||||
PYTHON_INC=$(ROOT)/usr/local/include/python2.0
|
||||
# libpython2.0.dll
|
||||
|
||||
ifeq "$(OS)" "Windows_NT"
|
||||
ROOT=c:/cygnus
|
||||
INC = -Ic:/cygnus/usr/include/g++-3 -Ic:/cygnus/usr/include -Ic:/boost -I$(PYTHON_INC)
|
||||
MODULE_EXTENSION=dll
|
||||
PYTHON_LIB=c:/cygnus/usr/local/lib/python2.0/config/libpython2.0.dll.a
|
||||
else
|
||||
INC = -I$(PYTHON_INC)
|
||||
MODULE_EXTENSION=so
|
||||
endif
|
||||
|
||||
%.o: ../src/%.cpp
|
||||
g++ -fPIC -Wall -W $(INC) -o $*.o -c $<
|
||||
|
||||
%.d: ../src/%.cpp
|
||||
@echo creating $@
|
||||
@set -e; g++ -M $(INC) -c $< \
|
||||
| sed 's/\($*\)\.o[ :]*/\1.o $@ : /g' > $@; \
|
||||
[ -s $@ ] || rm -f $@
|
||||
|
||||
|
||||
PYTHON = python
|
||||
|
||||
test: comprehensive.o libboost_python.a
|
||||
g++ $(CXXFLAGS) -shared -o ../test/boost_python_test.$(MODULE_EXTENSION) comprehensive.o -L. -lboost_python $(PYTHON_LIB)
|
||||
$(PYTHON) ../test/comprehensive.py
|
||||
|
||||
comprehensive.o: ../test/comprehensive.cpp
|
||||
g++ $(CXXFLAGS) --template-depth-32 -fPIC -Wall -W $(INC) -o $*.o -c $<
|
||||
|
||||
|
||||
example1: example1.o libboost_python.a
|
||||
g++ $(CXXFLAGS) -shared -o ../example/hellomodule.$(MODULE_EXTENSION) example1.o -L. -lboost_python $(PYTHON_LIB)
|
||||
$(PYTHON) ../example/test_example1.py
|
||||
|
||||
example1.o: ../example/example1.cpp
|
||||
g++ $(CXXFLAGS) --template-depth-32 -fPIC -Wall -W $(INC) -o $*.o -c $<
|
||||
|
||||
|
||||
clean:
|
||||
rm -rf *.o *.$(MODULE_EXTENSION) *.a *.d *.pyc *.bak a.out
|
||||
|
||||
libboost_python.a: $(LIBOBJ)
|
||||
rm -f libboost_python.a
|
||||
ar cq libboost_python.a $(LIBOBJ)
|
||||
|
||||
DEP = $(OBJ:.o=.d)
|
||||
|
||||
ifneq "$(MAKECMDGOALS)" "clean"
|
||||
include $(DEP)
|
||||
endif
|
||||
@@ -1,136 +0,0 @@
|
||||
# Microsoft Developer Studio Project File - Name="getting_started1" - Package Owner=<4>
|
||||
# Microsoft Developer Studio Generated Build File, Format Version 6.00
|
||||
# ** DO NOT EDIT **
|
||||
|
||||
# TARGTYPE "Win32 (x86) Dynamic-Link Library" 0x0102
|
||||
|
||||
CFG=getting_started1 - Win32 DebugPython
|
||||
!MESSAGE This is not a valid makefile. To build this project using NMAKE,
|
||||
!MESSAGE use the Export Makefile command and run
|
||||
!MESSAGE
|
||||
!MESSAGE NMAKE /f "getting_started1.mak".
|
||||
!MESSAGE
|
||||
!MESSAGE You can specify a configuration when running NMAKE
|
||||
!MESSAGE by defining the macro CFG on the command line. For example:
|
||||
!MESSAGE
|
||||
!MESSAGE NMAKE /f "getting_started1.mak" CFG="getting_started1 - Win32 DebugPython"
|
||||
!MESSAGE
|
||||
!MESSAGE Possible choices for configuration are:
|
||||
!MESSAGE
|
||||
!MESSAGE "getting_started1 - Win32 Release" (based on "Win32 (x86) Dynamic-Link Library")
|
||||
!MESSAGE "getting_started1 - Win32 Debug" (based on "Win32 (x86) Dynamic-Link Library")
|
||||
!MESSAGE "getting_started1 - Win32 DebugPython" (based on "Win32 (x86) Dynamic-Link Library")
|
||||
!MESSAGE
|
||||
|
||||
# Begin Project
|
||||
# PROP AllowPerConfigDependencies 0
|
||||
# PROP Scc_ProjName ""
|
||||
# PROP Scc_LocalPath ""
|
||||
CPP=xicl6.exe
|
||||
MTL=midl.exe
|
||||
RSC=rc.exe
|
||||
|
||||
!IF "$(CFG)" == "getting_started1 - Win32 Release"
|
||||
|
||||
# PROP BASE Use_MFC 0
|
||||
# PROP BASE Use_Debug_Libraries 0
|
||||
# PROP BASE Output_Dir "Release"
|
||||
# PROP BASE Intermediate_Dir "Release"
|
||||
# PROP BASE Target_Dir ""
|
||||
# PROP Use_MFC 0
|
||||
# PROP Use_Debug_Libraries 0
|
||||
# PROP Output_Dir "Release"
|
||||
# PROP Intermediate_Dir "Release"
|
||||
# PROP Ignore_Export_Lib 0
|
||||
# PROP Target_Dir ""
|
||||
# ADD BASE CPP /nologo /MT /W3 /GX /O2 /D "WIN32" /D "NDEBUG" /D "_WINDOWS" /YX /FD /c
|
||||
# ADD CPP /nologo /MD /W3 /GR /GX /O2 /I "..\..\..\.." /I "c:\tools\python\include" /D "WIN32" /D "NDEBUG" /D "_WINDOWS" /YX /FD /c
|
||||
# ADD BASE MTL /nologo /D "NDEBUG" /mktyplib203 /win32
|
||||
# ADD MTL /nologo /D "NDEBUG" /mktyplib203 /win32
|
||||
# ADD BASE RSC /l 0x409 /d "NDEBUG"
|
||||
# ADD RSC /l 0x409 /d "NDEBUG"
|
||||
BSC32=bscmake.exe
|
||||
# ADD BASE BSC32 /nologo
|
||||
# ADD BSC32 /nologo
|
||||
LINK32=xilink6.exe
|
||||
# ADD BASE LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /subsystem:windows /dll /machine:I386
|
||||
# ADD LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /subsystem:windows /dll /machine:I386 /libpath:"c:\tools\python\libs"
|
||||
|
||||
!ELSEIF "$(CFG)" == "getting_started1 - Win32 Debug"
|
||||
|
||||
# PROP BASE Use_MFC 0
|
||||
# PROP BASE Use_Debug_Libraries 1
|
||||
# PROP BASE Output_Dir "Debug"
|
||||
# PROP BASE Intermediate_Dir "Debug"
|
||||
# PROP BASE Target_Dir ""
|
||||
# PROP Use_MFC 0
|
||||
# PROP Use_Debug_Libraries 1
|
||||
# PROP Output_Dir "Debug"
|
||||
# PROP Intermediate_Dir "Debug"
|
||||
# PROP Ignore_Export_Lib 0
|
||||
# PROP Target_Dir ""
|
||||
# ADD BASE CPP /nologo /MTd /W3 /Gm /GX /ZI /Od /D "WIN32" /D "_DEBUG" /D "_WINDOWS" /YX /FD /GZ /c
|
||||
# ADD CPP /nologo /MDd /W3 /GR /GX /ZI /Od /I "..\..\..\.." /I "c:\tools\python\include" /D "WIN32" /D "_DEBUG" /D "_WINDOWS" /YX /FD /GZ /c
|
||||
# ADD BASE MTL /nologo /D "_DEBUG" /mktyplib203 /win32
|
||||
# ADD MTL /nologo /D "_DEBUG" /mktyplib203 /win32
|
||||
# ADD BASE RSC /l 0x409 /d "_DEBUG"
|
||||
# ADD RSC /l 0x409 /d "_DEBUG"
|
||||
BSC32=bscmake.exe
|
||||
# ADD BASE BSC32 /nologo
|
||||
# ADD BSC32 /nologo
|
||||
LINK32=xilink6.exe
|
||||
# ADD BASE LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /subsystem:windows /dll /debug /machine:I386 /pdbtype:sept
|
||||
# ADD LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /subsystem:windows /dll /debug /machine:I386 /pdbtype:sept /libpath:"c:\tools\python\libs"
|
||||
|
||||
!ELSEIF "$(CFG)" == "getting_started1 - Win32 DebugPython"
|
||||
|
||||
# PROP BASE Use_MFC 0
|
||||
# PROP BASE Use_Debug_Libraries 1
|
||||
# PROP BASE Output_Dir "DebugPython"
|
||||
# PROP BASE Intermediate_Dir "DebugPython"
|
||||
# PROP BASE Target_Dir ""
|
||||
# PROP Use_MFC 0
|
||||
# PROP Use_Debug_Libraries 1
|
||||
# PROP Output_Dir "DebugPython"
|
||||
# PROP Intermediate_Dir "DebugPython"
|
||||
# PROP Ignore_Export_Lib 1
|
||||
# PROP Target_Dir ""
|
||||
# ADD BASE CPP /nologo /MTd /W3 /Gm /GX /ZI /Od /D "WIN32" /D "_DEBUG" /D "_WINDOWS" /YX /FD /GZ /c
|
||||
# ADD CPP /nologo /MDd /W3 /GR /GX /Zi /Od /I "..\..\..\.." /I "c:\tools\python\include" /D "WIN32" /D "_DEBUG" /D "_WINDOWS" /D "_MBCS" /D "_USRDLL" /D "TEST_EXPORTS" /D "BOOST_DEBUG_PYTHON" /YX /FD /GZ /c
|
||||
# ADD BASE MTL /nologo /D "_DEBUG" /mktyplib203 /win32
|
||||
# ADD MTL /nologo /D "_DEBUG" /mktyplib203 /win32
|
||||
# ADD BASE RSC /l 0x409 /d "_DEBUG"
|
||||
# ADD RSC /l 0x409 /d "_DEBUG"
|
||||
BSC32=bscmake.exe
|
||||
# ADD BASE BSC32 /nologo
|
||||
# ADD BSC32 /nologo
|
||||
LINK32=xilink6.exe
|
||||
# ADD BASE LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /subsystem:windows /dll /debug /machine:I386 /pdbtype:sept
|
||||
# ADD LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /dll /incremental:no /pdb:"DebugPython/boost_python_test_d.pdb" /debug /machine:I386 /out:"DebugPython/getting_started1_d.dll" /pdbtype:sept /libpath:"c:\tools\python\src\PCbuild"
|
||||
# SUBTRACT LINK32 /pdb:none
|
||||
|
||||
!ENDIF
|
||||
|
||||
# Begin Target
|
||||
|
||||
# Name "getting_started1 - Win32 Release"
|
||||
# Name "getting_started1 - Win32 Debug"
|
||||
# Name "getting_started1 - Win32 DebugPython"
|
||||
# Begin Group "Source Files"
|
||||
|
||||
# PROP Default_Filter "cpp;c;cxx;rc;def;r;odl;idl;hpj;bat"
|
||||
# Begin Source File
|
||||
|
||||
SOURCE=..\..\example\getting_started1.cpp
|
||||
# End Source File
|
||||
# End Group
|
||||
# Begin Group "Header Files"
|
||||
|
||||
# PROP Default_Filter "h;hpp;hxx;hm;inl"
|
||||
# End Group
|
||||
# Begin Group "Resource Files"
|
||||
|
||||
# PROP Default_Filter "ico;cur;bmp;dlg;rc2;rct;bin;rgs;gif;jpg;jpeg;jpe"
|
||||
# End Group
|
||||
# End Target
|
||||
# End Project
|
||||
@@ -1,135 +0,0 @@
|
||||
# Microsoft Developer Studio Project File - Name="getting_started2" - Package Owner=<4>
|
||||
# Microsoft Developer Studio Generated Build File, Format Version 6.00
|
||||
# ** DO NOT EDIT **
|
||||
|
||||
# TARGTYPE "Win32 (x86) Dynamic-Link Library" 0x0102
|
||||
|
||||
CFG=getting_started2 - Win32 DebugPython
|
||||
!MESSAGE This is not a valid makefile. To build this project using NMAKE,
|
||||
!MESSAGE use the Export Makefile command and run
|
||||
!MESSAGE
|
||||
!MESSAGE NMAKE /f "getting_started2.mak".
|
||||
!MESSAGE
|
||||
!MESSAGE You can specify a configuration when running NMAKE
|
||||
!MESSAGE by defining the macro CFG on the command line. For example:
|
||||
!MESSAGE
|
||||
!MESSAGE NMAKE /f "getting_started2.mak" CFG="getting_started2 - Win32 DebugPython"
|
||||
!MESSAGE
|
||||
!MESSAGE Possible choices for configuration are:
|
||||
!MESSAGE
|
||||
!MESSAGE "getting_started2 - Win32 Release" (based on "Win32 (x86) Dynamic-Link Library")
|
||||
!MESSAGE "getting_started2 - Win32 Debug" (based on "Win32 (x86) Dynamic-Link Library")
|
||||
!MESSAGE "getting_started2 - Win32 DebugPython" (based on "Win32 (x86) Dynamic-Link Library")
|
||||
!MESSAGE
|
||||
|
||||
# Begin Project
|
||||
# PROP AllowPerConfigDependencies 0
|
||||
# PROP Scc_ProjName "getting_started2"
|
||||
# PROP Scc_LocalPath "."
|
||||
CPP=xicl6.exe
|
||||
MTL=midl.exe
|
||||
RSC=rc.exe
|
||||
|
||||
!IF "$(CFG)" == "getting_started2 - Win32 Release"
|
||||
|
||||
# PROP BASE Use_MFC 0
|
||||
# PROP BASE Use_Debug_Libraries 0
|
||||
# PROP BASE Output_Dir "Release"
|
||||
# PROP BASE Intermediate_Dir "Release"
|
||||
# PROP BASE Target_Dir ""
|
||||
# PROP Use_MFC 0
|
||||
# PROP Use_Debug_Libraries 0
|
||||
# PROP Output_Dir "Release"
|
||||
# PROP Intermediate_Dir "Release"
|
||||
# PROP Ignore_Export_Lib 0
|
||||
# PROP Target_Dir ""
|
||||
# ADD BASE CPP /nologo /MT /W3 /GX /O2 /D "WIN32" /D "NDEBUG" /D "_WINDOWS" /YX /FD /c
|
||||
# ADD CPP /nologo /MD /W3 /GR /GX /O2 /I "..\..\..\.." /I "c:\tools\python\include" /D "WIN32" /D "NDEBUG" /D "_WINDOWS" /YX /FD /c
|
||||
# ADD BASE MTL /nologo /D "NDEBUG" /mktyplib203 /win32
|
||||
# ADD MTL /nologo /D "NDEBUG" /mktyplib203 /win32
|
||||
# ADD BASE RSC /l 0x409 /d "NDEBUG"
|
||||
# ADD RSC /l 0x409 /d "NDEBUG"
|
||||
BSC32=bscmake.exe
|
||||
# ADD BASE BSC32 /nologo
|
||||
# ADD BSC32 /nologo
|
||||
LINK32=xilink6.exe
|
||||
# ADD BASE LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /subsystem:windows /dll /machine:I386
|
||||
# ADD LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /subsystem:windows /dll /machine:I386 /libpath:"c:\tools\python\libs"
|
||||
|
||||
!ELSEIF "$(CFG)" == "getting_started2 - Win32 Debug"
|
||||
|
||||
# PROP BASE Use_MFC 0
|
||||
# PROP BASE Use_Debug_Libraries 1
|
||||
# PROP BASE Output_Dir "Debug"
|
||||
# PROP BASE Intermediate_Dir "Debug"
|
||||
# PROP BASE Target_Dir ""
|
||||
# PROP Use_MFC 0
|
||||
# PROP Use_Debug_Libraries 1
|
||||
# PROP Output_Dir "Debug"
|
||||
# PROP Intermediate_Dir "Debug"
|
||||
# PROP Ignore_Export_Lib 0
|
||||
# PROP Target_Dir ""
|
||||
# ADD BASE CPP /nologo /MTd /W3 /Gm /GX /ZI /Od /D "WIN32" /D "_DEBUG" /D "_WINDOWS" /YX /FD /GZ /c
|
||||
# ADD CPP /nologo /MDd /W3 /Gm- /GR /GX /Zi /Od /I "..\..\..\.." /I "c:\tools\python\include" /D "WIN32" /D "_DEBUG" /D "_WINDOWS" /FR /YX /FD /GZ /c
|
||||
# ADD BASE MTL /nologo /D "_DEBUG" /mktyplib203 /win32
|
||||
# ADD MTL /nologo /D "_DEBUG" /mktyplib203 /win32
|
||||
# ADD BASE RSC /l 0x409 /d "_DEBUG"
|
||||
# ADD RSC /l 0x409 /d "_DEBUG"
|
||||
BSC32=bscmake.exe
|
||||
# ADD BASE BSC32 /nologo
|
||||
# ADD BSC32 /nologo
|
||||
LINK32=xilink6.exe
|
||||
# ADD BASE LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /subsystem:windows /dll /debug /machine:I386 /pdbtype:sept
|
||||
# ADD LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /subsystem:windows /dll /debug /machine:I386 /pdbtype:sept /libpath:"c:\tools\python\libs"
|
||||
|
||||
!ELSEIF "$(CFG)" == "getting_started2 - Win32 DebugPython"
|
||||
|
||||
# PROP BASE Use_MFC 0
|
||||
# PROP BASE Use_Debug_Libraries 1
|
||||
# PROP BASE Output_Dir "getting_started2___Win32_DebugPython"
|
||||
# PROP BASE Intermediate_Dir "getting_started2___Win32_DebugPython"
|
||||
# PROP BASE Target_Dir ""
|
||||
# PROP Use_MFC 0
|
||||
# PROP Use_Debug_Libraries 1
|
||||
# PROP Output_Dir "getting_started2___Win32_DebugPython"
|
||||
# PROP Intermediate_Dir "getting_started2___Win32_DebugPython"
|
||||
# PROP Ignore_Export_Lib 1
|
||||
# PROP Target_Dir ""
|
||||
# ADD BASE CPP /nologo /MTd /W3 /Gm /GX /ZI /Od /D "WIN32" /D "_DEBUG" /D "_WINDOWS" /YX /FD /GZ /c
|
||||
# ADD CPP /nologo /MDd /W3 /Gm- /GR /GX /Zi /Od /I "..\..\..\.." /I "c:\tools\python\include" /D "WIN32" /D "_DEBUG" /D "_WINDOWS" /D "_MBCS" /D "_USRDLL" /D "TEST_EXPORTS" /D "BOOST_DEBUG_PYTHON" /FR /YX /FD /GZ /c
|
||||
# ADD BASE MTL /nologo /D "_DEBUG" /mktyplib203 /win32
|
||||
# ADD MTL /nologo /D "_DEBUG" /mktyplib203 /win32
|
||||
# ADD BASE RSC /l 0x409 /d "_DEBUG"
|
||||
# ADD RSC /l 0x409 /d "_DEBUG"
|
||||
BSC32=bscmake.exe
|
||||
# ADD BASE BSC32 /nologo
|
||||
# ADD BSC32 /nologo
|
||||
LINK32=xilink6.exe
|
||||
# ADD BASE LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /subsystem:windows /dll /debug /machine:I386 /pdbtype:sept
|
||||
# ADD LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /subsystem:windows /dll /debug /machine:I386 /out:"DebugPython/getting_started2_d.dll" /pdbtype:sept /libpath:"c:\tools\python\src\pcbuild"
|
||||
|
||||
!ENDIF
|
||||
|
||||
# Begin Target
|
||||
|
||||
# Name "getting_started2 - Win32 Release"
|
||||
# Name "getting_started2 - Win32 Debug"
|
||||
# Name "getting_started2 - Win32 DebugPython"
|
||||
# Begin Group "Source Files"
|
||||
|
||||
# PROP Default_Filter "cpp;c;cxx;rc;def;r;odl;idl;hpj;bat"
|
||||
# Begin Source File
|
||||
|
||||
SOURCE=..\..\example\getting_started2.cpp
|
||||
# End Source File
|
||||
# End Group
|
||||
# Begin Group "Header Files"
|
||||
|
||||
# PROP Default_Filter "h;hpp;hxx;hm;inl"
|
||||
# End Group
|
||||
# Begin Group "Resource Files"
|
||||
|
||||
# PROP Default_Filter "ico;cur;bmp;dlg;rc2;rct;bin;rgs;gif;jpg;jpeg;jpe"
|
||||
# End Group
|
||||
# End Target
|
||||
# End Project
|
||||
@@ -1,166 +0,0 @@
|
||||
# Usage:
|
||||
#
|
||||
# Create a new empty directory anywhere (preferably not in the boost tree).
|
||||
# Copy this Makefile to that new directory and rename it to "Makefile"
|
||||
# Set the BOOST pathname below.
|
||||
#
|
||||
# make softlinks Create softlinks to source code and tests
|
||||
# make Compile all sources
|
||||
# make test Run doctest tests
|
||||
# make clean Remove all object files
|
||||
# make unlink Remove softlinks
|
||||
|
||||
BOOST= /net/cci/rwgk/boost
|
||||
|
||||
PYEXE= /usr/local/Python-1.5.2/bin/python
|
||||
PYINC= -I/usr/local/Python-1.5.2/include/python1.5
|
||||
#PYEXE= /usr/local/Python-2.0/bin/python
|
||||
#PYINC= -I/usr/local/Python-2.0/include/python2.0
|
||||
#STLPORTINC= -I/usr/local/STLport-4.1b3/stlport
|
||||
#STLPORTOPTS= \
|
||||
# -D__USE_STD_IOSTREAM \
|
||||
# -D__STL_NO_SGI_IOSTREAMS \
|
||||
# -D__STL_USE_NATIVE_STRING \
|
||||
# -D__STL_NO_NEW_C_HEADERS \
|
||||
# -D_RWSTD_COMPILE_INSTANTIATE=1
|
||||
#STLPORTINC= -I/usr/local/STLport-4.1b4/stlport
|
||||
#STLPORTOPTS= -D__NO_USE_STD_IOSTREAM -D__STL_NO_SGI_IOSTREAMS
|
||||
#STLPORTINC= -I/net/cci/xp/C++_C_headers
|
||||
|
||||
STDOPTS= -ftemplate-depth-21
|
||||
WARNOPTS=
|
||||
# use -msg_display_number to obtain integer tags for -msg_disable
|
||||
|
||||
CPP= g++
|
||||
CPPOPTS= $(STLPORTINC) $(STLPORTOPTS) -I$(BOOST) $(PYINC) \
|
||||
$(STDOPTS) $(WARNOPTS) -g
|
||||
MAKEDEP= -M
|
||||
|
||||
LD= g++
|
||||
LDOPTS= -shared
|
||||
|
||||
#HIDDEN= -hidden
|
||||
|
||||
BPL_SRC = $(BOOST)/libs/python/src
|
||||
BPL_TST = $(BOOST)/libs/python/test
|
||||
BPL_EXA = $(BOOST)/libs/python/example
|
||||
SOFTLINKS = \
|
||||
$(BPL_SRC)/classes.cpp \
|
||||
$(BPL_SRC)/conversions.cpp \
|
||||
$(BPL_SRC)/extension_class.cpp \
|
||||
$(BPL_SRC)/functions.cpp \
|
||||
$(BPL_SRC)/init_function.cpp \
|
||||
$(BPL_SRC)/module_builder.cpp \
|
||||
$(BPL_SRC)/objects.cpp \
|
||||
$(BPL_SRC)/types.cpp \
|
||||
$(BPL_TST)/comprehensive.cpp \
|
||||
$(BPL_TST)/comprehensive.hpp \
|
||||
$(BPL_TST)/comprehensive.py \
|
||||
$(BPL_TST)/doctest.py \
|
||||
$(BPL_EXA)/abstract.cpp \
|
||||
$(BPL_EXA)/getting_started1.cpp \
|
||||
$(BPL_EXA)/getting_started2.cpp \
|
||||
$(BPL_EXA)/getting_started3.cpp \
|
||||
$(BPL_EXA)/getting_started4.cpp \
|
||||
$(BPL_EXA)/getting_started5.cpp \
|
||||
$(BPL_EXA)/test_abstract.py \
|
||||
$(BPL_EXA)/test_getting_started1.py \
|
||||
$(BPL_EXA)/test_getting_started2.py \
|
||||
$(BPL_EXA)/test_getting_started3.py \
|
||||
$(BPL_EXA)/test_getting_started4.py \
|
||||
$(BPL_EXA)/test_getting_started5.py
|
||||
|
||||
OBJ = classes.o conversions.o extension_class.o functions.o \
|
||||
init_function.o module_builder.o \
|
||||
objects.o types.o
|
||||
DEPOBJ= $(OBJ) comprehensive.o abstract.o \
|
||||
getting_started1.o getting_started2.o getting_started3.o \
|
||||
getting_started4.o getting_started5.o
|
||||
|
||||
.SUFFIXES: .o .cpp
|
||||
|
||||
all: libboost_python.a boost_python_test.so abstract.so \
|
||||
getting_started1.so getting_started2.so getting_started3.so \
|
||||
getting_started4.so getting_started5.so
|
||||
|
||||
softlinks:
|
||||
@ for pn in $(SOFTLINKS); \
|
||||
do \
|
||||
bn=`basename "$$pn"`; \
|
||||
if [ ! -e "$$bn" ]; then \
|
||||
echo "ln -s $$pn ."; \
|
||||
ln -s "$$pn" .; \
|
||||
else \
|
||||
echo "info: no softlink created (file exists): $$bn"; \
|
||||
fi; \
|
||||
done
|
||||
|
||||
unlink:
|
||||
@ for pn in $(SOFTLINKS); \
|
||||
do \
|
||||
bn=`basename "$$pn"`; \
|
||||
if [ -L "$$bn" ]; then \
|
||||
echo "rm $$bn"; \
|
||||
rm "$$bn"; \
|
||||
elif [ -e "$$bn" ]; then \
|
||||
echo "info: not a softlink: $$bn"; \
|
||||
fi; \
|
||||
done
|
||||
|
||||
libboost_python.a: $(OBJ)
|
||||
rm -f libboost_python.a
|
||||
ar r libboost_python.a $(OBJ)
|
||||
|
||||
boost_python_test.so: $(OBJ) comprehensive.o
|
||||
$(LD) $(LDOPTS) $(OBJ) comprehensive.o -o boost_python_test.so -lm
|
||||
|
||||
abstract.so: $(OBJ) abstract.o
|
||||
$(LD) $(LDOPTS) $(OBJ) abstract.o -o abstract.so
|
||||
|
||||
getting_started1.so: $(OBJ) getting_started1.o
|
||||
$(LD) $(LDOPTS) $(OBJ) getting_started1.o -o getting_started1.so
|
||||
|
||||
getting_started2.so: $(OBJ) getting_started2.o
|
||||
$(LD) $(LDOPTS) $(OBJ) getting_started2.o -o getting_started2.so
|
||||
|
||||
getting_started3.so: $(OBJ) getting_started3.o
|
||||
$(LD) $(LDOPTS) $(OBJ) getting_started3.o -o getting_started3.so
|
||||
|
||||
getting_started4.so: $(OBJ) getting_started4.o
|
||||
$(LD) $(LDOPTS) $(OBJ) getting_started4.o -o getting_started4.so
|
||||
|
||||
getting_started5.so: $(OBJ) getting_started5.o
|
||||
$(LD) $(LDOPTS) $(OBJ) getting_started5.o -o getting_started5.so
|
||||
|
||||
.cpp.o:
|
||||
$(CPP) $(CPPOPTS) -c $*.cpp
|
||||
|
||||
test:
|
||||
$(PYEXE) comprehensive.py
|
||||
$(PYEXE) test_abstract.py
|
||||
$(PYEXE) test_getting_started1.py
|
||||
$(PYEXE) test_getting_started2.py
|
||||
$(PYEXE) test_getting_started3.py
|
||||
$(PYEXE) test_getting_started4.py
|
||||
$(PYEXE) test_getting_started5.py
|
||||
|
||||
clean:
|
||||
rm -f $(OBJ) libboost_python.a libboost_python.a.input
|
||||
rm -f comprehensive.o boost_python_test.so
|
||||
rm -f abstract.o abstract.so
|
||||
rm -f getting_started1.o getting_started1.so
|
||||
rm -f getting_started2.o getting_started2.so
|
||||
rm -f getting_started3.o getting_started3.so
|
||||
rm -f getting_started4.o getting_started4.so
|
||||
rm -f getting_started5.o getting_started5.so
|
||||
rm -f so_locations *.pyc
|
||||
rm -rf cxx_repository
|
||||
|
||||
depend:
|
||||
@ cat Makefile.nodepend; \
|
||||
for obj in $(DEPOBJ); \
|
||||
do \
|
||||
bn=`echo "$$obj" | cut -d. -f1`; \
|
||||
$(CPP) $(CPPOPTS) $(MAKEDEP) "$$bn".cpp; \
|
||||
done
|
||||
|
||||
@@ -1,210 +0,0 @@
|
||||
# Usage:
|
||||
#
|
||||
# Create a new empty directory anywhere (preferably not in the boost tree).
|
||||
# Copy this Makefile to that new directory and rename it to "Makefile"
|
||||
# Set the BOOST_* pathnames below.
|
||||
#
|
||||
# The idea is that the build directory is on a Unix filesystem that
|
||||
# is mounted on a PC using SAMBA. Use this makefile under both Unix
|
||||
# and Windows:
|
||||
#
|
||||
# Unix: make softlinks Create softlinks to source code and tests
|
||||
# Win: make Compile all sources
|
||||
# Win: make test Run doctest tests
|
||||
# Unix: make clean Remove all object files
|
||||
# Unix: make unlink Remove softlinks
|
||||
|
||||
# To install mingw32, follow instructions at:
|
||||
# http://starship.python.net/crew/kernr/mingw32/Notes.html
|
||||
# In particular, install:
|
||||
# ftp://ftp.xraylith.wisc.edu/pub/khan/gnu-win32/mingw32/gcc-2.95.2/gcc-2.95.2-msvcrt.exe
|
||||
# ftp://ftp.xraylith.wisc.edu/pub/khan/gnu-win32/mingw32/gcc-2.95.2/fixes/quote-fix-msvcrt.exe
|
||||
# http://starship.python.net/crew/kernr/mingw32/Python-1.5.2-mingw32.zip
|
||||
# Unpack the first two archives in the default locations and update your PATH.
|
||||
# Unpack the third archive in \usr.
|
||||
|
||||
# Note: comprehensive.cpp generates compiler errors and later crashes.
|
||||
# L:\boost\boost\python\detail\extension_class.hpp:643: warning:
|
||||
# alignment of `vtable for class
|
||||
# boost::python::detail::held_instance<bpl_test::Derived1>'
|
||||
# is greater than maximum object file alignment. Using 16.
|
||||
# Could this be fixed with compiler options?
|
||||
# -fhuge-objects looks interesting, but requires recompiling the C++ library.
|
||||
# (what exactly does that mean?)
|
||||
# -fvtable-thunks eliminates the compiler warning,
|
||||
# but "import boost_python_test" still causes a crash.
|
||||
|
||||
BOOST_UNIX= /net/cci/rwgk/boost
|
||||
BOOST_WIN= "L:\boost"
|
||||
|
||||
PYEXE= "C:\Program files\Python\python.exe"
|
||||
PYINC= -I"C:\usr\include\python1.5"
|
||||
PYLIB= "C:\usr\lib\libpython15.a"
|
||||
|
||||
STDOPTS= -ftemplate-depth-21
|
||||
WARNOPTS=
|
||||
|
||||
CPP= g++
|
||||
CPPOPTS= $(STLPORTINC) $(STLPORTOPTS) -I$(BOOST_WIN) $(PYINC) \
|
||||
$(STDOPTS) $(WARNOPTS) -g
|
||||
|
||||
LD= g++
|
||||
LDOPTS= -shared
|
||||
|
||||
BPL_SRC = $(BOOST_UNIX)/libs/python/src
|
||||
BPL_TST = $(BOOST_UNIX)/libs/python/test
|
||||
BPL_EXA = $(BOOST_UNIX)/libs/python/example
|
||||
SOFTLINKS = \
|
||||
$(BPL_SRC)/classes.cpp \
|
||||
$(BPL_SRC)/conversions.cpp \
|
||||
$(BPL_SRC)/extension_class.cpp \
|
||||
$(BPL_SRC)/functions.cpp \
|
||||
$(BPL_SRC)/init_function.cpp \
|
||||
$(BPL_SRC)/module_builder.cpp \
|
||||
$(BPL_SRC)/objects.cpp \
|
||||
$(BPL_SRC)/types.cpp \
|
||||
$(BPL_TST)/comprehensive.cpp \
|
||||
$(BPL_TST)/comprehensive.hpp \
|
||||
$(BPL_TST)/comprehensive.py \
|
||||
$(BPL_TST)/doctest.py \
|
||||
$(BPL_EXA)/abstract.cpp \
|
||||
$(BPL_EXA)/getting_started1.cpp \
|
||||
$(BPL_EXA)/getting_started2.cpp \
|
||||
$(BPL_EXA)/getting_started3.cpp \
|
||||
$(BPL_EXA)/getting_started4.cpp \
|
||||
$(BPL_EXA)/getting_started5.cpp \
|
||||
$(BPL_EXA)/passing_char.cpp \
|
||||
$(BPL_EXA)/test_abstract.py \
|
||||
$(BPL_EXA)/test_getting_started1.py \
|
||||
$(BPL_EXA)/test_getting_started2.py \
|
||||
$(BPL_EXA)/test_getting_started3.py \
|
||||
$(BPL_EXA)/test_getting_started4.py \
|
||||
$(BPL_EXA)/test_getting_started5.py
|
||||
|
||||
DEFS= \
|
||||
boost_python_test \
|
||||
abstract \
|
||||
getting_started1 \
|
||||
getting_started2 \
|
||||
getting_started3 \
|
||||
getting_started4 \
|
||||
getting_started5
|
||||
|
||||
OBJ = classes.o conversions.o extension_class.o functions.o \
|
||||
init_function.o module_builder.o \
|
||||
objects.o types.o
|
||||
|
||||
.SUFFIXES: .o .cpp
|
||||
|
||||
all: libboost_python.a boost_python_test.pyd abstract.pyd \
|
||||
getting_started1.pyd getting_started2.pyd getting_started3.pyd \
|
||||
getting_started4.pyd getting_started5.pyd
|
||||
|
||||
softlinks: defs
|
||||
@ for pn in $(SOFTLINKS); \
|
||||
do \
|
||||
bn=`basename "$$pn"`; \
|
||||
if [ ! -e "$$bn" ]; then \
|
||||
echo "ln -s $$pn ."; \
|
||||
ln -s "$$pn" .; \
|
||||
else \
|
||||
echo "info: no softlink created (file exists): $$bn"; \
|
||||
fi; \
|
||||
done
|
||||
|
||||
unlink: rmdefs
|
||||
@ for pn in $(SOFTLINKS); \
|
||||
do \
|
||||
bn=`basename "$$pn"`; \
|
||||
if [ -L "$$bn" ]; then \
|
||||
echo "rm $$bn"; \
|
||||
rm "$$bn"; \
|
||||
elif [ -e "$$bn" ]; then \
|
||||
echo "info: not a softlink: $$bn"; \
|
||||
fi; \
|
||||
done
|
||||
|
||||
defs:
|
||||
@ for def in $(DEFS); \
|
||||
do \
|
||||
echo "EXPORTS\n\tinit$$def" > $$def.def; \
|
||||
done
|
||||
|
||||
rmdefs:
|
||||
@ for def in $(DEFS); \
|
||||
do \
|
||||
rm $$def.def; \
|
||||
done
|
||||
|
||||
libboost_python.a: $(OBJ)
|
||||
del libboost_python.a
|
||||
ar r libboost_python.a $(OBJ)
|
||||
|
||||
DLLWRAPOPTS= -s --driver-name g++ -s
|
||||
--entry _DllMainCRTStartup@12 --target=i386-mingw32
|
||||
|
||||
boost_python_test.pyd: $(OBJ) comprehensive.o
|
||||
dllwrap $(DLLWRAPOPTS) \
|
||||
--dllname boost_python_test.pyd \
|
||||
--def boost_python_test.def \
|
||||
$(OBJ) comprehensive.o $(PYLIB)
|
||||
|
||||
abstract.pyd: $(OBJ) abstract.o
|
||||
dllwrap $(DLLWRAPOPTS) \
|
||||
--dllname abstract.pyd \
|
||||
--def abstract.def \
|
||||
$(OBJ) abstract.o $(PYLIB)
|
||||
|
||||
getting_started1.pyd: $(OBJ) getting_started1.o
|
||||
dllwrap $(DLLWRAPOPTS) \
|
||||
--dllname getting_started1.pyd \
|
||||
--def getting_started1.def \
|
||||
$(OBJ) getting_started1.o $(PYLIB)
|
||||
|
||||
getting_started2.pyd: $(OBJ) getting_started2.o
|
||||
dllwrap $(DLLWRAPOPTS) \
|
||||
--dllname getting_started2.pyd \
|
||||
--def getting_started2.def \
|
||||
$(OBJ) getting_started2.o $(PYLIB)
|
||||
|
||||
getting_started3.pyd: $(OBJ) getting_started3.o
|
||||
dllwrap $(DLLWRAPOPTS) \
|
||||
--dllname getting_started3.pyd \
|
||||
--def getting_started3.def \
|
||||
$(OBJ) getting_started3.o $(PYLIB)
|
||||
|
||||
getting_started4.pyd: $(OBJ) getting_started4.o
|
||||
dllwrap $(DLLWRAPOPTS) \
|
||||
--dllname getting_started4.pyd \
|
||||
--def getting_started4.def \
|
||||
$(OBJ) getting_started4.o $(PYLIB)
|
||||
|
||||
getting_started5.pyd: $(OBJ) getting_started5.o
|
||||
dllwrap $(DLLWRAPOPTS) \
|
||||
--dllname getting_started5.pyd \
|
||||
--def getting_started5.def \
|
||||
$(OBJ) getting_started5.o $(PYLIB)
|
||||
|
||||
.cpp.o:
|
||||
$(CPP) $(CPPOPTS) -c $*.cpp
|
||||
|
||||
test:
|
||||
$(PYEXE) comprehensive.py
|
||||
$(PYEXE) test_abstract.py
|
||||
$(PYEXE) test_getting_started1.py
|
||||
$(PYEXE) test_getting_started2.py
|
||||
$(PYEXE) test_getting_started3.py
|
||||
$(PYEXE) test_getting_started4.py
|
||||
$(PYEXE) test_getting_started5.py
|
||||
|
||||
clean:
|
||||
rm -f $(OBJ) libboost_python.a libboost_python.a.input
|
||||
rm -f comprehensive.o boost_python_test.pyd
|
||||
rm -f abstract.o abstract.pyd
|
||||
rm -f getting_started1.o getting_started1.pyd
|
||||
rm -f getting_started2.o getting_started2.pyd
|
||||
rm -f getting_started3.o getting_started3.pyd
|
||||
rm -f getting_started4.o getting_started4.pyd
|
||||
rm -f getting_started5.o getting_started5.pyd
|
||||
rm -f so_locations *.pyc
|
||||
rm -rf cxx_repository
|
||||
@@ -1,135 +0,0 @@
|
||||
# Microsoft Developer Studio Project File - Name="rwgk1" - Package Owner=<4>
|
||||
# Microsoft Developer Studio Generated Build File, Format Version 6.00
|
||||
# ** DO NOT EDIT **
|
||||
|
||||
# TARGTYPE "Win32 (x86) Dynamic-Link Library" 0x0102
|
||||
|
||||
CFG=rwgk1 - Win32 DebugPython
|
||||
!MESSAGE This is not a valid makefile. To build this project using NMAKE,
|
||||
!MESSAGE use the Export Makefile command and run
|
||||
!MESSAGE
|
||||
!MESSAGE NMAKE /f "rwgk1.mak".
|
||||
!MESSAGE
|
||||
!MESSAGE You can specify a configuration when running NMAKE
|
||||
!MESSAGE by defining the macro CFG on the command line. For example:
|
||||
!MESSAGE
|
||||
!MESSAGE NMAKE /f "rwgk1.mak" CFG="rwgk1 - Win32 DebugPython"
|
||||
!MESSAGE
|
||||
!MESSAGE Possible choices for configuration are:
|
||||
!MESSAGE
|
||||
!MESSAGE "rwgk1 - Win32 Release" (based on "Win32 (x86) Dynamic-Link Library")
|
||||
!MESSAGE "rwgk1 - Win32 Debug" (based on "Win32 (x86) Dynamic-Link Library")
|
||||
!MESSAGE "rwgk1 - Win32 DebugPython" (based on "Win32 (x86) Dynamic-Link Library")
|
||||
!MESSAGE
|
||||
|
||||
# Begin Project
|
||||
# PROP AllowPerConfigDependencies 0
|
||||
# PROP Scc_ProjName ""
|
||||
# PROP Scc_LocalPath ""
|
||||
CPP=cl.exe
|
||||
MTL=midl.exe
|
||||
RSC=rc.exe
|
||||
|
||||
!IF "$(CFG)" == "rwgk1 - Win32 Release"
|
||||
|
||||
# PROP BASE Use_MFC 0
|
||||
# PROP BASE Use_Debug_Libraries 0
|
||||
# PROP BASE Output_Dir "Release"
|
||||
# PROP BASE Intermediate_Dir "Release"
|
||||
# PROP BASE Target_Dir ""
|
||||
# PROP Use_MFC 0
|
||||
# PROP Use_Debug_Libraries 0
|
||||
# PROP Output_Dir "Release"
|
||||
# PROP Intermediate_Dir "Release"
|
||||
# PROP Target_Dir ""
|
||||
# ADD BASE CPP /nologo /MT /W3 /GX /O2 /D "WIN32" /D "NDEBUG" /D "_WINDOWS" /D "_MBCS" /D "_USRDLL" /D "RWGK1_EXPORTS" /YX /FD /c
|
||||
# ADD CPP /nologo /MD /W3 /GX /O2 /I "..\..\..\.." /I "c:\tools\python\include" /D "WIN32" /D "NDEBUG" /D "_WINDOWS" /D "_MBCS" /D "_USRDLL" /D "RWGK1_EXPORTS" /YX /FD /c
|
||||
# ADD BASE MTL /nologo /D "NDEBUG" /mktyplib203 /win32
|
||||
# ADD MTL /nologo /D "NDEBUG" /mktyplib203 /win32
|
||||
# ADD BASE RSC /l 0x409 /d "NDEBUG"
|
||||
# ADD RSC /l 0x409 /d "NDEBUG"
|
||||
BSC32=bscmake.exe
|
||||
# ADD BASE BSC32 /nologo
|
||||
# ADD BSC32 /nologo
|
||||
LINK32=link.exe
|
||||
# ADD BASE LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /dll /machine:I386
|
||||
# ADD LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /dll /machine:I386 /libpath:"c:\tools\python\libs"
|
||||
|
||||
!ELSEIF "$(CFG)" == "rwgk1 - Win32 Debug"
|
||||
|
||||
# PROP BASE Use_MFC 0
|
||||
# PROP BASE Use_Debug_Libraries 1
|
||||
# PROP BASE Output_Dir "Debug"
|
||||
# PROP BASE Intermediate_Dir "Debug"
|
||||
# PROP BASE Target_Dir ""
|
||||
# PROP Use_MFC 0
|
||||
# PROP Use_Debug_Libraries 1
|
||||
# PROP Output_Dir "Debug"
|
||||
# PROP Intermediate_Dir "Debug"
|
||||
# PROP Ignore_Export_Lib 0
|
||||
# PROP Target_Dir ""
|
||||
# ADD BASE CPP /nologo /MTd /W3 /Gm /GX /ZI /Od /D "WIN32" /D "_DEBUG" /D "_WINDOWS" /D "_MBCS" /D "_USRDLL" /D "RWGK1_EXPORTS" /YX /FD /GZ /c
|
||||
# ADD CPP /nologo /MDd /W3 /Gm- /GX /Zi /Od /I "..\..\..\.." /I "c:\tools\python\include" /D "WIN32" /D "_DEBUG" /D "_WINDOWS" /D "_MBCS" /D "_USRDLL" /D "RWGK1_EXPORTS" /YX /FD /GZ /c
|
||||
# ADD BASE MTL /nologo /D "_DEBUG" /mktyplib203 /win32
|
||||
# ADD MTL /nologo /D "_DEBUG" /mktyplib203 /win32
|
||||
# ADD BASE RSC /l 0x409 /d "_DEBUG"
|
||||
# ADD RSC /l 0x409 /d "_DEBUG"
|
||||
BSC32=bscmake.exe
|
||||
# ADD BASE BSC32 /nologo
|
||||
# ADD BSC32 /nologo
|
||||
LINK32=link.exe
|
||||
# ADD BASE LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /dll /debug /machine:I386 /pdbtype:sept
|
||||
# ADD LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /dll /incremental:no /debug /machine:I386 /pdbtype:sept /libpath:"c:\tools\python\libs"
|
||||
|
||||
!ELSEIF "$(CFG)" == "rwgk1 - Win32 DebugPython"
|
||||
|
||||
# PROP BASE Use_MFC 0
|
||||
# PROP BASE Use_Debug_Libraries 1
|
||||
# PROP BASE Output_Dir "rwgk1___Win32_DebugPython"
|
||||
# PROP BASE Intermediate_Dir "rwgk1___Win32_DebugPython"
|
||||
# PROP BASE Ignore_Export_Lib 0
|
||||
# PROP BASE Target_Dir ""
|
||||
# PROP Use_MFC 0
|
||||
# PROP Use_Debug_Libraries 1
|
||||
# PROP Output_Dir "DebugPython"
|
||||
# PROP Intermediate_Dir "DebugPython"
|
||||
# PROP Ignore_Export_Lib 1
|
||||
# PROP Target_Dir ""
|
||||
# ADD BASE CPP /nologo /MDd /W3 /Gm /GX /Zi /Od /I "..\..\..\.." /I "c:\tools\python\include" /D "WIN32" /D "_DEBUG" /D "_WINDOWS" /D "_MBCS" /D "_USRDLL" /D "RWGK1_EXPORTS" /YX /FD /GZ /c
|
||||
# ADD CPP /nologo /MDd /W3 /Gm- /GX /Zi /Od /I "..\..\..\.." /I "c:\tools\python\include" /D "WIN32" /D "_DEBUG" /D "_WINDOWS" /D "_MBCS" /D "_USRDLL" /D "RWGK1_EXPORTS" /D "BOOST_DEBUG_PYTHON" /YX /FD /GZ /c
|
||||
# ADD BASE MTL /nologo /D "_DEBUG" /mktyplib203 /win32
|
||||
# ADD MTL /nologo /D "_DEBUG" /mktyplib203 /win32
|
||||
# ADD BASE RSC /l 0x409 /d "_DEBUG"
|
||||
# ADD RSC /l 0x409 /d "_DEBUG"
|
||||
BSC32=bscmake.exe
|
||||
# ADD BASE BSC32 /nologo
|
||||
# ADD BSC32 /nologo
|
||||
LINK32=link.exe
|
||||
# ADD BASE LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /dll /incremental:no /debug /machine:I386 /pdbtype:sept /libpath:"c:\tools\python\libs"
|
||||
# ADD LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /dll /incremental:no /debug /machine:I386 /out:"DebugPython/rwgk1_d.dll" /pdbtype:sept /libpath:"C:\tools\python\src\PCbuild"
|
||||
|
||||
!ENDIF
|
||||
|
||||
# Begin Target
|
||||
|
||||
# Name "rwgk1 - Win32 Release"
|
||||
# Name "rwgk1 - Win32 Debug"
|
||||
# Name "rwgk1 - Win32 DebugPython"
|
||||
# Begin Group "Source Files"
|
||||
|
||||
# PROP Default_Filter "cpp;c;cxx;rc;def;r;odl;idl;hpj;bat"
|
||||
# Begin Source File
|
||||
|
||||
SOURCE=..\..\example\rwgk1.cpp
|
||||
# End Source File
|
||||
# End Group
|
||||
# Begin Group "Header Files"
|
||||
|
||||
# PROP Default_Filter "h;hpp;hxx;hm;inl"
|
||||
# End Group
|
||||
# Begin Group "Resource Files"
|
||||
|
||||
# PROP Default_Filter "ico;cur;bmp;dlg;rc2;rct;bin;rgs;gif;jpg;jpeg;jpe"
|
||||
# End Group
|
||||
# End Target
|
||||
# End Project
|
||||
@@ -1,145 +0,0 @@
|
||||
# Microsoft Developer Studio Project File - Name="test" - Package Owner=<4>
|
||||
# Microsoft Developer Studio Generated Build File, Format Version 6.00
|
||||
# ** DO NOT EDIT **
|
||||
|
||||
# TARGTYPE "Win32 (x86) Dynamic-Link Library" 0x0102
|
||||
|
||||
CFG=test - Win32 DebugPython
|
||||
!MESSAGE This is not a valid makefile. To build this project using NMAKE,
|
||||
!MESSAGE use the Export Makefile command and run
|
||||
!MESSAGE
|
||||
!MESSAGE NMAKE /f "test.mak".
|
||||
!MESSAGE
|
||||
!MESSAGE You can specify a configuration when running NMAKE
|
||||
!MESSAGE by defining the macro CFG on the command line. For example:
|
||||
!MESSAGE
|
||||
!MESSAGE NMAKE /f "test.mak" CFG="test - Win32 DebugPython"
|
||||
!MESSAGE
|
||||
!MESSAGE Possible choices for configuration are:
|
||||
!MESSAGE
|
||||
!MESSAGE "test - Win32 Release" (based on "Win32 (x86) Dynamic-Link Library")
|
||||
!MESSAGE "test - Win32 Debug" (based on "Win32 (x86) Dynamic-Link Library")
|
||||
!MESSAGE "test - Win32 DebugPython" (based on "Win32 (x86) Dynamic-Link Library")
|
||||
!MESSAGE
|
||||
|
||||
# Begin Project
|
||||
# PROP AllowPerConfigDependencies 0
|
||||
# PROP Scc_ProjName ""
|
||||
# PROP Scc_LocalPath ""
|
||||
CPP=cl.exe
|
||||
MTL=midl.exe
|
||||
RSC=rc.exe
|
||||
|
||||
!IF "$(CFG)" == "test - Win32 Release"
|
||||
|
||||
# PROP BASE Use_MFC 0
|
||||
# PROP BASE Use_Debug_Libraries 0
|
||||
# PROP BASE Output_Dir "Release"
|
||||
# PROP BASE Intermediate_Dir "Release"
|
||||
# PROP BASE Target_Dir ""
|
||||
# PROP Use_MFC 0
|
||||
# PROP Use_Debug_Libraries 0
|
||||
# PROP Output_Dir "Release"
|
||||
# PROP Intermediate_Dir "Release"
|
||||
# PROP Ignore_Export_Lib 0
|
||||
# PROP Target_Dir ""
|
||||
# ADD BASE CPP /nologo /MT /W3 /GX /O2 /D "WIN32" /D "NDEBUG" /D "_WINDOWS" /D "_MBCS" /D "_USRDLL" /D "TEST_EXPORTS" /YX /FD /c
|
||||
# ADD CPP /nologo /MD /W3 /GR /GX /O2 /I "..\..\..\.." /I "c:\tools\python\include" /D "WIN32" /D "NDEBUG" /D "_WINDOWS" /D "_MBCS" /D "_USRDLL" /D "TEST_EXPORTS" /YX /FD /Zm200 /c
|
||||
# SUBTRACT CPP /Fr
|
||||
# ADD BASE MTL /nologo /D "NDEBUG" /mktyplib203 /win32
|
||||
# ADD MTL /nologo /D "NDEBUG" /mktyplib203 /win32
|
||||
# ADD BASE RSC /l 0x409 /d "NDEBUG"
|
||||
# ADD RSC /l 0x409 /d "NDEBUG"
|
||||
BSC32=bscmake.exe
|
||||
# ADD BASE BSC32 /nologo
|
||||
# ADD BSC32 /nologo
|
||||
LINK32=link.exe
|
||||
# ADD BASE LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /dll /machine:I386
|
||||
# ADD LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /dll /machine:I386 /out:"Release/boost_python_test.dll" /libpath:"c:\tools\python\libs"
|
||||
|
||||
!ELSEIF "$(CFG)" == "test - Win32 Debug"
|
||||
|
||||
# PROP BASE Use_MFC 0
|
||||
# PROP BASE Use_Debug_Libraries 1
|
||||
# PROP BASE Output_Dir "Debug"
|
||||
# PROP BASE Intermediate_Dir "Debug"
|
||||
# PROP BASE Target_Dir ""
|
||||
# PROP Use_MFC 0
|
||||
# PROP Use_Debug_Libraries 1
|
||||
# PROP Output_Dir "Debug"
|
||||
# PROP Intermediate_Dir "Debug"
|
||||
# PROP Ignore_Export_Lib 0
|
||||
# PROP Target_Dir ""
|
||||
# ADD BASE CPP /nologo /MTd /W3 /Gm /GX /ZI /Od /D "WIN32" /D "_DEBUG" /D "_WINDOWS" /D "_MBCS" /D "_USRDLL" /D "TEST_EXPORTS" /YX /FD /GZ /c
|
||||
# ADD CPP /nologo /MDd /W3 /Gm- /GR /GX /Zi /Od /I "..\..\..\.." /I "c:\tools\python\include" /D "WIN32" /D "_DEBUG" /D "_WINDOWS" /D "_MBCS" /D "_USRDLL" /D "TEST_EXPORTS" /YX /FD /GZ /Zm200 /c
|
||||
# SUBTRACT CPP /Fr
|
||||
# ADD BASE MTL /nologo /D "_DEBUG" /mktyplib203 /win32
|
||||
# ADD MTL /nologo /D "_DEBUG" /mktyplib203 /win32
|
||||
# ADD BASE RSC /l 0x409 /d "_DEBUG"
|
||||
# ADD RSC /l 0x409 /d "_DEBUG"
|
||||
BSC32=bscmake.exe
|
||||
# ADD BASE BSC32 /nologo
|
||||
# ADD BSC32 /nologo
|
||||
LINK32=link.exe
|
||||
# ADD BASE LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /dll /debug /machine:I386 /pdbtype:sept
|
||||
# ADD LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /dll /incremental:no /debug /machine:I386 /out:"Debug/boost_python_test.dll" /pdbtype:sept /libpath:"c:\tools\python\libs"
|
||||
# SUBTRACT LINK32 /pdb:none
|
||||
|
||||
!ELSEIF "$(CFG)" == "test - Win32 DebugPython"
|
||||
|
||||
# PROP BASE Use_MFC 0
|
||||
# PROP BASE Use_Debug_Libraries 1
|
||||
# PROP BASE Output_Dir "test___Win32_DebugPython"
|
||||
# PROP BASE Intermediate_Dir "test___Win32_DebugPython"
|
||||
# PROP BASE Ignore_Export_Lib 0
|
||||
# PROP BASE Target_Dir ""
|
||||
# PROP Use_MFC 0
|
||||
# PROP Use_Debug_Libraries 1
|
||||
# PROP Output_Dir "DebugPython"
|
||||
# PROP Intermediate_Dir "DebugPython"
|
||||
# PROP Ignore_Export_Lib 1
|
||||
# PROP Target_Dir ""
|
||||
# ADD BASE CPP /nologo /MDd /W3 /Gm /GR /GX /Zi /Od /I "..\..\..\.." /I "c:\tools\python\include" /D "WIN32" /D "_DEBUG" /D "_WINDOWS" /D "_MBCS" /D "_USRDLL" /D "TEST_EXPORTS" /YX /FD /GZ /Zm200 /c
|
||||
# ADD CPP /nologo /MDd /W3 /Gm- /GR /GX /Zi /Od /I "..\..\..\.." /I "c:\tools\python\include" /D "WIN32" /D "_DEBUG" /D "_WINDOWS" /D "_MBCS" /D "_USRDLL" /D "TEST_EXPORTS" /D "BOOST_DEBUG_PYTHON" /YX /FD /GZ /Zm200 /EHs /c
|
||||
# ADD BASE MTL /nologo /D "_DEBUG" /mktyplib203 /win32
|
||||
# ADD MTL /nologo /D "_DEBUG" /mktyplib203 /win32
|
||||
# ADD BASE RSC /l 0x409 /d "_DEBUG"
|
||||
# ADD RSC /l 0x409 /d "_DEBUG"
|
||||
BSC32=bscmake.exe
|
||||
# ADD BASE BSC32 /nologo
|
||||
# ADD BSC32 /nologo
|
||||
LINK32=link.exe
|
||||
# ADD BASE LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /dll /incremental:no /debug /machine:I386 /pdbtype:sept /libpath:"c:\tools\python\libs"
|
||||
# SUBTRACT BASE LINK32 /pdb:none
|
||||
# ADD LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /dll /incremental:no /debug /machine:I386 /out:"DebugPython/boost_python_test_d.dll" /pdbtype:sept /libpath:"c:\tools\python\src\PCbuild"
|
||||
# SUBTRACT LINK32 /pdb:none
|
||||
|
||||
!ENDIF
|
||||
|
||||
# Begin Target
|
||||
|
||||
# Name "test - Win32 Release"
|
||||
# Name "test - Win32 Debug"
|
||||
# Name "test - Win32 DebugPython"
|
||||
# Begin Group "Source Files"
|
||||
|
||||
# PROP Default_Filter "cpp;c;cxx;rc;def;r;odl;idl;hpj;bat"
|
||||
# Begin Source File
|
||||
|
||||
SOURCE=..\..\test\comprehensive.cpp
|
||||
# End Source File
|
||||
# End Group
|
||||
# Begin Group "Header Files"
|
||||
|
||||
# PROP Default_Filter "h;hpp;hxx;hm;inl"
|
||||
# Begin Source File
|
||||
|
||||
SOURCE=..\..\test\comprehensive.hpp
|
||||
# End Source File
|
||||
# End Group
|
||||
# Begin Group "Resource Files"
|
||||
|
||||
# PROP Default_Filter "ico;cur;bmp;dlg;rc2;rct;bin;rgs;gif;jpg;jpeg;jpe"
|
||||
# End Group
|
||||
# End Target
|
||||
# End Project
|
||||
@@ -1,170 +0,0 @@
|
||||
# Usage:
|
||||
#
|
||||
# Create a new empty directory anywhere (preferably not in the boost tree).
|
||||
# Copy this Makefile to that new directory and rename it to "Makefile"
|
||||
# Set the BOOST pathname below.
|
||||
#
|
||||
# make softlinks Create softlinks to source code and tests
|
||||
# make Compile all sources
|
||||
# make test Run doctest tests
|
||||
# make clean Remove all object files
|
||||
# make unlink Remove softlinks
|
||||
|
||||
BOOST= /net/cci/rwgk/boost
|
||||
|
||||
PYEXE= /usr/local/Python-1.5.2/bin/python
|
||||
PYINC= -I/usr/local/Python-1.5.2/include/python1.5
|
||||
#PYEXE= /usr/local/Python-2.0/bin/python
|
||||
#PYINC= -I/usr/local/Python-2.0/include/python2.0
|
||||
#STLPORTINC= -I/usr/local/STLport-4.1b3/stlport
|
||||
#STLPORTOPTS= \
|
||||
# -D__USE_STD_IOSTREAM \
|
||||
# -D__STL_NO_SGI_IOSTREAMS \
|
||||
# -D__STL_USE_NATIVE_STRING \
|
||||
# -D__STL_NO_NEW_C_HEADERS \
|
||||
# -D_RWSTD_COMPILE_INSTANTIATE=1
|
||||
#STLPORTINC= -I/usr/local/STLport-4.1b4/stlport
|
||||
#STLPORTOPTS= -D__NO_USE_STD_IOSTREAM -D__STL_NO_SGI_IOSTREAMS
|
||||
STLPORTINC= -I/net/cci/xp/C++_C_headers
|
||||
|
||||
STDOPTS= -std strict_ansi
|
||||
WARNOPTS= -msg_disable 186,450,1115
|
||||
# use -msg_display_number to obtain integer tags for -msg_disable
|
||||
|
||||
CPP= cxx
|
||||
CPPOPTS= $(STLPORTINC) $(STLPORTOPTS) -I$(BOOST) $(PYINC) \
|
||||
$(STDOPTS) $(WARNOPTS) -g
|
||||
MAKEDEP= -Em
|
||||
|
||||
LD= cxx
|
||||
LDOPTS= -shared -expect_unresolved 'Py*' -expect_unresolved '_Py*'
|
||||
|
||||
#HIDDEN= -hidden
|
||||
|
||||
BPL_SRC = $(BOOST)/libs/python/src
|
||||
BPL_TST = $(BOOST)/libs/python/test
|
||||
BPL_EXA = $(BOOST)/libs/python/example
|
||||
SOFTLINKS = \
|
||||
$(BPL_SRC)/classes.cpp \
|
||||
$(BPL_SRC)/conversions.cpp \
|
||||
$(BPL_SRC)/extension_class.cpp \
|
||||
$(BPL_SRC)/functions.cpp \
|
||||
$(BPL_SRC)/init_function.cpp \
|
||||
$(BPL_SRC)/module_builder.cpp \
|
||||
$(BPL_SRC)/objects.cpp \
|
||||
$(BPL_SRC)/types.cpp \
|
||||
$(BPL_TST)/comprehensive.cpp \
|
||||
$(BPL_TST)/comprehensive.hpp \
|
||||
$(BPL_TST)/comprehensive.py \
|
||||
$(BPL_TST)/doctest.py \
|
||||
$(BPL_EXA)/abstract.cpp \
|
||||
$(BPL_EXA)/getting_started1.cpp \
|
||||
$(BPL_EXA)/getting_started2.cpp \
|
||||
$(BPL_EXA)/getting_started3.cpp \
|
||||
$(BPL_EXA)/getting_started4.cpp \
|
||||
$(BPL_EXA)/getting_started5.cpp \
|
||||
$(BPL_EXA)/test_abstract.py \
|
||||
$(BPL_EXA)/test_getting_started1.py \
|
||||
$(BPL_EXA)/test_getting_started2.py \
|
||||
$(BPL_EXA)/test_getting_started3.py \
|
||||
$(BPL_EXA)/test_getting_started4.py \
|
||||
$(BPL_EXA)/test_getting_started5.py
|
||||
|
||||
OBJ = classes.o conversions.o extension_class.o functions.o \
|
||||
init_function.o module_builder.o \
|
||||
objects.o types.o
|
||||
DEPOBJ= $(OBJ) comprehensive.o abstract.o \
|
||||
getting_started1.o getting_started2.o getting_started3.o \
|
||||
getting_started4.o getting_started5.o
|
||||
|
||||
.SUFFIXES: .o .cpp
|
||||
|
||||
all: libboost_python.a boost_python_test.so abstract.so \
|
||||
getting_started1.so getting_started2.so getting_started3.so \
|
||||
getting_started4.so getting_started5.so
|
||||
|
||||
softlinks:
|
||||
@ for pn in $(SOFTLINKS); \
|
||||
do \
|
||||
bn=`basename "$$pn"`; \
|
||||
if [ ! -e "$$bn" ]; then \
|
||||
echo "ln -s $$pn ."; \
|
||||
ln -s "$$pn" .; \
|
||||
else \
|
||||
echo "info: no softlink created (file exists): $$bn"; \
|
||||
fi; \
|
||||
done
|
||||
|
||||
unlink:
|
||||
@ for pn in $(SOFTLINKS); \
|
||||
do \
|
||||
bn=`basename "$$pn"`; \
|
||||
if [ -L "$$bn" ]; then \
|
||||
echo "rm $$bn"; \
|
||||
rm "$$bn"; \
|
||||
elif [ -e "$$bn" ]; then \
|
||||
echo "info: not a softlink: $$bn"; \
|
||||
fi; \
|
||||
done
|
||||
|
||||
libboost_python.a: $(OBJ)
|
||||
rm -f libboost_python.a
|
||||
cd cxx_repository; \
|
||||
ls -1 > ../libboost_python.a.input; \
|
||||
ar r ../libboost_python.a -input ../libboost_python.a.input
|
||||
rm -f libboost_python.a.input
|
||||
ar r libboost_python.a $(OBJ)
|
||||
|
||||
boost_python_test.so: $(OBJ) comprehensive.o
|
||||
$(LD) $(LDOPTS) $(OBJ) comprehensive.o -o boost_python_test.so -lm
|
||||
|
||||
abstract.so: $(OBJ) abstract.o
|
||||
$(LD) $(LDOPTS) $(OBJ) abstract.o -o abstract.so
|
||||
|
||||
getting_started1.so: $(OBJ) getting_started1.o
|
||||
$(LD) $(LDOPTS) $(OBJ) getting_started1.o -o getting_started1.so
|
||||
|
||||
getting_started2.so: $(OBJ) getting_started2.o
|
||||
$(LD) $(LDOPTS) $(OBJ) getting_started2.o -o getting_started2.so
|
||||
|
||||
getting_started3.so: $(OBJ) getting_started3.o
|
||||
$(LD) $(LDOPTS) $(OBJ) getting_started3.o -o getting_started3.so
|
||||
|
||||
getting_started4.so: $(OBJ) getting_started4.o
|
||||
$(LD) $(LDOPTS) $(OBJ) getting_started4.o -o getting_started4.so
|
||||
|
||||
getting_started5.so: $(OBJ) getting_started5.o
|
||||
$(LD) $(LDOPTS) $(OBJ) getting_started5.o -o getting_started5.so
|
||||
|
||||
.cpp.o:
|
||||
$(CPP) $(CPPOPTS) -c $*.cpp
|
||||
|
||||
test:
|
||||
$(PYEXE) comprehensive.py
|
||||
$(PYEXE) test_abstract.py
|
||||
$(PYEXE) test_getting_started1.py
|
||||
$(PYEXE) test_getting_started2.py
|
||||
$(PYEXE) test_getting_started3.py
|
||||
$(PYEXE) test_getting_started4.py
|
||||
$(PYEXE) test_getting_started5.py
|
||||
|
||||
clean:
|
||||
rm -f $(OBJ) libboost_python.a libboost_python.a.input
|
||||
rm -f comprehensive.o boost_python_test.so
|
||||
rm -f abstract.o abstract.so
|
||||
rm -f getting_started1.o getting_started1.so
|
||||
rm -f getting_started2.o getting_started2.so
|
||||
rm -f getting_started3.o getting_started3.so
|
||||
rm -f getting_started4.o getting_started4.so
|
||||
rm -f getting_started5.o getting_started5.so
|
||||
rm -f so_locations *.pyc
|
||||
rm -rf cxx_repository
|
||||
|
||||
depend:
|
||||
@ cat Makefile.nodepend; \
|
||||
for obj in $(DEPOBJ); \
|
||||
do \
|
||||
bn=`echo "$$obj" | cut -d. -f1`; \
|
||||
$(CPP) $(CPPOPTS) $(MAKEDEP) "$$bn".cpp; \
|
||||
done
|
||||
|
||||
@@ -1,157 +0,0 @@
|
||||
<!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN">
|
||||
|
||||
<meta name="generator" content="HTML Tidy, see www.w3.org">
|
||||
|
||||
<title>Building an Extension Module</title>
|
||||
|
||||
<div>
|
||||
<h1><img width="277" height="86" id="_x0000_i1025" align="center" src=
|
||||
"../../../c++boost.gif" alt="c++boost.gif (8819 bytes)">Building an
|
||||
Extension Module</h1>
|
||||
|
||||
<p>The build process for Boost is currently undergoing some evolution,
|
||||
and, it is to be hoped, improvement. The following facts may help:
|
||||
|
||||
<ul>
|
||||
<li>
|
||||
Makefiles for various platforms reside in the Boost subdirectory
|
||||
<tt>libs/python/build</tt>:
|
||||
|
||||
<ul>
|
||||
<li><a href="../build/como.mak">como.mak</a> (Comeau C++ on Linux)
|
||||
|
||||
<li><a href="../build/linux_gcc.mak">linux_gcc.mak</a> (GCC on
|
||||
Linux/Unix)
|
||||
|
||||
<li><a href="../build/gcc.mak">gcc.mak</a> (older makefile for GCC
|
||||
on Linux/Unix. Deprecated.)
|
||||
|
||||
<li><a href="../build/mingw32.mak">mingw32.mak</a>
|
||||
(highly-specialized makefile for mingw32 (Win32-targeted) GCC. Read
|
||||
the header comment).
|
||||
|
||||
<li><a href="../build/tru64_cxx.mak">tru64_cxx.mak</a> (Compaq
|
||||
Alpha).
|
||||
</ul>
|
||||
<br>
|
||||
|
||||
<li>
|
||||
A project workspace for Microsoft Visual Studio is provided at <tt><a
|
||||
href="../build/build.dsw">libs/python/build/build.dsw</a></tt>. The
|
||||
include paths for this project may need to be changed for your
|
||||
installation. They currently assume that python has been installed at
|
||||
<tt>c:\tools\python</tt>. Three configurations of all targets are
|
||||
supported:
|
||||
|
||||
<ul>
|
||||
<li>Release (optimization, <tt>-DNDEBUG</tt>)
|
||||
|
||||
<li>Debug (no optimization <tt>-D_DEBUG</tt>)
|
||||
|
||||
<li>DebugPython (no optimization, <tt>-D_DEBUG
|
||||
-DBOOST_DEBUG_PYTHON</tt>)
|
||||
</ul>
|
||||
|
||||
<p>When extension modules are built with Visual C++ using
|
||||
<tt>-D_DEBUG</tt>, Python defaults to <i>force</i> linking with a
|
||||
special debugging version of the Python DLL. Since this debug DLL
|
||||
isn't supplied with the default Python installation for Windows,
|
||||
Boost.Python uses <tt><a href=
|
||||
"../../../boost/python/detail/wrap_python.hpp">boost/python/detail/wrap_python.hpp</a></tt>
|
||||
to temporarily undefine <tt>_DEBUG</tt> when <tt>Python.h</tt> is
|
||||
<tt>#include</tt>d.
|
||||
|
||||
<p>If you want the extra runtime checks available with the debugging
|
||||
version of the library, <tt>#define BOOST_DEBUG_PYTHON</tt> to
|
||||
re-enable library forcing, and link with the DebugPython version of
|
||||
<tt>boost_python.lib</tt>. You'll need to get the debugging version
|
||||
of the Python executable (<tt>python_d.exe</tt>) and DLL
|
||||
(<tt>python20_d.dll</tt> or <tt>python15_d.dll</tt>). The Python
|
||||
sources include project files for building these. If you <a href=
|
||||
"http://www.python.org">download</a> them, change the name of the
|
||||
top-level directory to <tt>src</tt>, and install it under
|
||||
<tt>c:\tools\python</tt>, the workspace supplied by Boost.Python will
|
||||
be able to use it without modification. Just open
|
||||
<tt>c:\tools\python\src\pcbuild\pcbuild.dsw</tt> and invoke "build
|
||||
all" to generate all the debugging targets.
|
||||
|
||||
<p>If you do not <tt>#define BOOST_DEBUG_PYTHON</tt>, be sure that
|
||||
any source files <tt>#include <<a href=
|
||||
"../../../boost/python/detail/wrap_python.hpp">boost/python/detail/wrap_python.hpp</a>></tt>
|
||||
instead of the usual <tt>Python.h</tt>, or you will have link
|
||||
incompatibilities.<br>
|
||||
<br>
|
||||
|
||||
|
||||
<li>
|
||||
The makefiles and Visual Studio project can all build at least the
|
||||
following:
|
||||
|
||||
<ul>
|
||||
<li>The <tt>boost_python</tt> library for static linking with your
|
||||
extension module. On the various Unices, this library will be
|
||||
called <tt>libboost_python.a</tt>. On Win32 platforms, the library
|
||||
will be called <tt>boost_python.lib</tt>.
|
||||
|
||||
<li>A comprehensive test of Boost.Python features. This test builds
|
||||
a Boost.Python extension module, then runs Python to import the
|
||||
module, and runs a series of tests on it using <tt><a href=
|
||||
"../test/doctest.py">doctest</a></tt>. Source code for the module
|
||||
and tests is available in the Boost subdirectory
|
||||
<tt>libs/python/test</tt>.<br>
|
||||
|
||||
|
||||
<li>Various examples from the Boost subdirectory
|
||||
<tt>libs/python/example</tt>. Which examples are built currently
|
||||
depends on the platform. The most up-to-date examples are
|
||||
<tt>getting_started</tt><i>n</i><tt>.cpp</tt> from <a href=
|
||||
"http://cci.lbl.gov/staff/ralf_grosse-kunstleve.html">Ralf W.
|
||||
Grosse-Kunstleve</a>. All these examples include a doctest modeled
|
||||
on the comprehensive test above.<br>
|
||||
<br>
|
||||
|
||||
</ul>
|
||||
|
||||
<li>
|
||||
If your platform isn't directly supported, you can build a static
|
||||
library from the following source files (in the Boost subdirectory
|
||||
<tt>libs/python/src</tt>), or compile them directly and link the
|
||||
resulting objects into your extension module:
|
||||
|
||||
<ul>
|
||||
<li><a href=
|
||||
"../../../libs/python/src/extension_class.cpp">extension_class.cpp</a>
|
||||
|
||||
<li><a href=
|
||||
"../../../libs/python/src/functions.cpp">functions.cpp</a>
|
||||
|
||||
<li><a href=
|
||||
"../../../libs/python/src/init_function.cpp">init_function.cpp</a>
|
||||
|
||||
<li><a href=
|
||||
"../../../libs/python/src/module_builder.cpp">module_builder.cpp</a>
|
||||
|
||||
<li><a href="../../../libs/python/src/types.cpp">types.cpp</a>
|
||||
|
||||
<li><a href="../../../libs/python/src/objects.cpp">objects.cpp</a>
|
||||
|
||||
<li><a href=
|
||||
"../../../libs/python/src/conversions.cpp">conversions.cpp</a>
|
||||
|
||||
<li><a href="../../../libs/python/src/classes.cpp">classes.cpp</a>
|
||||
</ul>
|
||||
</ul>
|
||||
|
||||
<p>Next: <a href="enums.html">Wrapping Enums</a> Previous: <a href=
|
||||
"under-the-hood.html">A Peek Under the Hood</a> Up: <a href=
|
||||
"index.html">Top</a>
|
||||
|
||||
<p>© Copyright David Abrahams 2000. Permission to copy, use, modify,
|
||||
sell and distribute this document is granted provided this copyright
|
||||
notice appears in all copies. This document is provided ``as is'' without
|
||||
express or implied warranty, and with no claim as to its suitability for
|
||||
any purpose.
|
||||
|
||||
<p>Updated: Mar 6, 2001
|
||||
</div>
|
||||
|
||||
@@ -1,231 +0,0 @@
|
||||
<!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.0//EN"
|
||||
"http://www.w3.org/TR/REC-html40/strict.dtd">
|
||||
<title>
|
||||
Comparisons with Other Systems
|
||||
</title>
|
||||
<div>
|
||||
<h1>
|
||||
<img width="277" height="86" id="_x0000_i1025" align="center"
|
||||
src="../../../c++boost.gif" alt= "c++boost.gif (8819 bytes)"><br>
|
||||
Comparisons with
|
||||
Other Systems
|
||||
</h1>
|
||||
|
||||
<h2>CXX</h2>
|
||||
<p>
|
||||
Like Boost.Python, <a href="http://cxx.sourceforge.net/">CXX</a> attempts to
|
||||
provide a C++-oriented interface to Python. In most cases, as with the
|
||||
boost library, it relieves the user from worrying about
|
||||
reference-counts. Both libraries automatically convert thrown C++
|
||||
exceptions into Python exceptions. As far as I can tell, CXX has no
|
||||
support for subclassing C++ extension types in Python. An even
|
||||
more significant difference is that a user's C++ code is still basically
|
||||
``dealing with Python objects'', though they are wrapped in
|
||||
C++ classes. This means such jobs as argument parsing and conversion are
|
||||
still left to be done explicitly by the user.
|
||||
|
||||
<p>
|
||||
CXX claims to interoperate well with the C++ Standard Library
|
||||
(a.k.a. STL) by providing iterators into Python Lists and Dictionaries,
|
||||
but the claim is unfortunately unsupportable. The problem is that in
|
||||
general, access to Python sequence and mapping elements through
|
||||
iterators requires the use of proxy objects as the return value of
|
||||
iterator dereference operations. This usage conflicts with the basic
|
||||
ForwardIterator requirements in <a
|
||||
href="http://anubis.dkuug.dk/jtc1/sc22/open/n2356/lib-iterators.html#lib.forward.iterators">
|
||||
section 24.1.3 of the standard</a> (dereferencing must produce a
|
||||
reference). Although you may be able to use these iterators with some
|
||||
operations in some standard library implementations, it is neither
|
||||
guaranteed to work nor portable.
|
||||
|
||||
<p>
|
||||
As far as I can tell, CXX enables one to write what is essentially
|
||||
idiomatic Python code in C++, manipulating Python objects through the
|
||||
same fully-generic interfaces we use in Python. While you're hardly
|
||||
programming directly to the ``bare metal'' with CXX, it basically
|
||||
presents a ``C++-ized'' version of the Python 'C' API. Some fraction of
|
||||
that capability is available in Boost.Python through <tt><a
|
||||
href="../../../boost/python/objects.hpp">boost/python/objects.hpp</a></tt>,
|
||||
which provides C++ objects corresponding to Python lists, tuples,
|
||||
strings, and dictionaries, and through <tt><a
|
||||
href="../../../boost/python/callback.hpp">boost/python/callback.hpp</a></tt>,
|
||||
which allows you to call back into python with C++ arguments.
|
||||
|
||||
<p>
|
||||
<a href="mailto:dubois1@llnl.gov">Paul F. Dubois</a>, the original
|
||||
author of CXX, has told me that what I've described is only half of the
|
||||
picture with CXX, but I never understood his explanation well-enough to
|
||||
fill in the other half. Here is his response to the commentary above:
|
||||
|
||||
<blockquote>
|
||||
``My intention with CXX was not to do what you are doing. It was to enable a
|
||||
person to write an extension directly in C++ rather than C. I figured others had
|
||||
the wrapping business covered. I thought maybe CXX would provide an easier
|
||||
target language for those making wrappers, but I never explored
|
||||
that.''<br><i>-<a href="mailto:dubois1@llnl.gov">Paul Dubois</a></i>
|
||||
</blockquote>
|
||||
|
||||
<h2>SWIG</h2>
|
||||
<p>
|
||||
<a href= "http://www.swig.org/">SWIG</a> is an impressively mature tool
|
||||
for exporting an existing ANSI 'C' interface into various scripting
|
||||
languages. Swig relies on a parser to read your source code and produce
|
||||
additional source code files which can be compiled into a Python (or
|
||||
Perl or Tcl) extension module. It has been successfully used to create
|
||||
many Python extension modules. Like Boost.Python, SWIG is trying to allow an
|
||||
existing interface to be wrapped with little or no change to the
|
||||
existing code. The documentation says ``SWIG parses a form of ANSI C
|
||||
syntax that has been extended with a number of special directives. As a
|
||||
result, interfaces are usually built by grabbing a header file and
|
||||
tweaking it a little bit.'' For C++ interfaces, the tweaking has often
|
||||
proven to amount to more than just a little bit. One user
|
||||
writes:
|
||||
|
||||
<blockquote> ``The problem with swig (when I used it) is that it
|
||||
couldnt handle templates, didnt do func overloading properly etc. For
|
||||
ANSI C libraries this was fine. But for usual C++ code this was a
|
||||
problem. Simple things work. But for anything very complicated (or
|
||||
realistic), one had to write code by hand. I believe Boost.Python doesn't have
|
||||
this problem[<a href="#sic">sic</a>]... IMHO overloaded functions are very important to
|
||||
wrap correctly.''<br><i>-Prabhu Ramachandran</i>
|
||||
</blockquote>
|
||||
|
||||
<p>
|
||||
By contrast, Boost.Python doesn't attempt to parse C++ - the problem is simply
|
||||
too complex to do correctly. <a name="sic">Technically</a>, one does
|
||||
write code by hand to use Boost.Python. The goal, however, has been to make
|
||||
that code nearly as simple as listing the names of the classes and
|
||||
member functions you want to expose in Python.
|
||||
|
||||
<h2>SIP</h2>
|
||||
<p>
|
||||
<a
|
||||
href="http://www.thekompany.com/projects/pykde/background.php3?dhtml_ok=1">SIP</a>
|
||||
is a system similar to SWIG, though seemingly more
|
||||
C++-oriented. The author says that like Boost.Python, SIP supports overriding
|
||||
extension class member functions in Python subclasses. It appears to
|
||||
have been designed specifically to directly support some features of
|
||||
PyQt/PyKDE, which is its primary client. Documentation is almost
|
||||
entirely missing at the time of this writing, so a detailed comparison
|
||||
is difficult.
|
||||
|
||||
<h2>ILU</h2>
|
||||
<p>
|
||||
<a
|
||||
href="http://www.cl.cam.ac.uk/Research/Rainbow/projects/origami/ilu-1.8-manual">ILU</a>
|
||||
is a very ambitious project which tries to describe a module's interface
|
||||
(types and functions) in terms of an <a
|
||||
href="http://www.cl.cam.ac.uk/Research/Rainbow/projects/origami/ilu-1.8-manual/manual_2.html">Interface
|
||||
Specification Language</a> (ISL) so that it can be uniformly interfaced
|
||||
to a wide range of computer languages, including Common Lisp, C++, C,
|
||||
Modula-3, and Python. ILU can parse the ISL to generate a C++ language
|
||||
header file describing the interface, of which the user is expected to
|
||||
provide an implementation. Unlike Boost.Python, this means that the system
|
||||
imposes implementation details on your C++ code at the deepest level. It
|
||||
is worth noting that some of the C++ names generated by ILU are supposed
|
||||
to be reserved to the C++ implementation. It is unclear from the
|
||||
documentation whether ILU supports overriding C++ virtual functions in Python.
|
||||
|
||||
<h2>GRAD</h2>
|
||||
<p>
|
||||
<a
|
||||
href="http://www.python.org/workshops/1996-11/papers/GRAD/html/GRADcover.html">GRAD</a>
|
||||
is another very ambitious project aimed at generating Python wrappers for
|
||||
interfaces written in ``legacy languages'', among which C++ is the first one
|
||||
implemented. Like SWIG, it aims to parse source code and automatically
|
||||
generate wrappers, though it appears to take a more sophisticated approach
|
||||
to parsing in general and C++ in particular, so it should do a much better
|
||||
job with C++. It appears to support function overloading. The
|
||||
documentation is missing a lot of information I'd like to see, so it is
|
||||
difficult to give an accurate and fair assessment. I am left with the
|
||||
following questions:
|
||||
<ul>
|
||||
<li>Does it support overriding of virtual functions?
|
||||
<li>What about overriding private or protected virtual functions (the documentation indicates
|
||||
that only public interfaces are supported)?
|
||||
<li>Which C++ language constructs are supportd?
|
||||
<li>Does it support implicit conversions between wrapped C++ classes that have
|
||||
an inheritance relationship?
|
||||
<li>Does it support smart pointers?
|
||||
</ul>
|
||||
<p>
|
||||
Anyone in the possession of the answers to these questions will earn my
|
||||
gratitude for a write-up <code>;-)</code>
|
||||
|
||||
<h2>Zope ExtensionClasses</h2>
|
||||
<p>
|
||||
<a href="http:http://www.digicool.com/releases/ExtensionClass">
|
||||
ExtensionClasses in Zope</a> use the same underlying mechanism as Boost.Python
|
||||
to support subclassing of extension types in Python, including
|
||||
multiple-inheritance. Both systems support pickling/unpickling of
|
||||
extension class instances in very similar ways. Both systems rely on the
|
||||
same ``<a
|
||||
href="http://www.python.org/workshops/1994-11/BuiltInClasses/Welcome.html">Don
|
||||
Beaudry Hack</a>'' that also inspired Don's MESS System.
|
||||
<p>
|
||||
The major differences are:
|
||||
<ul>
|
||||
<li>Zope is entirely 'C' language-based. It doesn't require a C++
|
||||
compiler, so it's much more portable than Boost.Python, which stresses
|
||||
the limits of even some modern C++ implementations.
|
||||
|
||||
<li>
|
||||
Boost.Python lifts the burden on the user to parse and convert function
|
||||
argument types. Zope provides no such facility.
|
||||
<li>
|
||||
Boost.Python lifts the burden on the user to maintain Python
|
||||
reference-counts.
|
||||
<li>
|
||||
Boost.Python supports function overloading; Zope does not.
|
||||
<li>
|
||||
Boost.Python supplies a simple mechanism for exposing read-only and
|
||||
read/write access to data members of the wrapped C++ type as Python
|
||||
attributes.
|
||||
<li>
|
||||
Writing a Zope ExtensionClass is significantly more complex than
|
||||
exposing a C++ class to python using Boost.Python (mostly a summary of the
|
||||
previous 4 items). <a href=
|
||||
"http://www.digicool.com/releases/ExtensionClass/MultiMapping.html">A
|
||||
Zope Example</a> illustrates the differences.
|
||||
<li>
|
||||
Zope's ExtensionClasses are specifically motivated by ``the need for a
|
||||
C-based persistence mechanism''. Boost.Python's are motivated by the desire
|
||||
to simply reflect a C++ API into Python with as little modification as
|
||||
possible.
|
||||
<li>
|
||||
The following Zope restriction does not apply to Boost.Python: ``At most one
|
||||
base extension direct or indirect super class may define C data
|
||||
members. If an extension subclass inherits from multiple base
|
||||
extension classes, then all but one must be mix-in classes that
|
||||
provide extension methods but no data.''
|
||||
<li>
|
||||
Zope requires use of the somewhat funky inheritedAttribute (search for
|
||||
``inheritedAttribute'' on <a
|
||||
href="http://www.digicool.com/releases/ExtensionClass">this page</a>)
|
||||
method to access base class methods. In Boost.Python, base class methods can
|
||||
be accessed in the usual way by writing
|
||||
``<code>BaseClass.method</code>''.
|
||||
<li>
|
||||
Zope supplies some creative but esoteric idioms such as <a href=
|
||||
"http://www.digicool.com/releases/ExtensionClass/Acquisition.html">
|
||||
Acquisition</a>. No specific support for this is built into Boost.Python.
|
||||
<li>
|
||||
Zope's ComputedAttribute support is designed to be used from Python.
|
||||
<a href="special.html#getter_setter">The analogous feature of
|
||||
Boost.Python</a> can be used from C++ or Python. The feature is arguably
|
||||
easier to use in Boost.Python.
|
||||
</ul>
|
||||
<p>
|
||||
Next: <a href="example1.html">A Simple Example Using Boost.Python</a>
|
||||
Previous: <a href="extending.html">A Brief Introduction to writing Python Extension Modules</a>
|
||||
Up: <a href="index.html">Top</a>
|
||||
<p>
|
||||
© Copyright David Abrahams 2000. Permission to copy, use, modify,
|
||||
sell and distribute this document is granted provided this copyright
|
||||
notice appears in all copies. This document is provided ``as is'' without
|
||||
express or implied warranty, and with no claim as to its suitability
|
||||
for any purpose.
|
||||
<p>
|
||||
Updated: Mar 6, 2001
|
||||
</div>
|
||||
|
||||
@@ -1,192 +0,0 @@
|
||||
Given a real Python class 'A', a wrapped C++ class 'B', and this definition:
|
||||
|
||||
class C(A, B):
|
||||
def __init__(self):
|
||||
B.__init__(self)
|
||||
self.x = 1
|
||||
...
|
||||
|
||||
c = C()
|
||||
|
||||
this diagram describes the internal structure of an instance of 'C', including
|
||||
its inheritance relationships. Note that ExtensionClass<B> is derived from
|
||||
Class<ExtensionInstance>, and is in fact identical for all intents and purposes.
|
||||
|
||||
MetaClass<ExtensionInstance>
|
||||
+---------+ +---------+
|
||||
types.ClassType: | | | |
|
||||
| | | |
|
||||
| | | |
|
||||
+---------+ +---------+
|
||||
^ ^ ^
|
||||
PyClassObject | ExtensionClass<B> | |
|
||||
A: +------------+ | B: +------------+ | |
|
||||
| ob_type -+-+ | ob_type -+-----+ |
|
||||
| | ()<--+- __bases__ | |
|
||||
| | | __dict__ -+->{...} |
|
||||
| | 'B'<-+- __name__ | |
|
||||
+------------+ +------------+ |
|
||||
^ ^ |
|
||||
| | |
|
||||
+-----+ +-------------+ |
|
||||
| | |
|
||||
| | Class<ExtensionInstance> |
|
||||
| | C: +------------+ |
|
||||
| | | ob_type -+------------+
|
||||
tuple:(*, *)<--+- __bases__ |
|
||||
| __dict__ -+->{__module__, <methods, etc.>}
|
||||
'C' <-+- __name__ |
|
||||
+------------+
|
||||
^ (in case of inheritance from more than one
|
||||
| extension class, this vector would contain
|
||||
+---------------+ a pointer to an instance holder for the data
|
||||
| of each corresponding C++ class)
|
||||
| ExtensionInstance
|
||||
| c: +---------------------+ std::vector<InstanceHolderBase>
|
||||
+----+- __class__ | +---+--
|
||||
| m_wrapped_objects -+->| * | ...
|
||||
{'x': 1}<-+- __dict__ | +-|-+--
|
||||
+---------------------+ | InstanceValueHolder<B>
|
||||
| +--------------------------------+
|
||||
+-->| (contains a C++ instance of B) |
|
||||
+--------------------------------+
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
In our inheritance test cases in extclass_demo.cpp/test_extclass.py, we have the
|
||||
following C++ inheritance hierarchy:
|
||||
|
||||
+-----+ +----+
|
||||
| A1 | | A2 |
|
||||
+-----+ +----+
|
||||
^ ^ ^ ^ ^
|
||||
| | | | |
|
||||
+-----+ | +---------+-----+
|
||||
| | | |
|
||||
| +---+----------+
|
||||
.......!...... | |
|
||||
: A_callback : +-+--+ +-+--+
|
||||
:............: | B1 | | B2 |
|
||||
+----+ +----+
|
||||
^
|
||||
|
|
||||
+-------+---------+
|
||||
| |
|
||||
+-+-+ ......!.......
|
||||
| C | : B_callback :
|
||||
+---+ :............:
|
||||
|
||||
|
||||
A_callback and B_callback are used as part of the wrapping mechanism but not
|
||||
represented in Python. C is also not represented in Python but is delivered
|
||||
there polymorphically through a smart pointer.
|
||||
|
||||
This is the data structure in Python.
|
||||
|
||||
ExtensionClass<A1>
|
||||
A1: +------------+
|
||||
()<--+- __bases__ |
|
||||
| __dict__ -+->{...}
|
||||
+------------+
|
||||
^
|
||||
| ExtensionInstance
|
||||
| a1: +---------------------+ vec InstanceValueHolder<A1,A_callback>
|
||||
+---------+- __class__ | +---+ +---------------------+
|
||||
| | m_wrapped_objects -+->| *-+-->| contains A_callback |
|
||||
| +---------------------+ +---+ +---------------------+
|
||||
|
|
||||
| ExtensionInstance
|
||||
| pa1_a1: +---------------------+ vec InstancePtrHolder<auto_ptr<A1>,A1>
|
||||
+---------+- __class__ | +---+ +---+
|
||||
| | m_wrapped_objects -+->| *-+-->| *-+-+ A1
|
||||
| +---------------------+ +---+ +---+ | +---+
|
||||
| +->| |
|
||||
| ExtensionInstance +---+
|
||||
| pb1_a1: +---------------------+ vec InstancePtrHolder<auto_ptr<A1>,A1>
|
||||
+---------+- __class__ | +---+ +---+
|
||||
| | m_wrapped_objects -+->| *-+-->| *-+-+ B1
|
||||
| +---------------------+ +---+ +---+ | +---+
|
||||
| +->| |
|
||||
| ExtensionInstance +---+
|
||||
| pb2_a1: +---------------------+ vec InstancePtrHolder<auto_ptr<A1>,A1>
|
||||
+---------+- __class__ | +---+ +---+
|
||||
| | m_wrapped_objects -+->| *-+-->| *-+-+ B2
|
||||
| +---------------------+ +---+ +---+ | +---+
|
||||
| +->| |
|
||||
| +---+
|
||||
| ExtensionClass<A1>
|
||||
| A2: +------------+
|
||||
| ()<--+- __bases__ |
|
||||
| | __dict__ -+->{...}
|
||||
| +------------+
|
||||
| ^
|
||||
| | ExtensionInstance
|
||||
| a2: | +---------------------+ vec InstanceValueHolder<A2>
|
||||
| +-+- __class__ | +---+ +-------------+
|
||||
| | | m_wrapped_objects -+->| *-+-->| contains A2 |
|
||||
| | +---------------------+ +---+ +-------------+
|
||||
| |
|
||||
| | ExtensionInstance
|
||||
| pa2_a2: | +---------------------+ vec InstancePtrHolder<auto_ptr<A2>,A2>
|
||||
| +-+- __class__ | +---+ +---+
|
||||
| | | m_wrapped_objects -+->| *-+-->| *-+-+ A2
|
||||
| | +---------------------+ +---+ +---+ | +---+
|
||||
| | +->| |
|
||||
| | ExtensionInstance +---+
|
||||
| pb1_a2: | +---------------------+ vec InstancePtrHolder<auto_ptr<A2>,A2>
|
||||
| +-+- __class__ | +---+ +---+
|
||||
| | | m_wrapped_objects -+->| *-+-->| *-+-+ B1
|
||||
| | +---------------------+ +---+ +---+ | +---+
|
||||
| | +->| |
|
||||
| | +---+
|
||||
| |
|
||||
| +---------------+------------------------------+
|
||||
| | |
|
||||
+------+-------------------------+-|----------------------------+ |
|
||||
| | | | |
|
||||
| Class<ExtensionInstance> | | ExtensionClass<B1> | | ExtensionClass<B1>
|
||||
| DA1: +------------+ | | B1: +------------+ | | B2: +------------+
|
||||
(*,)<---+- __bases__ | (*,*)<---+- __bases__ | (*,*)<---+- __bases__ |
|
||||
| __dict__ -+->{...} | __dict__ -+->{...} | __dict__ -+->{...}
|
||||
+------------+ +------------+ +------------+
|
||||
^ ^ ^
|
||||
| ExtensionInstance | |
|
||||
| da1: +---------------------+ | vec InstanceValueHolder<A1,A_callback>
|
||||
+-------+- __class__ | | +---+ +---------------------+ |
|
||||
| m_wrapped_objects -+--|-->| *-+-->| contains A_callback | |
|
||||
+---------------------+ | +---+ +---------------------+ |
|
||||
+--------------------------------------+ |
|
||||
| ExtensionInstance |
|
||||
b1: | +---------------------+ vec InstanceValueHolder<B1,B_callback> |
|
||||
+-+- __class__ | +---+ +---------------------+ |
|
||||
| | m_wrapped_objects -+->| *-+-->| contains B_callback | |
|
||||
| +---------------------+ +---+ +---------------------+ |
|
||||
| |
|
||||
| ExtensionInstance |
|
||||
pb1_b1: | +---------------------+ vec InstancePtrHolder<auto_ptr<B1>,B1> |
|
||||
+-+- __class__ | +---+ +---+ |
|
||||
| | m_wrapped_objects -+->| *-+-->| *-+-+ B1 |
|
||||
| +---------------------+ +---+ +---+ | +---+ |
|
||||
| +->| | |
|
||||
| ExtensionInstance +---+ |
|
||||
pc_b1: | +---------------------+ vec InstancePtrHolder<auto_ptr<B1>,B1> |
|
||||
+-+- __class__ | +---+ +---+ |
|
||||
| | m_wrapped_objects -+->| *-+-->| *-+-+ C |
|
||||
| +---------------------+ +---+ +---+ | +---+ |
|
||||
| +->| | |
|
||||
| +---+ |
|
||||
| |
|
||||
| Class<ExtensionInstance> +---------------------------------------+
|
||||
| DB1: +------------+ | ExtensionInstance
|
||||
(*,)<---+- __bases__ | a2: | +---------------------+ vec InstanceValueHolder<A2>
|
||||
| __dict__ -+->{...} +-+- __class__ | +---+ +-------------+
|
||||
+------------+ | m_wrapped_objects -+->| *-+-->| contains A2 |
|
||||
^ +---------------------+ +---+ +-------------+
|
||||
| ExtensionInstance
|
||||
db1: | +---------------------+ vec InstanceValueHolder<B1,B_callback>
|
||||
+-+- __class__ | +---+ +----------------------+
|
||||
| m_wrapped_objects -+-->| *-+-->| contains B1_callback |
|
||||
+---------------------+ +---+ +----------------------+
|
||||
120
doc/enums.html
120
doc/enums.html
@@ -1,120 +0,0 @@
|
||||
<!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.0//EN"
|
||||
"http://www.w3.org/TR/REC-html40/strict.dtd">
|
||||
<title>
|
||||
Wrapping enums
|
||||
</title>
|
||||
<div>
|
||||
<h1>
|
||||
<img width="277" height="86" id="_x0000_i1025" align="center"
|
||||
src="../../../c++boost.gif" alt= "c++boost.gif (8819 bytes)"><br>
|
||||
Wrapping enums
|
||||
</h1>
|
||||
|
||||
<p>Because there is in general no way to deduce that a value of arbitrary type T
|
||||
is an enumeration constant, the Boost Python Library cannot automatically
|
||||
convert enum values to and from Python. To handle this case, you need to decide
|
||||
how you want the enum to show up in Python (since Python doesn't have
|
||||
enums). Once you have done that, you can write some simple
|
||||
<code>from_python()</code> and <code>to_python()</code> functions.
|
||||
|
||||
<p>If you are satisfied with a Python int as a way to represent your enum
|
||||
values, we provide a shorthand for these functions. You just need to cause
|
||||
<code>boost::python::enum_as_int_converters<EnumType></code> to be
|
||||
instantiated, where
|
||||
<code>EnumType</code> is your enumerated type. There are two convenient ways to do this:
|
||||
|
||||
<ol>
|
||||
<li>Explicit instantiation:
|
||||
|
||||
<blockquote><pre>
|
||||
template class boost::python::enum_as_int_converters<my_enum>;
|
||||
</blockquote></pre>
|
||||
|
||||
Some buggy C++ implementations require a class to be instantiated in the same
|
||||
namespace in which it is defined. In that case, the simple incantation above becomes:
|
||||
|
||||
<blockquote>
|
||||
<pre>
|
||||
...
|
||||
} // close my_namespace
|
||||
|
||||
// drop into namespace python and explicitly instantiate
|
||||
namespace boost { namespace python {
|
||||
template class enum_as_int_converters<my_enum_type>;
|
||||
}} // namespace boost::python
|
||||
|
||||
namespace my_namespace { // re-open my_namespace
|
||||
...
|
||||
</pre>
|
||||
</blockquote>
|
||||
|
||||
|
||||
<li>If you have such an implementation, you may find this technique more convenient
|
||||
<blockquote><pre>
|
||||
// instantiate as base class in any namespace
|
||||
struct EnumTypeConverters
|
||||
: boost::python::enum_as_int_converters<EnumType>
|
||||
{
|
||||
};
|
||||
</blockquote></pre>
|
||||
</ol>
|
||||
|
||||
<p>Either of the above is equivalent to the following declarations:
|
||||
<blockquote><pre>
|
||||
BOOST_PYTHON_BEGIN_CONVERSION_NAMESPACE // this is a gcc 2.95.2 bug workaround
|
||||
|
||||
MyEnumType from_python(PyObject* x, boost::python::type<MyEnumType>)
|
||||
{
|
||||
return static_cast<MyEnum>(
|
||||
from_python(x, boost::python::type<long>()));
|
||||
}
|
||||
|
||||
MyEnumType from_python(PyObject* x, boost::python::type<const MyEnumType&>)
|
||||
{
|
||||
return static_cast<MyEnum>(
|
||||
from_python(x, boost::python::type<long>()));
|
||||
}
|
||||
|
||||
PyObject* to_python(MyEnumType x)
|
||||
{
|
||||
return to_python(static_cast<long>(x));
|
||||
}
|
||||
BOOST_PYTHON_END_CONVERSION_NAMESPACE
|
||||
</pre></blockquote>
|
||||
|
||||
<p>This technique defines the conversions of
|
||||
<code>MyEnumType</code> in terms of the conversions for the built-in
|
||||
<code>long</code> type.
|
||||
|
||||
You may also want to add a bunch of lines like this to your module
|
||||
initialization. These bind the corresponding enum values to the appropriate
|
||||
names so they can be used from Python:
|
||||
|
||||
<blockquote><pre>
|
||||
mymodule.add(boost::python::to_python(enum_value_1), "enum_value_1");
|
||||
mymodule.add(boost::python::to_python(enum_value_2), "enum_value_2");
|
||||
...
|
||||
</pre></blockquote>
|
||||
|
||||
You can also add these to an extension class definition, if your enum happens to
|
||||
be local to a class and you want the analogous interface in Python:
|
||||
|
||||
<blockquote><pre>
|
||||
my_class_builder.add(boost::python::to_python(enum_value_1), "enum_value_1");
|
||||
my_class_builder.add(boost::python::to_python(enum_value_2), "enum_value_2");
|
||||
...
|
||||
</pre></blockquote>
|
||||
<p>
|
||||
Next: <a href="pointers.html">Pointers and Smart Pointers</a>
|
||||
Previous: <a href="building.html">Building an Extension Module</a>
|
||||
Up: <a href="index.html">Top</a>
|
||||
<p>
|
||||
© Copyright David Abrahams 2000. Permission to copy, use, modify,
|
||||
sell and distribute this document is granted provided this copyright
|
||||
notice appears in all copies. This document is provided ``as
|
||||
is'' without express or implied warranty, and with no claim as to
|
||||
its suitability for any purpose.
|
||||
<p>
|
||||
Updated: Mar 6, 2001
|
||||
</div>
|
||||
|
||||
@@ -1,82 +0,0 @@
|
||||
<!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.0//EN"
|
||||
"http://www.w3.org/TR/REC-html40/strict.dtd">
|
||||
<title>
|
||||
A Simple Example
|
||||
</title>
|
||||
<div>
|
||||
<h1>
|
||||
<img width="277" height="86" id="_x0000_i1025" src="../../../c++boost.gif" alt=
|
||||
"c++boost.gif (8819 bytes)">
|
||||
</h1>
|
||||
<h1>
|
||||
A Simple Example
|
||||
</h1>
|
||||
<p>
|
||||
Suppose we have the following C++ API which we want to expose in
|
||||
Python:
|
||||
<blockquote>
|
||||
<pre>
|
||||
#include <string>
|
||||
|
||||
namespace { // Avoid cluttering the global namespace.
|
||||
|
||||
// A couple of simple C++ functions that we want to expose to Python.
|
||||
std::string greet() { return "hello, world"; }
|
||||
int square(int number) { return number * number; }
|
||||
}
|
||||
|
||||
</pre>
|
||||
</blockquote>
|
||||
<p>
|
||||
Here is the C++ code for a python module called <tt>getting_started1</tt>
|
||||
which exposes the API.
|
||||
<blockquote>
|
||||
<pre>
|
||||
#include <boost/python/class_builder.hpp>
|
||||
namespace python = boost::python;
|
||||
|
||||
BOOST_PYTHON_MODULE_INIT(getting_started1)
|
||||
{
|
||||
try
|
||||
{
|
||||
// Create an object representing this extension module.
|
||||
python::module_builder this_module("getting_started1");
|
||||
|
||||
// Add regular functions to the module.
|
||||
this_module.def(greet, "greet");
|
||||
this_module.def(square, "square");
|
||||
}
|
||||
catch(...)
|
||||
{
|
||||
python::handle_exception(); // Deal with the exception for Python
|
||||
}
|
||||
}
|
||||
</pre>
|
||||
</blockquote>
|
||||
<p>
|
||||
That's it! If we build this shared library and put it on our <code>
|
||||
PYTHONPATH</code> we can now access our C++ functions from
|
||||
Python.
|
||||
<blockquote>
|
||||
<pre>
|
||||
>>> import getting_started1
|
||||
>>> print getting_started1.greet()
|
||||
hello, world
|
||||
>>> number = 11
|
||||
>>> print number, '*', number, '=', getting_started1.square(number)
|
||||
11 * 11 = 121
|
||||
</pre>
|
||||
<p>
|
||||
Next: <a href="exporting_classes.html">Exporting Classes</a>
|
||||
Previous: <a href="comparisons.html">Comparisons with other systems</a> Up:
|
||||
<a href="index.html">Top</a>
|
||||
<p>
|
||||
© Copyright David Abrahams 2000. Permission to copy, use, modify,
|
||||
sell and distribute this document is granted provided this copyright
|
||||
notice appears in all copies. This document is provided "as is" without
|
||||
express or implied warranty, and with no claim as to its suitability
|
||||
for any purpose.
|
||||
<p>
|
||||
Updated: Mar 6, 2000
|
||||
</div>
|
||||
|
||||
@@ -1,144 +0,0 @@
|
||||
<!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.0//EN"
|
||||
"http://www.w3.org/TR/REC-html40/strict.dtd">
|
||||
<title>
|
||||
Exporting Classes
|
||||
</title>
|
||||
<div>
|
||||
<h1>
|
||||
<img width="277" height="86" id="_x0000_i1025" src="../../../c++boost.gif" alt=
|
||||
"c++boost.gif (8819 bytes)">
|
||||
</h1>
|
||||
<h1>
|
||||
Exporting Classes
|
||||
</h1>
|
||||
<p>
|
||||
Now let's expose a C++ class to Python:
|
||||
|
||||
<blockquote><pre>
|
||||
#include <iostream>
|
||||
#include <string>
|
||||
|
||||
namespace { // Avoid cluttering the global namespace.
|
||||
|
||||
// A friendly class.
|
||||
class hello
|
||||
{
|
||||
public:
|
||||
hello(const std::string& country) { this->country = country; }
|
||||
std::string greet() const { return "Hello from " + country; }
|
||||
private:
|
||||
std::string country;
|
||||
};
|
||||
|
||||
// A function taking a hello object as an argument.
|
||||
std::string invite(const hello& w) {
|
||||
return w.greet() + "! Please come soon!";
|
||||
}
|
||||
}
|
||||
|
||||
</blockquote></pre> <p>
|
||||
To expose the class, we use a <tt>class_builder</tt> in addition to the
|
||||
<tt>module_builder</tt> from the previous example. Class member functions
|
||||
are exposed by using the <tt>def()</tt> member function on the
|
||||
<tt>class_builder</tt>:
|
||||
<blockquote><pre>
|
||||
#include <boost/python/class_builder.hpp>
|
||||
namespace python = boost::python;
|
||||
|
||||
BOOST_PYTHON_MODULE_INIT(getting_started2)
|
||||
{
|
||||
try
|
||||
{
|
||||
// Create an object representing this extension module.
|
||||
python::module_builder this_module("getting_started2");
|
||||
|
||||
// Create the Python type object for our extension class.
|
||||
python::class_builder<hello> hello_class(this_module, "hello");
|
||||
|
||||
// Add the __init__ function.
|
||||
hello_class.def(python::constructor<std::string>());
|
||||
// Add a regular member function.
|
||||
hello_class.def(&hello::greet, "greet");
|
||||
|
||||
// Add invite() as a regular function to the module.
|
||||
this_module.def(invite, "invite");
|
||||
|
||||
// Even better, invite() can also be made a member of hello_class!!!
|
||||
hello_class.def(invite, "invite");
|
||||
}
|
||||
catch(...)
|
||||
{
|
||||
python::handle_exception(); // Deal with the exception for Python
|
||||
}
|
||||
}
|
||||
</blockquote></pre>
|
||||
<p>
|
||||
Now we can use the class normally from Python:
|
||||
|
||||
<blockquote><pre>
|
||||
>>> from getting_started2 import *
|
||||
>>> hi = hello('California')
|
||||
>>> hi.greet()
|
||||
'Hello from California'
|
||||
>>> invite(hi)
|
||||
'Hello from California! Please come soon!'
|
||||
>>> hi.invite()
|
||||
'Hello from California! Please come soon!'
|
||||
</blockquote></pre>
|
||||
|
||||
Notes:<ul>
|
||||
<li> We expose the class' constructor by calling <tt>def()</tt> on the
|
||||
<tt>class_builder</tt> with an argument whose type is
|
||||
<tt>constructor<</tt><i>params</i><tt>></tt>, where <i>params</i>
|
||||
matches the list of constructor argument types:
|
||||
|
||||
|
||||
<li>Regular member functions are defined by calling <tt>def()</tt> with a
|
||||
member function pointer and its Python name:
|
||||
|
||||
<li>Any function added to a class whose initial argument matches the class (or
|
||||
any base) will act like a member function in Python.
|
||||
</ul>
|
||||
<p>
|
||||
We can even make a subclass of <code>hello.world</code>:
|
||||
|
||||
<blockquote><pre>
|
||||
>>> class wordy(hello):
|
||||
... def greet(self):
|
||||
... return hello.greet(self) + ', where the weather is fine'
|
||||
...
|
||||
>>> hi2 = wordy('Florida')
|
||||
>>> hi2.greet()
|
||||
'Hello from Florida, where the weather is fine'
|
||||
>>> invite(hi2)
|
||||
'Hello from Florida! Please come soon!'
|
||||
</blockquote></pre>
|
||||
<p>
|
||||
Pretty cool! You can't do that with an ordinary Python extension type!
|
||||
|
||||
Of course, you may now have a slightly empty feeling in the pit of
|
||||
your little pythonic stomach. Perhaps you wanted to see the following
|
||||
<tt>wordy</tt> invitation:
|
||||
|
||||
<blockquote><pre>
|
||||
'Hello from Florida, where the weather is fine! Please come soon!'
|
||||
</blockquote></pre>
|
||||
|
||||
After all, <tt>invite</tt> calls <tt>hello::greet()</tt>, and you
|
||||
reimplemented that in your Python subclass, <tt>wordy</tt>. If so, <a
|
||||
href= "overriding.html">read on</a>...
|
||||
|
||||
<p>
|
||||
Next: <a href="overriding.html">Overridable virtual functions</a>
|
||||
Previous: <a href="example1.html">A Simple Example</a> Up:
|
||||
<a href="index.html">Top</a>
|
||||
<p>
|
||||
© Copyright David Abrahams 2000. Permission to copy, use, modify,
|
||||
sell and distribute this document is granted provided this copyright
|
||||
notice appears in all copies. This document is provided "as is" without
|
||||
express or implied warranty, and with no claim as to its suitability
|
||||
for any purpose.
|
||||
<p>
|
||||
Updated: Mar 6, 2001
|
||||
</div>
|
||||
|
||||
@@ -1,73 +0,0 @@
|
||||
<!DOCTYPE html PUBLIC "-//W3C//DTD HTML 3.2//EN">
|
||||
<meta http-equiv="Content-Type" content="text/html; charset=windows-1252">
|
||||
<title>
|
||||
A Brief Introduction to writing Python extension modules
|
||||
</title>
|
||||
<h1>
|
||||
<img src="../../../c++boost.gif" alt="c++boost.gif (8819 bytes)" align="center"
|
||||
width="277" height="86">
|
||||
</h1>
|
||||
<h1>
|
||||
A Brief Introduction to writing Python extension modules
|
||||
</h1>
|
||||
<p>
|
||||
Interfacing any language to Python involves building a module which can
|
||||
be loaded by the Python interpreter, but which isn't written in Python.
|
||||
This is known as an <em>extension module</em>. Many of the <a href=
|
||||
"http://www.python.org/doc/current/lib/lib.html">built-in Python
|
||||
libraries</a> are constructed in 'C' this way; Python even supplies its
|
||||
<a href="http://www.python.org/doc/current/lib/types.html">fundamental
|
||||
types</a> using the same mechanism. An extension module can be statically
|
||||
linked with the Python interpreter, but it more commonly resides in a
|
||||
shared library or DLL.
|
||||
<p>
|
||||
As you can see from <a href=
|
||||
"http://www.python.org/doc/current/ext/ext.html"> The Python Extending
|
||||
and Embedding Tutorial</a>, writing an extension module normally means
|
||||
worrying about
|
||||
<ul>
|
||||
<li>
|
||||
<a href="http://www.python.org/doc/current/ext/refcounts.html">
|
||||
maintaining reference counts</a>
|
||||
<li>
|
||||
<a href="http://www.python.org/doc/current/ext/callingPython.html"> how
|
||||
to call back into Python</a>
|
||||
<li>
|
||||
<a href="http://www.python.org/doc/current/ext/parseTuple.html">
|
||||
function argument parsing and typechecking</a>
|
||||
</ul>
|
||||
This last item typically occupies a great deal of code in an extension
|
||||
module. Remember that Python is a completely dynamic language. A callable
|
||||
object receives its arguments in a tuple; it is up to that object to extract
|
||||
those arguments from the tuple, check their types, and raise appropriate
|
||||
exceptions. There are numerous other tedious details that need to be
|
||||
managed; too many to mention here. The Boost Python Library is designed to
|
||||
lift most of that burden.<br>
|
||||
<br>
|
||||
|
||||
<p>
|
||||
Another obstacle that most people run into eventually when extending
|
||||
Python is that there's no way to make a true Python class in an extension
|
||||
module. The typical solution is to create a new Python type in the
|
||||
extension module, and then write an additional module in 100% Python. The
|
||||
Python module defines a Python class which dispatches to an instance of
|
||||
the extension type, which it contains. This allows users to write
|
||||
subclasses of the class in the Python module, almost as though they were
|
||||
sublcassing the extension type. Aside from being tedious, it's not really
|
||||
the same as having a true class, because there's no way for the user to
|
||||
override a method of the extension type which is called from the
|
||||
extension module. Boost.Python solves this problem by taking advantage of <a
|
||||
href="http://www.python.org/doc/essays/metaclasses/">Python's metaclass
|
||||
feature</a> to provide objects which look, walk, and hiss almost exactly
|
||||
like regular Python classes. Boost.Python classes are actually cleaner than
|
||||
Python classes in some subtle ways; a more detailed discussion will
|
||||
follow (someday).</p>
|
||||
<p>Next: <a href="comparisons.html">Comparisons with Other Systems</a> Up: <a
|
||||
href="index.html">Top</a> </p>
|
||||
<p>
|
||||
© Copyright David Abrahams 2000. Permission to copy, use, modify,
|
||||
sell and distribute this document is granted provided this copyright
|
||||
notice appears in all copies. This document is provided "as is" without
|
||||
express or implied warranty, and with no claim as to its suitability for
|
||||
any purpose.</p>
|
||||
|
||||
165
doc/index.html
165
doc/index.html
@@ -1,165 +0,0 @@
|
||||
<!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.0//EN"
|
||||
"http://www.w3.org/TR/REC-html40/strict.dtd">
|
||||
<meta http-equiv="Content-Type" content="text/html; charset=windows-1252">
|
||||
<title>
|
||||
The Boost Python Library (Boost.Python)
|
||||
</title>
|
||||
<h1>
|
||||
<img src="../../../c++boost.gif" alt="c++boost.gif (8819 bytes)" width="277"
|
||||
align="center" height="86"><br>The Boost Python Library (Boost.Python)
|
||||
</h1>
|
||||
|
||||
<h2>Synopsis</h2>
|
||||
<p>
|
||||
Use the Boost Python Library to quickly and easily export a C++ library to <a
|
||||
href="http://www.python.org">Python</a> such that the Python interface is
|
||||
very similar to the C++ interface. It is designed to be minimally
|
||||
intrusive on your C++ design. In most cases, you should not have to alter
|
||||
your C++ classes in any way in order to use them with Boost.Python. The system
|
||||
<em>should</em> simply ``reflect'' your C++ classes and functions into
|
||||
Python. The major features of Boost.Python include support for:
|
||||
<ul>
|
||||
<li><a href="inheritance.html">Subclassing extension types in Python</a>
|
||||
<li><a href="overriding.html">Overriding virtual functions in Python</a>
|
||||
<li><a href="overloading.html">[Member] function Overloading</a>
|
||||
<li><a href="special.html#numeric_auto">Automatic wrapping of numeric operators</a>
|
||||
</ul>
|
||||
among others.
|
||||
|
||||
|
||||
<h2>Supported Platforms</h2>
|
||||
<p>Boost.Python is known to have been tested in the following configurations:
|
||||
|
||||
<ul>
|
||||
<li>Against Python 2.0 using the following compiler/library combinations:
|
||||
<ul>
|
||||
<li><a
|
||||
href="http://msdn.microsoft.com/vstudio/sp/vs6sp4/dnldoverview.asp">MSVC++6sp4</a>
|
||||
with the native library.
|
||||
|
||||
<li>An upcoming release of <a
|
||||
href="http://www.metrowerks.com/products/windows/">Metrowerks
|
||||
CodeWarrior Pro6 for Windows</a> with the native library (the first
|
||||
release has a bug that's fatal to Boost.Python)
|
||||
|
||||
<li><a
|
||||
href="http://developer.intel.com/software/products/compilers/c50/">Intel
|
||||
C++ 5.0</a>. Compilation succeeds, but tests <font
|
||||
color="#FF0000"><b>FAILED at runtime</b></font> due to a bug in its
|
||||
exception-handling implementation.
|
||||
</ul>
|
||||
|
||||
<li>Against Python 1.5.2 using the following compiler/library:
|
||||
|
||||
<ul>
|
||||
<li><a
|
||||
href="http://msdn.microsoft.com/vstudio/sp/vs6sp4/dnldoverview.asp">MSVC++6sp4</a>
|
||||
|
||||
<li><a
|
||||
href="http://msdn.microsoft.com/vstudio/sp/vs6sp4/dnldoverview.asp">MSVC++6sp4</a>/<a
|
||||
href="http://www.stlport.org">STLport 4.0</a>
|
||||
|
||||
<li><a href="http://gcc.gnu.org/">GCC 2.95.2</a> [by <a href="mailto:koethe@informatik.uni-hamburg.de">Ullrich
|
||||
Koethe</a>]
|
||||
|
||||
<li><a href="http://gcc.gnu.org/">GCC 2.95.2</a>/<a href="http://www.stlport.org">STLport 4.0</a>
|
||||
|
||||
<li>Compaq C++ V6.2-024 for Digital UNIX V5.0 Rev. 910 (an <a
|
||||
href="http://www.edg.com/">EDG</a>-based compiler) with <a
|
||||
href="http://www.stlport.org/beta.html">STLport-4.1b3</a> [by <a
|
||||
href="mailto:rwgk@cci.lbl.gov">Ralf W. Grosse-Kunstleve</a>]
|
||||
|
||||
<li>An upcoming release of <a href="http://www.metrowerks.com/products/windows/">Metrowerks CodeWarrior
|
||||
Pro6 for Windows</a> (the first release has a bug that's fatal to Boost.Python)
|
||||
</ul>
|
||||
</ul>
|
||||
|
||||
<h2>Credits</h2>
|
||||
<ul>
|
||||
<li><a href="../../../people/dave_abrahams.htm">David Abrahams</a> originated
|
||||
and wrote most of the library, and continues to coordinate development.
|
||||
|
||||
<li><a href="mailto:koethe@informatik.uni-hamburg.de">Ullrich Koethe</a>
|
||||
had independently developed a similar system. When he discovered Boost.Python,
|
||||
he generously contributed countless hours of coding and much insight into
|
||||
improving it. He is responsible for an early version of the support for <a
|
||||
href="overloading.html">function overloading</a> and wrote the support for
|
||||
<a href="inheritance.html#implicit_conversion">reflecting C++ inheritance
|
||||
relationships</a>. He has helped to improve error-reporting from both
|
||||
Python and C++, and has designed an extremely easy-to-use way of
|
||||
exposing <a href="special.html#numeric">numeric operators</a>, including
|
||||
a way to avoid explicit coercion by means of overloading.
|
||||
|
||||
<li><a href="http://cci.lbl.gov/staff/ralf_grosse-kunstleve.html">Ralf W.
|
||||
Grosse-Kunstleve</a> contributed <a href="pickle.html">pickle support</a>
|
||||
and numerous other small improvements. He's working on a way to allow
|
||||
types exported by multiple modules to interact.
|
||||
|
||||
<li>The members of the boost mailing list and the Python community
|
||||
supplied invaluable early feedback. In particular, Ron Clarke, Mark Evans,
|
||||
Anton Gluck, Chuck Ingold, Prabhu Ramachandran, and Barry Scott took the
|
||||
brave step of trying to use Boost.Python while it was still in early
|
||||
stages of development.
|
||||
|
||||
<li>The development of Boost.Python wouldn't have been possible without
|
||||
the generous support of <a href="http://www.dragonsys.com/">Dragon
|
||||
Systems/Lernout and Hauspie, Inc</a> who supported its development as an
|
||||
open-source project.
|
||||
</ul>
|
||||
|
||||
<h2>Table of Contents</h2>
|
||||
|
||||
<ol>
|
||||
<li><a href="extending.html">A Brief Introduction to writing Python
|
||||
extension modules</a>
|
||||
|
||||
<li><a href="comparisons.html">Comparisons between Boost.Python and other
|
||||
systems for extending Python</a>
|
||||
|
||||
<li><a href="example1.html">A Simple Example</a>
|
||||
|
||||
<li><a href="exporting_classes.html">Exporting Classes</a>
|
||||
|
||||
<li><a href="overriding.html">Overridable Virtual Functions</a>
|
||||
|
||||
<li><a href="overloading.html">Function Overloading</a>
|
||||
|
||||
<li><a href="inheritance.html">Inheritance</a>
|
||||
|
||||
<li><a href="special.html">Special Method and Operator Support</a>
|
||||
|
||||
<li><a href="under-the-hood.html">A Peek Under the Hood</a>
|
||||
|
||||
<li><a href="building.html">Building an Extension Module</a>
|
||||
|
||||
<li><a href="pickle.html">Pickle Support</a>
|
||||
|
||||
<li><a href="enums.html">Wrapping Enums</a>
|
||||
|
||||
<li><a href="pointers.html">Pointers and Smart Pointers</a>
|
||||
|
||||
<li><a href="data_structures.txt">Internal Data Structures</a>
|
||||
|
||||
</ol>
|
||||
|
||||
<p>
|
||||
Documentation is a major ongoing project; assistance is greatly
|
||||
appreciated! In the meantime, useful examples of every Boost.Python feature should
|
||||
be evident in the regression test files <code>test/comprehensive.[<a
|
||||
href="../test/comprehensive.py">py</a>/<a
|
||||
href="../test/comprehensive.hpp">hpp</a>/<a
|
||||
href="../test/comprehensive.cpp">cpp</a>]</code>
|
||||
|
||||
<p>
|
||||
Questions should be directed to <a href=
|
||||
"http://www.egroups.com/list/boost">the boost mailing list</a>.
|
||||
|
||||
<p>
|
||||
© Copyright David Abrahams 2001. Permission to copy, use, modify,
|
||||
sell and distribute this document is granted provided this copyright
|
||||
notice appears in all copies. This document is provided ``as is'' without
|
||||
express or implied warranty, and with no claim as to its suitability for
|
||||
any purpose.
|
||||
<p>
|
||||
Updated: Mar 6, 2001
|
||||
|
||||
@@ -1,173 +0,0 @@
|
||||
<!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.0//EN"
|
||||
"http://www.w3.org/TR/REC-html40/strict.dtd">
|
||||
<title>
|
||||
Inheritance
|
||||
</title>
|
||||
<div>
|
||||
<h1>
|
||||
<img width="277" height="86" id="_x0000_i1025" align="center"
|
||||
src="../../../c++boost.gif" alt= "c++boost.gif (8819 bytes)">Inheritance
|
||||
</h1>
|
||||
|
||||
<h2>Inheritance in Python</h2>
|
||||
|
||||
<p>
|
||||
Boost.Python extension classes support single and multiple-inheritance in
|
||||
Python, just like regular Python classes. You can arbitrarily mix
|
||||
built-in Python classes with extension classes in a derived class'
|
||||
tuple of bases. Whenever a Boost.Python extension class is among the bases for a
|
||||
new class in Python, the result is an extension class:
|
||||
<blockquote>
|
||||
<pre>
|
||||
>>> class MyPythonClass:
|
||||
... def f(): return 'MyPythonClass.f()'
|
||||
...
|
||||
>>> import my_extension_module
|
||||
>>> class Derived(my_extension_module.MyExtensionClass, MyPythonClass):
|
||||
... '''This is an extension class'''
|
||||
... pass
|
||||
...
|
||||
>>> x = Derived()
|
||||
>>> x.f()
|
||||
'MyPythonClass.f()'
|
||||
>>> x.g()
|
||||
'MyExtensionClass.g()'
|
||||
</pre>
|
||||
</blockquote>
|
||||
|
||||
<h2><a name="implicit_conversion">Reflecting C++ Inheritance Relationships</a></h2>
|
||||
<p>
|
||||
Boost.Python also allows us to represent C++ inheritance relationships so that
|
||||
wrapped derived classes may be passed where values, pointers, or
|
||||
references to a base class are expected as arguments. The
|
||||
<code>declare_base</code> member function of
|
||||
<code>class_builder<></code> is used to establish the relationship
|
||||
between base and derived classes:
|
||||
|
||||
<blockquote>
|
||||
<pre>
|
||||
#include <memory> // for std::auto_ptr<>
|
||||
|
||||
struct Base {
|
||||
virtual ~Base() {}
|
||||
virtual const char* name() const { return "Base"; }
|
||||
};
|
||||
|
||||
struct Derived : Base {
|
||||
Derived() : x(-1) {}
|
||||
virtual const char* name() const { return "Derived"; }
|
||||
int x;
|
||||
};
|
||||
|
||||
std::auto_ptr<Base> derived_as_base() {
|
||||
return std::auto_ptr<Base>(new Derived);
|
||||
}
|
||||
|
||||
const char* get_name(const Base& b) {
|
||||
return b.name();
|
||||
}
|
||||
|
||||
int get_derived_x(const Derived& d) {
|
||||
return d.x;
|
||||
}
|
||||
<hr>
|
||||
#include <boost/python/class_builder.hpp>
|
||||
|
||||
// namespace alias for code brevity
|
||||
namespace python = boost::python;
|
||||
|
||||
BOOST_PYTHON_MODULE_INIT(my_module)
|
||||
{
|
||||
try
|
||||
{
|
||||
python::module_builder my_module("my_module");
|
||||
|
||||
python::class_builder<Base> base_class(my_module, "Base");
|
||||
base_class.def(python::constructor<void>());
|
||||
|
||||
python::class_builder<Derived> derived_class(my_module, "Derived");
|
||||
derived_class.def(python::constructor<void>());
|
||||
<b>// Establish the inheritance relationship between Base and Derived
|
||||
derived_class.declare_base(base_class);</b>
|
||||
|
||||
my_module.def(derived_as_base, "derived_as_base");
|
||||
my_module.def(get_name, "get_name");
|
||||
my_module.def(get_derived_x, "get_derived_x");
|
||||
}
|
||||
catch(...)
|
||||
{
|
||||
python::handle_exception(); // Deal with the exception for Python
|
||||
}
|
||||
}
|
||||
</pre>
|
||||
</blockquote>
|
||||
|
||||
<p>
|
||||
Then, in Python:
|
||||
<blockquote>
|
||||
<pre>
|
||||
>>> from my_module import *
|
||||
>>> base = Base()
|
||||
>>> derived = Derived()
|
||||
>>> get_name(base)
|
||||
'Base'
|
||||
</pre>
|
||||
</blockquote>
|
||||
<i>objects of wrapped class Derived may be passed where Base is expected</i>
|
||||
<blockquote>
|
||||
<pre>
|
||||
>>> get_name(derived)
|
||||
'Derived'
|
||||
</pre>
|
||||
</blockquote>
|
||||
<i>objects of wrapped class Derived can be passed where Derived is
|
||||
expected but where type information has been lost.</i>
|
||||
<blockquote>
|
||||
<pre>
|
||||
>>> get_derived_x(derived_as_base())
|
||||
-1
|
||||
</pre>
|
||||
</blockquote>
|
||||
|
||||
<h2>Inheritance Without Virtual Functions</h2>
|
||||
|
||||
<p>
|
||||
If for some reason your base class has no virtual functions but you still want
|
||||
to represent the inheritance relationship between base and derived classes,
|
||||
pass the special symbol <code>boost::python::without_downcast</code> as the 2nd parameter
|
||||
to <code>declare_base</code>:
|
||||
|
||||
<blockquote>
|
||||
<pre>
|
||||
struct Base2 {};
|
||||
struct Derived2 { int f(); };
|
||||
<hr>
|
||||
...
|
||||
python::class_builder<Base> base2_class(my_module, "Base2");
|
||||
base2_class.def(python::constructor<void>());
|
||||
|
||||
python::class_builder<Derived2> derived2_class(my_module, "Derived2");
|
||||
derived2_class.def(python::constructor<void>());
|
||||
derived_class.declare_base(base_class, <b>python::without_downcast</b>);
|
||||
</pre>
|
||||
</blockquote>
|
||||
|
||||
<p>This approach will allow <code>Derived2</code> objects to be passed where
|
||||
<code>Base2</code> is expected, but does not attempt to implicitly convert (downcast)
|
||||
smart-pointers to <code>Base2</code> into <code>Derived2</code> pointers,
|
||||
references, or values.
|
||||
|
||||
<p>
|
||||
Next: <a href="special.html">Special Method and Operator Support</a>
|
||||
Previous: <a href="overloading.html">Function Overloading</a>
|
||||
Up: <a href="index.html">Top</a>
|
||||
<p>
|
||||
© Copyright David Abrahams 2000. Permission to copy, use, modify,
|
||||
sell and distribute this document is granted provided this copyright
|
||||
notice appears in all copies. This document is provided "as is" without
|
||||
express or implied warranty, and with no claim as to its suitability
|
||||
for any purpose.
|
||||
<p>
|
||||
Updated: Nov 26, 2000
|
||||
</div>
|
||||
|
||||
@@ -1,155 +0,0 @@
|
||||
<!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.0//EN"
|
||||
"http://www.w3.org/TR/REC-html40/strict.dtd">
|
||||
<title>
|
||||
Function Overloading
|
||||
</title>
|
||||
<div>
|
||||
<h1>
|
||||
<img width="277" height="86" id="_x0000_i1025" align="center"
|
||||
src="../../../c++boost.gif" alt= "c++boost.gif (8819 bytes)">Function Overloading
|
||||
</h1>
|
||||
|
||||
<h2>An Example</h2>
|
||||
<p>
|
||||
To expose overloaded functions in Python, simply <code>def()</code> each
|
||||
one with the same Python name:
|
||||
<blockquote>
|
||||
<pre>
|
||||
inline int f1() { return 3; }
|
||||
inline int f2(int x) { return x + 1; }
|
||||
|
||||
class X {
|
||||
public:
|
||||
X() : m_value(0) {}
|
||||
X(int n) : m_value(n) {}
|
||||
int value() const { return m_value; }
|
||||
void value(int v) { m_value = v; }
|
||||
private:
|
||||
int m_value;
|
||||
};
|
||||
...
|
||||
|
||||
BOOST_PYTHON_MODULE_INIT(overload_demo)
|
||||
{
|
||||
try
|
||||
{
|
||||
boost::python::module_builder overload_demo("overload_demo");
|
||||
// Overloaded functions at module scope
|
||||
overload_demo.def(f1, "f");
|
||||
overload_demo.def(f2, "f");
|
||||
|
||||
boost::python::class_builder<X> x_class(overload_demo, "X");
|
||||
// Overloaded constructors
|
||||
x_class.def(boost::python::constructor<>());
|
||||
x_class.def(boost::python::constructor<int>());
|
||||
|
||||
// Overloaded member functions
|
||||
x_class.def((int (X::*)() const)&X::value, "value");
|
||||
x_class.def((void (X::*)(int))&X::value, "value");
|
||||
...
|
||||
</pre>
|
||||
</blockquote>
|
||||
|
||||
<p>
|
||||
Now in Python:
|
||||
<blockquote>
|
||||
<pre>
|
||||
>>> from overload_demo import *
|
||||
>>> x0 = X()
|
||||
>>> x1 = X(1)
|
||||
>>> x0.value()
|
||||
0
|
||||
>>> x1.value()
|
||||
1
|
||||
>>> x0.value(3)
|
||||
>>> x0.value()
|
||||
3
|
||||
>>> X('hello')
|
||||
TypeError: No overloaded functions match (X, string). Candidates are:
|
||||
void (*)()
|
||||
void (*)(int)
|
||||
>>> f()
|
||||
3
|
||||
>>> f(4)
|
||||
5
|
||||
</pre>
|
||||
</blockquote>
|
||||
|
||||
<h2>Discussion</h2>
|
||||
<p>
|
||||
Notice that overloading in the Python module was produced three ways:<ol>
|
||||
<li>by combining the non-overloaded C++ functions <code>int f1()</code>
|
||||
and <code>int f2(int)</code> and exposing them as <code>f</code> in Python.
|
||||
<li>by exposing the overloaded constructors of <code>class X</code>
|
||||
<li>by exposing the overloaded member functions <code>X::value</code>.
|
||||
</ol>
|
||||
<p>
|
||||
Techniques 1. and 3. above are really alternatives. In case 3, you need
|
||||
to form a pointer to each of the overloaded functions. The casting
|
||||
syntax shown above is one way to do that in C++. Case 1 does not require
|
||||
complicated-looking casts, but may not be viable if you can't change
|
||||
your C++ interface. N.B. There's really nothing unsafe about casting an
|
||||
overloaded (member) function address this way: the compiler won't let
|
||||
you write it at all unless you get it right.
|
||||
|
||||
<h2>An Alternative to Casting</h2>
|
||||
<p>
|
||||
This approach is not neccessarily better, but may be preferable for some
|
||||
people who have trouble writing out the types of (member) function
|
||||
pointers or simply prefer to avoid all casts as a matter of principle:
|
||||
<blockquote>
|
||||
<pre>
|
||||
// Forwarding functions for X::value
|
||||
inline void set_x_value(X& self, int v) { self.value(v); }
|
||||
inline int get_x_value(X& self) { return self.value(); }
|
||||
...
|
||||
// Overloaded member functions
|
||||
x_class.def(set_x_value, "value");
|
||||
x_class.def(get_x_value, "value");
|
||||
</pre>
|
||||
</blockquote>
|
||||
<p>Here we are taking advantage of the ability to expose C++ functions at
|
||||
namespace scope as Python member functions.
|
||||
|
||||
<h2>Overload Resolution</h2>
|
||||
<p>
|
||||
The function overload resolution mechanism works as follows:
|
||||
|
||||
<ul>
|
||||
|
||||
<li>Attribute lookup for extension classes proceeds in <a
|
||||
href="http://www.python.org/doc/current/tut/node11.html#SECTION0011510000000000000000">the
|
||||
usual Python way</a> using a depth-first, left-to-right search. When a
|
||||
class is found which has a matching attribute, only functions overloaded
|
||||
in the context of that class are candidates for overload resolution. In
|
||||
this sense, overload resolution mirrors the C++ mechanism, where a name
|
||||
in a derived class ``hides'' all functions with the same name from a base
|
||||
class.
|
||||
<p>
|
||||
|
||||
<li>Within a name-space context (extension class or module), overloaded
|
||||
functions are tried in the same order they were
|
||||
<code>def()</code>ed. The first function whose signature can be made to
|
||||
match each argument passed is the one which is ultimately called.
|
||||
This means in particular that you cannot overload the same function on
|
||||
both ``<code>int</code>'' and ``<code>float</code>'' because Python
|
||||
automatically converts either of the two types into the other one.
|
||||
If the ``<code>float</code>'' overload is found first, it is used
|
||||
also used for arguments of type ``<code>int</code>'' as well, and the
|
||||
``<code>int</code>'' version of the function is never invoked.
|
||||
</ul>
|
||||
|
||||
<p>
|
||||
Next: <a href="inheritance.html">Inheritance</a>
|
||||
Previous: <a href="overriding.html">Overridable Virtual Functions</a>
|
||||
Up: <a href="index.html">Top</a>
|
||||
<p>
|
||||
© Copyright David Abrahams 2001. Permission to copy, use, modify,
|
||||
sell and distribute this document is granted provided this copyright
|
||||
notice appears in all copies. This document is provided ``as
|
||||
is'' without express or implied warranty, and with no claim as to
|
||||
its suitability for any purpose.
|
||||
<p>
|
||||
Updated: Mar 6, 2001
|
||||
</div>
|
||||
|
||||
@@ -1,215 +0,0 @@
|
||||
<!DOCTYPE html PUBLIC "-//W3C//DTD HTML 3.2//EN">
|
||||
<meta http-equiv="Content-Type" content="text/html; charset=windows-1252">
|
||||
|
||||
<title>Overridable Virtual Functions</title>
|
||||
|
||||
<img src="../../../c++boost.gif" alt="c++boost.gif (8819 bytes)" align="center"
|
||||
width="277" height="86">
|
||||
|
||||
<h1>Overridable Virtual Functions</h1>
|
||||
|
||||
<p>
|
||||
In the <a href="exporting_classes.html">previous example</a> we exposed a simple
|
||||
C++ class in Python and showed that we could write a subclass. We even
|
||||
redefined one of the functions in our derived class. Now we will learn
|
||||
how to make the function behave virtually <em>when called from C++</em>.
|
||||
|
||||
|
||||
<h2><a name="overriding_example">Example</a></h2>
|
||||
|
||||
<p>In this example, it is assumed that <code>hello::greet()</code> is a virtual
|
||||
member function:
|
||||
|
||||
<blockquote><pre>
|
||||
class hello
|
||||
{
|
||||
public:
|
||||
hello(const std::string& country) { this->country = country; }
|
||||
<b>virtual</b> std::string greet() const { return "Hello from " + country; }
|
||||
virtual ~hello(); // Good practice
|
||||
...
|
||||
};
|
||||
</pre></blockquote>
|
||||
|
||||
<p>
|
||||
We'll need a derived class<a href="#why_derived">*</a> to help us
|
||||
dispatch the call to Python. In our derived class, we need the following
|
||||
elements:
|
||||
|
||||
<ol>
|
||||
|
||||
<li><a name="derived_1">A</a> <code>PyObject*</code> data member (usually
|
||||
called <tt>self</tt>) that holds a pointer to the Python object corresponding
|
||||
to our C++ <tt>hello</tt> instance.
|
||||
|
||||
<li><a name="derived_2">For</a> each exposed constructor of the
|
||||
base class <tt>T</tt>, a constructor which takes the same parameters preceded by an initial
|
||||
<code>PyObject*</code> argument. The initial argument should be stored in the <tt>self</tt> data
|
||||
member described above.
|
||||
|
||||
<li>If the class being wrapped is ever returned <i>by
|
||||
value</i> from a wrapped function, be sure you do the same for the
|
||||
<tt>T</tt>'s copy constructor: you'll need a constructor taking arguments
|
||||
<tt>(PyObject*, const T&)</tt>.
|
||||
|
||||
<li><a name="derived_3">An</a> implementation of each virtual function you may
|
||||
wish to override in Python which uses
|
||||
<tt>callback<</tt><i>return-type</i><tt>>::call_method(self, "</tt><i>name</i><tt>", </tt><i>args...</i><tt>)</tt> to call
|
||||
the Python override.
|
||||
|
||||
<li><a name="derived_4">For</a> each non-pure virtual function meant to be
|
||||
overridable from Python, a static member function (or a free function) taking
|
||||
a reference or pointer to the <tt>T</tt> as the first parameter and which
|
||||
forwards any additional parameters neccessary to the <i>default</i>
|
||||
implementation of the virtual function. See also <a href="#private">this
|
||||
note</a> if the base class virtual function is private.
|
||||
|
||||
</ol>
|
||||
|
||||
<blockquote><pre>
|
||||
struct hello_callback : hello
|
||||
{
|
||||
// hello constructor storing initial self_ parameter
|
||||
hello_callback(PyObject* self_, const std::string& x) // <a href="#derived_2">2</a>
|
||||
: hello(x), self(self_) {}
|
||||
|
||||
// In case hello is returned by-value from a wrapped function
|
||||
hello_callback(PyObject* self_, const hello& x) // <a href="#derived_3">3</a>
|
||||
: hello(x), self(self_) {}
|
||||
|
||||
// Override greet to call back into Python
|
||||
std::string greet() const // <a href="#derived_4">4</a>
|
||||
{ return boost::python::callback<std::string>::call_method(self, "greet"); }
|
||||
|
||||
// Supplies the default implementation of greet
|
||||
static std::string <a name= "default_implementation">default_greet</a>(const hello& self_) const // <a href="#derived_5">5</a>
|
||||
{ return self_.hello::greet(); }
|
||||
private:
|
||||
PyObject* self; // <a href="#derived_1">1</a>
|
||||
};
|
||||
</pre></blockquote>
|
||||
|
||||
<p>
|
||||
Finally, we add <tt>hello_callback</tt> to the <tt>
|
||||
class_builder<></tt> declaration in our module initialization
|
||||
function, and when we define the function, we must tell Boost.Python about the default
|
||||
implementation:
|
||||
|
||||
<blockquote><pre>
|
||||
// Create the <a name=
|
||||
"hello_class">Python type object</a> for our extension class
|
||||
boost::python::class_builder<hello<strong>,hello_callback></strong> hello_class(hello, "hello");
|
||||
// Add a virtual member function
|
||||
hello_class.def(&hello::greet, "greet", &<b>hello_callback::default_greet</b>);
|
||||
</pre></blockquote>
|
||||
|
||||
<p>
|
||||
Now our Python subclass of <tt>hello</tt> behaves as expected:
|
||||
|
||||
<blockquote><pre>
|
||||
>>> class wordy(hello):
|
||||
... def greet(self):
|
||||
... return hello.greet(self) + ', where the weather is fine'
|
||||
...
|
||||
>>> hi2 = wordy('Florida')
|
||||
>>> hi2.greet()
|
||||
'Hello from Florida, where the weather is fine'
|
||||
>>> invite(hi2)
|
||||
'Hello from Florida, where the weather is fine! Please come soon!'
|
||||
</pre></blockquote>
|
||||
<p>
|
||||
<a name="why_derived">*</a>You may ask, "Why do we need this derived
|
||||
class? This could have been designed so that everything gets done right
|
||||
inside of <tt>hello</tt>." 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.
|
||||
|
||||
<h2>Pure Virtual Functions</h2>
|
||||
|
||||
<p>
|
||||
A pure virtual function with no implementation is actually a lot easier to
|
||||
deal with than a virtual function with a default implementation. First of
|
||||
all, you obviously don't need to <a href="#default_implementation"> supply
|
||||
a default implementation</a>. Secondly, you don't need to call
|
||||
<tt>def()</tt> on the <tt>extension_class<></tt> instance
|
||||
for the virtual function. In fact, you wouldn't <em>want</em> to: if the
|
||||
corresponding attribute on the Python class stays undefined, you'll get an
|
||||
<tt>AttributeError</tt> in Python when you try to call the function,
|
||||
indicating that it should have been implemented. For example:
|
||||
<blockquote>
|
||||
<pre>
|
||||
struct baz {
|
||||
<strong>virtual</strong> int pure(int) = 0;
|
||||
int calls_pure(int x) { return pure(x) + 1000; }
|
||||
};
|
||||
|
||||
struct baz_callback {
|
||||
int pure(int x) { boost::python::callback<int>::call_method(m_self, "pure", x); }
|
||||
};
|
||||
|
||||
BOOST_PYTHON_MODULE_INIT(foobar)
|
||||
{
|
||||
try
|
||||
{
|
||||
boost::python::module_builder foobar("foobar");
|
||||
boost::python::class_builder<baz,baz_callback> baz_class("baz");
|
||||
baz_class.def(&baz::calls_pure, "calls_pure");
|
||||
}
|
||||
catch(...)
|
||||
{
|
||||
boost::python::handle_exception(); // Deal with the exception for Python
|
||||
}
|
||||
}
|
||||
</pre>
|
||||
</blockquote>
|
||||
<p>
|
||||
Now in Python:
|
||||
<blockquote>
|
||||
<pre>
|
||||
>>> from foobar import baz
|
||||
>>> x = baz()
|
||||
>>> x.pure(1)
|
||||
Traceback (innermost last):
|
||||
File "<stdin>", line 1, in ?
|
||||
AttributeError: pure
|
||||
>>> x.calls_pure(1)
|
||||
Traceback (innermost last):
|
||||
File "<stdin>", line 1, in ?
|
||||
AttributeError: pure
|
||||
>>> class mumble(baz):
|
||||
... def pure(self, x): return x + 1
|
||||
...
|
||||
>>> y = mumble()
|
||||
>>> y.pure(99)
|
||||
100
|
||||
>>> y.calls_pure(99)
|
||||
1100
|
||||
</pre></blockquote>
|
||||
|
||||
<a name="private"><h2>Private Non-Pure Virtual Functions</h2></a>
|
||||
|
||||
<p>This is one area where some minor intrusiveness on the wrapped library is
|
||||
required. Once it has been overridden, the only way to call the base class
|
||||
implementation of a private virtual function is to make the derived class a
|
||||
friend of the base class. You didn't hear it from me, but most C++
|
||||
implementations will allow you to change the declaration of the base class in
|
||||
this limited way without breaking binary compatibility (though it will certainly
|
||||
break the <a
|
||||
href="http://cs.calvin.edu/c++/C++Standard-Nov97/basic.html#basic.def.odr">ODR</a>).
|
||||
|
||||
<hr>
|
||||
<p>
|
||||
Next: <a href="overloading.html">Function Overloading</a>
|
||||
Previous: <a href="exporting_classes.html">Exporting Classes</a>
|
||||
Up: <a href="index.html">Top</a>
|
||||
<p>
|
||||
© Copyright David Abrahams 2001. Permission to copy, use, modify,
|
||||
sell and distribute this document is granted provided this copyright
|
||||
notice appears in all copies. This document is provided "as is" without
|
||||
express or implied warranty, and with no claim as to its suitability for
|
||||
any purpose.
|
||||
<p>
|
||||
Updated: Mar 6, 2001
|
||||
|
||||
245
doc/pickle.html
245
doc/pickle.html
@@ -1,245 +0,0 @@
|
||||
<!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.0//EN"
|
||||
"http://www.w3.org/TR/REC-html40/strict.dtd">
|
||||
|
||||
<title>Boost.Python Pickle Support</title>
|
||||
|
||||
<div>
|
||||
|
||||
<img src="../../../c++boost.gif"
|
||||
alt="c++boost.gif (8819 bytes)"
|
||||
align="center"
|
||||
width="277" height="86">
|
||||
|
||||
<hr>
|
||||
<h1>Boost.Python Pickle Support</h1>
|
||||
|
||||
Pickle is a Python module for object serialization, also known
|
||||
as persistence, marshalling, or flattening.
|
||||
|
||||
<p>
|
||||
It is often necessary to save and restore the contents of an object to
|
||||
a file. One approach to this problem is to write a pair of functions
|
||||
that read and write data from a file in a special format. A powerful
|
||||
alternative approach is to use Python's pickle module. Exploiting
|
||||
Python's ability for introspection, the pickle module recursively
|
||||
converts nearly arbitrary Python objects into a stream of bytes that
|
||||
can be written to a file.
|
||||
|
||||
<p>
|
||||
The Boost Python Library supports the pickle module by emulating the
|
||||
interface implemented by Jim Fulton's ExtensionClass module that is
|
||||
included in the
|
||||
<a href="http://www.zope.org/"
|
||||
>ZOPE</a>
|
||||
distribution.
|
||||
This interface is similar to that for regular Python classes as
|
||||
described in detail in the
|
||||
<a href="http://www.python.org/doc/current/lib/module-pickle.html"
|
||||
>Python Library Reference for pickle.</a>
|
||||
|
||||
<hr>
|
||||
<h2>The Boost.Python Pickle Interface</h2>
|
||||
|
||||
At the user level, the Boost.Python pickle interface involves three special
|
||||
methods:
|
||||
|
||||
<dl>
|
||||
<dt>
|
||||
<strong><tt>__getinitargs__</tt></strong>
|
||||
<dd>
|
||||
When an instance of a Boost.Python extension class is pickled, the
|
||||
pickler tests if the instance has a <tt>__getinitargs__</tt> method.
|
||||
This method must return a Python tuple (it is most convenient to use
|
||||
a boost::python::tuple). When the instance is restored by the
|
||||
unpickler, the contents of this tuple are used as the arguments for
|
||||
the class constructor.
|
||||
|
||||
<p>
|
||||
If <tt>__getinitargs__</tt> is not defined, the class constructor
|
||||
will be called without arguments.
|
||||
|
||||
<p>
|
||||
<dt>
|
||||
<strong><tt>__getstate__</tt></strong>
|
||||
|
||||
<dd>
|
||||
When an instance of a Boost.Python extension class is pickled, the
|
||||
pickler tests if the instance has a <tt>__getstate__</tt> method.
|
||||
This method should return a Python object representing the state of
|
||||
the instance.
|
||||
|
||||
<p>
|
||||
If <tt>__getstate__</tt> is not defined, the instance's
|
||||
<tt>__dict__</tt> is pickled (if it is not empty).
|
||||
|
||||
<p>
|
||||
<dt>
|
||||
<strong><tt>__setstate__</tt></strong>
|
||||
|
||||
<dd>
|
||||
When an instance of a Boost.Python extension class is restored by the
|
||||
unpickler, it is first constructed using the result of
|
||||
<tt>__getinitargs__</tt> as arguments (see above). Subsequently the
|
||||
unpickler tests if the new instance has a <tt>__setstate__</tt>
|
||||
method. If so, this method is called with the result of
|
||||
<tt>__getstate__</tt> (a Python object) as the argument.
|
||||
|
||||
<p>
|
||||
If <tt>__setstate__</tt> is not defined, the result of
|
||||
<tt>__getstate__</tt> must be a Python dictionary. The items of this
|
||||
dictionary are added to the instance's <tt>__dict__</tt>.
|
||||
|
||||
</dl>
|
||||
|
||||
If both <tt>__getstate__</tt> and <tt>__setstate__</tt> are defined,
|
||||
the Python object returned by <tt>__getstate__</tt> need not be a
|
||||
dictionary. The <tt>__getstate__</tt> and <tt>__setstate__</tt> methods
|
||||
can do what they want.
|
||||
|
||||
<hr>
|
||||
<h2>Pitfalls and Safety Guards</h2>
|
||||
|
||||
In Boost.Python extension modules with many extension classes,
|
||||
providing complete pickle support for all classes would be a
|
||||
significant overhead. In general complete pickle support should only be
|
||||
implemented for extension classes that will eventually be pickled.
|
||||
However, the author of a Boost.Python extension module might not
|
||||
anticipate correctly which classes need support for pickle.
|
||||
Unfortunately, the pickle protocol described above has two important
|
||||
pitfalls that the end user of a Boost.Python extension module might not
|
||||
be aware of:
|
||||
|
||||
<dl>
|
||||
<dt>
|
||||
<strong>Pitfall 1:</strong>
|
||||
Both <tt>__getinitargs__</tt> and <tt>__getstate__</tt> are not defined.
|
||||
|
||||
<dd>
|
||||
In this situation the unpickler calls the class constructor without
|
||||
arguments and then adds the <tt>__dict__</tt> that was pickled by
|
||||
default to that of the new instance.
|
||||
|
||||
<p>
|
||||
However, most C++ classes wrapped with Boost.Python will have member
|
||||
data that are not restored correctly by this procedure. To alert the
|
||||
user to this problem, a safety guard is provided. If both
|
||||
<tt>__getinitargs__</tt> and <tt>__getstate__</tt> are not defined,
|
||||
Boost.Python tests if the class has an attribute
|
||||
<tt>__dict_defines_state__</tt>. An exception is raised if this
|
||||
attribute is not defined:
|
||||
|
||||
<pre>
|
||||
RuntimeError: Incomplete pickle support (__dict_defines_state__ not set)
|
||||
</pre>
|
||||
|
||||
In the rare cases where this is not the desired behavior, the safety
|
||||
guard can deliberately be disabled. The corresponding C++ code for
|
||||
this is, e.g.:
|
||||
|
||||
<pre>
|
||||
class_builder<your_class> py_your_class(your_module, "your_class");
|
||||
py_your_class.dict_defines_state();
|
||||
</pre>
|
||||
|
||||
It is also possible to override the safety guard at the Python level.
|
||||
E.g.:
|
||||
|
||||
<pre>
|
||||
import your_bpl_module
|
||||
class your_class(your_bpl_module.your_class):
|
||||
__dict_defines_state__ = 1
|
||||
</pre>
|
||||
|
||||
<p>
|
||||
<dt>
|
||||
<strong>Pitfall 2:</strong>
|
||||
<tt>__getstate__</tt> is defined and the instance's <tt>__dict__</tt> is not empty.
|
||||
|
||||
<dd>
|
||||
The author of a Boost.Python extension class might provide a
|
||||
<tt>__getstate__</tt> method without considering the possibilities
|
||||
that:
|
||||
|
||||
<p>
|
||||
<ul>
|
||||
<li>
|
||||
his class is used in Python as a base class. Most likely the
|
||||
<tt>__dict__</tt> of instances of the derived class needs to be
|
||||
pickled in order to restore the instances correctly.
|
||||
|
||||
<p>
|
||||
<li>
|
||||
the user adds items to the instance's <tt>__dict__</tt> directly.
|
||||
Again, the <tt>__dict__</tt> of the instance then needs to be
|
||||
pickled.
|
||||
|
||||
</ul>
|
||||
<p>
|
||||
|
||||
To alert the user to this highly unobvious problem, a safety guard is
|
||||
provided. If <tt>__getstate__</tt> is defined and the instance's
|
||||
<tt>__dict__</tt> is not empty, Boost.Python tests if the class has
|
||||
an attribute <tt>__getstate_manages_dict__</tt>. An exception is
|
||||
raised if this attribute is not defined:
|
||||
|
||||
<pre>
|
||||
RuntimeError: Incomplete pickle support (__getstate_manages_dict__ not set)
|
||||
</pre>
|
||||
|
||||
To resolve this problem, it should first be established that the
|
||||
<tt>__getstate__</tt> and <tt>__setstate__</tt> methods manage the
|
||||
instances's <tt>__dict__</tt> correctly. Note that this can be done
|
||||
both at the C++ and the Python level. Finally, the safety guard
|
||||
should intentionally be overridden. E.g. in C++:
|
||||
|
||||
<pre>
|
||||
class_builder<your_class> py_your_class(your_module, "your_class");
|
||||
py_your_class.getstate_manages_dict();
|
||||
</pre>
|
||||
|
||||
In Python:
|
||||
|
||||
<pre>
|
||||
import your_bpl_module
|
||||
class your_class(your_bpl_module.your_class):
|
||||
__getstate_manages_dict__ = 1
|
||||
def __getstate__(self):
|
||||
# your code here
|
||||
def __setstate__(self, state):
|
||||
# your code here
|
||||
</pre>
|
||||
</dl>
|
||||
|
||||
<hr>
|
||||
<h2>Practical Advice</h2>
|
||||
|
||||
<ul>
|
||||
<li>
|
||||
Avoid using <tt>__getstate__</tt> if the instance can also be
|
||||
reconstructed by way of <tt>__getinitargs__</tt>. This automatically
|
||||
avoids Pitfall 2.
|
||||
|
||||
<p>
|
||||
<li>
|
||||
If <tt>__getstate__</tt> is required, include the instance's
|
||||
<tt>__dict__</tt> in the Python object that is returned.
|
||||
|
||||
</ul>
|
||||
|
||||
<hr>
|
||||
<h2>Example</h2>
|
||||
|
||||
An example that shows how to configure pickle support is available in the
|
||||
<tt>boost/lib/python/example</tt> directory
|
||||
(<tt>getting_started3.cpp</tt>).
|
||||
|
||||
<hr>
|
||||
© Copyright Ralf W. Grosse-Kunstleve 2001. Permission to copy,
|
||||
use, modify, sell and distribute this document is granted provided this
|
||||
copyright notice appears in all copies. This document is provided "as
|
||||
is" without express or implied warranty, and with no claim as to its
|
||||
suitability for any purpose.
|
||||
|
||||
<p>
|
||||
Updated: March 10, 2001
|
||||
</div>
|
||||
@@ -1,148 +0,0 @@
|
||||
<!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.0//EN"
|
||||
"http://www.w3.org/TR/REC-html40/strict.dtd">
|
||||
<title>
|
||||
Pointers
|
||||
</title>
|
||||
<div>
|
||||
<h1>
|
||||
<img width="277" height="86" id="_x0000_i1025" align="center"
|
||||
src="../../../c++boost.gif" alt= "c++boost.gif (8819 bytes)">Pointers
|
||||
</h1>
|
||||
|
||||
<h2><a name="problem">The Problem With Pointers</a></h2>
|
||||
|
||||
<p>
|
||||
In general, raw pointers passed to or returned from functions are problematic
|
||||
for Boost.Python because pointers have too many potential meanings. Is it an iterator?
|
||||
A pointer to a single element? An array? When used as a return value, is the
|
||||
caller expected to manage (delete) the pointed-to object or is the pointer
|
||||
really just a reference? If the latter, what happens to Python references to the
|
||||
referent when some C++ code deletes it?
|
||||
<p>
|
||||
There are a few cases in which pointers are converted automatically:
|
||||
<ul>
|
||||
|
||||
<li>Both const- and non-const pointers to wrapped class instances can be passed
|
||||
<i>to</i> C++ functions.
|
||||
|
||||
<li>Values of type <code>const char*</code> are interpreted as
|
||||
null-terminated 'C' strings and when passed to or returned from C++ functions are
|
||||
converted from/to Python strings.
|
||||
|
||||
</ul>
|
||||
|
||||
<h3>Can you avoid the problem?</h3>
|
||||
|
||||
<p>My first piece of advice to anyone with a case not covered above is
|
||||
``find a way to avoid the problem.'' For example, if you have just one
|
||||
or two functions that return a pointer to an individual <code>const
|
||||
T</code>, and <code>T</code> is a wrapped class, you may be able to write a ``thin
|
||||
converting wrapper'' over those two functions as follows:
|
||||
|
||||
<blockquote><pre>
|
||||
const Foo* f(); // original function
|
||||
const Foo& f_wrapper() { return *f(); }
|
||||
...
|
||||
my_module.def(f_wrapper, "f");
|
||||
</pre></blockquote>
|
||||
<p>
|
||||
Foo must have a public copy constructor for this technique to work, since Boost.Python
|
||||
converts <code>const T&</code> values <code>to_python</code> by copying the <code>T</code>
|
||||
value into a new extension instance.
|
||||
|
||||
<h2>Dealing with the problem</h2>
|
||||
|
||||
<p>The first step in handling the remaining cases is to figure out what the pointer
|
||||
means. Several potential solutions are provided in the examples that follow:
|
||||
|
||||
<h3>Returning a pointer to a wrapped type</h3>
|
||||
|
||||
<h4>Returning a const pointer</h4>
|
||||
|
||||
<p>If you have lots of functions returning a <code>const T*</code> for some
|
||||
wrapped <code>T</code>, you may want to provide an automatic
|
||||
<code>to_python</code> conversion function so you don't have to write lots of
|
||||
thin wrappers. You can do this simply as follows:
|
||||
|
||||
<blockquote><pre>
|
||||
BOOST_PYTHON_BEGIN_CONVERSION_NAMESPACE // this is a gcc 2.95.2 bug workaround
|
||||
PyObject* to_python(const Foo* p) {
|
||||
return to_python(*p); // convert const Foo* in terms of const Foo&
|
||||
}
|
||||
BOOST_PYTHON_END_CONVERSION_NAMESPACE
|
||||
</pre></blockquote>
|
||||
|
||||
<h4>If you can't (afford to) copy the referent, or the pointer is non-const</h4>
|
||||
|
||||
<p>If the wrapped type doesn't have a public copy constructor, if copying is
|
||||
<i>extremely</i> costly (remember, we're dealing with Python here), or if the
|
||||
pointer is non-const and you really need to be able to modify the referent from
|
||||
Python, you can use the following dangerous trick. Why dangerous? Because python
|
||||
can not control the lifetime of the referent, so it may be destroyed by your C++
|
||||
code before the last Python reference to it disappears:
|
||||
|
||||
<blockquote><pre>
|
||||
BOOST_PYTHON_BEGIN_CONVERSION_NAMESPACE // this is a gcc 2.95.2 bug workaround
|
||||
PyObject* to_python(Foo* p)
|
||||
{
|
||||
return boost::python::python_extension_class_converters<Foo>::ptr_to_python(p);
|
||||
}
|
||||
|
||||
PyObject* to_python(const Foo* p)
|
||||
{
|
||||
return to_python(const_cast<Foo*>(p));
|
||||
}
|
||||
BOOST_PYTHON_END_CONVERSION_NAMESPACE
|
||||
</pre></blockquote>
|
||||
|
||||
This will cause the Foo* to be treated as though it were an owning smart
|
||||
pointer, even though it's not. Be sure you don't use the reference for anything
|
||||
from Python once the pointer becomes invalid, though. Don't worry too much about
|
||||
the <code>const_cast<></code> above: Const-correctness is completely lost
|
||||
to Python anyway!
|
||||
|
||||
<h3>[In/]Out Parameters and Immutable Types</h3>
|
||||
|
||||
<p>If you have an interface that uses non-const pointers (or references) as
|
||||
in/out parameters to types which in Python are immutable (e.g. int, string),
|
||||
there simply is <i>no way</i> to get the same interface in Python. You must
|
||||
resort to transforming your interface with simple thin wrappers as shown below:
|
||||
<blockquote><pre>
|
||||
const void f(int* in_out_x); // original function
|
||||
const int f_wrapper(int in_x) { f(in_x); return in_x; }
|
||||
...
|
||||
my_module.def(f_wrapper, "f");
|
||||
</pre></blockquote>
|
||||
|
||||
<p>Of course, [in/]out parameters commonly occur only when there is already a
|
||||
return value. You can handle this case by returning a Python tuple:
|
||||
<blockquote><pre>
|
||||
typedef unsigned ErrorCode;
|
||||
const char* f(int* in_out_x); // original function
|
||||
...
|
||||
#include <boost/python/objects.hpp>
|
||||
const boost::python::tuple f_wrapper(int in_x) {
|
||||
const char* s = f(in_x);
|
||||
return boost::python::tuple(s, in_x);
|
||||
}
|
||||
...
|
||||
my_module.def(f_wrapper, "f");
|
||||
</pre></blockquote>
|
||||
<p>Now, in Python:
|
||||
<blockquote><pre>
|
||||
>>> str,out_x = f(3)
|
||||
</pre></blockquote>
|
||||
|
||||
<p>
|
||||
Previous: <a href="enums.html">Enums</a>
|
||||
Up: <a href="index.html">Top</a>
|
||||
<p>
|
||||
© Copyright David Abrahams 2000. Permission to copy, use, modify,
|
||||
sell and distribute this document is granted provided this copyright
|
||||
notice appears in all copies. This document is provided "as is" without
|
||||
express or implied warranty, and with no claim as to its suitability
|
||||
for any purpose.
|
||||
<p>
|
||||
Updated: Nov 26, 2000
|
||||
</div>
|
||||
|
||||
905
doc/special.html
905
doc/special.html
@@ -1,905 +0,0 @@
|
||||
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0 Transitional//EN">
|
||||
<title>
|
||||
Special Method and Operator Support
|
||||
</title>
|
||||
<div>
|
||||
<h1>
|
||||
<img width="277" height="86" id="_x0000_i1025" align="middle" src=
|
||||
"../../../c++boost.gif" alt="c++boost.gif (8819 bytes)">Special Method and
|
||||
Operator Support
|
||||
</h1>
|
||||
<h2>
|
||||
Overview
|
||||
</h2>
|
||||
<p>
|
||||
Boost.Python supports all of the standard <a href=
|
||||
"http://www.python.org/doc/current/ref/specialnames.html">
|
||||
special method names</a> supported by real Python class instances <em>
|
||||
except</em> <code>__complex__</code> (more on the reasons <a href=
|
||||
"#reasons">below</a>). In addition, it can quickly and easily expose
|
||||
suitable C++ functions and operators as Python operators. The following
|
||||
categories of special method names are supported:
|
||||
<ul>
|
||||
<li><a href="#general">Basic Customization</a>
|
||||
<li><a href="#numeric">Numeric Operators</a>
|
||||
<li><a href="#sequence_and_mapping">Sequence and Mapping protocols</a>
|
||||
<li><a href="#getter_setter">Attribute Getters and Setters</a>
|
||||
</ul>
|
||||
|
||||
<h2><a name="general">Basic Customization</a></h2>
|
||||
|
||||
|
||||
<p>
|
||||
Python provides a number of special operators for basic customization of a
|
||||
class. Only a brief description is provided below; more complete
|
||||
documentation can be found <a
|
||||
href="http://www.python.org/doc/current/ref/customization.html">here</a>.
|
||||
|
||||
<dl>
|
||||
<dt>
|
||||
<b><tt class='method'>__init__</tt></b>(<i>self</i>)
|
||||
<dd>
|
||||
Initialize the class instance. For extension classes not subclassed in
|
||||
Python, <code> __init__</code> is defined by
|
||||
|
||||
<pre> my_class.def(boost::python::constructor<...>())</pre>
|
||||
|
||||
(see section <a href="example1.html">"A Simple Example Using Boost.Python"</a>).<p>
|
||||
<dt>
|
||||
<b><tt class='method'>__del__</tt></b>(<i>self</i>)
|
||||
<dd>
|
||||
Called when the extension instance is about to be destroyed. For extension classes
|
||||
not subclassed in Python, <code> __del__</code> is always defined automatically by
|
||||
means of the class' destructor.
|
||||
<dt>
|
||||
<b><tt class='method'>__repr__</tt></b>(<i>self</i>)
|
||||
<dd>
|
||||
Create a string representation from which the object can be
|
||||
reconstructed.
|
||||
<dt>
|
||||
<b><tt class='method'>__str__</tt></b>(<i>self</i>)
|
||||
<dd>
|
||||
Create a string representation which is suitable for printing.
|
||||
<dt>
|
||||
<b><tt class='method'>__cmp__</tt></b>(<i>self, other</i>)
|
||||
<dd>
|
||||
Three-way compare function, used to implement comparison operators
|
||||
(< etc.) Should return a negative integer if <code> self < other
|
||||
</code> , zero if <code> self == other </code> , a positive integer if
|
||||
<code> self > other </code>.
|
||||
<dt>
|
||||
<b><tt class='method'>__hash__</tt></b>(<i>self</i>)
|
||||
<dd>
|
||||
Called for the key object for dictionary operations, and by the
|
||||
built-in function hash(). Should return a 32-bit integer usable as a
|
||||
hash value for dictionary operations (only allowed if __cmp__ is also
|
||||
defined)
|
||||
<dt>
|
||||
<b><tt class='method'>__nonzero__</tt></b>(<i>self</i>)
|
||||
<dd>
|
||||
called if the object is used as a truth value (e.g. in an if
|
||||
statement)
|
||||
<dt>
|
||||
<b><tt class='method'>__call__</tt></b> (<var>self</var><big>[</big><var>, args...</var><big>]</big>)
|
||||
<dd>
|
||||
Called when the instance is ``called'' as a function; if this method
|
||||
is defined, <code><var>x</var>(arg1, arg2, ...)</code> is a shorthand for
|
||||
<code><var>x</var>.__call__(arg1, arg2, ...)</code>.
|
||||
</dl>
|
||||
|
||||
If we have a suitable C++ function that supports any of these features,
|
||||
we can export it like any other function, using its Python special name.
|
||||
For example, suppose that class <code>Foo</code> provides a string
|
||||
conversion function:
|
||||
<blockquote><pre>
|
||||
std::string to_string(Foo const& f)
|
||||
{
|
||||
std::ostringstream s;
|
||||
s << f;
|
||||
return s.str();
|
||||
}
|
||||
</pre></blockquote>
|
||||
This function would be wrapped like this:
|
||||
<blockquote><pre>
|
||||
boost::python::class_builder<Foo> foo_class(my_module, "Foo");
|
||||
foo_class.def(&to_string, "__str__");
|
||||
</pre></blockquote>
|
||||
Note that Boost.Python also supports <em>automatic wrapping</em> of
|
||||
<code>__str__</code> and <code>__cmp__</code>. This is explained in the <a
|
||||
href="#numeric">next section</a> and the <a href="#numeric_table">Table of
|
||||
Automatically Wrapped Methods</a>.
|
||||
|
||||
<h2><a name="numeric">Numeric Operators</a></h2>
|
||||
|
||||
<p>
|
||||
Numeric operators can be exposed manually, by <code>def</code>ing C++
|
||||
[member] functions that support the standard Python <a
|
||||
href="http://www.python.org/doc/current/ref/numeric-types.html">numeric
|
||||
protocols</a>. This is the same basic technique used to expose
|
||||
<code>to_string()</code> as <code>__str__()</code> above, and is <a
|
||||
href="#numeric_manual">covered in detail below</a>. Boost.Python also supports
|
||||
<i>automatic wrapping</i> of numeric operators whenever they have already
|
||||
been defined in C++.
|
||||
|
||||
<h3><a name="numeric_auto">Exposing C++ Operators Automatically</a></h3>
|
||||
|
||||
<p>
|
||||
Supose we wanted to expose a C++ class
|
||||
<code>BigNum</code> which supports addition. That is, in C++ we can write:
|
||||
<blockquote><pre>
|
||||
BigNum a, b, c;
|
||||
...
|
||||
c = a + b;
|
||||
</pre></blockquote>
|
||||
<p>
|
||||
To enable the same functionality in Python, we first wrap the <code>
|
||||
BigNum</code> class as usual:
|
||||
<blockquote><pre>
|
||||
boost::python::class_builder<BigNum> bignum_class(my_module, "BigNum");
|
||||
bignum_class.def(boost::python::constructor<>());
|
||||
...
|
||||
</pre></blockquote>
|
||||
Then we export the addition operator like this:
|
||||
|
||||
<blockquote><pre>
|
||||
bignum_class.def(boost::python::operators<boost::python::op_add>());
|
||||
</pre></blockquote>
|
||||
|
||||
Since BigNum also supports subtraction, multiplication, and division, we
|
||||
want to export those also. This can be done in a single command by
|
||||
``or''ing the operator identifiers together (a complete list of these
|
||||
identifiers and the corresponding operators can be found in the <a href=
|
||||
"#numeric_table">Table of Automatically Wrapped Methods</a>):
|
||||
<blockquote><pre>
|
||||
bignum_class.def(boost::python::operators<(boost::python::op_sub | boost::python::op_mul | boost::python::op_div)>());
|
||||
</pre></blockquote>
|
||||
[Note that the or-expression must be enclosed in parentheses.]
|
||||
|
||||
<p>This form of operator definition can be used to wrap unary and
|
||||
homogeneous binary operators (a <i>homogeneous</i> operator has left and
|
||||
right operands of the same type). Now suppose that our C++ library also
|
||||
supports addition of BigNums and plain integers:
|
||||
|
||||
<blockquote><pre>
|
||||
BigNum a, b;
|
||||
int i;
|
||||
...
|
||||
a = b + i;
|
||||
a = i + b;
|
||||
</pre></blockquote>
|
||||
To wrap these heterogeneous operators, we need to specify a different type for
|
||||
one of the operands. This is done using the <code>right_operand</code>
|
||||
and <code>left_operand</code> templates:
|
||||
<blockquote><pre>
|
||||
bignum_class.def(boost::python::operators<boost::python::op_add>(), boost::python::right_operand<int>());
|
||||
bignum_class.def(boost::python::operators<boost::python::op_add>(), boost::python::left_operand<int>());
|
||||
</pre></blockquote>
|
||||
Boost.Python uses overloading to register several variants of the same
|
||||
operation (more on this in the context of <a href="#coercion">
|
||||
coercion</a>). Again, several operators can be exported at once:
|
||||
<blockquote><pre>
|
||||
bignum_class.def(boost::python::operators<(boost::python::op_sub | boost::python::op_mul | boost::python::op_div)>(),
|
||||
boost::python::right_operand<int>());
|
||||
bignum_class.def(boost::python::operators<(boost::python::op_sub | boost::python::op_mul | boost::python::op_div)>(),
|
||||
boost::python::left_operand<int>());
|
||||
</pre></blockquote>
|
||||
The type of the operand not mentioned is taken from the class being wrapped. In
|
||||
our example, the class object is <code>bignum_class</code>, and thus the
|
||||
other operand's type is ``<code>BigNum const&</code>''. You can override
|
||||
this default by explicitly specifying a type in the <code>
|
||||
operators</code> template:
|
||||
<blockquote><pre>
|
||||
bignum_class.def(boost::python::operators<boost::python::op_add, BigNum>(), boost::python::right_operand<int>());
|
||||
</pre></blockquote>
|
||||
<p>
|
||||
Note that automatic wrapping uses the <em>expression</em>
|
||||
``<code>left + right</code>'' and can be used uniformly
|
||||
regardless of whether the C++ operators are supplied as free functions
|
||||
|
||||
<blockquote><pre>
|
||||
BigNum operator+(BigNum, BigNum)
|
||||
</pre></blockquote>
|
||||
|
||||
or as member functions
|
||||
|
||||
<blockquote><pre>
|
||||
BigNum::operator+(BigNum).
|
||||
</pre></blockquote>
|
||||
|
||||
<p>
|
||||
For the Python built-in functions <code>pow()</code> and
|
||||
<code>abs()</code>, there is no corresponding C++ operator. Instead,
|
||||
automatic wrapping attempts to wrap C++ functions of the same name. This
|
||||
only works if those functions are known in namespace
|
||||
<code>python</code>. On some compilers (e.g. MSVC) it might be
|
||||
necessary to add a using declaration prior to wrapping:
|
||||
|
||||
<blockquote><pre>
|
||||
namespace boost { namespace python {
|
||||
using my_namespace::pow;
|
||||
using my_namespace::abs;
|
||||
}
|
||||
</pre></blockquote>
|
||||
|
||||
<h3><a name="numeric_manual">Wrapping Numeric Operators Manually</a></h3>
|
||||
<p>
|
||||
In some cases, automatic wrapping of operators may be impossible or
|
||||
undesirable. Suppose, for example, that the modulo operation for BigNums
|
||||
is defined by a set of functions called <code>mod()</code>:
|
||||
|
||||
<blockquote><pre>
|
||||
BigNum mod(BigNum const& left, BigNum const& right);
|
||||
BigNum mod(BigNum const& left, int right);
|
||||
BigNum mod(int left, BigNum const& right);
|
||||
</pre></blockquote>
|
||||
|
||||
<p>
|
||||
For automatic wrapping of the modulo function, <code>operator%()</code> would be needed.
|
||||
Therefore, the <code>mod()</code>-functions must be wrapped manually. That is, we have
|
||||
to export them explicitly with the Python special name "__mod__":
|
||||
|
||||
<blockquote><pre>
|
||||
bignum_class.def((BigNum (*)(BigNum const&, BigNum const&))&mod, "__mod__");
|
||||
bignum_class.def((BigNum (*)(BigNum const&, int))&mod, "__mod__");
|
||||
</pre></blockquote>
|
||||
|
||||
<p>
|
||||
The third form of <code>mod()</code> (with <code>int</code> as left operand) cannot
|
||||
be wrapped directly. We must first create a function <code>rmod()</code> with the
|
||||
operands reversed:
|
||||
|
||||
<blockquote><pre>
|
||||
BigNum rmod(BigNum const& right, int left)
|
||||
{
|
||||
return mod(left, right);
|
||||
}
|
||||
</pre></blockquote>
|
||||
|
||||
This function must be wrapped under the name "__rmod__" (standing for "reverse mod"):
|
||||
|
||||
<blockquote><pre>
|
||||
bignum_class.def(&rmod, "__rmod__");
|
||||
</pre></blockquote>
|
||||
|
||||
Many of the possible operator names can be found in the <a href=
|
||||
"#numeric_table">Table of Automatically Wrapped Methods</a>. Special treatment is
|
||||
necessary to export the <a href="#ternary_pow">ternary pow</a> operator.
|
||||
|
||||
<p>
|
||||
Automatic and manual wrapping can be mixed arbitrarily. Note that you
|
||||
cannot overload the same operator for a given extension class on both
|
||||
``<code>int</code>'' and ``<code>float</code>'', because Python implicitly
|
||||
converts these types into each other. Thus, the overloaded variant
|
||||
found first (be it ``<code>int</code>`` or ``<code>float</code>'') will be
|
||||
used for either of the two types.
|
||||
|
||||
<h3><a name="coercion">Coercion</a></h3>
|
||||
|
||||
|
||||
Plain Python can only execute operators with identical types on the left
|
||||
and right hand side. If it encounters an expression where the types of
|
||||
the left and right operand differ, it tries to coerce these types to a
|
||||
common type before invoking the actual operator. Implementing good
|
||||
coercion functions can be difficult if many type combinations must be
|
||||
supported.
|
||||
<p>
|
||||
Boost.Python solves this problem the same way that C++ does: with <em><a
|
||||
href="overloading.html">overloading</a></em>. This technique drastically
|
||||
simplifies the code neccessary to support operators: you just register
|
||||
operators for all desired type combinations, and Boost.Python automatically
|
||||
ensures that the correct function is called in each case; there is no
|
||||
need for user-defined coercion functions. To enable operator
|
||||
overloading, Boost.Python provides a standard coercion which is <em>implicitly
|
||||
registered</em> whenever automatic operator wrapping is used.
|
||||
<p>
|
||||
If you wrap all operator functions manually, but still want to use
|
||||
operator overloading, you have to register the standard coercion
|
||||
function explicitly:
|
||||
|
||||
<blockquote><pre>
|
||||
// this is not necessary if automatic operator wrapping is used
|
||||
bignum_class.def_standard_coerce();
|
||||
</pre></blockquote>
|
||||
|
||||
If you encounter a situation where you absolutely need a customized
|
||||
coercion, you can still define the "__coerce__" operator manually. The signature
|
||||
of a coercion function should look like one of the following (the first is
|
||||
the safest):
|
||||
|
||||
<blockquote><pre>
|
||||
boost::python::tuple custom_coerce(boost::python::reference left, boost::python::reference right);
|
||||
boost::python::tuple custom_coerce(PyObject* left, PyObject* right);
|
||||
PyObject* custom_coerce(PyObject* left, PyObject* right);
|
||||
</pre></blockquote>
|
||||
|
||||
The resulting <code>tuple</code> must contain two elements which
|
||||
represent the values of <code>left</code> and <code>right</code>
|
||||
converted to the same type. Such a function is wrapped as usual:
|
||||
|
||||
<blockquote><pre>
|
||||
// this must be called before any use of automatic operator
|
||||
// wrapping or a call to some_class.def_standard_coerce()
|
||||
some_class.def(&custom_coerce, "__coerce__");
|
||||
</pre></blockquote>
|
||||
|
||||
Note that the standard coercion (defined by use of automatic
|
||||
operator wrapping on a <code>class_builder</code> or a call to
|
||||
<code>class_builder::def_standard_coerce()</code>) will never be applied if
|
||||
a custom coercion function has been registered. Therefore, in
|
||||
your coercion function you should call
|
||||
|
||||
<blockquote><pre>
|
||||
boost::python::standard_coerce(left, right);
|
||||
</pre></blockquote>
|
||||
|
||||
for all cases that you don't want to handle yourself.
|
||||
|
||||
<h3><a name="ternary_pow">The Ternary <code>pow()</code> Operator</a></h3>
|
||||
|
||||
<p>
|
||||
In addition to the usual binary <code>pow(x, y)</code> operator (meaning
|
||||
<i>x<sup>y</sup></i>), Python also provides a ternary variant that implements
|
||||
<i>x<sup>y</sup> <b>mod</b> z</i>, presumably using a more efficient algorithm than
|
||||
concatenation of power and modulo operators. Automatic operator wrapping
|
||||
can only be used with the binary variant. Ternary <code>pow()</code> must
|
||||
always be wrapped manually. For a homgeneous ternary <code>pow()</code>,
|
||||
this is done as usual:
|
||||
|
||||
<blockquote><pre>
|
||||
BigNum power(BigNum const& first, BigNum const& second, BigNum const& modulus);
|
||||
typedef BigNum (ternary_function1)(const BigNum&, const BigNum&, const BigNum&);
|
||||
...
|
||||
bignum_class.def((ternary_function1)&power, "__pow__");
|
||||
</pre></blockquote>
|
||||
|
||||
If you want to support this function with non-uniform argument
|
||||
types, wrapping is a little more involved. Suppose you have to wrap:
|
||||
|
||||
<blockquote><pre>
|
||||
BigNum power(BigNum const& first, int second, int modulus);
|
||||
BigNum power(int first, BigNum const& second, int modulus);
|
||||
BigNum power(int first, int second, BigNum const& modulus);
|
||||
</pre></blockquote>
|
||||
|
||||
The first variant can be wrapped as usual:
|
||||
|
||||
<blockquote><pre>
|
||||
typedef BigNum (ternary_function2)(const BigNum&, int, int);
|
||||
bignum_class.def((ternary_function2)&power, "__pow__");
|
||||
</pre></blockquote>
|
||||
|
||||
In the second variant, however, <code>BigNum</code> appears only as second
|
||||
argument, and in the last one it's the third argument. These functions
|
||||
must be presented to Boost.Python such that that the <code>BigNum</code>
|
||||
argument appears in first position:
|
||||
|
||||
<blockquote><pre>
|
||||
BigNum rpower(BigNum const& second, int first, int modulus)
|
||||
{
|
||||
return power(first, second, modulus);
|
||||
}
|
||||
|
||||
BigNum rrpower(BigNum const& modulus, int first, int second)
|
||||
{
|
||||
return power(first, second, modulus);
|
||||
}
|
||||
</pre></blockquote>
|
||||
|
||||
<p>These functions must be wrapped under the names "__rpow__" and "__rrpow__"
|
||||
respectively:
|
||||
|
||||
<blockquote><pre>
|
||||
bignum_class.def((ternary_function2)&rpower, "__rpow__");
|
||||
bignum_class.def((ternary_function2)&rrpower, "__rrpow__");
|
||||
</pre></blockquote>
|
||||
|
||||
Note that "__rrpow__" is an extension not present in plain Python.
|
||||
|
||||
<h2><a name="numeric_table">Table of Automatically Wrapped Methods</a></h2>
|
||||
<p>
|
||||
Boost.Python can automatically wrap the following <a href=
|
||||
"http://www.python.org/doc/current/ref/specialnames.html">
|
||||
special methods</a>:
|
||||
|
||||
<p>
|
||||
<table summary="special numeric methods" cellpadding="5" border="1"
|
||||
width="100%">
|
||||
<tr>
|
||||
<td align="center">
|
||||
<b>Python Operator Name</b>
|
||||
<td align="center">
|
||||
<b>Python Expression</b>
|
||||
<td align="center">
|
||||
<b>C++ Operator Id</b>
|
||||
<td align="center">
|
||||
<b>C++ Expression Used For Automatic Wrapping</b><br>
|
||||
with <code>cpp_left = from_python(left,
|
||||
type<Left>())</code>,<br>
|
||||
<code>cpp_right = from_python(right,
|
||||
type<Right>())</code>,<br>
|
||||
and <code>cpp_oper = from_python(oper, type<Oper>())</code>
|
||||
<tr>
|
||||
<td>
|
||||
<code>__add__, __radd__</code>
|
||||
<td>
|
||||
<code>left + right</code>
|
||||
<td>
|
||||
<code>op_add</code>
|
||||
<td>
|
||||
<code>cpp_left + cpp_right</code>
|
||||
<tr>
|
||||
<td>
|
||||
<code>__sub__, __rsub__</code>
|
||||
<td>
|
||||
<code>left - right</code>
|
||||
<td>
|
||||
<code>op_sub</code>
|
||||
<td>
|
||||
<code>cpp_left - cpp_right</code>
|
||||
<tr>
|
||||
<td>
|
||||
<code>__mul__, __rmul__</code>
|
||||
<td>
|
||||
<code>left * right</code>
|
||||
<td>
|
||||
<code>op_mul</code>
|
||||
<td>
|
||||
<code>cpp_left * cpp_right</code>
|
||||
<tr>
|
||||
<td>
|
||||
<code>__div__, __rdiv__</code>
|
||||
<td>
|
||||
<code>left / right</code>
|
||||
<td>
|
||||
<code>op_div</code>
|
||||
<td>
|
||||
<code>cpp_left / cpp_right</code>
|
||||
<tr>
|
||||
<td>
|
||||
<code>__mod__, __rmod__</code>
|
||||
<td>
|
||||
<code>left % right</code>
|
||||
<td>
|
||||
<code>op_mod</code>
|
||||
<td>
|
||||
<code>cpp_left % cpp_right</code>
|
||||
<tr>
|
||||
<td>
|
||||
<code>__divmod__, __rdivmod__</code>
|
||||
<td>
|
||||
<code>(quotient, remainder)<br>
|
||||
= divmod(left, right)</code>
|
||||
<td>
|
||||
<code>op_divmod</code>
|
||||
<td>
|
||||
<code>cpp_left / cpp_right</code>
|
||||
<br><code>cpp_left % cpp_right</code>
|
||||
<tr>
|
||||
<td>
|
||||
<code>__pow__, __rpow__</code>
|
||||
<td>
|
||||
<code>pow(left, right)</code><br>
|
||||
(binary power)
|
||||
<td>
|
||||
<code>op_pow</code>
|
||||
<td>
|
||||
<code>pow(cpp_left, cpp_right)</code>
|
||||
<tr>
|
||||
<td>
|
||||
<code>__rrpow__</code>
|
||||
<td>
|
||||
<code>pow(left, right, modulo)</code><br>
|
||||
(ternary power modulo)
|
||||
<td colspan="2">
|
||||
no automatic wrapping, <a href="#ternary_pow">special treatment</a>
|
||||
required
|
||||
<tr>
|
||||
<td>
|
||||
<code>__lshift__, __rlshift__</code>
|
||||
<td>
|
||||
<code>left << right</code>
|
||||
<td>
|
||||
<code>op_lshift</code>
|
||||
<td>
|
||||
<code>cpp_left << cpp_right</code>
|
||||
<tr>
|
||||
<td>
|
||||
<code>__rshift__, __rrshift__</code>
|
||||
<td>
|
||||
<code>left >> right</code>
|
||||
<td>
|
||||
<code>op_rshift</code>
|
||||
<td>
|
||||
<code>cpp_left >> cpp_right</code>
|
||||
<tr>
|
||||
<td>
|
||||
<code>__and__, __rand__</code>
|
||||
<td>
|
||||
<code>left & right</code>
|
||||
<td>
|
||||
<code>op_and</code>
|
||||
<td>
|
||||
<code>cpp_left & cpp_right</code>
|
||||
<tr>
|
||||
<td>
|
||||
<code>__xor__, __rxor__</code>
|
||||
<td>
|
||||
<code>left ^ right</code>
|
||||
<td>
|
||||
<code>op_xor</code>
|
||||
<td>
|
||||
<code>cpp_left ^ cpp_right</code>
|
||||
<tr>
|
||||
<td>
|
||||
<code>__or__, __ror__</code>
|
||||
<td>
|
||||
<code>left | right</code>
|
||||
<td>
|
||||
<code>op_or</code>
|
||||
<td>
|
||||
<code>cpp_left | cpp_right</code>
|
||||
|
||||
<tr>
|
||||
<td>
|
||||
<code>__cmp__, __rcmp__</code>
|
||||
<td>
|
||||
<code>cmp(left, right)</code><br>
|
||||
<code>left < right</code><br>
|
||||
<code>left <= right</code><br>
|
||||
<code>left > right</code><br>
|
||||
<code>left >= right</code><br>
|
||||
<code>left == right</code><br>
|
||||
<code>left != right</code>
|
||||
<td>
|
||||
<code>op_cmp</code>
|
||||
<td>
|
||||
<code>cpp_left < cpp_right </code>
|
||||
<br><code>cpp_right < cpp_left</code>
|
||||
|
||||
<tr>
|
||||
<td>
|
||||
<code>__neg__</code>
|
||||
<td>
|
||||
<code>-oper </code> (unary negation)
|
||||
<td>
|
||||
<code>op_neg</code>
|
||||
<td>
|
||||
<code>-cpp_oper</code>
|
||||
<tr>
|
||||
<td>
|
||||
<code>__pos__</code>
|
||||
<td>
|
||||
<code>+oper </code> (identity)
|
||||
<td>
|
||||
<code>op_pos</code>
|
||||
<td>
|
||||
<code>+cpp_oper</code>
|
||||
<tr>
|
||||
<td>
|
||||
<code>__abs__</code>
|
||||
<td>
|
||||
<code>abs(oper) </code> (absolute value)
|
||||
<td>
|
||||
<code>op_abs</code>
|
||||
<td>
|
||||
<code>abs(cpp_oper)</code>
|
||||
<tr>
|
||||
<td>
|
||||
<code>__invert__</code>
|
||||
<td>
|
||||
<code>~oper </code> (bitwise inversion)
|
||||
<td>
|
||||
<code>op_invert</code>
|
||||
<td>
|
||||
<code>~cpp_oper</code>
|
||||
<tr>
|
||||
<td>
|
||||
<code>__int__</code>
|
||||
<td>
|
||||
<code>int(oper) </code> (integer conversion)
|
||||
<td>
|
||||
<code>op_int</code>
|
||||
<td>
|
||||
<code>long(cpp_oper)</code>
|
||||
<tr>
|
||||
<td>
|
||||
<code>__long__</code>
|
||||
<td>
|
||||
<code>long(oper) </code><br>
|
||||
(infinite precision integer conversion)
|
||||
<td>
|
||||
<code>op_long</code>
|
||||
<td>
|
||||
<code>PyLong_FromLong(cpp_oper)</code>
|
||||
<tr>
|
||||
<td>
|
||||
<code>__float__</code>
|
||||
<td>
|
||||
<code>float(oper) </code> (float conversion)
|
||||
<td>
|
||||
<code>op_float</code>
|
||||
<td>
|
||||
<code>double(cpp_oper)</code>
|
||||
<tr>
|
||||
<td>
|
||||
<code>__str__</code>
|
||||
<td>
|
||||
<code>str(oper) </code> (string conversion)
|
||||
<td>
|
||||
<code>op_str</code>
|
||||
<td>
|
||||
<code>std::ostringstream s; s << oper;</code>
|
||||
<tr>
|
||||
<td>
|
||||
<code>__coerce__</code>
|
||||
<td>
|
||||
<code>coerce(left, right)</code>
|
||||
<td colspan="2">
|
||||
usually defined automatically, otherwise <a href="#coercion">
|
||||
special treatment</a> required
|
||||
</table>
|
||||
|
||||
<h2><a name="sequence_and_mapping">Sequence and Mapping Operators</a></h2>
|
||||
|
||||
<p>
|
||||
Sequence and mapping operators let wrapped objects behave in accordance
|
||||
to Python's iteration and access protocols. These protocols differ
|
||||
considerably from the ones found in C++. For example, Python's typical
|
||||
iteration idiom looks like
|
||||
|
||||
<blockquote><pre>
|
||||
for i in S:
|
||||
</pre></blockquote>
|
||||
|
||||
while in C++ one writes
|
||||
|
||||
<blockquote><pre>
|
||||
for (iterator i = S.begin(), end = S.end(); i != end; ++i)
|
||||
</pre></blockquote>
|
||||
|
||||
<p>One could try to wrap C++ iterators in order to carry the C++ idiom into
|
||||
Python. However, this does not work very well because
|
||||
|
||||
<ol>
|
||||
<li>It leads to
|
||||
non-uniform Python code (wrapped sequences support a usage different from
|
||||
Python built-in sequences) and
|
||||
|
||||
<li>Iterators (e.g. <code>std::vector::iterator</code>) are often implemented as plain C++
|
||||
pointers which are <a href="pointers.html#problem">problematic</a> for any automatic
|
||||
wrapping system.
|
||||
</ol>
|
||||
|
||||
<p>
|
||||
It is a better idea to support the standard <a
|
||||
href="http://www.python.org/doc/current/ref/sequence-types.html">Python
|
||||
sequence and mapping protocols</a> for your wrapped containers. These
|
||||
operators have to be wrapped manually because there are no corresponding
|
||||
C++ operators that could be used for automatic wrapping. The Python
|
||||
documentation lists the relevant <a href=
|
||||
"http://www.python.org/doc/current/ref/sequence-types.html">
|
||||
container operators</a>. In particular, expose __getitem__, __setitem__
|
||||
and remember to raise the appropriate Python exceptions
|
||||
(<code>PyExc_IndexError</code> for sequences,
|
||||
<code>PyExc_KeyError</code> for mappings) when the requested item is not
|
||||
present.
|
||||
|
||||
<p>
|
||||
In the following example, we expose <code>std::map<std::size_t,std::string></code>:
|
||||
<blockquote>
|
||||
<pre>
|
||||
typedef std::map<std::size_t, std::string> StringMap;
|
||||
|
||||
// A helper function for dealing with errors. Throw a Python exception
|
||||
// if p == m.end().
|
||||
void throw_key_error_if_end(
|
||||
const StringMap& m,
|
||||
StringMap::const_iterator p,
|
||||
std::size_t key)
|
||||
{
|
||||
if (p == m.end())
|
||||
{
|
||||
PyErr_SetObject(PyExc_KeyError, boost::python::converters::to_python(key));
|
||||
throw boost::python::error_already_set();
|
||||
}
|
||||
}
|
||||
|
||||
// Define some simple wrapper functions which match the Python protocol
|
||||
// for __getitem__, __setitem__, and __delitem__. Just as in Python, a
|
||||
// free function with a ``self'' first parameter makes a fine class method.
|
||||
|
||||
const std::string& get_item(const StringMap& self, std::size_t key)
|
||||
{
|
||||
const StringMap::const_iterator p = self.find(key);
|
||||
throw_key_error_if_end(self, p, key);
|
||||
return p->second;
|
||||
}
|
||||
|
||||
// Sets the item corresponding to key in the map.
|
||||
void StringMapPythonClass::set_item(StringMap& self, std::size_t key, const std::string& value)
|
||||
{
|
||||
self[key] = value;
|
||||
}
|
||||
|
||||
// Deletes the item corresponding to key from the map.
|
||||
void StringMapPythonClass::del_item(StringMap& self, std::size_t key)
|
||||
{
|
||||
const StringMap::iterator p = self.find(key);
|
||||
throw_key_error_if_end(self, p, key);
|
||||
self.erase(p);
|
||||
}
|
||||
|
||||
class_builder<StringMap> string_map(my_module, "StringMap");
|
||||
string_map.def(boost::python::constructor<>());
|
||||
string_map.def(&StringMap::size, "__len__");
|
||||
string_map.def(get_item, "__getitem__");
|
||||
string_map.def(set_item, "__setitem__");
|
||||
string_map.def(del_item, "__delitem__");
|
||||
</pre>
|
||||
</blockquote>
|
||||
<p>
|
||||
Then in Python:
|
||||
<blockquote>
|
||||
<pre>
|
||||
>>> m = StringMap()
|
||||
>>> m[1]
|
||||
Traceback (innermost last):
|
||||
File "<stdin>", line 1, in ?
|
||||
KeyError: 1
|
||||
>>> m[1] = 'hello'
|
||||
>>> m[1]
|
||||
'hello'
|
||||
>>> del m[1]
|
||||
>>> m[1] # prove that it's gone
|
||||
Traceback (innermost last):
|
||||
File "<stdin>", line 1, in ?
|
||||
KeyError: 1
|
||||
>>> del m[2]
|
||||
Traceback (innermost last):
|
||||
File "<stdin>", line 1, in ?
|
||||
KeyError: 2
|
||||
>>> len(m)
|
||||
0
|
||||
>>> m[0] = 'zero'
|
||||
>>> m[1] = 'one'
|
||||
>>> m[2] = 'two'
|
||||
>>> m[3] = 'three'
|
||||
>>> len(m)
|
||||
4
|
||||
</pre>
|
||||
</blockquote>
|
||||
|
||||
<h2><a name="getter_setter">Customized Attribute Access</a></h2>
|
||||
|
||||
<p>
|
||||
Just like built-in Python classes, Boost.Python extension classes support <a
|
||||
href="http://www.python.org/doc/current/ref/attribute-access.html">special
|
||||
the usual attribute access methods</a> <code>__getattr__</code>,
|
||||
<code>__setattr__</code>, and <code>__delattr__</code>.
|
||||
Because writing these functions can
|
||||
be tedious in the common case where the attributes being accessed are
|
||||
known statically, Boost.Python checks the special names
|
||||
|
||||
<ul>
|
||||
<li>
|
||||
<code>__getattr__<em><name></em>__</code>
|
||||
<li>
|
||||
<code>__setattr__<em><name></em>__</code>
|
||||
<li>
|
||||
<code>__delattr__<em><name></em>__</code>
|
||||
</ul>
|
||||
|
||||
to provide functional access to the attribute <em><name></em>. This
|
||||
facility can be used from C++ or entirely from Python. For example, the
|
||||
following shows how we can implement a ``computed attribute'' in Python:
|
||||
<blockquote>
|
||||
<pre>
|
||||
>>> class Range(AnyBoost.PythonExtensionClass):
|
||||
... def __init__(self, start, end):
|
||||
... self.start = start
|
||||
... self.end = end
|
||||
... def __getattr__length__(self):
|
||||
... return self.end - self.start
|
||||
...
|
||||
>>> x = Range(3, 9)
|
||||
>>> x.length
|
||||
6
|
||||
</pre>
|
||||
</blockquote>
|
||||
<h4>
|
||||
Direct Access to Data Members
|
||||
</h4>
|
||||
<p>
|
||||
Boost.Python uses the special <code>
|
||||
__xxxattr__<em><name></em>__</code> functionality described above
|
||||
to allow direct access to data members through the following special
|
||||
functions on <code>class_builder<></code> and <code>
|
||||
extension_class<></code>:
|
||||
<ul>
|
||||
<li>
|
||||
<code>def_getter(<em>pointer-to-member</em>, <em>name</em>)</code> //
|
||||
read access to the member via attribute <em>name</em>
|
||||
<li>
|
||||
<code>def_setter(<em>pointer-to-member</em>, <em>name</em>)</code> //
|
||||
write access to the member via attribute <em>name</em>
|
||||
<li>
|
||||
<code>def_readonly(<em>pointer-to-member</em>, <em>name</em>)</code>
|
||||
// read-only access to the member via attribute <em>name</em>
|
||||
<li>
|
||||
<code>def_read_write(<em>pointer-to-member</em>, <em>
|
||||
name</em>)</code> // read/write access to the member via attribute
|
||||
<em>name</em>
|
||||
</ul>
|
||||
<p>
|
||||
Note that the first two functions, used alone, may produce surprising
|
||||
behavior. For example, when <code>def_getter()</code> is used, the
|
||||
default functionality for <code>setattr()</code> and <code>
|
||||
delattr()</code> remains in effect, operating on items in the extension
|
||||
instance's name-space (i.e., its <code>__dict__</code>). For that
|
||||
reason, you'll usually want to stick with <code>def_readonly</code> and
|
||||
<code>def_read_write</code>.
|
||||
<p>
|
||||
For example, to expose a <code>std::pair<int,long></code> we
|
||||
might write:
|
||||
<blockquote>
|
||||
<pre>
|
||||
typedef std::pair<int,long> Pil;
|
||||
int first(const Pil& x) { return x.first; }
|
||||
long second(const Pil& x) { return x.second; }
|
||||
...
|
||||
my_module.def(first, "first");
|
||||
my_module.def(second, "second");
|
||||
|
||||
class_builder<Pil> pair_int_long(my_module, "Pair");
|
||||
pair_int_long.def(boost::python::constructor<>());
|
||||
pair_int_long.def(boost::python::constructor<int,long>());
|
||||
pair_int_long.def_read_write(&Pil::first, "first");
|
||||
pair_int_long.def_read_write(&Pil::second, "second");
|
||||
</pre>
|
||||
</blockquote>
|
||||
<p>
|
||||
Now your Python class has attributes <code>first</code> and <code>
|
||||
second</code> which, when accessed, actually modify or reflect the
|
||||
values of corresponding data members of the underlying C++ object. Now
|
||||
in Python:
|
||||
<blockquote>
|
||||
<pre>
|
||||
>>> x = Pair(3,5)
|
||||
>>> x.first
|
||||
3
|
||||
>>> x.second
|
||||
5
|
||||
>>> x.second = 8
|
||||
>>> x.second
|
||||
8
|
||||
>>> second(x) # Prove that we're not just changing the instance __dict__
|
||||
8
|
||||
</pre>
|
||||
</blockquote>
|
||||
<h2>
|
||||
<a name="reasons">And what about <code>__complex__</code>?</a>
|
||||
</h2>
|
||||
<p>
|
||||
That, dear reader, is one problem we don't know how to solve. The
|
||||
Python source contains the following fragment, indicating the
|
||||
special-case code really is hardwired:
|
||||
<blockquote>
|
||||
<pre>
|
||||
/* XXX Hack to support classes with __complex__ method */
|
||||
if (PyInstance_Check(r)) { ...
|
||||
</pre>
|
||||
</blockquote>
|
||||
<p>
|
||||
Next: <a href="under-the-hood.html">A Peek Under the Hood</a>
|
||||
Previous: <a href="inheritance.html">Inheritance</a>
|
||||
Up: <a href= "index.html">Top</a>
|
||||
<p>
|
||||
© Copyright David Abrahams and Ullrich Köthe 2000.
|
||||
Permission to copy, use, modify, sell and distribute this document is
|
||||
granted provided this copyright notice appears in all copies. This
|
||||
document is provided ``as is'' without express or implied
|
||||
warranty, and with no claim as to its suitability for any purpose.
|
||||
<p>
|
||||
Updated: Nov 26, 2000
|
||||
</div>
|
||||
|
||||
@@ -1,62 +0,0 @@
|
||||
<!DOCTYPE html PUBLIC "-//W3C//DTD HTML 3.2//EN">
|
||||
<meta http-equiv="Content-Type" content="text/html; charset=windows-1252">
|
||||
<title>
|
||||
A Peek Under the Hood
|
||||
</title>
|
||||
<h1>
|
||||
<img src="../../../c++boost.gif" alt="c++boost.gif (8819 bytes)" align="center"
|
||||
width="277" height="86">
|
||||
</h1>
|
||||
<h1>
|
||||
A Peek Under the Hood
|
||||
</h1>
|
||||
<p>
|
||||
Declaring a <code>class_builder<T></code> causes the instantiation
|
||||
of an <code>extension_class<T></code> to which it forwards all
|
||||
member function calls and which is doing most of the real work.
|
||||
<code>extension_class<T></code> is a subclass of <code>
|
||||
PyTypeObject</code>, the <code> struct</code> which Python's 'C' API uses
|
||||
to describe a type. <a href="example1.html#world_class">An instance of the
|
||||
<code>extension_class<></code></a> becomes the Python type object
|
||||
corresponding to <code>hello::world</code>. When we <a href=
|
||||
"example1.html#add_world_class">add it to the module</a> it goes into the
|
||||
module's dictionary to be looked up under the name "world".
|
||||
<p>
|
||||
Boost.Python uses C++'s template argument deduction mechanism to determine the
|
||||
types of arguments to functions (except constructors, for which we must
|
||||
<a href="example1.html#Constructor_example">provide an argument list</a>
|
||||
because they can't be named in C++). Then, it calls the appropriate
|
||||
overloaded functions <code>PyObject*
|
||||
to_python(</code><em>S</em><code>)</code> and <em>
|
||||
S'</em><code>from_python(PyObject*,
|
||||
type<</code><em>S</em><code>>)</code> which convert between any C++
|
||||
type <em>S</em> and a <code>PyObject*</code>, the type which represents a
|
||||
reference to any Python object in its 'C' API. The <a href=
|
||||
"example1.html#world_class"><code>extension_class<T></code></a>
|
||||
template defines a whole raft of these conversions (for <code>T, T*,
|
||||
T&, std::auto_ptr<T></code>, etc.), using the same inline
|
||||
friend function technique employed by <a href=
|
||||
"http://www.boost.org/libs/utility/operators.htm">the boost operators
|
||||
library</a>.
|
||||
<p>
|
||||
Because the <code>to_python</code> and <code>from_python</code> functions
|
||||
for a user-defined class are defined by <code>
|
||||
extension_class<T></code>, it is important that an instantiation of
|
||||
<code> extension_class<T></code> is visible to any code which wraps
|
||||
a C++ function with a <code>T, T*, const T&</code>, etc. parameter or
|
||||
return value. In particular, you may want to create all of the classes at
|
||||
the top of your module's init function, then <code>def</code> the member
|
||||
functions later to avoid problems with inter-class dependencies.
|
||||
<p>
|
||||
Next: <a href="building.html">Building a Module with Boost.Python</a>
|
||||
Previous: <a href="special.html">Special Method and Operator Support</a>
|
||||
Up: <a href="index.html">Top</a>
|
||||
<p>
|
||||
© Copyright David Abrahams 2000. Permission to copy, use, modify,
|
||||
sell and distribute this document is granted provided this copyright
|
||||
notice appears in all copies. This document is provided "as is" without
|
||||
express or implied warranty, and with no claim as to its suitability for
|
||||
any purpose.
|
||||
<p>
|
||||
Updated: Nov 26, 2000
|
||||
|
||||
@@ -1,6 +0,0 @@
|
||||
To get started with the Boost Python Library, use the examples
|
||||
getting_started?.cpp and abstract.cpp.
|
||||
|
||||
The files example1.cpp and rwgk1.cpp are obsolete. They are only
|
||||
included because the makefiles in the build directory still refer to
|
||||
them. This will be fixed later.
|
||||
@@ -1,34 +0,0 @@
|
||||
// Example by Ullrich Koethe
|
||||
#include "boost/python/class_builder.hpp"
|
||||
#include <string>
|
||||
|
||||
struct Abstract
|
||||
{
|
||||
virtual std::string test() = 0;
|
||||
};
|
||||
|
||||
struct Abstract_callback: Abstract
|
||||
{
|
||||
Abstract_callback(PyObject * self)
|
||||
: m_self(self)
|
||||
{}
|
||||
|
||||
std::string test()
|
||||
{
|
||||
return boost::python::callback<std::string>::call_method(m_self, "test");
|
||||
}
|
||||
|
||||
PyObject * m_self;
|
||||
};
|
||||
|
||||
extern "C"
|
||||
DL_EXPORT(void)
|
||||
initabstract()
|
||||
{
|
||||
boost::python::module_builder a("abstract");
|
||||
|
||||
boost::python::class_builder<Abstract, Abstract_callback>
|
||||
a_class(a, "Abstract");
|
||||
a_class.def(boost::python::constructor<>()); // wrap a constructor
|
||||
a_class.def(&Abstract::test, "test");
|
||||
}
|
||||
@@ -1,54 +0,0 @@
|
||||
#include <string.h>
|
||||
|
||||
namespace hello {
|
||||
class world
|
||||
{
|
||||
public:
|
||||
world(int) {}
|
||||
~world() {}
|
||||
const char* get() const { return "hi, world"; }
|
||||
};
|
||||
|
||||
size_t length(const world& x) { return strlen(x.get()); }
|
||||
}
|
||||
|
||||
#include <boost/python/class_builder.hpp>
|
||||
|
||||
// Python requires an exported function called init<module-name> in every
|
||||
// extension module. This is where we build the module contents.
|
||||
extern "C"
|
||||
#ifdef _WIN32
|
||||
__declspec(dllexport)
|
||||
#endif
|
||||
void inithello()
|
||||
{
|
||||
try
|
||||
{
|
||||
// create an object representing this extension module
|
||||
boost::python::module_builder hello("hello");
|
||||
|
||||
// Create the Python type object for our extension class
|
||||
boost::python::class_builder<hello::world> world_class(hello, "world");
|
||||
|
||||
// Add the __init__ function
|
||||
world_class.def(boost::python::constructor<int>());
|
||||
// Add a regular member function
|
||||
world_class.def(&hello::world::get, "get");
|
||||
|
||||
// Add a regular function to the module
|
||||
hello.def(hello::length, "length");
|
||||
}
|
||||
catch(...)
|
||||
{
|
||||
boost::python::handle_exception(); // Deal with the exception for Python
|
||||
}
|
||||
}
|
||||
|
||||
// Win32 DLL boilerplate
|
||||
#if defined(_WIN32)
|
||||
#include <windows.h>
|
||||
extern "C" BOOL WINAPI DllMain(HINSTANCE, DWORD, LPVOID)
|
||||
{
|
||||
return 1;
|
||||
}
|
||||
#endif // _WIN32
|
||||
@@ -1,30 +0,0 @@
|
||||
#include <string>
|
||||
|
||||
namespace { // Avoid cluttering the global namespace.
|
||||
|
||||
// A couple of simple C++ functions that we want to expose to Python.
|
||||
std::string greet() { return "hello, world"; }
|
||||
int square(int number) { return number * number; }
|
||||
}
|
||||
|
||||
#include <boost/python/class_builder.hpp>
|
||||
namespace python = boost::python;
|
||||
|
||||
// Python requires an exported function called init<module-name> in every
|
||||
// extension module. This is where we build the module contents.
|
||||
BOOST_PYTHON_MODULE_INIT(getting_started1)
|
||||
{
|
||||
try
|
||||
{
|
||||
// Create an object representing this extension module.
|
||||
python::module_builder this_module("getting_started1");
|
||||
|
||||
// Add regular functions to the module.
|
||||
this_module.def(greet, "greet");
|
||||
this_module.def(square, "square");
|
||||
}
|
||||
catch(...)
|
||||
{
|
||||
python::handle_exception(); // Deal with the exception for Python
|
||||
}
|
||||
}
|
||||
@@ -1,50 +0,0 @@
|
||||
#include <iostream>
|
||||
#include <string>
|
||||
|
||||
namespace { // Avoid cluttering the global namespace.
|
||||
|
||||
// A friendly class.
|
||||
class hello
|
||||
{
|
||||
public:
|
||||
hello(const std::string& country) { this->country = country; }
|
||||
std::string greet() const { return "Hello from " + country; }
|
||||
private:
|
||||
std::string country;
|
||||
};
|
||||
|
||||
// A function taking a hello object as an argument.
|
||||
std::string invite(const hello& w) {
|
||||
return w.greet() + "! Please come soon!";
|
||||
}
|
||||
}
|
||||
|
||||
#include <boost/python/class_builder.hpp>
|
||||
namespace python = boost::python;
|
||||
|
||||
BOOST_PYTHON_MODULE_INIT(getting_started2)
|
||||
{
|
||||
try
|
||||
{
|
||||
// Create an object representing this extension module.
|
||||
python::module_builder this_module("getting_started2");
|
||||
|
||||
// Create the Python type object for our extension class.
|
||||
python::class_builder<hello> hello_class(this_module, "hello");
|
||||
|
||||
// Add the __init__ function.
|
||||
hello_class.def(python::constructor<std::string>());
|
||||
// Add a regular member function.
|
||||
hello_class.def(&hello::greet, "greet");
|
||||
|
||||
// Add invite() as a regular function to the module.
|
||||
this_module.def(invite, "invite");
|
||||
|
||||
// Even better, invite() can also be made a member of hello_class!!!
|
||||
hello_class.def(invite, "invite");
|
||||
}
|
||||
catch(...)
|
||||
{
|
||||
python::handle_exception(); // Deal with the exception for Python
|
||||
}
|
||||
}
|
||||
@@ -1,120 +0,0 @@
|
||||
/*
|
||||
This example shows how to make an Extension Class "pickleable".
|
||||
|
||||
Python's pickle module implements a basic but powerful algorithm
|
||||
for "pickling" (a.k.a. serializing, marshalling or flattening)
|
||||
nearly arbitrary Python objects.
|
||||
|
||||
The user can influence how an Extension Class instance is pickled
|
||||
by defining three special methods: __getinitargs__(),
|
||||
__getstate__(), and __setstate(). This interface is similar to
|
||||
that for regular Python classes as described in detail in the
|
||||
Python Library Reference for pickle:
|
||||
|
||||
http://www.python.org/doc/current/lib/module-pickle.html
|
||||
|
||||
When an Extension Class instance is pickled, __getinitargs__() is
|
||||
called, if implemented. This method should return a tuple
|
||||
containing the arguments to be passed to the class constructor when
|
||||
the object is restored.
|
||||
|
||||
If there is no __getstate__() method, the instance's __dict__ is
|
||||
pickled if it is not empty. If __getstate__() is defined, it should
|
||||
return an object representing the state of the instance.
|
||||
|
||||
If there is no __setstate__() method, __getstate__() must return a
|
||||
dictionary. When the instance is restored, the items in this dictionary
|
||||
are added to the instance's __dict__.
|
||||
|
||||
If the Extension Class defines __setstate__(), the pickle loader
|
||||
calls it with the result of __getstate__() as arguments. In this
|
||||
case, the state object need not be a dictionary. The
|
||||
__getstate__() and __setstate__() methods can do what they want.
|
||||
|
||||
If both __getinitargs__() and __getstate__() are defined, the
|
||||
instance is restored by first calling the constructor with
|
||||
the result of __getinitargs__() as argument. After the instance
|
||||
is reconstructed, the __dict__ is updated or __setstate__() is
|
||||
called if implemented.
|
||||
|
||||
The mechanism described here is an exact replication of that one
|
||||
implemented by Jim Fulton's ExtensionClass (included in Zope 2.2.2).
|
||||
*/
|
||||
|
||||
#include <iostream>
|
||||
#include <string>
|
||||
|
||||
#include <boost/python/class_builder.hpp>
|
||||
namespace python = boost::python;
|
||||
|
||||
namespace { // Avoid cluttering the global namespace.
|
||||
|
||||
// A friendly class.
|
||||
class world
|
||||
{
|
||||
private:
|
||||
std::string country;
|
||||
int secret_number;
|
||||
public:
|
||||
world(const std::string& country) : secret_number(0) {
|
||||
this->country = country;
|
||||
}
|
||||
std::string greet() const { return "Hello from " + country + "!"; }
|
||||
std::string get_country() const { return country; }
|
||||
void set_secret_number(int number) { secret_number = number; }
|
||||
int get_secret_number() const { return secret_number; }
|
||||
};
|
||||
|
||||
// Support for pickle.
|
||||
python::tuple world_getinitargs(const world& w) {
|
||||
python::tuple result(1);
|
||||
result.set_item(0, w.get_country());
|
||||
return result;
|
||||
}
|
||||
|
||||
python::tuple world_getstate(const world& w) {
|
||||
python::tuple result(1);
|
||||
result.set_item(0, w.get_secret_number());
|
||||
return result;
|
||||
}
|
||||
|
||||
void world_setstate(world& w, python::tuple state) {
|
||||
if (state.size() != 1) {
|
||||
PyErr_SetString(PyExc_ValueError,
|
||||
"Unexpected argument in call to __setstate__.");
|
||||
throw python::error_already_set();
|
||||
}
|
||||
int number = BOOST_PYTHON_CONVERSION::from_python(state[0].get(),
|
||||
python::type<int>());
|
||||
if (number != 42)
|
||||
w.set_secret_number(number);
|
||||
}
|
||||
}
|
||||
|
||||
BOOST_PYTHON_MODULE_INIT(getting_started3)
|
||||
{
|
||||
try
|
||||
{
|
||||
// Create an object representing this extension module.
|
||||
python::module_builder this_module("getting_started3");
|
||||
|
||||
// Create the Python type object for our extension class.
|
||||
python::class_builder<world> world_class(this_module, "world");
|
||||
|
||||
// Add the __init__ function.
|
||||
world_class.def(python::constructor<std::string>());
|
||||
// Add a regular member function.
|
||||
world_class.def(&world::greet, "greet");
|
||||
world_class.def(&world::get_secret_number, "get_secret_number");
|
||||
world_class.def(&world::set_secret_number, "set_secret_number");
|
||||
|
||||
// Support for pickle.
|
||||
world_class.def(world_getinitargs, "__getinitargs__");
|
||||
world_class.def(world_getstate, "__getstate__");
|
||||
world_class.def(world_setstate, "__setstate__");
|
||||
}
|
||||
catch(...)
|
||||
{
|
||||
python::handle_exception(); // Deal with the exception for Python
|
||||
}
|
||||
}
|
||||
@@ -1,102 +0,0 @@
|
||||
#include <boost/python/class_builder.hpp>
|
||||
namespace python = boost::python;
|
||||
|
||||
namespace { // Avoid cluttering the global namespace.
|
||||
|
||||
// A wrapper is used to define additional constructors.
|
||||
//
|
||||
struct vector_double_wrapper: std::vector<double>
|
||||
{
|
||||
// Tell the compiler how to convert a base class object to
|
||||
// this wrapper object.
|
||||
vector_double_wrapper(PyObject*, const std::vector<double>& vd)
|
||||
: std::vector<double>(vd) {}
|
||||
|
||||
vector_double_wrapper(PyObject* self)
|
||||
: std::vector<double>() {}
|
||||
|
||||
vector_double_wrapper(PyObject* self, const int n)
|
||||
: std::vector<double>(n) {}
|
||||
|
||||
vector_double_wrapper(PyObject* self, python::tuple tuple)
|
||||
: std::vector<double>(tuple.size())
|
||||
{
|
||||
std::vector<double>::iterator vd = begin();
|
||||
for (int i = 0; i < tuple.size(); i++)
|
||||
vd[i] = BOOST_PYTHON_CONVERSION::from_python(tuple[i].get(),
|
||||
python::type<double>());
|
||||
}
|
||||
};
|
||||
|
||||
double getitem(const std::vector<double>& vd, const std::size_t key) {
|
||||
return vd[key];
|
||||
}
|
||||
|
||||
void setitem(std::vector<double>& vd, const std::size_t key,
|
||||
const double &d) {
|
||||
std::vector<double>::iterator vditer = vd.begin();
|
||||
vditer[key] = d;
|
||||
}
|
||||
|
||||
void delitem(std::vector<double>& vd, const std::size_t key) {
|
||||
std::vector<double>::iterator vditer = vd.begin();
|
||||
vd.erase(&vditer[key]);
|
||||
}
|
||||
|
||||
// Convert vector_double to a regular Python tuple.
|
||||
//
|
||||
python::tuple as_tuple(const std::vector<double>& vd)
|
||||
{
|
||||
python::tuple t(vd.size());
|
||||
for (int i = 0; i < vd.size(); i++) t.set_item(i,
|
||||
python::ref(BOOST_PYTHON_CONVERSION::to_python(vd[i])));
|
||||
return t;
|
||||
}
|
||||
|
||||
// Function returning a vector_double object to Python.
|
||||
//
|
||||
std::vector<double> foo(int n)
|
||||
{
|
||||
std::vector<double> vd(n);
|
||||
std::vector<double>::iterator vditer = vd.begin();
|
||||
for (int i = 0; i < n; i++) vditer[i] = double(i);
|
||||
return vd;
|
||||
}
|
||||
|
||||
// Same as foo(), but avoid copying on return.
|
||||
//
|
||||
std::auto_ptr<std::vector<double> > bar(int n)
|
||||
{
|
||||
std::auto_ptr<std::vector<double> > vdptr(new std::vector<double>(n));
|
||||
std::vector<double>::iterator vditer = vdptr->begin();
|
||||
for (int i = 0; i < n; i++) vditer[i] = double(10 * i);
|
||||
return vdptr;
|
||||
}
|
||||
}
|
||||
|
||||
BOOST_PYTHON_MODULE_INIT(getting_started4)
|
||||
{
|
||||
try
|
||||
{
|
||||
python::module_builder this_module("getting_started4");
|
||||
|
||||
python::class_builder<std::vector<double>, vector_double_wrapper>
|
||||
vector_double(this_module, "vector_double");
|
||||
|
||||
vector_double.def(python::constructor<>());
|
||||
vector_double.def(python::constructor<const int>());
|
||||
vector_double.def(python::constructor<python::tuple>());
|
||||
vector_double.def(&std::vector<double>::size, "__len__");
|
||||
vector_double.def(getitem, "__getitem__");
|
||||
vector_double.def(setitem, "__setitem__");
|
||||
vector_double.def(delitem, "__delitem__");
|
||||
vector_double.def(as_tuple, "as_tuple");
|
||||
|
||||
this_module.def(foo, "foo");
|
||||
this_module.def(bar, "bar");
|
||||
}
|
||||
catch(...)
|
||||
{
|
||||
python::handle_exception(); // Deal with the exception for Python
|
||||
}
|
||||
}
|
||||
@@ -1,126 +0,0 @@
|
||||
/*
|
||||
This example shows how to convert a class from and to native
|
||||
Python objects, such as tuples.
|
||||
|
||||
We do not want to expose the helper class MillerIndex as an
|
||||
Extension Class. However, in order to simplify the wrapper code,
|
||||
we want to define from_python() and to_python() functions for
|
||||
class MillerIndex.
|
||||
|
||||
Consider the alternatives:
|
||||
|
||||
- Expose MillerIndex as an Extension Class.
|
||||
We need a constructor MillerIndex(python::tuple).
|
||||
Python function calls become more complex:
|
||||
foo(MillerIndex((1,2,3)) instead of foo((1,2,3))
|
||||
We need a method such as MillerIndex().as_tuple().
|
||||
|
||||
- Define a wrapper function for each function that we
|
||||
want to expose, e.g.:
|
||||
void add(const IndexingSet& ixset, const python::tuple PyMIx)
|
||||
|
||||
The first alternative introduces a new type that the user has to
|
||||
deal with. Other modules using Miller indices might organize them in
|
||||
different ways, for example to increase runtime efficiency for
|
||||
important procedures. This means, the user has to know how to
|
||||
convert between the different kinds of Miller index representations.
|
||||
This can quickly become a nuisance. Relying on native Python data
|
||||
structures minimizes the number of special types the user has to
|
||||
learn and convert. Of course, this argument is only valid for
|
||||
small and relatively simply classes.
|
||||
|
||||
If there are many member functions with MillerIndex arguments, the
|
||||
second alternative is impractical, and concentrating the conversion
|
||||
mechanism in one central place is essential for code
|
||||
maintainability. An added benefit is that more convenient (smarter)
|
||||
conversion functions can be provided without cluttering the rest of
|
||||
the wrapper code.
|
||||
|
||||
*/
|
||||
|
||||
#include <string>
|
||||
#include <vector>
|
||||
#include <boost/python/class_builder.hpp>
|
||||
namespace python = boost::python;
|
||||
|
||||
namespace { // Avoid cluttering the global namespace.
|
||||
|
||||
// The helper class.
|
||||
//
|
||||
class MillerIndex {
|
||||
public:
|
||||
int v[3];
|
||||
};
|
||||
|
||||
// The main class. Imagine that there are MANY member functions
|
||||
// like add() and get().
|
||||
//
|
||||
class IndexingSet {
|
||||
private:
|
||||
std::vector<MillerIndex> VMIx;
|
||||
public:
|
||||
void add(const MillerIndex& MIx) { VMIx.push_back(MIx); }
|
||||
MillerIndex get(const std::size_t i) const { return VMIx[i]; }
|
||||
};
|
||||
}
|
||||
|
||||
BOOST_PYTHON_BEGIN_CONVERSION_NAMESPACE
|
||||
|
||||
// Convert a Python tuple to a MillerIndex object.
|
||||
//
|
||||
MillerIndex from_python(PyObject* p, python::type<const MillerIndex&>)
|
||||
{
|
||||
python::tuple tup
|
||||
= python::tuple(python::ref(p, python::ref::increment_count));
|
||||
if (tup.size() != 3) {
|
||||
PyErr_SetString(PyExc_ValueError,
|
||||
"expecting exactly 3 values in tuple.");
|
||||
throw python::error_already_set();
|
||||
}
|
||||
MillerIndex result;
|
||||
for (int i = 0; i < 3; i++)
|
||||
result.v[i] = from_python(tup[i].get(), python::type<int>());
|
||||
return result;
|
||||
}
|
||||
|
||||
// Similar conversion for MillerIndex objects passed by value.
|
||||
// Not actually used, but included to show the principle.
|
||||
//
|
||||
MillerIndex from_python(PyObject* p, python::type<MillerIndex>)
|
||||
{
|
||||
return from_python(p, python::type<const MillerIndex&>());
|
||||
}
|
||||
|
||||
// Convert a MillerIndex object to a Python tuple.
|
||||
//
|
||||
PyObject* to_python(const MillerIndex& hkl)
|
||||
{
|
||||
python::tuple result(3);
|
||||
for (int i = 0; i < 3; i++)
|
||||
result.set_item(i, python::ref(to_python(hkl.v[i])));
|
||||
return result.reference().release();
|
||||
}
|
||||
|
||||
BOOST_PYTHON_END_CONVERSION_NAMESPACE
|
||||
|
||||
BOOST_PYTHON_MODULE_INIT(getting_started5)
|
||||
{
|
||||
try
|
||||
{
|
||||
// Create an object representing this extension module.
|
||||
python::module_builder this_module("getting_started5");
|
||||
|
||||
// Create the Python type object for our extension class.
|
||||
python::class_builder<IndexingSet> ixset_class(this_module, "IndexingSet");
|
||||
|
||||
// Add the __init__ function.
|
||||
ixset_class.def(python::constructor<>());
|
||||
// Add the member functions.
|
||||
ixset_class.def(&IndexingSet::add, "add");
|
||||
ixset_class.def(&IndexingSet::get, "get");
|
||||
}
|
||||
catch(...)
|
||||
{
|
||||
python::handle_exception(); // Deal with the exception for Python
|
||||
}
|
||||
}
|
||||
@@ -1,41 +0,0 @@
|
||||
#include <string>
|
||||
|
||||
namespace { // Avoid cluttering the global namespace.
|
||||
|
||||
// A couple of simple C++ functions that we want to expose to Python.
|
||||
std::string greet() { return "hello, world"; }
|
||||
int square(int number) { return number * number; }
|
||||
}
|
||||
|
||||
#include <boost/python/class_builder.hpp>
|
||||
|
||||
namespace python = boost::python;
|
||||
|
||||
// Python requires an exported function called init<module-name> in every
|
||||
// extension module. This is where we build the module contents.
|
||||
extern "C"
|
||||
#ifdef _WIN32
|
||||
__declspec(dllexport)
|
||||
#endif
|
||||
void initrwgk1()
|
||||
{
|
||||
try
|
||||
{
|
||||
// Create an object representing this extension module.
|
||||
python::module_builder this_module("rwgk1");
|
||||
|
||||
// Add regular functions to the module.
|
||||
this_module.def(greet, "greet");
|
||||
this_module.def(square, "square");
|
||||
}
|
||||
catch(...)
|
||||
{
|
||||
python::handle_exception(); // Deal with the exception for Python
|
||||
}
|
||||
}
|
||||
|
||||
// Win32 DLL boilerplate
|
||||
#if defined(_WIN32)
|
||||
#include <windows.h>
|
||||
extern "C" BOOL WINAPI DllMain(HINSTANCE, DWORD, LPVOID) { return 1; }
|
||||
#endif // _WIN32
|
||||
@@ -1,23 +0,0 @@
|
||||
# Example by Ullrich Koethe
|
||||
r'''>>> from abstract import *
|
||||
>>> class A(Abstract):
|
||||
... def __init__(self, text):
|
||||
... Abstract.__init__(self) # call the base class constructor
|
||||
... self.text = text
|
||||
... def test(self): # implement abstract function
|
||||
... return self.text
|
||||
...
|
||||
>>> a = A("Hello")
|
||||
>>> a.test()
|
||||
'Hello'
|
||||
'''
|
||||
|
||||
def run(args = None):
|
||||
if args is not None:
|
||||
import sys
|
||||
sys.argv = args
|
||||
import doctest, test_abstract
|
||||
doctest.testmod(test_abstract)
|
||||
|
||||
if __name__ == '__main__':
|
||||
run()
|
||||
@@ -1,50 +0,0 @@
|
||||
r'''
|
||||
// (C) Copyright David Abrahams 2000. 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.
|
||||
//
|
||||
// The author gratefully acknowleges the support of Dragon Systems, Inc., in
|
||||
// producing this work.
|
||||
|
||||
That's it! If we build this shared library and put it on our PYTHONPATH we can
|
||||
now access our C++ class and function from Python.
|
||||
|
||||
>>> import hello
|
||||
>>> hi_world = hello.world(3)
|
||||
>>> hi_world.get()
|
||||
'hi, world'
|
||||
>>> hello.length(hi_world)
|
||||
9
|
||||
|
||||
We can even make a subclass of hello.world:
|
||||
|
||||
|
||||
>>> class my_subclass(hello.world):
|
||||
... def get(self):
|
||||
... return 'hello, world'
|
||||
...
|
||||
>>> y = my_subclass(2)
|
||||
>>> y.get()
|
||||
'hello, world'
|
||||
|
||||
Pretty cool! You can't do that with an ordinary Python extension type!
|
||||
|
||||
>>> hello.length(y)
|
||||
9
|
||||
|
||||
Of course, you may now have a slightly empty feeling in the pit of your little
|
||||
pythonic stomach. Perhaps you feel your subclass deserves to have a length() of
|
||||
12? If so, read on...
|
||||
'''
|
||||
from hello import *
|
||||
|
||||
def run(args = None):
|
||||
if args is not None:
|
||||
import sys
|
||||
sys.argv = args
|
||||
import doctest, test_example1
|
||||
doctest.testmod(test_example1)
|
||||
|
||||
if __name__ == '__main__':
|
||||
run()
|
||||
@@ -1,17 +0,0 @@
|
||||
r'''>>> import getting_started1
|
||||
>>> print getting_started1.greet()
|
||||
hello, world
|
||||
>>> number = 11
|
||||
>>> print number, '*', number, '=', getting_started1.square(number)
|
||||
11 * 11 = 121
|
||||
'''
|
||||
|
||||
def run(args = None):
|
||||
if args is not None:
|
||||
import sys
|
||||
sys.argv = args
|
||||
import doctest, test_getting_started1
|
||||
doctest.testmod(test_getting_started1)
|
||||
|
||||
if __name__ == '__main__':
|
||||
run()
|
||||
@@ -1,29 +0,0 @@
|
||||
r'''>>> from getting_started2 import *
|
||||
>>> hi = hello('California')
|
||||
>>> hi.greet()
|
||||
'Hello from California'
|
||||
>>> invite(hi)
|
||||
'Hello from California! Please come soon!'
|
||||
>>> hi.invite()
|
||||
'Hello from California! Please come soon!'
|
||||
|
||||
>>> class wordy(hello):
|
||||
... def greet(self):
|
||||
... return hello.greet(self) + ', where the weather is fine'
|
||||
...
|
||||
>>> hi2 = wordy('Florida')
|
||||
>>> hi2.greet()
|
||||
'Hello from Florida, where the weather is fine'
|
||||
>>> invite(hi2)
|
||||
'Hello from Florida! Please come soon!'
|
||||
'''
|
||||
|
||||
def run(args = None):
|
||||
if args is not None:
|
||||
import sys
|
||||
sys.argv = args
|
||||
import doctest, test_getting_started2
|
||||
doctest.testmod(test_getting_started2)
|
||||
|
||||
if __name__ == '__main__':
|
||||
run()
|
||||
@@ -1,56 +0,0 @@
|
||||
r'''>>> import getting_started3
|
||||
>>> import re
|
||||
>>> import pickle
|
||||
>>> getting_started3.world.__module__
|
||||
'getting_started3'
|
||||
>>> getting_started3.world.__safe_for_unpickling__
|
||||
1
|
||||
>>> getting_started3.world.__reduce__()
|
||||
'world'
|
||||
>>> assert re.match(
|
||||
... "\(<extension class getting_started3.world at [0-9a-fA-FxX]+>, \('Hello',\), \(0,\)\)",
|
||||
... repr(getting_started3.world('Hello').__reduce__()))
|
||||
>>>
|
||||
>>> for number in (24, 42):
|
||||
... wd = getting_started3.world('California')
|
||||
... wd.set_secret_number(number)
|
||||
... pstr = pickle.dumps(wd)
|
||||
... print pstr
|
||||
... wl = pickle.loads(pstr)
|
||||
... print wd.greet(), wd.get_secret_number()
|
||||
... print wl.greet(), wl.get_secret_number()
|
||||
cgetting_started3
|
||||
world
|
||||
p0
|
||||
(S'California'
|
||||
p1
|
||||
tp2
|
||||
R(I24
|
||||
tp3
|
||||
bp4
|
||||
.
|
||||
Hello from California! 24
|
||||
Hello from California! 24
|
||||
cgetting_started3
|
||||
world
|
||||
p0
|
||||
(S'California'
|
||||
p1
|
||||
tp2
|
||||
R(I42
|
||||
tp3
|
||||
bp4
|
||||
.
|
||||
Hello from California! 42
|
||||
Hello from California! 0
|
||||
'''
|
||||
|
||||
def run(args = None):
|
||||
if args is not None:
|
||||
import sys
|
||||
sys.argv = args
|
||||
import doctest, test_getting_started3
|
||||
doctest.testmod(test_getting_started3)
|
||||
|
||||
if __name__ == '__main__':
|
||||
run()
|
||||
@@ -1,35 +0,0 @@
|
||||
r'''>>> import getting_started4
|
||||
>>> v=getting_started4.vector_double()
|
||||
>>> print v.as_tuple()
|
||||
()
|
||||
>>> v=getting_started4.vector_double(5)
|
||||
>>> print v.as_tuple()
|
||||
(0.0, 0.0, 0.0, 0.0, 0.0)
|
||||
>>> print len(v)
|
||||
5
|
||||
>>> v=getting_started4.vector_double((3,4,5))
|
||||
>>> print v.as_tuple()
|
||||
(3.0, 4.0, 5.0)
|
||||
>>> print v[1]
|
||||
4.0
|
||||
>>> v[1] = 40
|
||||
>>> print v.as_tuple()
|
||||
(3.0, 40.0, 5.0)
|
||||
>>> del v[1]
|
||||
>>> print v.as_tuple()
|
||||
(3.0, 5.0)
|
||||
>>> print getting_started4.foo(11).as_tuple()
|
||||
(0.0, 1.0, 2.0, 3.0, 4.0, 5.0, 6.0, 7.0, 8.0, 9.0, 10.0)
|
||||
>>> print getting_started4.bar(12).as_tuple()
|
||||
(0.0, 10.0, 20.0, 30.0, 40.0, 50.0, 60.0, 70.0, 80.0, 90.0, 100.0, 110.0)
|
||||
'''
|
||||
|
||||
def run(args = None):
|
||||
if args is not None:
|
||||
import sys
|
||||
sys.argv = args
|
||||
import doctest, test_getting_started4
|
||||
doctest.testmod(test_getting_started4)
|
||||
|
||||
if __name__ == '__main__':
|
||||
run()
|
||||
@@ -1,22 +0,0 @@
|
||||
r'''>>> import getting_started5
|
||||
>>> ixset = getting_started5.IndexingSet()
|
||||
>>> ixset.add((1,2,3))
|
||||
>>> ixset.add((4,5,6))
|
||||
>>> ixset.add((7,8,9))
|
||||
>>> print ixset.get(0)
|
||||
(1, 2, 3)
|
||||
>>> print ixset.get(1)
|
||||
(4, 5, 6)
|
||||
>>> print ixset.get(2)
|
||||
(7, 8, 9)
|
||||
'''
|
||||
|
||||
def run(args = None):
|
||||
if args is not None:
|
||||
import sys
|
||||
sys.argv = args
|
||||
import doctest, test_getting_started5
|
||||
doctest.testmod(test_getting_started5)
|
||||
|
||||
if __name__ == '__main__':
|
||||
run()
|
||||
@@ -1,17 +0,0 @@
|
||||
r'''>>> import rwgk1
|
||||
>>> print rwgk1.greet()
|
||||
hello, world
|
||||
>>> number = 11
|
||||
>>> print number, '*', number, '=', rwgk1.square(number)
|
||||
11 * 11 = 121
|
||||
'''
|
||||
|
||||
def run(args = None):
|
||||
if args is not None:
|
||||
import sys
|
||||
sys.argv = args
|
||||
import doctest, test_rwgk1
|
||||
doctest.testmod(test_rwgk1)
|
||||
|
||||
if __name__ == '__main__':
|
||||
run()
|
||||
52
include/boost/python/arg_from_python.hpp
Executable file
52
include/boost/python/arg_from_python.hpp
Executable file
@@ -0,0 +1,52 @@
|
||||
// Copyright David Abrahams 2002. Permission to copy, use,
|
||||
// modify, sell and distribute this software is granted provided this
|
||||
// copyright notice appears in all copies. This software is provided
|
||||
// "as is" without express or implied warranty, and with no claim as
|
||||
// to its suitability for any purpose.
|
||||
#ifndef ARG_FROM_PYTHON_DWA2002128_HPP
|
||||
# define ARG_FROM_PYTHON_DWA2002128_HPP
|
||||
|
||||
# include <boost/python/converter/arg_from_python.hpp>
|
||||
|
||||
namespace boost { namespace python {
|
||||
|
||||
template <class T>
|
||||
struct arg_from_python
|
||||
: converter::select_arg_from_python<T>::type
|
||||
{
|
||||
typedef typename converter::select_arg_from_python<T>::type base;
|
||||
arg_from_python(PyObject*);
|
||||
};
|
||||
|
||||
// specialization for PyObject*
|
||||
template <>
|
||||
struct arg_from_python<PyObject*>
|
||||
{
|
||||
typedef PyObject* result_type;
|
||||
|
||||
arg_from_python(PyObject*) {}
|
||||
bool convertible() const { return true; }
|
||||
PyObject* operator()(PyObject* source) const { return source; }
|
||||
};
|
||||
|
||||
template <>
|
||||
struct arg_from_python<PyObject* const&>
|
||||
{
|
||||
typedef PyObject* const& result_type;
|
||||
arg_from_python(PyObject*) {}
|
||||
bool convertible() const { return true; }
|
||||
PyObject*const& operator()(PyObject*const& source) const { return source; }
|
||||
};
|
||||
|
||||
//
|
||||
// implementations
|
||||
//
|
||||
template <class T>
|
||||
inline arg_from_python<T>::arg_from_python(PyObject* source)
|
||||
: base(source)
|
||||
{
|
||||
}
|
||||
|
||||
}} // namespace boost::python
|
||||
|
||||
#endif // ARG_FROM_PYTHON_DWA2002128_HPP
|
||||
34
include/boost/python/args.hpp
Normal file
34
include/boost/python/args.hpp
Normal file
@@ -0,0 +1,34 @@
|
||||
// Copyright David Abrahams 2002. Permission to copy, use,
|
||||
// modify, sell and distribute this software is granted provided this
|
||||
// copyright notice appears in all copies. This software is provided
|
||||
// "as is" without express or implied warranty, and with no claim as
|
||||
// to its suitability for any purpose.
|
||||
#ifndef ARGS_DWA2002323_HPP
|
||||
# define ARGS_DWA2002323_HPP
|
||||
# include <boost/config.hpp>
|
||||
# include <boost/python/detail/preprocessor.hpp>
|
||||
# include <boost/python/detail/type_list.hpp>
|
||||
|
||||
namespace boost { namespace python {
|
||||
|
||||
enum no_init_t { no_init };
|
||||
|
||||
namespace detail
|
||||
{
|
||||
template <class Args>
|
||||
struct args_base {};
|
||||
}
|
||||
}}
|
||||
|
||||
namespace boost { namespace python {
|
||||
|
||||
// A type list for specifying arguments
|
||||
template < BOOST_PYTHON_ENUM_WITH_DEFAULT(BOOST_PYTHON_MAX_ARITY, typename A, mpl::void_) >
|
||||
struct args : detail::args_base<args<BOOST_PYTHON_UNARY_ENUM(BOOST_PYTHON_MAX_ARITY, A)> >
|
||||
, detail::type_list< BOOST_PYTHON_UNARY_ENUM(BOOST_PYTHON_MAX_ARITY, A) >::type
|
||||
{};
|
||||
|
||||
}} // namespace boost::python
|
||||
|
||||
|
||||
# endif // ARGS_DWA2002323_HPP
|
||||
101
include/boost/python/back_reference.hpp
Normal file
101
include/boost/python/back_reference.hpp
Normal file
@@ -0,0 +1,101 @@
|
||||
// Copyright David Abrahams 2002. Permission to copy, use,
|
||||
// modify, sell and distribute this software is granted provided this
|
||||
// copyright notice appears in all copies. This software is provided
|
||||
// "as is" without express or implied warranty, and with no claim as
|
||||
// to its suitability for any purpose.
|
||||
#ifndef BACK_REFERENCE_DWA2002510_HPP
|
||||
# define BACK_REFERENCE_DWA2002510_HPP
|
||||
|
||||
# include <boost/python/object_fwd.hpp>
|
||||
# include <boost/python/detail/dependent.hpp>
|
||||
# include <boost/python/detail/raw_pyobject.hpp>
|
||||
|
||||
namespace boost { namespace python {
|
||||
|
||||
template <class T>
|
||||
struct back_reference
|
||||
{
|
||||
private: // types
|
||||
typedef typename detail::dependent<object,T>::type source_t;
|
||||
public:
|
||||
typedef T type;
|
||||
|
||||
back_reference(PyObject*, T);
|
||||
source_t const& source() const;
|
||||
T get() const;
|
||||
private:
|
||||
source_t m_source;
|
||||
T m_value;
|
||||
};
|
||||
|
||||
# ifndef BOOST_NO_TEMPLATE_PARTIAL_SPECIALIZATION
|
||||
template<typename T>
|
||||
class is_back_reference
|
||||
{
|
||||
public:
|
||||
BOOST_STATIC_CONSTANT(bool, value = false);
|
||||
};
|
||||
|
||||
template<typename T>
|
||||
class is_back_reference<back_reference<T> >
|
||||
{
|
||||
public:
|
||||
BOOST_STATIC_CONSTANT(bool, value = true);
|
||||
};
|
||||
|
||||
# else // no partial specialization
|
||||
|
||||
}} // namespace boost::python
|
||||
|
||||
#include <boost/type.hpp>
|
||||
|
||||
namespace boost { namespace python {
|
||||
|
||||
namespace detail
|
||||
{
|
||||
typedef char (&yes_back_reference_t)[1];
|
||||
typedef char (&no_back_reference_t)[2];
|
||||
|
||||
no_back_reference_t is_back_reference_test(...);
|
||||
|
||||
template<typename T>
|
||||
yes_back_reference_t is_back_reference_test(boost::type< back_reference<T> >);
|
||||
}
|
||||
|
||||
template<typename T>
|
||||
class is_back_reference
|
||||
{
|
||||
public:
|
||||
BOOST_STATIC_CONSTANT(
|
||||
bool, value = (
|
||||
sizeof(detail::is_back_reference_test(boost::type<T>()))
|
||||
== sizeof(detail::yes_back_reference_t)));
|
||||
};
|
||||
|
||||
# endif // BOOST_NO_TEMPLATE_PARTIAL_SPECIALIZATION
|
||||
|
||||
//
|
||||
// implementations
|
||||
//
|
||||
template <class T>
|
||||
back_reference<T>::back_reference(PyObject* p, T x)
|
||||
: m_source(detail::borrowed_reference(p))
|
||||
, m_value(x)
|
||||
{
|
||||
}
|
||||
|
||||
template <class T>
|
||||
typename back_reference<T>::source_t const& back_reference<T>::source() const
|
||||
{
|
||||
return m_source;
|
||||
}
|
||||
|
||||
template <class T>
|
||||
T back_reference<T>::get() const
|
||||
{
|
||||
return m_value;
|
||||
}
|
||||
|
||||
}} // namespace boost::python
|
||||
|
||||
#endif // BACK_REFERENCE_DWA2002510_HPP
|
||||
36
include/boost/python/base_type_traits.hpp
Executable file
36
include/boost/python/base_type_traits.hpp
Executable file
@@ -0,0 +1,36 @@
|
||||
// Copyright David Abrahams 2002. Permission to copy, use,
|
||||
// modify, sell and distribute this software is granted provided this
|
||||
// copyright notice appears in all copies. This software is provided
|
||||
// "as is" without express or implied warranty, and with no claim as
|
||||
// to its suitability for any purpose.
|
||||
#ifndef BASE_TYPE_TRAITS_DWA2002614_HPP
|
||||
# define BASE_TYPE_TRAITS_DWA2002614_HPP
|
||||
|
||||
namespace boost { namespace python {
|
||||
|
||||
namespace detail
|
||||
{
|
||||
struct unspecialized {};
|
||||
}
|
||||
|
||||
// Derive from unspecialized so we can detect whether traits are
|
||||
// specialized
|
||||
template <class T> struct base_type_traits
|
||||
: detail::unspecialized
|
||||
{};
|
||||
|
||||
template <>
|
||||
struct base_type_traits<PyObject>
|
||||
{
|
||||
typedef PyObject type;
|
||||
};
|
||||
|
||||
template <>
|
||||
struct base_type_traits<PyTypeObject>
|
||||
{
|
||||
typedef PyObject type;
|
||||
};
|
||||
|
||||
}} // namespace boost::python
|
||||
|
||||
#endif // BASE_TYPE_TRAITS_DWA2002614_HPP
|
||||
60
include/boost/python/bases.hpp
Normal file
60
include/boost/python/bases.hpp
Normal file
@@ -0,0 +1,60 @@
|
||||
// Copyright David Abrahams 2002. Permission to copy, use,
|
||||
// modify, sell and distribute this software is granted provided this
|
||||
// copyright notice appears in all copies. This software is provided
|
||||
// "as is" without express or implied warranty, and with no claim as
|
||||
// to its suitability for any purpose.
|
||||
#ifndef BASES_DWA2002321_HPP
|
||||
# define BASES_DWA2002321_HPP
|
||||
# include <boost/type_traits/object_traits.hpp>
|
||||
# include <boost/python/detail/type_list.hpp>
|
||||
# include <boost/mpl/if.hpp>
|
||||
# include <boost/preprocessor/enum_params_with_a_default.hpp>
|
||||
# include <boost/preprocessor/enum_params.hpp>
|
||||
|
||||
namespace boost { namespace python {
|
||||
|
||||
// A type list for specifying bases
|
||||
template < BOOST_PP_ENUM_PARAMS_WITH_A_DEFAULT(BOOST_PYTHON_MAX_BASES, typename B, mpl::void_) >
|
||||
struct bases : detail::type_list< BOOST_PP_ENUM_PARAMS(BOOST_PYTHON_MAX_BASES, B) >::type
|
||||
{};
|
||||
|
||||
namespace detail
|
||||
{
|
||||
# ifndef BOOST_NO_TEMPLATE_PARTIAL_SPECIALIZATION
|
||||
template <class T> struct specifies_bases
|
||||
{
|
||||
BOOST_STATIC_CONSTANT(bool, value = false);
|
||||
};
|
||||
template < BOOST_PP_ENUM_PARAMS(BOOST_PYTHON_MAX_BASES, class B) >
|
||||
struct specifies_bases< bases< BOOST_PP_ENUM_PARAMS(BOOST_PYTHON_MAX_BASES, B) > >
|
||||
{
|
||||
BOOST_STATIC_CONSTANT(bool, value = true);
|
||||
};
|
||||
# else
|
||||
template < BOOST_PP_ENUM_PARAMS(BOOST_PYTHON_MAX_BASES, class B) >
|
||||
static char is_bases_helper(bases< BOOST_PP_ENUM_PARAMS(BOOST_PYTHON_MAX_BASES, B) > const&);
|
||||
|
||||
static char (& is_bases_helper(...) )[256];
|
||||
|
||||
template <class T> struct specifies_bases
|
||||
{
|
||||
private:
|
||||
static typename add_reference<T>::type make();
|
||||
BOOST_STATIC_CONSTANT(bool, non_ref = !is_reference<T>::value);
|
||||
public:
|
||||
BOOST_STATIC_CONSTANT(bool, value = non_ref & (sizeof(is_bases_helper(make())) == 1));
|
||||
};
|
||||
# endif
|
||||
template <class T, class Prev = bases<> >
|
||||
struct select_bases
|
||||
: mpl::if_c<
|
||||
specifies_bases<T>::value
|
||||
, T
|
||||
, Prev
|
||||
>
|
||||
{
|
||||
};
|
||||
}
|
||||
}} // namespace boost::python
|
||||
|
||||
#endif // BASES_DWA2002321_HPP
|
||||
20
include/boost/python/borrowed.hpp
Executable file
20
include/boost/python/borrowed.hpp
Executable file
@@ -0,0 +1,20 @@
|
||||
// Copyright David Abrahams 2002. Permission to copy, use,
|
||||
// modify, sell and distribute this software is granted provided this
|
||||
// copyright notice appears in all copies. This software is provided
|
||||
// "as is" without express or implied warranty, and with no claim as
|
||||
// to its suitability for any purpose.
|
||||
#ifndef BORROWED_DWA2002614_HPP
|
||||
# define BORROWED_DWA2002614_HPP
|
||||
# include <boost/python/detail/borrowed_ptr.hpp>
|
||||
|
||||
namespace boost { namespace python {
|
||||
|
||||
template <class T>
|
||||
inline python::detail::borrowed<T>* borrowed(T* p)
|
||||
{
|
||||
return (detail::borrowed<T>*)p;
|
||||
}
|
||||
|
||||
}} // namespace boost::python
|
||||
|
||||
#endif // BORROWED_DWA2002614_HPP
|
||||
64
include/boost/python/call.hpp
Normal file
64
include/boost/python/call.hpp
Normal file
@@ -0,0 +1,64 @@
|
||||
#if !defined(BOOST_PP_IS_ITERATING)
|
||||
|
||||
// Copyright David Abrahams 2002. Permission to copy, use,
|
||||
// modify, sell and distribute this software is granted provided this
|
||||
// copyright notice appears in all copies. This software is provided
|
||||
// "as is" without express or implied warranty, and with no claim as
|
||||
// to its suitability for any purpose.
|
||||
|
||||
# ifndef CALL_DWA2002411_HPP
|
||||
# define CALL_DWA2002411_HPP
|
||||
|
||||
# include <boost/type.hpp>
|
||||
|
||||
# include <boost/python/converter/arg_to_python.hpp>
|
||||
# include <boost/python/converter/return_from_python.hpp>
|
||||
# include <boost/python/detail/preprocessor.hpp>
|
||||
# include <boost/python/detail/void_return.hpp>
|
||||
|
||||
# include <boost/preprocessor/comma_if.hpp>
|
||||
# include <boost/preprocessor/iterate.hpp>
|
||||
# include <boost/preprocessor/repeat.hpp>
|
||||
# include <boost/preprocessor/debug/line.hpp>
|
||||
|
||||
namespace boost { namespace python {
|
||||
|
||||
# define BOOST_PYTHON_FAST_ARG_TO_PYTHON_GET(z, n, _) \
|
||||
, converter::arg_to_python<A##n>(a##n).get()
|
||||
|
||||
# define BOOST_PP_ITERATION_PARAMS_1 (3, (0, BOOST_PYTHON_MAX_ARITY, <boost/python/call.hpp>))
|
||||
# include BOOST_PP_ITERATE()
|
||||
|
||||
# undef BOOST_PYTHON_FAST_ARG_TO_PYTHON_GET
|
||||
|
||||
}} // namespace boost::python
|
||||
|
||||
# endif // CALL_DWA2002411_HPP
|
||||
|
||||
#elif BOOST_PP_ITERATION_DEPTH() == 1
|
||||
# line BOOST_PP_LINE(__LINE__, call.hpp)
|
||||
|
||||
# define N BOOST_PP_ITERATION()
|
||||
|
||||
template <
|
||||
class R
|
||||
BOOST_PP_COMMA_IF(N) BOOST_PYTHON_UNARY_ENUM(N, class A)
|
||||
>
|
||||
typename detail::returnable<R>::type
|
||||
call(PyObject* callable
|
||||
BOOST_PP_COMMA_IF(N) BOOST_PYTHON_BINARY_ENUM(N, A, const& a)
|
||||
, boost::type<R>* = 0
|
||||
)
|
||||
{
|
||||
converter::return_from_python<R> converter;
|
||||
return converter(
|
||||
PyEval_CallFunction(
|
||||
callable
|
||||
, const_cast<char*>("(" BOOST_PP_REPEAT_1ST(N, BOOST_PYTHON_FIXED, "O") ")")
|
||||
BOOST_PP_REPEAT_1ST(N, BOOST_PYTHON_FAST_ARG_TO_PYTHON_GET, nil)
|
||||
));
|
||||
}
|
||||
|
||||
# undef N
|
||||
|
||||
#endif
|
||||
64
include/boost/python/call_method.hpp
Normal file
64
include/boost/python/call_method.hpp
Normal file
@@ -0,0 +1,64 @@
|
||||
#if !defined(BOOST_PP_IS_ITERATING)
|
||||
|
||||
// Copyright David Abrahams 2002. Permission to copy, use,
|
||||
// modify, sell and distribute this software is granted provided this
|
||||
// copyright notice appears in all copies. This software is provided
|
||||
// "as is" without express or implied warranty, and with no claim as
|
||||
// to its suitability for any purpose.
|
||||
# ifndef CALL_METHOD_DWA2002411_HPP
|
||||
# define CALL_METHOD_DWA2002411_HPP
|
||||
|
||||
# include <boost/type.hpp>
|
||||
|
||||
# include <boost/python/converter/arg_to_python.hpp>
|
||||
# include <boost/python/converter/return_from_python.hpp>
|
||||
# include <boost/python/detail/preprocessor.hpp>
|
||||
# include <boost/python/detail/void_return.hpp>
|
||||
|
||||
# include <boost/preprocessor/comma_if.hpp>
|
||||
# include <boost/preprocessor/iterate.hpp>
|
||||
# include <boost/preprocessor/repeat.hpp>
|
||||
# include <boost/preprocessor/debug/line.hpp>
|
||||
|
||||
namespace boost { namespace python {
|
||||
|
||||
# define BOOST_PYTHON_FAST_ARG_TO_PYTHON_GET(z, n, _) \
|
||||
, converter::arg_to_python<A##n>(a##n).get()
|
||||
|
||||
# define BOOST_PP_ITERATION_PARAMS_1 (3, (0, BOOST_PYTHON_MAX_ARITY, <boost/python/call_method.hpp>))
|
||||
# include BOOST_PP_ITERATE()
|
||||
|
||||
# undef BOOST_PYTHON_FAST_ARG_TO_PYTHON_GET
|
||||
|
||||
}} // namespace boost::python
|
||||
|
||||
# endif // CALL_METHOD_DWA2002411_HPP
|
||||
|
||||
#elif BOOST_PP_ITERATION_DEPTH() == 1
|
||||
# line BOOST_PP_LINE(__LINE__, call_method.hpp)
|
||||
|
||||
# define N BOOST_PP_ITERATION()
|
||||
|
||||
template <
|
||||
class R
|
||||
BOOST_PP_COMMA_IF(N) BOOST_PYTHON_UNARY_ENUM(N, class A)
|
||||
>
|
||||
typename detail::returnable<R>::type
|
||||
call_method(PyObject* self, char const* name
|
||||
BOOST_PP_COMMA_IF(N) BOOST_PYTHON_BINARY_ENUM(N, A, const& a)
|
||||
, boost::type<R>* = 0
|
||||
)
|
||||
{
|
||||
converter::return_from_python<R> converter;
|
||||
return converter(
|
||||
PyEval_CallMethod(
|
||||
self
|
||||
, const_cast<char*>(name)
|
||||
, const_cast<char*>("(" BOOST_PP_REPEAT_1ST(N, BOOST_PYTHON_FIXED, "O") ")")
|
||||
BOOST_PP_REPEAT_1ST(N, BOOST_PYTHON_FAST_ARG_TO_PYTHON_GET, nil)
|
||||
));
|
||||
}
|
||||
|
||||
# undef N
|
||||
|
||||
#endif // BOOST_PP_IS_ITERATING
|
||||
106
include/boost/python/cast.hpp
Executable file
106
include/boost/python/cast.hpp
Executable file
@@ -0,0 +1,106 @@
|
||||
// Copyright David Abrahams 2002. Permission to copy, use,
|
||||
// modify, sell and distribute this software is granted provided this
|
||||
// copyright notice appears in all copies. This software is provided
|
||||
// "as is" without express or implied warranty, and with no claim as
|
||||
// to its suitability for any purpose.
|
||||
#ifndef CAST_DWA200269_HPP
|
||||
# define CAST_DWA200269_HPP
|
||||
|
||||
# include <boost/python/detail/wrap_python.hpp>
|
||||
# include <boost/type_traits/same_traits.hpp>
|
||||
# include <boost/type_traits/cv_traits.hpp>
|
||||
# include <boost/type.hpp>
|
||||
# include <boost/python/base_type_traits.hpp>
|
||||
# include <boost/python/detail/convertible.hpp>
|
||||
|
||||
namespace boost { namespace python {
|
||||
|
||||
namespace detail
|
||||
{
|
||||
template <class Source, class Target> inline Target* upcast_impl(Source*, Target*);
|
||||
|
||||
template <class Source, class Target>
|
||||
inline Target* upcast(Source* p, yes_convertible, no_convertible, Target*)
|
||||
{
|
||||
return p;
|
||||
}
|
||||
|
||||
template <class Source, class Target>
|
||||
inline Target* upcast(Source* p, no_convertible, no_convertible, Target*)
|
||||
{
|
||||
typedef typename base_type_traits<Source>::type base;
|
||||
|
||||
return detail::upcast_impl((base*)p, (Target*)0);
|
||||
}
|
||||
|
||||
template <bool is_same = true>
|
||||
struct upcaster
|
||||
{
|
||||
template <class T>
|
||||
static inline T* execute(T* x, T*) { return x; }
|
||||
};
|
||||
|
||||
template <>
|
||||
struct upcaster<false>
|
||||
{
|
||||
template <class Source, class Target>
|
||||
static inline Target* execute(Source* x, Target*)
|
||||
{
|
||||
return detail::upcast(
|
||||
x, detail::convertible<Target*>::check(x)
|
||||
, detail::convertible<Source*>::check((Target*)0)
|
||||
, (Target*)0);
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
template <class Target, class Source>
|
||||
inline Target* downcast(Source* p, yes_convertible)
|
||||
{
|
||||
return static_cast<Target*>(p);
|
||||
}
|
||||
|
||||
template <class Target, class Source>
|
||||
inline Target* downcast(Source* p, no_convertible, boost::type<Target>* = 0)
|
||||
{
|
||||
typedef typename base_type_traits<Source>::type base;
|
||||
return (Target*)detail::downcast<base>(p, convertible<Source*>::check((base*)0));
|
||||
}
|
||||
|
||||
template <class T>
|
||||
inline void assert_castable(boost::type<T>* = 0)
|
||||
{
|
||||
typedef char must_be_a_complete_type[sizeof(T)];
|
||||
}
|
||||
|
||||
template <class Source, class Target>
|
||||
inline Target* upcast_impl(Source* x, Target*)
|
||||
{
|
||||
typedef typename add_cv<Source>::type src_t;
|
||||
typedef typename add_cv<Target>::type target_t;
|
||||
static bool const same = is_same<src_t,target_t>::value;
|
||||
|
||||
return detail::upcaster<same>::execute(x, (Target*)0);
|
||||
}
|
||||
}
|
||||
|
||||
template <class Target, class Source>
|
||||
inline Target* upcast(Source* x, Target* = 0)
|
||||
{
|
||||
detail::assert_castable<Source>();
|
||||
detail::assert_castable<Target>();
|
||||
return detail::upcast_impl(x, (Target*)0);
|
||||
|
||||
}
|
||||
|
||||
template <class Target, class Source>
|
||||
inline Target* downcast(Source* x, Target* = 0)
|
||||
{
|
||||
detail::assert_castable<Source>();
|
||||
detail::assert_castable<Target>();
|
||||
return detail::downcast<Target>(x, detail::convertible<Source*>::check((Target*)0));
|
||||
}
|
||||
|
||||
}} // namespace boost::python
|
||||
|
||||
#endif // CAST_DWA200269_HPP
|
||||
436
include/boost/python/class.hpp
Normal file
436
include/boost/python/class.hpp
Normal file
@@ -0,0 +1,436 @@
|
||||
// Copyright David Abrahams 2002. Permission to copy, use,
|
||||
// modify, sell and distribute this software is granted provided this
|
||||
// copyright notice appears in all copies. This software is provided
|
||||
// "as is" without express or implied warranty, and with no claim as
|
||||
// to its suitability for any purpose.
|
||||
#ifndef CLASS_DWA200216_HPP
|
||||
# define CLASS_DWA200216_HPP
|
||||
|
||||
# include <boost/python/class_fwd.hpp>
|
||||
# include <boost/python/object/class.hpp>
|
||||
# include <boost/python/bases.hpp>
|
||||
# include <boost/python/args.hpp>
|
||||
|
||||
# include <boost/python/object.hpp>
|
||||
|
||||
# include <boost/python/type_id.hpp>
|
||||
# include <boost/python/detail/member_function_cast.hpp>
|
||||
# include <boost/python/object/class_converters.hpp>
|
||||
# include <boost/type_traits/ice.hpp>
|
||||
# include <boost/type_traits/same_traits.hpp>
|
||||
# include <boost/mpl/size.hpp>
|
||||
# include <boost/mpl/for_each.hpp>
|
||||
# include <boost/mpl/bool_c.hpp>
|
||||
# include <boost/python/object/select_holder.hpp>
|
||||
# include <boost/python/object/class_wrapper.hpp>
|
||||
# include <boost/python/object/make_instance.hpp>
|
||||
# include <boost/python/data_members.hpp>
|
||||
# include <boost/utility.hpp>
|
||||
# include <boost/python/detail/operator_id.hpp>
|
||||
# include <boost/python/object/pickle_support.hpp>
|
||||
# include <boost/python/make_function.hpp>
|
||||
# include <boost/python/object/add_to_namespace.hpp>
|
||||
# include <boost/python/detail/def_helper.hpp>
|
||||
# include <boost/python/detail/force_instantiate.hpp>
|
||||
# include <boost/python/detail/defaults_def.hpp>
|
||||
# include <boost/python/signature.hpp>
|
||||
# include <boost/python/init.hpp>
|
||||
|
||||
namespace boost { namespace python {
|
||||
|
||||
namespace detail
|
||||
{
|
||||
// This function object is used with mpl::for_each to write the id
|
||||
// of the type a pointer to which is passed as its 2nd compile-time
|
||||
// argument. into the iterator pointed to by its runtime argument
|
||||
struct write_type_id
|
||||
{
|
||||
write_type_id(type_info**p) : p(p) {}
|
||||
|
||||
// Here's the runtime behavior
|
||||
template <class T>
|
||||
void operator()(T*) const
|
||||
{
|
||||
*(*p)++ = type_id<T>();
|
||||
};
|
||||
|
||||
type_info** p;
|
||||
};
|
||||
|
||||
template <class T, class Prev = detail::not_specified>
|
||||
struct select_held_type;
|
||||
|
||||
template <class T1, class T2, class T3>
|
||||
struct has_noncopyable;
|
||||
|
||||
template <detail::operator_id, class L, class R>
|
||||
struct operator_;
|
||||
|
||||
// Register a to_python converter for a class T, depending on the
|
||||
// type of the first (tag) argument. The 2nd argument is a pointer
|
||||
// to the type of holder that must be created. The 3rd argument is a
|
||||
// reference to the Python type object to be created.
|
||||
template <class T, class SelectHolder>
|
||||
static inline void register_copy_constructor(mpl::bool_c<true> const&, SelectHolder const& , T* = 0)
|
||||
{
|
||||
typedef typename SelectHolder::type holder;
|
||||
force_instantiate(objects::class_wrapper<T,holder, objects::make_instance<T,holder> >());
|
||||
SelectHolder::register_();
|
||||
}
|
||||
|
||||
// Tag dispatched to have no effect.
|
||||
template <class T, class SelectHolder>
|
||||
static inline void register_copy_constructor(mpl::bool_c<false> const&, SelectHolder const&, T* = 0)
|
||||
{
|
||||
SelectHolder::register_();
|
||||
}
|
||||
|
||||
template <class T> int assert_default_constructible(T const&);
|
||||
}
|
||||
|
||||
//
|
||||
// class_<T,Bases,HolderGenerator>
|
||||
//
|
||||
// This is the primary mechanism through which users will expose
|
||||
// C++ classes to Python. The three template arguments are:
|
||||
//
|
||||
template <
|
||||
class T // class being wrapped
|
||||
, class X1 // = detail::not_specified
|
||||
, class X2 // = detail::not_specified
|
||||
, class X3 // = detail::not_specified
|
||||
>
|
||||
class class_ : public objects::class_base
|
||||
{
|
||||
private: // types
|
||||
typedef objects::class_base base;
|
||||
|
||||
typedef class_<T,X1,X2,X3> self;
|
||||
BOOST_STATIC_CONSTANT(bool, is_copyable = (!detail::has_noncopyable<X1,X2,X3>::value));
|
||||
|
||||
typedef typename detail::select_held_type<
|
||||
X1, typename detail::select_held_type<
|
||||
X2, typename detail::select_held_type<
|
||||
X3
|
||||
>::type>::type>::type held_type;
|
||||
|
||||
typedef objects::select_holder<T,held_type> holder_selector;
|
||||
|
||||
typedef typename detail::select_bases<X1
|
||||
, typename detail::select_bases<X2
|
||||
, typename boost::python::detail::select_bases<X3>::type
|
||||
>::type
|
||||
>::type bases;
|
||||
|
||||
// A helper class which will contain an array of id objects to be
|
||||
// passed to the base class constructor
|
||||
struct id_vector
|
||||
{
|
||||
id_vector()
|
||||
{
|
||||
// Stick the derived class id into the first element of the array
|
||||
ids[0] = type_id<T>();
|
||||
|
||||
// Write the rest of the elements into succeeding positions.
|
||||
type_info* p = ids + 1;
|
||||
mpl::for_each(detail::write_type_id(&p), (bases*)0, (add_pointer<mpl::_>*)0);
|
||||
}
|
||||
|
||||
BOOST_STATIC_CONSTANT(
|
||||
std::size_t, size = mpl::size<bases>::value + 1);
|
||||
type_info ids[size];
|
||||
};
|
||||
friend struct id_vector;
|
||||
|
||||
public:
|
||||
// Automatically derive the class name - only works on some
|
||||
// compilers because type_info::name is sometimes mangled (gcc)
|
||||
// class_(); // With default-constructor init function
|
||||
// class_(no_init_t); // With no init function
|
||||
|
||||
// Construct with the class name, with or without docstring, and default init() function
|
||||
class_(char const* name, char const* doc = 0);
|
||||
|
||||
// Construct with class name, no docstring, and no init() function
|
||||
class_(char const* name, no_init_t);
|
||||
|
||||
// Construct with class name, docstring, and no init() function
|
||||
class_(char const* name, char const* doc, no_init_t);
|
||||
|
||||
template <class DerivedT>
|
||||
inline class_(char const* name, init_base<DerivedT> const& i)
|
||||
: base(name, id_vector::size, id_vector().ids)
|
||||
{
|
||||
this->register_();
|
||||
define_init(*this, i.derived());
|
||||
this->set_instance_size(holder_selector::additional_size());
|
||||
}
|
||||
|
||||
template <class DerivedT>
|
||||
inline class_(char const* name, char const* doc, init_base<DerivedT> const& i)
|
||||
: base(name, id_vector::size, id_vector().ids, doc)
|
||||
{
|
||||
this->register_();
|
||||
define_init(*this, i.derived());
|
||||
this->set_instance_size(holder_selector::additional_size());
|
||||
}
|
||||
|
||||
// Wrap a member function or a non-member function which can take
|
||||
// a T, T cv&, or T cv* as its first parameter, or a callable
|
||||
// python object.
|
||||
template <class F>
|
||||
self& def(char const* name, F f)
|
||||
{
|
||||
this->def_impl(name, f, default_call_policies(), 0, &f);
|
||||
return *this;
|
||||
}
|
||||
|
||||
template <class DerivedT>
|
||||
self& def(init_base<DerivedT> const& i)
|
||||
{
|
||||
define_init(*this, i.derived());
|
||||
return *this;
|
||||
}
|
||||
|
||||
template <class Arg1T, class Arg2T>
|
||||
self& def(char const* name, Arg1T arg1, Arg2T const& arg2)
|
||||
{
|
||||
// The arguments may be:
|
||||
// def(name, function)
|
||||
// def(name, function, policy)
|
||||
// def(name, function, doc_string)
|
||||
// def(name, signature, stubs)
|
||||
|
||||
dispatch_def(&arg2, name, arg1, arg2);
|
||||
return *this;
|
||||
}
|
||||
|
||||
template <class Arg1T, class Arg2T, class Arg3T>
|
||||
self& def(char const* name, Arg1T arg1, Arg2T const& arg2, Arg3T const& arg3)
|
||||
{
|
||||
// The arguments are definitely:
|
||||
// def(name, function, policy, doc_string) // TODO: exchange policy, doc_string position
|
||||
|
||||
dispatch_def(&arg2, name, arg1, arg2, arg3);
|
||||
return *this;
|
||||
}
|
||||
|
||||
template <detail::operator_id id, class L, class R>
|
||||
self& def(detail::operator_<id,L,R> const& op)
|
||||
{
|
||||
typedef detail::operator_<id,L,R> op_t;
|
||||
return this->def(op.name(), &op_t::template apply<T>::execute);
|
||||
}
|
||||
|
||||
// Define the constructor with the given Args, which should be an
|
||||
// MPL sequence of types.
|
||||
template <class Args>
|
||||
self& def_init(Args const&)
|
||||
{
|
||||
return this->def("__init__",
|
||||
python::make_constructor<Args>(
|
||||
// Using runtime type selection works around a CWPro7 bug.
|
||||
holder_selector::execute((held_type*)0).get()
|
||||
)
|
||||
);
|
||||
}
|
||||
|
||||
template <class Args, class CallPolicyOrDoc>
|
||||
self& def_init(Args const&, CallPolicyOrDoc const& policy_or_doc, char const* doc = 0)
|
||||
{
|
||||
typedef detail::def_helper<CallPolicyOrDoc> helper;
|
||||
|
||||
return this->def(
|
||||
"__init__",
|
||||
python::make_constructor<Args>(
|
||||
helper::get_policy(policy_or_doc)
|
||||
// Using runtime type selection works around a CWPro7 bug.
|
||||
, holder_selector::execute((held_type*)0).get()
|
||||
)
|
||||
, helper::get_doc(policy_or_doc, doc)
|
||||
);
|
||||
}
|
||||
|
||||
// Define the default constructor.
|
||||
self& def_init()
|
||||
{
|
||||
this->def_init(mpl::list0<>::type());
|
||||
return *this;
|
||||
}
|
||||
|
||||
//
|
||||
// Data member access
|
||||
//
|
||||
template <class D>
|
||||
self& def_readonly(char const* name, D T::*pm)
|
||||
{
|
||||
this->add_property(name, make_getter(pm));
|
||||
return *this;
|
||||
}
|
||||
|
||||
template <class D>
|
||||
self& def_readwrite(char const* name, D T::*pm)
|
||||
{
|
||||
return this->add_property(name, make_getter(pm), make_setter(pm));
|
||||
}
|
||||
|
||||
// Property creation
|
||||
template <class Get>
|
||||
self& add_property(char const* name, Get const& fget)
|
||||
{
|
||||
base::add_property(name, object(fget));
|
||||
return *this;
|
||||
}
|
||||
|
||||
template <class Get, class Set>
|
||||
self& add_property(char const* name, Get const& fget, Set const& fset)
|
||||
{
|
||||
base::add_property(name, object(fget), object(fset));
|
||||
return *this;
|
||||
}
|
||||
|
||||
template <class U>
|
||||
self& setattr(char const* name, U const& x)
|
||||
{
|
||||
this->base::setattr(name, object(x));
|
||||
return *this;
|
||||
}
|
||||
|
||||
// Pickle support
|
||||
template <typename PickleSuiteType>
|
||||
self& def_pickle(PickleSuiteType const& x)
|
||||
{
|
||||
error_messages::must_be_derived_from_pickle_suite(x);
|
||||
detail::pickle_suite_finalize<PickleSuiteType>::register_(
|
||||
*this,
|
||||
&PickleSuiteType::getinitargs,
|
||||
&PickleSuiteType::getstate,
|
||||
&PickleSuiteType::setstate,
|
||||
PickleSuiteType::getstate_manages_dict());
|
||||
return *this;
|
||||
}
|
||||
|
||||
private: // helper functions
|
||||
|
||||
template <class Fn, class Policies>
|
||||
inline void def_impl(char const* name, Fn fn, Policies const& policies
|
||||
, char const* doc, ...)
|
||||
{
|
||||
objects::add_to_namespace(
|
||||
*this, name,
|
||||
make_function(
|
||||
// This bit of nastiness casts F to a member function of T if possible.
|
||||
detail::member_function_cast<T,Fn>::stage1(fn).stage2((T*)0).stage3(fn)
|
||||
, policies)
|
||||
, doc);
|
||||
}
|
||||
|
||||
template <class F>
|
||||
inline void def_impl(char const* name, F f, default_call_policies const&
|
||||
, char const* doc, object const*)
|
||||
{
|
||||
objects::add_to_namespace(*this, name, f, doc);
|
||||
}
|
||||
|
||||
inline void register_() const;
|
||||
|
||||
template <class Fn, class CallPolicyOrDoc>
|
||||
void dispatch_def(
|
||||
void const*,
|
||||
char const* name,
|
||||
Fn fn,
|
||||
CallPolicyOrDoc const& policy_or_doc,
|
||||
char const* doc = 0)
|
||||
{
|
||||
typedef detail::def_helper<CallPolicyOrDoc> helper;
|
||||
|
||||
this->def_impl(
|
||||
name, fn, helper::get_policy(policy_or_doc),
|
||||
helper::get_doc(policy_or_doc, doc), &fn);
|
||||
|
||||
}
|
||||
|
||||
template <class StubsT, class SigT>
|
||||
void dispatch_def(
|
||||
detail::func_stubs_base const*,
|
||||
char const* name,
|
||||
SigT sig,
|
||||
StubsT const& stubs)
|
||||
{
|
||||
// convert sig to a type_list (see detail::get_signature in signature.hpp)
|
||||
// before calling detail::define_with_defaults.
|
||||
detail::define_with_defaults(
|
||||
name, stubs, *this, detail::get_signature(sig));
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
//
|
||||
// implementations
|
||||
//
|
||||
// register converters
|
||||
template <class T, class X1, class X2, class X3>
|
||||
inline void class_<T,X1,X2,X3>::register_() const
|
||||
{
|
||||
objects::register_class_from_python<T,bases>();
|
||||
|
||||
detail::register_copy_constructor<T>(
|
||||
mpl::bool_c<is_copyable>()
|
||||
, holder_selector::execute((held_type*)0)
|
||||
);
|
||||
}
|
||||
|
||||
template <class T, class X1, class X2, class X3>
|
||||
inline class_<T,X1,X2,X3>::class_(char const* name, char const* doc)
|
||||
: base(name, id_vector::size, id_vector().ids, doc)
|
||||
{
|
||||
this->register_();
|
||||
detail::force_instantiate(sizeof(detail::assert_default_constructible(T())));
|
||||
this->def_init();
|
||||
this->set_instance_size(holder_selector::additional_size());
|
||||
}
|
||||
|
||||
template <class T, class X1, class X2, class X3>
|
||||
inline class_<T,X1,X2,X3>::class_(char const* name, no_init_t)
|
||||
: base(name, id_vector::size, id_vector().ids)
|
||||
{
|
||||
this->register_();
|
||||
this->def_no_init();
|
||||
}
|
||||
|
||||
template <class T, class X1, class X2, class X3>
|
||||
inline class_<T,X1,X2,X3>::class_(char const* name, char const* doc, no_init_t)
|
||||
: base(name, id_vector::size, id_vector().ids, doc)
|
||||
{
|
||||
this->register_();
|
||||
this->def_no_init();
|
||||
}
|
||||
|
||||
namespace detail
|
||||
{
|
||||
template <class T1, class T2, class T3>
|
||||
struct has_noncopyable
|
||||
: type_traits::ice_or<
|
||||
is_same<T1,noncopyable>::value
|
||||
, is_same<T2,noncopyable>::value
|
||||
, is_same<T3,noncopyable>::value>
|
||||
{};
|
||||
|
||||
|
||||
template <class T, class Prev>
|
||||
struct select_held_type
|
||||
: mpl::if_c<
|
||||
type_traits::ice_or<
|
||||
specifies_bases<T>::value
|
||||
, is_same<T,noncopyable>::value
|
||||
>::value
|
||||
, Prev
|
||||
, T
|
||||
>
|
||||
{
|
||||
};
|
||||
}
|
||||
|
||||
}} // namespace boost::python
|
||||
|
||||
#endif // CLASS_DWA200216_HPP
|
||||
@@ -25,6 +25,22 @@ class class_builder
|
||||
module.add(ref(as_object(m_class.get()), ref::increment_count), name);
|
||||
}
|
||||
|
||||
template <class OtherT, class OtherU>
|
||||
class_builder(class_builder<OtherT, OtherU>& cls, const char* name)
|
||||
: m_class(new detail::extension_class<T, U>(name))
|
||||
{
|
||||
cls.add(ref(as_object(m_class.get()), ref::increment_count), name);
|
||||
}
|
||||
|
||||
template <class OtherT, class OtherU>
|
||||
class_builder(detail::extension_class<OtherT, OtherU>* cls,
|
||||
const char* name)
|
||||
: m_class(new detail::extension_class<T, U>(name))
|
||||
{
|
||||
cls->set_attribute(name,
|
||||
ref(as_object(m_class.get()), ref::increment_count));
|
||||
}
|
||||
|
||||
~class_builder()
|
||||
{}
|
||||
|
||||
|
||||
30
include/boost/python/class_fwd.hpp
Normal file
30
include/boost/python/class_fwd.hpp
Normal file
@@ -0,0 +1,30 @@
|
||||
// Copyright David Abrahams 2002. Permission to copy, use,
|
||||
// modify, sell and distribute this software is granted provided this
|
||||
// copyright notice appears in all copies. This software is provided
|
||||
// "as is" without express or implied warranty, and with no claim as
|
||||
// to its suitability for any purpose.
|
||||
#ifndef CLASS_FWD_DWA200222_HPP
|
||||
# define CLASS_FWD_DWA200222_HPP
|
||||
# include <boost/python/detail/not_specified.hpp>
|
||||
# include <boost/python/args.hpp>
|
||||
# include <boost/python/bases.hpp>
|
||||
|
||||
namespace boost { namespace python {
|
||||
|
||||
namespace detail
|
||||
{
|
||||
struct empty_list;
|
||||
}
|
||||
|
||||
template <
|
||||
class T // class being wrapped
|
||||
// arbitrarily-ordered optional arguments. Full qualification needed for MSVC6
|
||||
, class X1 = ::boost::python::detail::not_specified
|
||||
, class X2 = ::boost::python::detail::not_specified
|
||||
, class X3 = ::boost::python::detail::not_specified
|
||||
>
|
||||
class class_;
|
||||
|
||||
}} // namespace boost::python
|
||||
|
||||
#endif // CLASS_FWD_DWA200222_HPP
|
||||
@@ -20,7 +20,7 @@
|
||||
namespace boost { namespace python {
|
||||
|
||||
// A simple type which acts something like a built-in Python class obj.
|
||||
class instance
|
||||
class BOOST_PYTHON_DECL instance
|
||||
: public boost::python::detail::python_object
|
||||
{
|
||||
public:
|
||||
@@ -70,6 +70,27 @@ class instance
|
||||
PyObject* oct();
|
||||
PyObject* hex();
|
||||
|
||||
// Rich comparisons
|
||||
PyObject* lt(PyObject* other);
|
||||
PyObject* le(PyObject* other);
|
||||
PyObject* eq(PyObject* other);
|
||||
PyObject* ne(PyObject* other);
|
||||
PyObject* gt(PyObject* other);
|
||||
PyObject* ge(PyObject* other);
|
||||
|
||||
// Inplace operations.
|
||||
PyObject* inplace_add(PyObject* other);
|
||||
PyObject* inplace_subtract(PyObject* other);
|
||||
PyObject* inplace_multiply(PyObject* other);
|
||||
PyObject* inplace_divide(PyObject* other);
|
||||
PyObject* inplace_remainder(PyObject* other);
|
||||
PyObject* inplace_power(PyObject* exponent, PyObject* modulus);
|
||||
PyObject* inplace_lshift(PyObject* other);
|
||||
PyObject* inplace_rshift(PyObject* other);
|
||||
PyObject* inplace_and(PyObject* other);
|
||||
PyObject* inplace_or(PyObject* other);
|
||||
PyObject* inplace_xor(PyObject* other);
|
||||
|
||||
private: // noncopyable, without the size bloat
|
||||
instance(const instance&);
|
||||
void operator=(const instance&);
|
||||
@@ -84,7 +105,7 @@ class instance
|
||||
template <class T> class meta_class;
|
||||
|
||||
namespace detail {
|
||||
class class_base : public type_object_base
|
||||
class BOOST_PYTHON_DECL class_base : public type_object_base
|
||||
{
|
||||
public:
|
||||
class_base(PyTypeObject* meta_class_obj, string name, tuple bases, const dictionary& name_space);
|
||||
@@ -107,6 +128,10 @@ namespace detail {
|
||||
|
||||
private: // boost::python::type_object_base required interface implementation
|
||||
void instance_dealloc(PyObject*) const; // subclasses should not override this
|
||||
|
||||
private: // noncopyable, without the size bloat
|
||||
class_base(const class_base&);
|
||||
void operator=(const class_base&);
|
||||
|
||||
private:
|
||||
string m_name;
|
||||
@@ -120,11 +145,11 @@ namespace detail {
|
||||
// A type which acts a lot like a built-in Python class. T is the obj type,
|
||||
// so class_t<instance> is a very simple "class-alike".
|
||||
template <class T>
|
||||
class class_t
|
||||
: public boost::python::detail::class_base
|
||||
class class_t : public boost::python::detail::class_base
|
||||
{
|
||||
public:
|
||||
class_t(meta_class<T>* meta_class_obj, string name, tuple bases, const dictionary& name_space);
|
||||
~class_t();
|
||||
|
||||
// Standard Python functions.
|
||||
PyObject* call(PyObject* args, PyObject* keywords);
|
||||
@@ -169,6 +194,26 @@ class class_t
|
||||
PyObject* instance_number_float(PyObject*) const;
|
||||
PyObject* instance_number_oct(PyObject*) const;
|
||||
PyObject* instance_number_hex(PyObject*) const;
|
||||
|
||||
PyObject* instance_number_inplace_add(PyObject*, PyObject*) const;
|
||||
PyObject* instance_number_inplace_subtract(PyObject*, PyObject*) const;
|
||||
PyObject* instance_number_inplace_multiply(PyObject*, PyObject*) const;
|
||||
PyObject* instance_number_inplace_divide(PyObject*, PyObject*) const;
|
||||
PyObject* instance_number_inplace_remainder(PyObject*, PyObject*) const;
|
||||
PyObject* instance_number_inplace_power(PyObject*, PyObject*, PyObject*) const;
|
||||
PyObject* instance_number_inplace_lshift(PyObject*, PyObject*) const;
|
||||
PyObject* instance_number_inplace_rshift(PyObject*, PyObject*) const;
|
||||
PyObject* instance_number_inplace_and(PyObject*, PyObject*) const;
|
||||
PyObject* instance_number_inplace_or(PyObject*, PyObject*) const;
|
||||
PyObject* instance_number_inplace_xor(PyObject*, PyObject*) const;
|
||||
|
||||
private: // Implement rich comparisons
|
||||
PyObject* instance_lt(PyObject*, PyObject*) const;
|
||||
PyObject* instance_le(PyObject*, PyObject*) const;
|
||||
PyObject* instance_eq(PyObject*, PyObject*) const;
|
||||
PyObject* instance_ne(PyObject*, PyObject*) const;
|
||||
PyObject* instance_gt(PyObject*, PyObject*) const;
|
||||
PyObject* instance_ge(PyObject*, PyObject*) const;
|
||||
|
||||
private: // Miscellaneous "special" methods
|
||||
PyObject* instance_call(PyObject* obj, PyObject* args, PyObject* keywords) const;
|
||||
@@ -177,10 +222,6 @@ class class_t
|
||||
|
||||
private: // Implementation of boost::python::detail::class_base required interface
|
||||
void delete_instance(PyObject*) const;
|
||||
|
||||
private: // noncopyable, without the size bloat
|
||||
class_t(const class_t<T>&);
|
||||
void operator=(const class_t&);
|
||||
};
|
||||
|
||||
// The type of a class_t<T> object.
|
||||
@@ -191,7 +232,7 @@ class meta_class
|
||||
boost::python::detail::getattrable<
|
||||
boost::python::detail::setattrable<
|
||||
boost::python::detail::type_object<class_t<T> > > > > >,
|
||||
boost::noncopyable
|
||||
private boost::noncopyable
|
||||
{
|
||||
public:
|
||||
meta_class();
|
||||
@@ -223,6 +264,11 @@ class_t<T>::class_t(meta_class<T>* meta_class_obj, string name, tuple bases, con
|
||||
{
|
||||
}
|
||||
|
||||
template <class T>
|
||||
class_t<T>::~class_t()
|
||||
{
|
||||
}
|
||||
|
||||
template <class T>
|
||||
void class_t<T>::delete_instance(PyObject* obj) const
|
||||
{
|
||||
@@ -303,19 +349,21 @@ int class_t<T>::instance_mapping_ass_subscript(PyObject* obj, PyObject* key, PyO
|
||||
return 0;
|
||||
}
|
||||
|
||||
void adjust_slice_indices(PyObject* obj, int& start, int& finish);
|
||||
bool BOOST_PYTHON_DECL adjust_slice_indices(PyObject* obj, int& start, int& finish);
|
||||
|
||||
template <class T>
|
||||
PyObject* class_t<T>::instance_sequence_slice(PyObject* obj, int start, int finish) const
|
||||
{
|
||||
adjust_slice_indices(obj, start, finish);
|
||||
if (!adjust_slice_indices(obj, start, finish))
|
||||
return 0;
|
||||
return downcast<T>(obj)->get_slice(start, finish);
|
||||
}
|
||||
|
||||
template <class T>
|
||||
int class_t<T>::instance_sequence_ass_slice(PyObject* obj, int start, int finish, PyObject* value) const
|
||||
{
|
||||
adjust_slice_indices(obj, start, finish);
|
||||
if (!adjust_slice_indices(obj, start, finish))
|
||||
return -1;
|
||||
downcast<T>(obj)->set_slice(start, finish, value);
|
||||
return 0;
|
||||
}
|
||||
@@ -477,6 +525,108 @@ PyObject* class_t<T>::instance_number_hex(PyObject* obj) const
|
||||
return downcast<T>(obj)->hex();
|
||||
}
|
||||
|
||||
template <class T>
|
||||
PyObject* class_t<T>::instance_number_inplace_add(PyObject* obj, PyObject* other) const
|
||||
{
|
||||
return downcast<T>(obj)->inplace_add(other);
|
||||
}
|
||||
|
||||
template <class T>
|
||||
PyObject* class_t<T>::instance_number_inplace_subtract(PyObject* obj, PyObject* other) const
|
||||
{
|
||||
return downcast<T>(obj)->inplace_subtract(other);
|
||||
}
|
||||
|
||||
template <class T>
|
||||
PyObject* class_t<T>::instance_number_inplace_multiply(PyObject* obj, PyObject* other) const
|
||||
{
|
||||
return downcast<T>(obj)->inplace_multiply(other);
|
||||
}
|
||||
|
||||
template <class T>
|
||||
PyObject* class_t<T>::instance_number_inplace_divide(PyObject* obj, PyObject* other) const
|
||||
{
|
||||
return downcast<T>(obj)->inplace_divide(other);
|
||||
}
|
||||
|
||||
template <class T>
|
||||
PyObject* class_t<T>::instance_number_inplace_remainder(PyObject* obj, PyObject* other) const
|
||||
{
|
||||
return downcast<T>(obj)->inplace_remainder(other);
|
||||
}
|
||||
|
||||
template <class T>
|
||||
PyObject* class_t<T>::instance_number_inplace_power(PyObject* obj, PyObject* exponent, PyObject* modulus) const
|
||||
{
|
||||
return downcast<T>(obj)->inplace_power(exponent, modulus);
|
||||
}
|
||||
|
||||
template <class T>
|
||||
PyObject* class_t<T>::instance_number_inplace_lshift(PyObject* obj, PyObject* other) const
|
||||
{
|
||||
return downcast<T>(obj)->inplace_lshift(other);
|
||||
}
|
||||
|
||||
template <class T>
|
||||
PyObject* class_t<T>::instance_number_inplace_rshift(PyObject* obj, PyObject* other) const
|
||||
{
|
||||
return downcast<T>(obj)->inplace_rshift(other);
|
||||
}
|
||||
|
||||
template <class T>
|
||||
PyObject* class_t<T>::instance_number_inplace_and(PyObject* obj, PyObject* other) const
|
||||
{
|
||||
return downcast<T>(obj)->inplace_and(other);
|
||||
}
|
||||
|
||||
template <class T>
|
||||
PyObject* class_t<T>::instance_number_inplace_or(PyObject* obj, PyObject* other) const
|
||||
{
|
||||
return downcast<T>(obj)->inplace_or(other);
|
||||
}
|
||||
|
||||
template <class T>
|
||||
PyObject* class_t<T>::instance_number_inplace_xor(PyObject* obj, PyObject* other) const
|
||||
{
|
||||
return downcast<T>(obj)->inplace_xor(other);
|
||||
}
|
||||
|
||||
template <class T>
|
||||
PyObject* class_t<T>::instance_lt(PyObject* obj, PyObject* other) const
|
||||
{
|
||||
return downcast<T>(obj)->lt(other);
|
||||
}
|
||||
|
||||
template <class T>
|
||||
PyObject* class_t<T>::instance_le(PyObject* obj, PyObject* other) const
|
||||
{
|
||||
return downcast<T>(obj)->le(other);
|
||||
}
|
||||
|
||||
template <class T>
|
||||
PyObject* class_t<T>::instance_eq(PyObject* obj, PyObject* other) const
|
||||
{
|
||||
return downcast<T>(obj)->eq(other);
|
||||
}
|
||||
|
||||
template <class T>
|
||||
PyObject* class_t<T>::instance_ne(PyObject* obj, PyObject* other) const
|
||||
{
|
||||
return downcast<T>(obj)->ne(other);
|
||||
}
|
||||
|
||||
template <class T>
|
||||
PyObject* class_t<T>::instance_gt(PyObject* obj, PyObject* other) const
|
||||
{
|
||||
return downcast<T>(obj)->gt(other);
|
||||
}
|
||||
|
||||
template <class T>
|
||||
PyObject* class_t<T>::instance_ge(PyObject* obj, PyObject* other) const
|
||||
{
|
||||
return downcast<T>(obj)->ge(other);
|
||||
}
|
||||
|
||||
namespace detail {
|
||||
inline dictionary& class_base::dict()
|
||||
{
|
||||
|
||||
@@ -7,6 +7,7 @@
|
||||
// producing this work.
|
||||
//
|
||||
// Revision History:
|
||||
// 31 Jul 01 convert int/double to complex (Peter Bienstman)
|
||||
// 04 Mar 01 Fixed std::complex<> stuff to work with MSVC (David Abrahams)
|
||||
// 03 Mar 01 added: converters for [plain] char and std::complex
|
||||
// (Ralf W. Grosse-Kunstleve)
|
||||
@@ -18,7 +19,7 @@
|
||||
# include <boost/python/detail/wrap_python.hpp>
|
||||
# include <boost/python/detail/none.hpp>
|
||||
# include <boost/python/detail/signatures.hpp>
|
||||
# include <boost/smart_ptr.hpp>
|
||||
# include <boost/shared_ptr.hpp>
|
||||
# include <boost/python/errors.hpp>
|
||||
# include <string>
|
||||
|
||||
@@ -73,17 +74,17 @@ inline void xdecref_impl(PyObject* p) { Py_XDECREF(p); }
|
||||
template <class T>
|
||||
inline void decref(T* p)
|
||||
{
|
||||
char* const raw_p = reinterpret_cast<char*>(p);
|
||||
char* const p_base = raw_p - offsetof(PyObject, ob_refcnt);
|
||||
decref_impl(reinterpret_cast<PyObject*>(p_base));
|
||||
char* const raw_p = reinterpret_cast<char*>(p);
|
||||
char* const p_base = raw_p - offsetof(PyObject, ob_refcnt);
|
||||
decref_impl(reinterpret_cast<PyObject*>(p_base));
|
||||
}
|
||||
|
||||
template <class T>
|
||||
inline void xdecref(T* p)
|
||||
{
|
||||
char* const raw_p = reinterpret_cast<char*>(p);
|
||||
char* const p_base = raw_p - offsetof(PyObject, ob_refcnt);
|
||||
xdecref_impl(reinterpret_cast<PyObject*>(p_base));
|
||||
char* const raw_p = reinterpret_cast<char*>(p);
|
||||
char* const p_base = raw_p - offsetof(PyObject, ob_refcnt);
|
||||
xdecref_impl(reinterpret_cast<PyObject*>(p_base));
|
||||
}
|
||||
|
||||
namespace detail {
|
||||
@@ -93,6 +94,10 @@ namespace detail {
|
||||
template <class T>
|
||||
std::complex<T> complex_from_python(PyObject* p, boost::python::type<T>)
|
||||
{
|
||||
if (PyInt_Check(p)) return std::complex<T>(PyInt_AS_LONG(p));
|
||||
if (PyLong_Check(p)) return std::complex<T>(PyLong_AsDouble(p));
|
||||
if (PyFloat_Check(p)) return std::complex<T>(PyFloat_AS_DOUBLE(p));
|
||||
|
||||
expect_complex(p);
|
||||
|
||||
return std::complex<T>(
|
||||
@@ -117,61 +122,67 @@ BOOST_PYTHON_BEGIN_CONVERSION_NAMESPACE
|
||||
// Converters
|
||||
//
|
||||
PyObject* to_python(long);
|
||||
long from_python(PyObject* p, boost::python::type<long>);
|
||||
BOOST_PYTHON_DECL long from_python(PyObject* p, boost::python::type<long>);
|
||||
long from_python(PyObject* p, boost::python::type<const long&>);
|
||||
|
||||
PyObject* to_python(unsigned long);
|
||||
unsigned long from_python(PyObject* p, boost::python::type<unsigned long>);
|
||||
BOOST_PYTHON_DECL PyObject* to_python(unsigned long);
|
||||
BOOST_PYTHON_DECL unsigned long from_python(PyObject* p, boost::python::type<unsigned long>);
|
||||
unsigned long from_python(PyObject* p, boost::python::type<const unsigned long&>);
|
||||
|
||||
PyObject* to_python(int);
|
||||
int from_python(PyObject*, boost::python::type<int>);
|
||||
BOOST_PYTHON_DECL int from_python(PyObject*, boost::python::type<int>);
|
||||
int from_python(PyObject*, boost::python::type<const int&>);
|
||||
|
||||
PyObject* to_python(unsigned int);
|
||||
unsigned int from_python(PyObject*, boost::python::type<unsigned int>);
|
||||
BOOST_PYTHON_DECL PyObject* to_python(unsigned int);
|
||||
BOOST_PYTHON_DECL unsigned int from_python(PyObject*, boost::python::type<unsigned int>);
|
||||
unsigned int from_python(PyObject*, boost::python::type<const unsigned int&>);
|
||||
|
||||
PyObject* to_python(short);
|
||||
short from_python(PyObject*, boost::python::type<short>);
|
||||
BOOST_PYTHON_DECL short from_python(PyObject*, boost::python::type<short>);
|
||||
short from_python(PyObject*, boost::python::type<const short&>);
|
||||
|
||||
PyObject* to_python(unsigned short);
|
||||
unsigned short from_python(PyObject*, boost::python::type<unsigned short>);
|
||||
BOOST_PYTHON_DECL PyObject* to_python(unsigned short);
|
||||
BOOST_PYTHON_DECL unsigned short from_python(PyObject*, boost::python::type<unsigned short>);
|
||||
unsigned short from_python(PyObject*, boost::python::type<const unsigned short&>);
|
||||
|
||||
PyObject* to_python(char);
|
||||
char from_python(PyObject*, boost::python::type<char>);
|
||||
BOOST_PYTHON_DECL PyObject* to_python(char);
|
||||
BOOST_PYTHON_DECL char from_python(PyObject*, boost::python::type<char>);
|
||||
char from_python(PyObject*, boost::python::type<const char&>);
|
||||
|
||||
PyObject* to_python(signed char);
|
||||
signed char from_python(PyObject*, boost::python::type<signed char>);
|
||||
BOOST_PYTHON_DECL PyObject* to_python(signed char);
|
||||
BOOST_PYTHON_DECL signed char from_python(PyObject*, boost::python::type<signed char>);
|
||||
signed char from_python(PyObject*, boost::python::type<const signed char&>);
|
||||
|
||||
PyObject* to_python(unsigned char);
|
||||
unsigned char from_python(PyObject*, boost::python::type<unsigned char>);
|
||||
BOOST_PYTHON_DECL PyObject* to_python(unsigned char);
|
||||
BOOST_PYTHON_DECL unsigned char from_python(PyObject*, boost::python::type<unsigned char>);
|
||||
unsigned char from_python(PyObject*, boost::python::type<const unsigned char&>);
|
||||
|
||||
BOOST_PYTHON_DECL float from_python(PyObject*, boost::python::type<float>);
|
||||
BOOST_PYTHON_DECL double from_python(PyObject*, boost::python::type<double>);
|
||||
|
||||
# if !defined(BOOST_MSVC) || BOOST_MSVC > 1300
|
||||
PyObject* to_python(float);
|
||||
float from_python(PyObject*, boost::python::type<float>);
|
||||
PyObject* to_python(double);
|
||||
# else
|
||||
BOOST_PYTHON_DECL PyObject* to_python(float);
|
||||
BOOST_PYTHON_DECL PyObject* to_python(double);
|
||||
# endif
|
||||
float from_python(PyObject*, boost::python::type<const float&>);
|
||||
|
||||
PyObject* to_python(double);
|
||||
double from_python(PyObject*, boost::python::type<double>);
|
||||
double from_python(PyObject*, boost::python::type<const double&>);
|
||||
|
||||
PyObject* to_python(bool);
|
||||
bool from_python(PyObject*, boost::python::type<bool>);
|
||||
BOOST_PYTHON_DECL bool from_python(PyObject*, boost::python::type<bool>);
|
||||
bool from_python(PyObject*, boost::python::type<const bool&>);
|
||||
|
||||
PyObject* to_python(void);
|
||||
void from_python(PyObject*, boost::python::type<void>);
|
||||
BOOST_PYTHON_DECL PyObject* to_python(void);
|
||||
BOOST_PYTHON_DECL void from_python(PyObject*, boost::python::type<void>);
|
||||
|
||||
PyObject* to_python(const char* s);
|
||||
const char* from_python(PyObject*, boost::python::type<const char*>);
|
||||
BOOST_PYTHON_DECL const char* from_python(PyObject*, boost::python::type<const char*>);
|
||||
|
||||
PyObject* to_python(const std::string& s);
|
||||
std::string from_python(PyObject*, boost::python::type<std::string>);
|
||||
BOOST_PYTHON_DECL PyObject* to_python(const std::string& s);
|
||||
BOOST_PYTHON_DECL std::string from_python(PyObject*, boost::python::type<std::string>);
|
||||
std::string from_python(PyObject*, boost::python::type<const std::string&>);
|
||||
|
||||
inline PyObject* to_python(const std::complex<float>& x)
|
||||
@@ -249,7 +260,7 @@ PyObject* from_python(PyObject*, boost::python::type<PyObject*>);
|
||||
// #endif
|
||||
// }} // namespace boost::python
|
||||
|
||||
#if !defined(BOOST_MSVC6_OR_EARLIER)
|
||||
#if !defined(BOOST_NO_FUNCTION_TEMPLATE_ORDERING)
|
||||
template <class T>
|
||||
boost::shared_ptr<T> from_python(PyObject*p, boost::python::type<boost::shared_ptr<T> >)
|
||||
{
|
||||
@@ -275,7 +286,7 @@ PyObject* to_python(boost::shared_ptr<T> p)
|
||||
// inline implementations
|
||||
//
|
||||
|
||||
#ifndef BOOST_MSVC6_OR_EARLIER
|
||||
#if !defined(BOOST_MSVC) || BOOST_MSVC > 1300
|
||||
inline PyObject* to_python(double d)
|
||||
{
|
||||
return PyFloat_FromDouble(d);
|
||||
@@ -285,26 +296,26 @@ inline PyObject* to_python(float f)
|
||||
{
|
||||
return PyFloat_FromDouble(f);
|
||||
}
|
||||
#endif // BOOST_MSVC6_OR_EARLIER
|
||||
#endif
|
||||
|
||||
inline PyObject* to_python(long l)
|
||||
{
|
||||
return PyInt_FromLong(l);
|
||||
return PyInt_FromLong(l);
|
||||
}
|
||||
|
||||
inline PyObject* to_python(int x)
|
||||
{
|
||||
return PyInt_FromLong(x);
|
||||
return PyInt_FromLong(x);
|
||||
}
|
||||
|
||||
inline PyObject* to_python(short x)
|
||||
{
|
||||
return PyInt_FromLong(x);
|
||||
return PyInt_FromLong(x);
|
||||
}
|
||||
|
||||
inline PyObject* to_python(bool b)
|
||||
{
|
||||
return PyInt_FromLong(b);
|
||||
return PyInt_FromLong(b);
|
||||
}
|
||||
|
||||
inline PyObject* to_python(void)
|
||||
@@ -314,7 +325,7 @@ inline PyObject* to_python(void)
|
||||
|
||||
inline PyObject* to_python(const char* s)
|
||||
{
|
||||
return PyString_FromString(s);
|
||||
return PyString_FromString(s);
|
||||
}
|
||||
|
||||
inline std::string from_python(PyObject* p, boost::python::type<const std::string&>)
|
||||
|
||||
336
include/boost/python/converter/arg_from_python.hpp
Executable file
336
include/boost/python/converter/arg_from_python.hpp
Executable file
@@ -0,0 +1,336 @@
|
||||
// Copyright David Abrahams 2002. Permission to copy, use,
|
||||
// modify, sell and distribute this software is granted provided this
|
||||
// copyright notice appears in all copies. This software is provided
|
||||
// "as is" without express or implied warranty, and with no claim as
|
||||
// to its suitability for any purpose.
|
||||
#ifndef ARG_FROM_PYTHON_DWA2002127_HPP
|
||||
# define ARG_FROM_PYTHON_DWA2002127_HPP
|
||||
|
||||
# include <boost/python/converter/from_python.hpp>
|
||||
# include <boost/python/detail/wrap_python.hpp>
|
||||
# include <boost/python/detail/indirect_traits.hpp>
|
||||
# include <boost/type_traits/transform_traits.hpp>
|
||||
# include <boost/type_traits/cv_traits.hpp>
|
||||
# include <boost/python/converter/rvalue_from_python_data.hpp>
|
||||
# include <boost/mpl/if.hpp>
|
||||
# include <boost/python/converter/registry.hpp>
|
||||
# include <boost/python/converter/registered.hpp>
|
||||
# include <boost/python/converter/registered_pointee.hpp>
|
||||
# include <boost/python/detail/void_ptr.hpp>
|
||||
# include <boost/python/back_reference.hpp>
|
||||
# include <boost/python/detail/referent_storage.hpp>
|
||||
# include <boost/python/converter/obj_mgr_arg_from_python.hpp>
|
||||
|
||||
namespace boost { namespace python
|
||||
{
|
||||
template <class T> struct arg_from_python;
|
||||
}}
|
||||
|
||||
// This header defines Python->C++ function argument converters,
|
||||
// parametrized on the argument type.
|
||||
|
||||
namespace boost { namespace python { namespace converter {
|
||||
|
||||
//
|
||||
// lvalue converters
|
||||
//
|
||||
// These require that an lvalue of the type U is stored somewhere in
|
||||
// the Python object being converted.
|
||||
|
||||
// Used when T == U*const&
|
||||
template <class T>
|
||||
struct pointer_cref_arg_from_python
|
||||
{
|
||||
typedef T result_type;
|
||||
|
||||
pointer_cref_arg_from_python(PyObject*);
|
||||
T operator()(PyObject*) const;
|
||||
bool convertible() const;
|
||||
|
||||
private: // storage for a U*
|
||||
// needed because not all compilers will let us declare U* as the
|
||||
// return type of operator() -- we return U*const& instead
|
||||
typename python::detail::referent_storage<T>::type m_result;
|
||||
};
|
||||
|
||||
// Base class for pointer and reference converters
|
||||
struct arg_lvalue_from_python_base
|
||||
{
|
||||
public: // member functions
|
||||
arg_lvalue_from_python_base(void* result);
|
||||
bool convertible() const;
|
||||
|
||||
protected: // member functions
|
||||
void*const& result() const;
|
||||
|
||||
private: // data members
|
||||
void* m_result;
|
||||
};
|
||||
|
||||
// Used when T == U*
|
||||
template <class T>
|
||||
struct pointer_arg_from_python : arg_lvalue_from_python_base
|
||||
{
|
||||
typedef T result_type;
|
||||
|
||||
pointer_arg_from_python(PyObject*);
|
||||
T operator()(PyObject*) const;
|
||||
};
|
||||
|
||||
// Used when T == U& and (T != V const& or T == W volatile&)
|
||||
template <class T>
|
||||
struct reference_arg_from_python : arg_lvalue_from_python_base
|
||||
{
|
||||
typedef T result_type;
|
||||
|
||||
reference_arg_from_python(PyObject*);
|
||||
T operator()(PyObject*) const;
|
||||
};
|
||||
|
||||
// ===================
|
||||
|
||||
//
|
||||
// rvalue converters
|
||||
//
|
||||
// These require only that an object of type T can be created from
|
||||
// the given Python object, but not that the T object exist
|
||||
// somewhere in storage.
|
||||
//
|
||||
|
||||
// Used when T is a plain value (non-pointer, non-reference) type or
|
||||
// a (non-volatile) const reference to a plain value type.
|
||||
template <class T>
|
||||
struct arg_rvalue_from_python
|
||||
{
|
||||
typedef typename boost::add_reference<
|
||||
typename boost::add_const<T>::type
|
||||
>::type result_type;
|
||||
|
||||
arg_rvalue_from_python(PyObject*);
|
||||
bool convertible() const;
|
||||
|
||||
result_type operator()(PyObject*);
|
||||
|
||||
private:
|
||||
rvalue_from_python_data<result_type> m_data;
|
||||
};
|
||||
|
||||
|
||||
// ==================
|
||||
|
||||
// Converts to a (PyObject*,T) bundle, for when you need a reference
|
||||
// back to the Python object
|
||||
template <class T>
|
||||
struct back_reference_arg_from_python
|
||||
: boost::python::arg_from_python<typename T::type>
|
||||
{
|
||||
typedef T result_type;
|
||||
|
||||
back_reference_arg_from_python(PyObject*);
|
||||
T operator()(PyObject*);
|
||||
private:
|
||||
typedef boost::python::arg_from_python<typename T::type> base;
|
||||
};
|
||||
|
||||
|
||||
// ==================
|
||||
|
||||
// This metafunction selects the appropriate arg_from_python converter
|
||||
// type for an argument of type T.
|
||||
template <class T>
|
||||
struct select_arg_from_python
|
||||
{
|
||||
BOOST_STATIC_CONSTANT(
|
||||
bool, obj_mgr = is_object_manager<T>::value);
|
||||
|
||||
BOOST_STATIC_CONSTANT(
|
||||
bool, obj_mgr_ref = is_reference_to_object_manager<T>::value);
|
||||
|
||||
BOOST_STATIC_CONSTANT(
|
||||
bool, ptr = is_pointer<T>::value);
|
||||
|
||||
BOOST_STATIC_CONSTANT(
|
||||
bool, ptr_cref
|
||||
= boost::python::detail::is_reference_to_pointer<T>::value
|
||||
&& boost::python::detail::is_reference_to_const<T>::value
|
||||
&& !boost::python::detail::is_reference_to_volatile<T>::value);
|
||||
|
||||
|
||||
BOOST_STATIC_CONSTANT(
|
||||
bool, ref =
|
||||
boost::python::detail::is_reference_to_non_const<T>::value
|
||||
|| boost::python::detail::is_reference_to_volatile<T>::value);
|
||||
|
||||
BOOST_STATIC_CONSTANT(
|
||||
bool, back_ref =
|
||||
boost::python::is_back_reference<T>::value);
|
||||
|
||||
typedef typename mpl::if_c<
|
||||
obj_mgr
|
||||
, object_manager_value_arg_from_python<T>
|
||||
, typename mpl::if_c<
|
||||
obj_mgr_ref
|
||||
, object_manager_ref_arg_from_python<T>
|
||||
, typename mpl::if_c<
|
||||
ptr
|
||||
, pointer_arg_from_python<T>
|
||||
, typename mpl::if_c<
|
||||
ptr_cref
|
||||
, pointer_cref_arg_from_python<T>
|
||||
, typename mpl::if_c<
|
||||
ref
|
||||
, reference_arg_from_python<T>
|
||||
, typename mpl::if_c<
|
||||
back_ref
|
||||
, back_reference_arg_from_python<T>
|
||||
, arg_rvalue_from_python<T>
|
||||
>::type
|
||||
>::type
|
||||
>::type
|
||||
>::type
|
||||
>::type
|
||||
>::type type;
|
||||
};
|
||||
|
||||
// ==================
|
||||
|
||||
//
|
||||
// implementations
|
||||
//
|
||||
|
||||
// arg_lvalue_from_python_base
|
||||
//
|
||||
inline arg_lvalue_from_python_base::arg_lvalue_from_python_base(void* result)
|
||||
: m_result(result)
|
||||
{
|
||||
}
|
||||
|
||||
inline bool arg_lvalue_from_python_base::convertible() const
|
||||
{
|
||||
return m_result != 0;
|
||||
}
|
||||
|
||||
inline void*const& arg_lvalue_from_python_base::result() const
|
||||
{
|
||||
return m_result;
|
||||
}
|
||||
|
||||
// pointer_cref_arg_from_python
|
||||
//
|
||||
namespace detail
|
||||
{
|
||||
// null_ptr_reference -- a function returning a reference to a null
|
||||
// pointer of type U. Needed so that extractors for T*const& can
|
||||
// convert Python's None.
|
||||
template <class T>
|
||||
struct null_ptr_owner
|
||||
{
|
||||
static T value;
|
||||
};
|
||||
template <class T> T null_ptr_owner<T>::value = 0;
|
||||
|
||||
template <class U>
|
||||
inline U& null_ptr_reference(U&(*)())
|
||||
{
|
||||
return null_ptr_owner<U>::value;
|
||||
}
|
||||
}
|
||||
|
||||
template <class T>
|
||||
inline pointer_cref_arg_from_python<T>::pointer_cref_arg_from_python(PyObject* p)
|
||||
{
|
||||
// T == U*const&: store a U* in the m_result storage. Nonzero
|
||||
// indicates success. If find returns nonzero, it's a pointer to
|
||||
// a U object.
|
||||
python::detail::write_void_ptr_reference(
|
||||
m_result.bytes
|
||||
, p == Py_None ? p : converter::get_lvalue_from_python(p, registered_pointee<T>::converters)
|
||||
, (T(*)())0);
|
||||
}
|
||||
|
||||
template <class T>
|
||||
inline bool pointer_cref_arg_from_python<T>::convertible() const
|
||||
{
|
||||
return python::detail::void_ptr_to_reference(m_result.bytes, (T(*)())0) != 0;
|
||||
}
|
||||
template <class T>
|
||||
inline T pointer_cref_arg_from_python<T>::operator()(PyObject* p) const
|
||||
{
|
||||
return (p == Py_None) // None ==> 0
|
||||
? detail::null_ptr_reference((T(*)())0)
|
||||
// Otherwise, return a U*const& to the m_result storage.
|
||||
: python::detail::void_ptr_to_reference(m_result.bytes, (T(*)())0);
|
||||
}
|
||||
|
||||
// pointer_arg_from_python
|
||||
//
|
||||
template <class T>
|
||||
inline pointer_arg_from_python<T>::pointer_arg_from_python(PyObject* p)
|
||||
: arg_lvalue_from_python_base(
|
||||
p == Py_None ? p : converter::get_lvalue_from_python(p, registered_pointee<T>::converters))
|
||||
{
|
||||
}
|
||||
|
||||
template <class T>
|
||||
inline T pointer_arg_from_python<T>::operator()(PyObject* p) const
|
||||
{
|
||||
return (p == Py_None) ? 0 : T(result());
|
||||
}
|
||||
|
||||
// reference_arg_from_python
|
||||
//
|
||||
template <class T>
|
||||
inline reference_arg_from_python<T>::reference_arg_from_python(PyObject* p)
|
||||
: arg_lvalue_from_python_base(converter::get_lvalue_from_python(p,registered<T>::converters))
|
||||
{
|
||||
}
|
||||
|
||||
template <class T>
|
||||
inline T reference_arg_from_python<T>::operator()(PyObject*) const
|
||||
{
|
||||
return python::detail::void_ptr_to_reference(result(), (T(*)())0);
|
||||
}
|
||||
|
||||
|
||||
// arg_rvalue_from_python
|
||||
//
|
||||
template <class T>
|
||||
inline arg_rvalue_from_python<T>::arg_rvalue_from_python(PyObject* obj)
|
||||
: m_data(converter::rvalue_from_python_stage1(obj, registered<T>::converters))
|
||||
{
|
||||
}
|
||||
|
||||
template <class T>
|
||||
inline bool arg_rvalue_from_python<T>::convertible() const
|
||||
{
|
||||
return m_data.stage1.convertible != 0;
|
||||
}
|
||||
|
||||
template <class T>
|
||||
inline typename arg_rvalue_from_python<T>::result_type
|
||||
arg_rvalue_from_python<T>::operator()(PyObject* p)
|
||||
{
|
||||
if (m_data.stage1.construct != 0)
|
||||
m_data.stage1.construct(p, &m_data.stage1);
|
||||
|
||||
return python::detail::void_ptr_to_reference(m_data.stage1.convertible, (result_type(*)())0);
|
||||
}
|
||||
|
||||
// back_reference_arg_from_python
|
||||
//
|
||||
template <class T>
|
||||
back_reference_arg_from_python<T>::back_reference_arg_from_python(PyObject* x)
|
||||
: base(x)
|
||||
{
|
||||
}
|
||||
|
||||
template <class T>
|
||||
inline T
|
||||
back_reference_arg_from_python<T>::operator()(PyObject* x)
|
||||
{
|
||||
return T(x, base::operator()(x));
|
||||
}
|
||||
|
||||
}}} // namespace boost::python::converter
|
||||
|
||||
#endif // ARG_FROM_PYTHON_DWA2002127_HPP
|
||||
247
include/boost/python/converter/arg_to_python.hpp
Executable file
247
include/boost/python/converter/arg_to_python.hpp
Executable file
@@ -0,0 +1,247 @@
|
||||
// Copyright David Abrahams 2002. Permission to copy, use,
|
||||
// modify, sell and distribute this software is granted provided this
|
||||
// copyright notice appears in all copies. This software is provided
|
||||
// "as is" without express or implied warranty, and with no claim as
|
||||
// to its suitability for any purpose.
|
||||
#ifndef ARG_TO_PYTHON_DWA200265_HPP
|
||||
# define ARG_TO_PYTHON_DWA200265_HPP
|
||||
|
||||
# include <boost/python/ptr.hpp>
|
||||
# include <boost/python/converter/registered.hpp>
|
||||
# include <boost/python/converter/registered_pointee.hpp>
|
||||
# include <boost/python/converter/arg_to_python_base.hpp>
|
||||
# include <boost/python/to_python_indirect.hpp>
|
||||
# include <boost/type_traits/cv_traits.hpp>
|
||||
# include <boost/type_traits/composite_traits.hpp>
|
||||
# include <boost/type_traits/function_traits.hpp>
|
||||
# include <boost/python/detail/indirect_traits.hpp>
|
||||
# include <boost/python/detail/convertible.hpp>
|
||||
# include <boost/python/detail/string_literal.hpp>
|
||||
# include <boost/python/base_type_traits.hpp>
|
||||
// Bring in specializations
|
||||
# include <boost/python/converter/builtin_converters.hpp>
|
||||
# include <boost/python/tag.hpp>
|
||||
# include <boost/python/object/function_handle.hpp>
|
||||
|
||||
namespace boost { namespace python { namespace converter {
|
||||
|
||||
template <class T> struct is_object_manager;
|
||||
|
||||
namespace detail
|
||||
{
|
||||
BOOST_PYTHON_DECL void throw_no_class_registered();
|
||||
|
||||
template <class T>
|
||||
struct function_arg_to_python : handle<>
|
||||
{
|
||||
function_arg_to_python(T const& x);
|
||||
};
|
||||
|
||||
template <class T>
|
||||
struct reference_arg_to_python : handle<>
|
||||
{
|
||||
reference_arg_to_python(T& x);
|
||||
private:
|
||||
static PyObject* get_object(T& x);
|
||||
};
|
||||
|
||||
template <class T>
|
||||
struct value_arg_to_python : arg_to_python_base
|
||||
{
|
||||
// Throw an exception if the conversion can't succeed
|
||||
value_arg_to_python(T const&);
|
||||
};
|
||||
|
||||
template <class Ptr>
|
||||
struct pointer_deep_arg_to_python : arg_to_python_base
|
||||
{
|
||||
// Throw an exception if the conversion can't succeed
|
||||
pointer_deep_arg_to_python(Ptr);
|
||||
};
|
||||
|
||||
template <class Ptr>
|
||||
struct pointer_shallow_arg_to_python : handle<>
|
||||
{
|
||||
// Throw an exception if the conversion can't succeed
|
||||
pointer_shallow_arg_to_python(Ptr);
|
||||
private:
|
||||
static PyObject* get_object(Ptr p);
|
||||
};
|
||||
|
||||
// Convert types that manage a Python object to_python
|
||||
template <class T>
|
||||
struct object_manager_arg_to_python
|
||||
{
|
||||
object_manager_arg_to_python(T const& x) : m_src(x) {}
|
||||
|
||||
PyObject* get() const
|
||||
{
|
||||
return python::upcast<PyObject>(get_managed_object(m_src, tag));
|
||||
}
|
||||
|
||||
private:
|
||||
T const& m_src;
|
||||
};
|
||||
|
||||
template <class T>
|
||||
struct select_arg_to_python
|
||||
{
|
||||
// Special handling for char const[N]; interpret them as char
|
||||
// const* for the sake of conversion
|
||||
BOOST_STATIC_CONSTANT(
|
||||
bool, is_string = python::detail::is_string_literal<T const>::value);
|
||||
|
||||
BOOST_STATIC_CONSTANT(
|
||||
bool, function = is_function<T>::value | python::detail::is_pointer_to_function<T>::value | is_member_function_pointer<T>::value);
|
||||
|
||||
BOOST_STATIC_CONSTANT(
|
||||
bool, manager = is_object_manager<T>::value);
|
||||
|
||||
BOOST_STATIC_CONSTANT(
|
||||
bool, ptr = is_pointer<T>::value);
|
||||
|
||||
BOOST_STATIC_CONSTANT(
|
||||
bool, ref_wrapper = is_reference_wrapper<T>::value);
|
||||
|
||||
BOOST_STATIC_CONSTANT(
|
||||
bool, ptr_wrapper = is_pointer_wrapper<T>::value);
|
||||
|
||||
typedef typename unwrap_reference<T>::type unwrapped_referent;
|
||||
typedef typename unwrap_pointer<T>::type unwrapped_ptr;
|
||||
|
||||
typedef typename mpl::if_c<
|
||||
is_string
|
||||
, arg_to_python<char const*>
|
||||
, typename mpl::if_c<
|
||||
function
|
||||
, function_arg_to_python<T>
|
||||
, typename mpl::if_c<
|
||||
manager
|
||||
, object_manager_arg_to_python<T>
|
||||
, typename mpl::if_c<
|
||||
ptr
|
||||
, pointer_deep_arg_to_python<T>
|
||||
, typename mpl::if_c<
|
||||
ptr_wrapper
|
||||
, pointer_shallow_arg_to_python<unwrapped_ptr>
|
||||
, typename mpl::if_c<
|
||||
ref_wrapper
|
||||
, reference_arg_to_python<unwrapped_referent>
|
||||
, value_arg_to_python<T>
|
||||
>::type
|
||||
>::type
|
||||
>::type
|
||||
>::type
|
||||
>::type
|
||||
>::type
|
||||
type;
|
||||
};
|
||||
}
|
||||
|
||||
template <class T>
|
||||
struct arg_to_python
|
||||
: detail::select_arg_to_python<T>::type
|
||||
{
|
||||
typedef typename detail::select_arg_to_python<T>::type base;
|
||||
public: // member functions
|
||||
// Throw an exception if the conversion can't succeed
|
||||
arg_to_python(T const& x);
|
||||
};
|
||||
|
||||
//
|
||||
// implementations
|
||||
//
|
||||
namespace detail
|
||||
{
|
||||
// reject_raw_object_ptr -- cause a compile-time error if the user
|
||||
// should pass a raw Python object pointer
|
||||
using python::detail::yes_convertible;
|
||||
using python::detail::no_convertible;
|
||||
using python::detail::unspecialized;
|
||||
|
||||
template <class T> struct cannot_convert_raw_PyObject;
|
||||
|
||||
template <class T, class Convertibility>
|
||||
struct reject_raw_object_helper
|
||||
{
|
||||
static void error(Convertibility)
|
||||
{
|
||||
cannot_convert_raw_PyObject<T*>::to_python_use_handle_instead();
|
||||
}
|
||||
static void error(...) {}
|
||||
};
|
||||
|
||||
template <class T>
|
||||
inline void reject_raw_object_ptr(T*)
|
||||
{
|
||||
reject_raw_object_helper<T,yes_convertible>::error(
|
||||
python::detail::convertible<PyObject const volatile*>::check((T*)0));
|
||||
|
||||
typedef typename remove_cv<T>::type value_type;
|
||||
|
||||
reject_raw_object_helper<T,no_convertible>::error(
|
||||
python::detail::convertible<unspecialized*>::check(
|
||||
(base_type_traits<value_type>*)0
|
||||
));
|
||||
}
|
||||
// ---------
|
||||
|
||||
template <class T>
|
||||
inline function_arg_to_python<T>::function_arg_to_python(T const& x)
|
||||
: handle<>(python::objects::make_function_handle(x))
|
||||
{
|
||||
}
|
||||
|
||||
template <class T>
|
||||
inline value_arg_to_python<T>::value_arg_to_python(T const& x)
|
||||
: arg_to_python_base(&x, registered<T>::converters)
|
||||
{
|
||||
}
|
||||
|
||||
template <class Ptr>
|
||||
inline pointer_deep_arg_to_python<Ptr>::pointer_deep_arg_to_python(Ptr x)
|
||||
: arg_to_python_base(x, registered_pointee<Ptr>::converters)
|
||||
{
|
||||
detail::reject_raw_object_ptr((Ptr)0);
|
||||
}
|
||||
|
||||
template <class T>
|
||||
inline PyObject* reference_arg_to_python<T>::get_object(T& x)
|
||||
{
|
||||
to_python_indirect<T&,python::detail::make_reference_holder> convert;
|
||||
if (!convert.convertible())
|
||||
throw_no_class_registered();
|
||||
return convert(x);
|
||||
}
|
||||
|
||||
template <class T>
|
||||
inline reference_arg_to_python<T>::reference_arg_to_python(T& x)
|
||||
: handle<>(reference_arg_to_python<T>::get_object(x))
|
||||
{
|
||||
}
|
||||
|
||||
template <class Ptr>
|
||||
inline pointer_shallow_arg_to_python<Ptr>::pointer_shallow_arg_to_python(Ptr x)
|
||||
: handle<>(pointer_shallow_arg_to_python<Ptr>::get_object(x))
|
||||
{
|
||||
detail::reject_raw_object_ptr((Ptr)0);
|
||||
}
|
||||
|
||||
template <class Ptr>
|
||||
inline PyObject* pointer_shallow_arg_to_python<Ptr>::get_object(Ptr x)
|
||||
{
|
||||
to_python_indirect<Ptr,python::detail::make_reference_holder> convert;
|
||||
if (!convert.convertible())
|
||||
throw_no_class_registered();
|
||||
return x ? convert(x) : python::detail::none();
|
||||
}
|
||||
}
|
||||
|
||||
template <class T>
|
||||
inline arg_to_python<T>::arg_to_python(T const& x)
|
||||
: base(x)
|
||||
{}
|
||||
|
||||
}}} // namespace boost::python::converter
|
||||
|
||||
#endif // ARG_TO_PYTHON_DWA200265_HPP
|
||||
35
include/boost/python/converter/arg_to_python_base.hpp
Executable file
35
include/boost/python/converter/arg_to_python_base.hpp
Executable file
@@ -0,0 +1,35 @@
|
||||
// Copyright David Abrahams 2002. Permission to copy, use,
|
||||
// modify, sell and distribute this software is granted provided this
|
||||
// copyright notice appears in all copies. This software is provided
|
||||
// "as is" without express or implied warranty, and with no claim as
|
||||
// to its suitability for any purpose.
|
||||
#ifndef ARG_TO_PYTHON_BASE_DWA200237_HPP
|
||||
# define ARG_TO_PYTHON_BASE_DWA200237_HPP
|
||||
# include <boost/python/converter/to_python_function_type.hpp>
|
||||
# include <boost/python/detail/wrap_python.hpp>
|
||||
# include <boost/python/handle.hpp>
|
||||
|
||||
namespace boost { namespace python { namespace converter {
|
||||
|
||||
struct registration;
|
||||
|
||||
namespace detail
|
||||
{
|
||||
struct BOOST_PYTHON_DECL arg_to_python_base
|
||||
# if !defined(BOOST_MSVC) || BOOST_MSVC <= 1300 || _MSC_FULL_VER > 13102179
|
||||
: handle<>
|
||||
# endif
|
||||
{
|
||||
arg_to_python_base(void const volatile* source, registration const&);
|
||||
# if defined(BOOST_MSVC) && BOOST_MSVC > 1300 && _MSC_FULL_VER <= 13102179
|
||||
PyObject* get() const { return m_ptr.get(); }
|
||||
PyObject* release() { return m_ptr.release(); }
|
||||
private:
|
||||
handle<> m_ptr;
|
||||
# endif
|
||||
};
|
||||
}
|
||||
|
||||
}}} // namespace boost::python::converter
|
||||
|
||||
#endif // ARG_TO_PYTHON_BASE_DWA200237_HPP
|
||||
123
include/boost/python/converter/builtin_converters.hpp
Normal file
123
include/boost/python/converter/builtin_converters.hpp
Normal file
@@ -0,0 +1,123 @@
|
||||
// Copyright David Abrahams 2002. Permission to copy, use,
|
||||
// modify, sell and distribute this software is granted provided this
|
||||
// copyright notice appears in all copies. This software is provided
|
||||
// "as is" without express or implied warranty, and with no claim as
|
||||
// to its suitability for any purpose.
|
||||
#ifndef BUILTIN_CONVERTERS_DWA2002124_HPP
|
||||
# define BUILTIN_CONVERTERS_DWA2002124_HPP
|
||||
# include <boost/python/detail/wrap_python.hpp>
|
||||
# include <boost/python/detail/none.hpp>
|
||||
# include <boost/python/handle.hpp>
|
||||
# include <string>
|
||||
# include <complex>
|
||||
|
||||
// Since all we can use to decide how to convert an object to_python
|
||||
// is its C++ type, there can be only one such converter for each
|
||||
// type. Therefore, for built-in conversions we can bypass registry
|
||||
// lookups using explicit specializations of arg_to_python and
|
||||
// result_to_python.
|
||||
|
||||
namespace boost { namespace python {
|
||||
|
||||
namespace converter
|
||||
{
|
||||
template <class T> struct arg_to_python;
|
||||
BOOST_PYTHON_DECL PyObject* do_return_to_python(char);
|
||||
BOOST_PYTHON_DECL PyObject* do_return_to_python(char const*);
|
||||
BOOST_PYTHON_DECL PyObject* do_return_to_python(PyObject*);
|
||||
BOOST_PYTHON_DECL PyObject* do_arg_to_python(PyObject*);
|
||||
}
|
||||
|
||||
// Provide specializations of to_python_value
|
||||
template <class T> struct to_python_value;
|
||||
|
||||
namespace detail
|
||||
{
|
||||
// Since there's no registry lookup, always report the existence of
|
||||
// a converter.
|
||||
struct builtin_to_python
|
||||
{
|
||||
static bool convertible() { return true; }
|
||||
};
|
||||
}
|
||||
|
||||
// Use expr to create the PyObject corresponding to x
|
||||
# define BOOST_PYTHON_RETURN_TO_PYTHON_BY_VALUE(T, expr) \
|
||||
template <> struct to_python_value<T&> \
|
||||
: detail::builtin_to_python \
|
||||
{ \
|
||||
inline PyObject* operator()(T const& x) const \
|
||||
{ \
|
||||
return (expr); \
|
||||
} \
|
||||
}; \
|
||||
template <> struct to_python_value<T const&> \
|
||||
: detail::builtin_to_python \
|
||||
{ \
|
||||
inline PyObject* operator()(T const& x) const \
|
||||
{ \
|
||||
return (expr); \
|
||||
} \
|
||||
};
|
||||
|
||||
# define BOOST_PYTHON_ARG_TO_PYTHON_BY_VALUE(T, expr) \
|
||||
namespace converter \
|
||||
{ \
|
||||
template <> struct arg_to_python< T > \
|
||||
: handle<> \
|
||||
{ \
|
||||
arg_to_python(T const& x) \
|
||||
: python::handle<>(expr) {} \
|
||||
}; \
|
||||
}
|
||||
|
||||
// Specialize argument and return value converters for T using expr
|
||||
# define BOOST_PYTHON_TO_PYTHON_BY_VALUE(T, expr) \
|
||||
BOOST_PYTHON_RETURN_TO_PYTHON_BY_VALUE(T,expr) \
|
||||
BOOST_PYTHON_ARG_TO_PYTHON_BY_VALUE(T,expr)
|
||||
|
||||
// Specialize converters for signed and unsigned T to Python Int
|
||||
# define BOOST_PYTHON_TO_INT(T) \
|
||||
BOOST_PYTHON_TO_PYTHON_BY_VALUE(signed T, PyInt_FromLong(x)) \
|
||||
BOOST_PYTHON_TO_PYTHON_BY_VALUE(unsigned T, PyInt_FromLong(x))
|
||||
|
||||
// Bool is not signed.
|
||||
BOOST_PYTHON_TO_PYTHON_BY_VALUE(bool, PyInt_FromLong(x))
|
||||
|
||||
// note: handles signed char and unsigned char, but not char (see below)
|
||||
BOOST_PYTHON_TO_INT(char)
|
||||
|
||||
BOOST_PYTHON_TO_INT(short)
|
||||
BOOST_PYTHON_TO_INT(int)
|
||||
BOOST_PYTHON_TO_INT(long)
|
||||
|
||||
// using Python's macro instead of Boost's - we don't seem to get the
|
||||
// config right all the time.
|
||||
# ifdef HAVE_LONG_LONG
|
||||
BOOST_PYTHON_TO_PYTHON_BY_VALUE(signed LONG_LONG, PyLong_FromLongLong(x))
|
||||
BOOST_PYTHON_TO_PYTHON_BY_VALUE(unsigned LONG_LONG, PyLong_FromUnsignedLongLong(x))
|
||||
# endif
|
||||
|
||||
# undef BOOST_TO_PYTHON_INT
|
||||
|
||||
BOOST_PYTHON_TO_PYTHON_BY_VALUE(char, converter::do_return_to_python(x))
|
||||
BOOST_PYTHON_TO_PYTHON_BY_VALUE(char const*, converter::do_return_to_python(x))
|
||||
BOOST_PYTHON_TO_PYTHON_BY_VALUE(std::string, PyString_FromString(x.c_str()))
|
||||
BOOST_PYTHON_TO_PYTHON_BY_VALUE(float, PyFloat_FromDouble(x))
|
||||
BOOST_PYTHON_TO_PYTHON_BY_VALUE(double, PyFloat_FromDouble(x))
|
||||
BOOST_PYTHON_TO_PYTHON_BY_VALUE(long double, PyFloat_FromDouble(x))
|
||||
BOOST_PYTHON_RETURN_TO_PYTHON_BY_VALUE(PyObject*, converter::do_return_to_python(x))
|
||||
BOOST_PYTHON_TO_PYTHON_BY_VALUE(std::complex<float>, PyComplex_FromDoubles(x.real(), x.imag()))
|
||||
BOOST_PYTHON_TO_PYTHON_BY_VALUE(std::complex<double>, PyComplex_FromDoubles(x.real(), x.imag()))
|
||||
BOOST_PYTHON_TO_PYTHON_BY_VALUE(std::complex<long double>, PyComplex_FromDoubles(x.real(), x.imag()))
|
||||
|
||||
namespace converter
|
||||
{
|
||||
|
||||
void initialize_builtin_converters();
|
||||
|
||||
}
|
||||
|
||||
}} // namespace boost::python::converter
|
||||
|
||||
#endif // BUILTIN_CONVERTERS_DWA2002124_HPP
|
||||
278
include/boost/python/converter/callback.hpp
Normal file
278
include/boost/python/converter/callback.hpp
Normal file
@@ -0,0 +1,278 @@
|
||||
// Copyright David Abrahams 2002. Permission to copy, use,
|
||||
// modify, sell and distribute this software is granted provided this
|
||||
// copyright notice appears in all copies. This software is provided
|
||||
// "as is" without express or implied warranty, and with no claim as
|
||||
// to its suitability for any purpose.
|
||||
#ifndef CALLBACK_DWA2002228_HPP
|
||||
# define CALLBACK_DWA2002228_HPP
|
||||
|
||||
# include <boost/python/converter/type_id.hpp>
|
||||
# include <boost/python/converter/to_python_function.hpp>
|
||||
# include <boost/python/converter/pointee_to_python_function.hpp>
|
||||
# include <boost/python/converter/from_python.hpp>
|
||||
# include <boost/mpl/select_if.hpp>
|
||||
# include <boost/python/converter/callback_to_python_base.hpp>
|
||||
# include <boost/python/converter/callback_from_python_base.hpp>
|
||||
# include <boost/python/converter/builtin_converters.hpp>
|
||||
# include <boost/python/to_python_indirect.hpp>
|
||||
# include <boost/python/detail/none.hpp>
|
||||
# include <boost/python/ptr.hpp>
|
||||
# include <boost/python/errors.hpp>
|
||||
|
||||
namespace boost { namespace python { namespace converter {
|
||||
|
||||
namespace detail
|
||||
{
|
||||
template <class T>
|
||||
struct pointer_callback_from_python
|
||||
{
|
||||
pointer_callback_from_python();
|
||||
T operator()(PyObject*) const;
|
||||
};
|
||||
|
||||
template <class T>
|
||||
struct reference_callback_from_python
|
||||
{
|
||||
reference_callback_from_python();
|
||||
T operator()(PyObject*) const;
|
||||
};
|
||||
|
||||
template <class T>
|
||||
struct rvalue_callback_from_python
|
||||
{
|
||||
rvalue_callback_from_python();
|
||||
T const& operator()(PyObject*);
|
||||
private:
|
||||
rvalue_data<T> m_data;
|
||||
};
|
||||
|
||||
template <class T>
|
||||
struct select_callback_from_python
|
||||
{
|
||||
BOOST_STATIC_CONSTANT(
|
||||
bool, ptr = is_pointer<T>::value);
|
||||
|
||||
BOOST_STATIC_CONSTANT(
|
||||
bool, ref = is_reference<T>::value);
|
||||
|
||||
typedef typename mpl::select_if_c<
|
||||
ptr
|
||||
, pointer_callback_from_python<T>
|
||||
, typename mpl::select_if_c<
|
||||
ref
|
||||
, reference_callback_from_python<T>
|
||||
, rvalue_callback_from_python<T>
|
||||
>::type
|
||||
>::type type;
|
||||
};
|
||||
|
||||
|
||||
template <class T>
|
||||
struct reference_callback_to_python : callback_to_python_holder
|
||||
{
|
||||
reference_callback_to_python(T& x);
|
||||
private:
|
||||
static PyObject* get_object(T& x);
|
||||
};
|
||||
|
||||
template <class T>
|
||||
struct value_callback_to_python : callback_to_python_base
|
||||
{
|
||||
// Throw an exception if the conversion can't succeed
|
||||
value_callback_to_python(T const&);
|
||||
};
|
||||
|
||||
template <class Ptr>
|
||||
struct pointer_deep_callback_to_python : callback_to_python_base
|
||||
{
|
||||
// Throw an exception if the conversion can't succeed
|
||||
pointer_deep_callback_to_python(Ptr);
|
||||
};
|
||||
|
||||
template <class Ptr>
|
||||
struct pointer_shallow_callback_to_python : callback_to_python_holder
|
||||
{
|
||||
// Throw an exception if the conversion can't succeed
|
||||
pointer_shallow_callback_to_python(Ptr);
|
||||
private:
|
||||
static PyObject* get_object(Ptr p);
|
||||
};
|
||||
|
||||
template <class T>
|
||||
struct select_callback_to_python
|
||||
{
|
||||
BOOST_STATIC_CONSTANT(
|
||||
bool, ptr = is_pointer<T>::value);
|
||||
|
||||
BOOST_STATIC_CONSTANT(
|
||||
bool, ref_wrapper = is_reference_wrapper<T>::value);
|
||||
|
||||
BOOST_STATIC_CONSTANT(
|
||||
bool, ptr_wrapper = is_pointer_wrapper<T>::value);
|
||||
|
||||
typedef typename unwrap_reference<T>::type unwrapped_referent;
|
||||
typedef typename unwrap_pointer<T>::type unwrapped_ptr;
|
||||
|
||||
typedef typename mpl::select_if_c<
|
||||
ptr
|
||||
, pointer_deep_callback_to_python<T>
|
||||
, typename mpl::select_if_c<
|
||||
ptr_wrapper
|
||||
, pointer_shallow_callback_to_python<unwrapped_ptr>
|
||||
, typename mpl::select_if_c<
|
||||
ref_wrapper
|
||||
, reference_callback_to_python<unwrapped_referent>
|
||||
, value_callback_to_python<T>
|
||||
>::type
|
||||
>::type
|
||||
>::type type;
|
||||
};
|
||||
}
|
||||
|
||||
template <class T>
|
||||
struct callback_from_python
|
||||
: detail::select_callback_from_python<T>::type
|
||||
{
|
||||
typedef T result_type;
|
||||
};
|
||||
|
||||
struct void_result
|
||||
{
|
||||
private:
|
||||
void_result() {}
|
||||
void operator=(void_result const&);
|
||||
|
||||
// I would prefer to make this completely untouchable, but few
|
||||
// compilers support template friends
|
||||
# if 0
|
||||
void_result(void_result const&);
|
||||
# endif
|
||||
friend struct callback_from_python<void>;
|
||||
};
|
||||
|
||||
// Specialization as a convenience for call and call_method
|
||||
template <>
|
||||
struct callback_from_python<void>
|
||||
{
|
||||
typedef void_result result_type;
|
||||
result_type operator()(PyObject* x) const
|
||||
{
|
||||
Py_DECREF(expect_non_null(x));
|
||||
return result_type();
|
||||
}
|
||||
};
|
||||
|
||||
template <class T>
|
||||
struct callback_to_python
|
||||
: detail::select_callback_to_python<T>::type
|
||||
{
|
||||
typedef typename detail::select_callback_to_python<T>::type base;
|
||||
public: // member functions
|
||||
// Throw an exception if the conversion can't succeed
|
||||
callback_to_python(T const& x);
|
||||
};
|
||||
|
||||
// Convenience macros for call<> and call_method<> code generation
|
||||
# define BOOST_PYTHON_CALLBACK_TO_PYTHON_GET(index,ignored) \
|
||||
converter::callback_to_python<BOOST_PP_CAT(A,index)>( \
|
||||
BOOST_PP_CAT(a,index)).get()
|
||||
|
||||
# define BOOST_PYTHON_ARG_STRING(nargs) \
|
||||
"(" BOOST_PP_REPEAT(nargs,BOOST_PYTHON_PROJECT_2ND,"O") ")"
|
||||
|
||||
//
|
||||
// Implementations
|
||||
//
|
||||
namespace detail
|
||||
{
|
||||
template <class T>
|
||||
inline rvalue_callback_from_python<T>::rvalue_callback_from_python()
|
||||
: m_data(rvalue_from_python_chain<T>::value)
|
||||
{
|
||||
throw_if_not_registered(m_data.stage1);
|
||||
}
|
||||
|
||||
template <class T>
|
||||
inline T const& rvalue_callback_from_python<T>::operator()(PyObject* obj)
|
||||
{
|
||||
return *(T*)convert_rvalue(obj, m_data.stage1, m_data.storage.bytes);
|
||||
}
|
||||
|
||||
BOOST_PYTHON_DECL void throw_no_class_registered();
|
||||
|
||||
template <class T>
|
||||
inline reference_callback_from_python<T>::reference_callback_from_python()
|
||||
{
|
||||
detail::throw_if_not_registered(lvalue_from_python_chain<T,true>::value);
|
||||
}
|
||||
|
||||
template <class T>
|
||||
inline T reference_callback_from_python<T>::operator()(PyObject* obj) const
|
||||
{
|
||||
return python::detail::void_ptr_to_reference(
|
||||
callback_convert_reference(obj, lvalue_from_python_chain<T,true>::value)
|
||||
, (T(*)())0);
|
||||
}
|
||||
|
||||
template <class T>
|
||||
inline pointer_callback_from_python<T>::pointer_callback_from_python()
|
||||
{
|
||||
detail::throw_if_not_registered(lvalue_from_python_chain<T,true>::value);
|
||||
}
|
||||
|
||||
template <class T>
|
||||
inline T pointer_callback_from_python<T>::operator()(PyObject* obj) const
|
||||
{
|
||||
return T(callback_convert_pointer(obj, lvalue_from_python_chain<T,true>::value));
|
||||
}
|
||||
|
||||
template <class T>
|
||||
inline value_callback_to_python<T>::value_callback_to_python(T const& x)
|
||||
: callback_to_python_base(&x, to_python_function<T>::value)
|
||||
{
|
||||
}
|
||||
|
||||
template <class Ptr>
|
||||
inline pointer_deep_callback_to_python<Ptr>::pointer_deep_callback_to_python(Ptr x)
|
||||
: callback_to_python_base(x, pointee_to_python_function<Ptr>::value)
|
||||
{
|
||||
}
|
||||
|
||||
template <class T>
|
||||
inline PyObject* reference_callback_to_python<T>::get_object(T& x)
|
||||
{
|
||||
to_python_indirect<T&,python::detail::make_reference_holder> convert;
|
||||
if (!convert.convertible())
|
||||
throw_no_class_registered();
|
||||
return convert(x);
|
||||
}
|
||||
|
||||
template <class T>
|
||||
inline reference_callback_to_python<T>::reference_callback_to_python(T& x)
|
||||
: callback_to_python_holder(get_object(x))
|
||||
{
|
||||
}
|
||||
|
||||
template <class Ptr>
|
||||
inline pointer_shallow_callback_to_python<Ptr>::pointer_shallow_callback_to_python(Ptr x)
|
||||
: callback_to_python_holder(get_object(x))
|
||||
{}
|
||||
|
||||
template <class Ptr>
|
||||
inline PyObject* pointer_shallow_callback_to_python<Ptr>::get_object(Ptr x)
|
||||
{
|
||||
to_python_indirect<Ptr,python::detail::make_reference_holder> convert;
|
||||
if (!convert.convertible())
|
||||
throw_no_class_registered();
|
||||
return x ? convert(x) : python::detail::none();
|
||||
}
|
||||
}
|
||||
|
||||
template <class T>
|
||||
inline callback_to_python<T>::callback_to_python(T const& x)
|
||||
: base(x)
|
||||
{}
|
||||
|
||||
}}} // namespace boost::python::converter
|
||||
|
||||
#endif // CALLBACK_DWA2002228_HPP
|
||||
25
include/boost/python/converter/callback_from_python_base.hpp
Normal file
25
include/boost/python/converter/callback_from_python_base.hpp
Normal file
@@ -0,0 +1,25 @@
|
||||
// Copyright David Abrahams 2002. Permission to copy, use,
|
||||
// modify, sell and distribute this software is granted provided this
|
||||
// copyright notice appears in all copies. This software is provided
|
||||
// "as is" without express or implied warranty, and with no claim as
|
||||
// to its suitability for any purpose.
|
||||
#ifndef CALLBACK_FROM_PYTHON_BASE_DWA200237_HPP
|
||||
# define CALLBACK_FROM_PYTHON_BASE_DWA200237_HPP
|
||||
|
||||
namespace boost { namespace python { namespace converter {
|
||||
|
||||
namespace detail
|
||||
{
|
||||
|
||||
// Throw an exception
|
||||
BOOST_PYTHON_DECL void throw_if_not_registered(rvalue_stage1_data const&);
|
||||
BOOST_PYTHON_DECL void* convert_rvalue(PyObject*, rvalue_stage1_data& data, void* storage);
|
||||
|
||||
BOOST_PYTHON_DECL void throw_if_not_registered(lvalue_from_python_registration*const&);
|
||||
BOOST_PYTHON_DECL void* callback_convert_reference(PyObject*, lvalue_from_python_registration*const&);
|
||||
BOOST_PYTHON_DECL void* callback_convert_pointer(PyObject*, lvalue_from_python_registration*const&);
|
||||
}
|
||||
|
||||
}}} // namespace boost::python::converter
|
||||
|
||||
#endif // CALLBACK_FROM_PYTHON_BASE_DWA200237_HPP
|
||||
45
include/boost/python/converter/callback_to_python_base.hpp
Normal file
45
include/boost/python/converter/callback_to_python_base.hpp
Normal file
@@ -0,0 +1,45 @@
|
||||
// Copyright David Abrahams 2002. Permission to copy, use,
|
||||
// modify, sell and distribute this software is granted provided this
|
||||
// copyright notice appears in all copies. This software is provided
|
||||
// "as is" without express or implied warranty, and with no claim as
|
||||
// to its suitability for any purpose.
|
||||
#ifndef CALLBACK_TO_PYTHON_BASE_DWA200237_HPP
|
||||
# define CALLBACK_TO_PYTHON_BASE_DWA200237_HPP
|
||||
# include <boost/python/converter/to_python_function_type.hpp>
|
||||
# include <boost/python/detail/wrap_python.hpp>
|
||||
# include <boost/python/reference.hpp>
|
||||
|
||||
namespace boost { namespace python { namespace converter {
|
||||
|
||||
namespace detail
|
||||
{
|
||||
struct callback_to_python_holder
|
||||
{
|
||||
callback_to_python_holder(PyObject* obj);
|
||||
inline PyObject* get() const;
|
||||
private:
|
||||
ref m_held;
|
||||
};
|
||||
|
||||
struct BOOST_PYTHON_DECL callback_to_python_base : callback_to_python_holder
|
||||
{
|
||||
callback_to_python_base(void const volatile* source, to_python_function_t);
|
||||
};
|
||||
|
||||
//
|
||||
// implmentation
|
||||
//
|
||||
inline callback_to_python_holder::callback_to_python_holder(PyObject* obj)
|
||||
: m_held(obj)
|
||||
{
|
||||
}
|
||||
|
||||
inline PyObject* callback_to_python_holder::get() const
|
||||
{
|
||||
return m_held.get();
|
||||
}
|
||||
}
|
||||
|
||||
}}} // namespace boost::python::converter
|
||||
|
||||
#endif // CALLBACK_TO_PYTHON_BASE_DWA200237_HPP
|
||||
18
include/boost/python/converter/constructor_function.hpp
Normal file
18
include/boost/python/converter/constructor_function.hpp
Normal file
@@ -0,0 +1,18 @@
|
||||
// Copyright David Abrahams 2002. Permission to copy, use,
|
||||
// modify, sell and distribute this software is granted provided this
|
||||
// copyright notice appears in all copies. This software is provided
|
||||
// "as is" without express or implied warranty, and with no claim as
|
||||
// to its suitability for any purpose.
|
||||
#ifndef CONSTRUCTOR_FUNCTION_DWA200278_HPP
|
||||
# define CONSTRUCTOR_FUNCTION_DWA200278_HPP
|
||||
|
||||
namespace boost { namespace python { namespace converter {
|
||||
|
||||
// Declares the type of functions used to construct C++ objects for
|
||||
// rvalue from_python conversions.
|
||||
struct rvalue_from_python_stage1_data;
|
||||
typedef void (*constructor_function)(PyObject* source, rvalue_from_python_stage1_data*);
|
||||
|
||||
}}} // namespace boost::python::converter
|
||||
|
||||
#endif // CONSTRUCTOR_FUNCTION_DWA200278_HPP
|
||||
15
include/boost/python/converter/convertible_function.hpp
Normal file
15
include/boost/python/converter/convertible_function.hpp
Normal file
@@ -0,0 +1,15 @@
|
||||
// Copyright David Abrahams 2002. Permission to copy, use,
|
||||
// modify, sell and distribute this software is granted provided this
|
||||
// copyright notice appears in all copies. This software is provided
|
||||
// "as is" without express or implied warranty, and with no claim as
|
||||
// to its suitability for any purpose.
|
||||
#ifndef CONVERTIBLE_FUNCTION_DWA200278_HPP
|
||||
# define CONVERTIBLE_FUNCTION_DWA200278_HPP
|
||||
|
||||
namespace boost { namespace python { namespace converter {
|
||||
|
||||
typedef void* (*convertible_function)(PyObject*);
|
||||
|
||||
}}} // namespace boost::python::converter
|
||||
|
||||
#endif // CONVERTIBLE_FUNCTION_DWA200278_HPP
|
||||
29
include/boost/python/converter/find_from_python.hpp
Normal file
29
include/boost/python/converter/find_from_python.hpp
Normal file
@@ -0,0 +1,29 @@
|
||||
// Copyright David Abrahams 2002. Permission to copy, use,
|
||||
// modify, sell and distribute this software is granted provided this
|
||||
// copyright notice appears in all copies. This software is provided
|
||||
// "as is" without express or implied warranty, and with no claim as
|
||||
// to its suitability for any purpose.
|
||||
#ifndef FIND_FROM_PYTHON_DWA2002223_HPP
|
||||
# define FIND_FROM_PYTHON_DWA2002223_HPP
|
||||
|
||||
# include <boost/python/detail/config.hpp>
|
||||
# include <boost/python/detail/wrap_python.hpp>
|
||||
# include <boost/python/converter/from_python_stage1_data.hpp>
|
||||
|
||||
namespace boost { namespace python { namespace converter {
|
||||
|
||||
struct lvalue_from_python_registration;
|
||||
struct rvalue_from_python_registration;
|
||||
|
||||
BOOST_PYTHON_DECL void* find(
|
||||
PyObject* source, lvalue_from_python_registration const*);
|
||||
|
||||
BOOST_PYTHON_DECL rvalue_stage1_data find(
|
||||
PyObject* source, rvalue_from_python_registration const*);
|
||||
|
||||
BOOST_PYTHON_DECL rvalue_from_python_registration const* find_chain(
|
||||
PyObject* source, rvalue_from_python_registration const*);
|
||||
|
||||
}}} // namespace boost::python::converter
|
||||
|
||||
#endif // FIND_FROM_PYTHON_DWA2002223_HPP
|
||||
43
include/boost/python/converter/from_python.hpp
Normal file
43
include/boost/python/converter/from_python.hpp
Normal file
@@ -0,0 +1,43 @@
|
||||
// Copyright David Abrahams 2002. Permission to copy, use,
|
||||
// modify, sell and distribute this software is granted provided this
|
||||
// copyright notice appears in all copies. This software is provided
|
||||
// "as is" without express or implied warranty, and with no claim as
|
||||
// to its suitability for any purpose.
|
||||
#ifndef FIND_FROM_PYTHON_DWA2002223_HPP
|
||||
# define FIND_FROM_PYTHON_DWA2002223_HPP
|
||||
|
||||
# include <boost/python/detail/config.hpp>
|
||||
# include <boost/python/detail/wrap_python.hpp>
|
||||
# include <boost/python/converter/rvalue_from_python_data.hpp>
|
||||
|
||||
namespace boost { namespace python { namespace converter {
|
||||
|
||||
struct registration;
|
||||
struct rvalue_from_python_chain;
|
||||
|
||||
BOOST_PYTHON_DECL void* get_lvalue_from_python(
|
||||
PyObject* source, registration const&);
|
||||
|
||||
BOOST_PYTHON_DECL rvalue_from_python_chain const* implicit_conversion_chain(
|
||||
PyObject* source, registration const&);
|
||||
|
||||
BOOST_PYTHON_DECL rvalue_from_python_stage1_data rvalue_from_python_stage1(
|
||||
PyObject* source, registration const&);
|
||||
|
||||
BOOST_PYTHON_DECL void* rvalue_from_python_stage2(
|
||||
PyObject* source, rvalue_from_python_stage1_data&, registration const&);
|
||||
|
||||
BOOST_PYTHON_DECL void* rvalue_result_from_python(
|
||||
PyObject*, rvalue_from_python_stage1_data&);
|
||||
|
||||
BOOST_PYTHON_DECL void* reference_result_from_python(PyObject*, registration const&);
|
||||
BOOST_PYTHON_DECL void* pointer_result_from_python(PyObject*, registration const&);
|
||||
|
||||
BOOST_PYTHON_DECL void void_result_from_python(PyObject*);
|
||||
|
||||
BOOST_PYTHON_DECL void throw_no_pointer_from_python(PyObject*, registration const&);
|
||||
BOOST_PYTHON_DECL void throw_no_reference_from_python(PyObject*, registration const&);
|
||||
|
||||
}}} // namespace boost::python::converter
|
||||
|
||||
#endif // FIND_FROM_PYTHON_DWA2002223_HPP
|
||||
129
include/boost/python/converter/from_python_data.hpp
Normal file
129
include/boost/python/converter/from_python_data.hpp
Normal file
@@ -0,0 +1,129 @@
|
||||
// Copyright David Abrahams 2002. Permission to copy, use,
|
||||
// modify, sell and distribute this software is granted provided this
|
||||
// copyright notice appears in all copies. This software is provided
|
||||
// "as is" without express or implied warranty, and with no claim as
|
||||
// to its suitability for any purpose.
|
||||
#ifndef FROM_PYTHON_AUX_DATA_DWA2002128_HPP
|
||||
# define FROM_PYTHON_AUX_DATA_DWA2002128_HPP
|
||||
|
||||
# include <boost/python/detail/char_array.hpp>
|
||||
# include <boost/mpl/select_if.hpp>
|
||||
# include <boost/type_traits/same_traits.hpp>
|
||||
# include <boost/type_traits/transform_traits.hpp>
|
||||
# include <boost/static_assert.hpp>
|
||||
# include <boost/python/converter/from_python_stage1_data.hpp>
|
||||
# include <boost/type_traits/composite_traits.hpp>
|
||||
# include <boost/type_traits/cv_traits.hpp>
|
||||
# include <boost/python/detail/destroy.hpp>
|
||||
# include <boost/preprocessor/list/for_each_i.hpp>
|
||||
# include <boost/preprocessor/tuple/to_list.hpp>
|
||||
# include <boost/preprocessor/cat.hpp>
|
||||
|
||||
namespace boost { namespace python { namespace converter {
|
||||
|
||||
namespace detail
|
||||
{
|
||||
template <class T> struct referent_size;
|
||||
|
||||
# ifndef BOOST_NO_TEMPLATE_PARTIAL_SPECIALIZATION
|
||||
|
||||
template <class T>
|
||||
struct referent_size<T&>
|
||||
{
|
||||
BOOST_STATIC_CONSTANT(
|
||||
std::size_t, value = sizeof(T));
|
||||
};
|
||||
|
||||
# else
|
||||
|
||||
template <class T> struct referent_size
|
||||
{
|
||||
static T f();
|
||||
BOOST_STATIC_CONSTANT(std::size_t, value = sizeof(f()));
|
||||
};
|
||||
|
||||
# endif
|
||||
struct alignment_dummy;
|
||||
typedef void (*function_ptr)();
|
||||
typedef int (alignment_dummy::*member_ptr);
|
||||
typedef int (alignment_dummy::*member_function_ptr)();
|
||||
|
||||
# define BOOST_PYTHON_ALIGNMENT_TYPES BOOST_PP_TUPLE_TO_LIST( \
|
||||
11, ( \
|
||||
char, short, int, long, float, double, long double \
|
||||
, void*, function_ptr, member_ptr, member_function_ptr))
|
||||
|
||||
# define BOOST_PYTHON_CHOOSE_LOWER_SIZE(R,P,I,T) \
|
||||
typename mpl::select_if_c< \
|
||||
sizeof(T) <= target, T, char>::type BOOST_PP_CAT(t,I);
|
||||
|
||||
# define BOOST_PYTHON_CHOOSE_T(R,P,I,T) T BOOST_PP_CAT(t,I);
|
||||
|
||||
template <std::size_t target>
|
||||
union lower_size
|
||||
{
|
||||
BOOST_PP_LIST_FOR_EACH_I(
|
||||
BOOST_PYTHON_CHOOSE_LOWER_SIZE
|
||||
, ignored, BOOST_PYTHON_ALIGNMENT_TYPES)
|
||||
};
|
||||
|
||||
template <class Align, std::size_t size>
|
||||
union aligned_storage
|
||||
{
|
||||
Align align;
|
||||
char bytes[size];
|
||||
};
|
||||
|
||||
template <class Reference>
|
||||
struct referent_storage
|
||||
{
|
||||
typedef lower_size<referent_size<Reference>::value> align_t;
|
||||
typedef aligned_storage<align_t,referent_size<Reference>::value> type;
|
||||
};
|
||||
}
|
||||
|
||||
template <class T>
|
||||
struct rvalue_base_data
|
||||
{
|
||||
rvalue_stage1_data stage1;
|
||||
|
||||
typename detail::referent_storage<
|
||||
typename add_reference<T>::type
|
||||
>::type storage;
|
||||
};
|
||||
|
||||
template <class T>
|
||||
struct rvalue_data : rvalue_base_data<T>
|
||||
{
|
||||
rvalue_data(rvalue_stage1_data const&);
|
||||
rvalue_data(void*);
|
||||
~rvalue_data();
|
||||
private:
|
||||
typedef typename add_reference<typename add_cv<T>::type>::type ref_type;
|
||||
};
|
||||
|
||||
//
|
||||
// Implementataions
|
||||
//
|
||||
template <class T>
|
||||
inline rvalue_data<T>::rvalue_data(rvalue_stage1_data const& stage1)
|
||||
{
|
||||
this->stage1 = stage1;
|
||||
}
|
||||
|
||||
template <class T>
|
||||
inline rvalue_data<T>::rvalue_data(void* convertible)
|
||||
{
|
||||
this->stage1.convertible = convertible;
|
||||
}
|
||||
|
||||
template <class T>
|
||||
inline rvalue_data<T>::~rvalue_data()
|
||||
{
|
||||
if (this->stage1.convertible == this->storage.bytes)
|
||||
python::detail::destroy_reference<ref_type>(this->storage.bytes);
|
||||
}
|
||||
|
||||
}}} // namespace boost::python::converter
|
||||
|
||||
#endif // FROM_PYTHON_AUX_DATA_DWA2002128_HPP
|
||||
18
include/boost/python/converter/from_python_function.hpp
Normal file
18
include/boost/python/converter/from_python_function.hpp
Normal file
@@ -0,0 +1,18 @@
|
||||
// Copyright David Abrahams 2002. Permission to copy, use,
|
||||
// modify, sell and distribute this software is granted provided this
|
||||
// copyright notice appears in all copies. This software is provided
|
||||
// "as is" without express or implied warranty, and with no claim as
|
||||
// to its suitability for any purpose.
|
||||
#ifndef FROM_PYTHON_FUNCTION_DWA2002128_HPP
|
||||
# define FROM_PYTHON_FUNCTION_DWA2002128_HPP
|
||||
|
||||
# include <boost/python/detail/wrap_python.hpp>
|
||||
|
||||
namespace boost { namespace python { namespace converter {
|
||||
|
||||
struct rvalue_stage1_data;
|
||||
typedef void (*constructor_function)(PyObject* source, rvalue_stage1_data*);
|
||||
|
||||
}}} // namespace boost::python::converter
|
||||
|
||||
#endif // FROM_PYTHON_FUNCTION_DWA2002128_HPP
|
||||
21
include/boost/python/converter/from_python_stage1_data.hpp
Normal file
21
include/boost/python/converter/from_python_stage1_data.hpp
Normal file
@@ -0,0 +1,21 @@
|
||||
// Copyright David Abrahams 2002. Permission to copy, use,
|
||||
// modify, sell and distribute this software is granted provided this
|
||||
// copyright notice appears in all copies. This software is provided
|
||||
// "as is" without express or implied warranty, and with no claim as
|
||||
// to its suitability for any purpose.
|
||||
#ifndef FROM_PYTHON_STAGE1_DATA_DWA2002223_HPP
|
||||
# define FROM_PYTHON_STAGE1_DATA_DWA2002223_HPP
|
||||
|
||||
# include <boost/python/converter/from_python_function.hpp>
|
||||
|
||||
namespace boost { namespace python { namespace converter {
|
||||
|
||||
struct rvalue_stage1_data
|
||||
{
|
||||
void* convertible;
|
||||
constructor_function construct;
|
||||
};
|
||||
|
||||
}}} // namespace boost::python::converter
|
||||
|
||||
#endif // FROM_PYTHON_STAGE1_DATA_DWA2002223_HPP
|
||||
57
include/boost/python/converter/implicit.hpp
Normal file
57
include/boost/python/converter/implicit.hpp
Normal file
@@ -0,0 +1,57 @@
|
||||
// Copyright David Abrahams 2002. Permission to copy, use,
|
||||
// modify, sell and distribute this software is granted provided this
|
||||
// copyright notice appears in all copies. This software is provided
|
||||
// "as is" without express or implied warranty, and with no claim as
|
||||
// to its suitability for any purpose.
|
||||
#ifndef IMPLICIT_DWA2002326_HPP
|
||||
# define IMPLICIT_DWA2002326_HPP
|
||||
# include <boost/python/converter/rvalue_from_python_data.hpp>
|
||||
# include <boost/python/converter/registrations.hpp>
|
||||
# include <boost/python/converter/registered.hpp>
|
||||
|
||||
namespace boost { namespace python { namespace converter {
|
||||
|
||||
template <class Source, class Target>
|
||||
struct implicit
|
||||
{
|
||||
static void* convertible(PyObject* obj)
|
||||
{
|
||||
// Find a converter chain which can produce a Source instance
|
||||
// from obj. The user has told us that Source can be converted
|
||||
// to Target, and instantiating construct() below, ensures
|
||||
// that at compile-time.
|
||||
return const_cast<rvalue_from_python_chain*>(
|
||||
converter::implicit_conversion_chain(obj, registered<Source>::converters));
|
||||
}
|
||||
|
||||
static void construct(PyObject* obj, rvalue_from_python_stage1_data* data)
|
||||
{
|
||||
// This is the chain we got from the convertible step
|
||||
rvalue_from_python_chain const* chain
|
||||
= static_cast<rvalue_from_python_chain*>(data->convertible);
|
||||
|
||||
// Call the convertible function again
|
||||
rvalue_from_python_data<Source> intermediate_data(chain->convertible(obj));
|
||||
|
||||
// Use the result to construct the source type if the first
|
||||
// converter was an rvalue converter.
|
||||
if (chain->construct != 0)
|
||||
chain->construct(obj, &intermediate_data.stage1);
|
||||
|
||||
void* storage = ((rvalue_from_python_storage<Target>*)data)->storage.bytes;
|
||||
# if !defined(BOOST_MSVC) || _MSC_FULL_VER != 13012108 // vc7.01 alpha workaround
|
||||
new (storage) Target(*static_cast<Source*>(intermediate_data.stage1.convertible));
|
||||
# else
|
||||
Target x(*static_cast<Source*>(intermediate_data.stage1.convertible));
|
||||
new (storage) Target(x);
|
||||
# endif
|
||||
|
||||
// record successful construction
|
||||
data->convertible = storage;
|
||||
|
||||
}
|
||||
};
|
||||
|
||||
}}} // namespace boost::python::converter
|
||||
|
||||
#endif // IMPLICIT_DWA2002326_HPP
|
||||
70
include/boost/python/converter/lvalue_from_python_chain.hpp
Normal file
70
include/boost/python/converter/lvalue_from_python_chain.hpp
Normal file
@@ -0,0 +1,70 @@
|
||||
// Copyright David Abrahams 2002. Permission to copy, use,
|
||||
// modify, sell and distribute this software is granted provided this
|
||||
// copyright notice appears in all copies. This software is provided
|
||||
// "as is" without express or implied warranty, and with no claim as
|
||||
// to its suitability for any purpose.
|
||||
#ifndef LVALUE_FROM_PYTHON_CHAIN_DWA200237_HPP
|
||||
# define LVALUE_FROM_PYTHON_CHAIN_DWA200237_HPP
|
||||
|
||||
# include <boost/python/converter/pointer_type_id.hpp>
|
||||
# include <boost/python/converter/registry.hpp>
|
||||
# include <boost/type_traits/cv_traits.hpp>
|
||||
|
||||
namespace boost { namespace python { namespace converter {
|
||||
|
||||
// Given T == U*cv&, T == U*, or T == U&, lvalue_from_python_chain<T>
|
||||
// declares a "templated global reference" to the lvalue from_python
|
||||
// converter chain for U. The optional bool second argument callback,
|
||||
// when true, removes special treatment for T == U*cv& so that the
|
||||
// converter for U* is found.
|
||||
namespace detail
|
||||
{
|
||||
template <class T>
|
||||
struct ptr_or_ptr_ref_lvalue_from_python_chain
|
||||
{
|
||||
static lvalue_from_python_registration*const& value;
|
||||
};
|
||||
|
||||
template <class T>
|
||||
lvalue_from_python_registration*const&
|
||||
ptr_or_ptr_ref_lvalue_from_python_chain<T>::value
|
||||
= registry::lvalue_converters(pointer_type_id<T>());
|
||||
|
||||
template <class T>
|
||||
struct ref_lvalue_from_python_chain
|
||||
{
|
||||
static lvalue_from_python_registration*const& value;
|
||||
};
|
||||
|
||||
template <class T>
|
||||
lvalue_from_python_registration*const&
|
||||
ref_lvalue_from_python_chain<T>::value
|
||||
= registry::lvalue_converters(undecorated_type_id<T>());
|
||||
|
||||
template <class T, bool callback>
|
||||
struct select_lvalue_from_python_chain
|
||||
{
|
||||
BOOST_STATIC_CONSTANT(
|
||||
bool, ptr
|
||||
= !callback && boost::python::detail::is_reference_to_pointer<T>::value
|
||||
|| is_pointer<T>::value);
|
||||
|
||||
typedef typename add_reference<typename add_cv<T>::type>::type normalized;
|
||||
|
||||
typedef typename mpl::select_if_c<
|
||||
ptr
|
||||
, ptr_or_ptr_ref_lvalue_from_python_chain<normalized>
|
||||
, ref_lvalue_from_python_chain<normalized>
|
||||
>::type type;
|
||||
};
|
||||
}
|
||||
|
||||
template <class T, bool callback = false>
|
||||
struct lvalue_from_python_chain
|
||||
: detail::select_lvalue_from_python_chain<T,callback>::type
|
||||
{
|
||||
};
|
||||
|
||||
}}} // namespace boost::python::converter
|
||||
|
||||
#endif // LVALUE_FROM_PYTHON_CHAIN_DWA200237_HPP
|
||||
116
include/boost/python/converter/obj_mgr_arg_from_python.hpp
Normal file
116
include/boost/python/converter/obj_mgr_arg_from_python.hpp
Normal file
@@ -0,0 +1,116 @@
|
||||
// Copyright David Abrahams 2002. Permission to copy, use,
|
||||
// modify, sell and distribute this software is granted provided this
|
||||
// copyright notice appears in all copies. This software is provided
|
||||
// "as is" without express or implied warranty, and with no claim as
|
||||
// to its suitability for any purpose.
|
||||
#ifndef OBJ_MGR_ARG_FROM_PYTHON_DWA2002628_HPP
|
||||
# define OBJ_MGR_ARG_FROM_PYTHON_DWA2002628_HPP
|
||||
|
||||
# include <boost/python/detail/wrap_python.hpp>
|
||||
# include <boost/python/detail/referent_storage.hpp>
|
||||
# include <boost/python/detail/destroy.hpp>
|
||||
# include <boost/python/detail/construct.hpp>
|
||||
# include <boost/python/converter/object_manager.hpp>
|
||||
# include <boost/python/detail/raw_pyobject.hpp>
|
||||
# include <boost/python/tag.hpp>
|
||||
|
||||
//
|
||||
// arg_from_python converters for Python type wrappers, to be used as
|
||||
// base classes for specializations.
|
||||
//
|
||||
namespace boost { namespace python { namespace converter {
|
||||
|
||||
template <class T>
|
||||
struct object_manager_value_arg_from_python
|
||||
{
|
||||
typedef T result_type;
|
||||
|
||||
object_manager_value_arg_from_python(PyObject*);
|
||||
bool convertible() const;
|
||||
T operator()(PyObject*) const;
|
||||
private:
|
||||
PyObject* m_source;
|
||||
};
|
||||
|
||||
// Used for converting reference-to-object-manager arguments from
|
||||
// python. The process used here is a little bit odd. Upon
|
||||
// construction, we build the object manager object in the m_result
|
||||
// object, *forcing* it to accept the source Python object by casting
|
||||
// its pointer to detail::borrowed_reference. This is supposed to
|
||||
// bypass any type checking of the source object. The convertible
|
||||
// check then extracts the owned object and checks it. If the check
|
||||
// fails, nothing else in the program ever gets to touch this strange
|
||||
// "forced" object.
|
||||
template <class Ref>
|
||||
struct object_manager_ref_arg_from_python
|
||||
{
|
||||
typedef Ref result_type;
|
||||
|
||||
object_manager_ref_arg_from_python(PyObject*);
|
||||
bool convertible() const;
|
||||
Ref operator()(PyObject*) const;
|
||||
~object_manager_ref_arg_from_python();
|
||||
private:
|
||||
typename python::detail::referent_storage<Ref>::type m_result;
|
||||
};
|
||||
|
||||
//
|
||||
// implementations
|
||||
//
|
||||
|
||||
template <class T>
|
||||
inline object_manager_value_arg_from_python<T>::object_manager_value_arg_from_python(PyObject* x)
|
||||
: m_source(x)
|
||||
{
|
||||
}
|
||||
|
||||
template <class T>
|
||||
inline bool object_manager_value_arg_from_python<T>::convertible() const
|
||||
{
|
||||
return object_manager_traits<T>::check(m_source);
|
||||
}
|
||||
|
||||
template <class T>
|
||||
inline T object_manager_value_arg_from_python<T>::operator()(PyObject* x) const
|
||||
{
|
||||
return T(python::detail::borrowed_reference(x));
|
||||
}
|
||||
|
||||
template <class Ref>
|
||||
inline object_manager_ref_arg_from_python<Ref>::object_manager_ref_arg_from_python(PyObject* x)
|
||||
{
|
||||
python::detail::construct_referent<Ref>(&m_result.bytes, python::detail::borrowed_reference(x));
|
||||
}
|
||||
|
||||
template <class Ref>
|
||||
inline object_manager_ref_arg_from_python<Ref>::~object_manager_ref_arg_from_python()
|
||||
{
|
||||
python::detail::destroy_referent<Ref>(this->m_result.bytes);
|
||||
}
|
||||
|
||||
namespace detail
|
||||
{
|
||||
template <class T>
|
||||
inline bool object_manager_ref_check(T const& x)
|
||||
{
|
||||
return object_manager_traits<T>::check(get_managed_object(x, tag));
|
||||
}
|
||||
}
|
||||
|
||||
template <class Ref>
|
||||
inline bool object_manager_ref_arg_from_python<Ref>::convertible() const
|
||||
{
|
||||
return detail::object_manager_ref_check(
|
||||
python::detail::void_ptr_to_reference(this->m_result.bytes, (Ref(*)())0));
|
||||
}
|
||||
|
||||
template <class Ref>
|
||||
inline Ref object_manager_ref_arg_from_python<Ref>::operator()(PyObject*) const
|
||||
{
|
||||
return python::detail::void_ptr_to_reference(
|
||||
this->m_result.bytes, (Ref(*)())0);
|
||||
}
|
||||
|
||||
}}} // namespace boost::python::converter
|
||||
|
||||
#endif // OBJ_MGR_ARG_FROM_PYTHON_DWA2002628_HPP
|
||||
232
include/boost/python/converter/object_manager.hpp
Executable file
232
include/boost/python/converter/object_manager.hpp
Executable file
@@ -0,0 +1,232 @@
|
||||
// Copyright David Abrahams 2002. Permission to copy, use,
|
||||
// modify, sell and distribute this software is granted provided this
|
||||
// copyright notice appears in all copies. This software is provided
|
||||
// "as is" without express or implied warranty, and with no claim as
|
||||
// to its suitability for any purpose.
|
||||
#ifndef OBJECT_MANAGER_DWA2002614_HPP
|
||||
# define OBJECT_MANAGER_DWA2002614_HPP
|
||||
|
||||
# include <boost/python/handle.hpp>
|
||||
# include <boost/python/cast.hpp>
|
||||
# include <boost/python/converter/pyobject_traits.hpp>
|
||||
# include <boost/type_traits/object_traits.hpp>
|
||||
# include <boost/mpl/if.hpp>
|
||||
# include <boost/python/detail/indirect_traits.hpp>
|
||||
|
||||
// Facilities for dealing with types which always manage Python
|
||||
// objects. Some examples are object, list, str, et. al. Different
|
||||
// to_python/from_python conversion rules apply here because in
|
||||
// contrast to other types which are typically embedded inside a
|
||||
// Python object, these are wrapped around a Python object. For most
|
||||
// object managers T, a C++ non-const T reference argument does not
|
||||
// imply the existence of a T lvalue embedded in the corresponding
|
||||
// Python argument, since mutating member functions on T actually only
|
||||
// modify the held Python object.
|
||||
//
|
||||
// handle<T> is an object manager, though strictly speaking it should
|
||||
// not be. In other words, even though mutating member functions of
|
||||
// hanlde<T> actually modify the handle<T> and not the T object,
|
||||
// handle<T>& arguments of wrapped functions will bind to "rvalues"
|
||||
// wrapping the actual Python argument, just as with other object
|
||||
// manager classes. Making an exception for handle<T> is simply not
|
||||
// worth the trouble.
|
||||
//
|
||||
// borrowed<T> cv* is an object manager so that we can use the general
|
||||
// to_python mechanisms to convert raw Python object pointers to
|
||||
// python, without the usual semantic problems of using raw pointers.
|
||||
|
||||
|
||||
// Object Manager Concept requirements:
|
||||
//
|
||||
// T is an Object Manager
|
||||
// p is a PyObject*
|
||||
// x is a T
|
||||
//
|
||||
// * object_manager_traits<T>::is_specialized == true
|
||||
//
|
||||
// * T(detail::borrowed_reference(p))
|
||||
// Manages p without checking its type
|
||||
//
|
||||
// * get_managed_object(x, boost::python::tag)
|
||||
// Convertible to PyObject*
|
||||
//
|
||||
// Additional requirements if T can be converted from_python:
|
||||
//
|
||||
// * T(object_manager_traits<T>::adopt(p))
|
||||
// steals a reference to p, or throws a TypeError exception if
|
||||
// p doesn't have an appropriate type. May assume p is non-null
|
||||
//
|
||||
// * X::check(p)
|
||||
// convertible to bool. True iff T(X::construct(p)) will not
|
||||
// throw.
|
||||
|
||||
// Forward declarations
|
||||
//
|
||||
namespace boost { namespace python
|
||||
{
|
||||
namespace api
|
||||
{
|
||||
class object;
|
||||
}
|
||||
}}
|
||||
|
||||
namespace boost { namespace python { namespace converter {
|
||||
|
||||
|
||||
// Specializations for handle<T>
|
||||
template <class T>
|
||||
struct handle_object_manager_traits
|
||||
: pyobject_traits<typename T::element_type>
|
||||
{
|
||||
private:
|
||||
typedef pyobject_traits<typename T::element_type> base;
|
||||
|
||||
public:
|
||||
BOOST_STATIC_CONSTANT(bool, is_specialized = true);
|
||||
|
||||
// Initialize with a null_ok pointer for efficiency, bypassing the
|
||||
// null check since the source is always non-null.
|
||||
static null_ok<typename T::element_type>* adopt(PyObject* p)
|
||||
{
|
||||
return python::allow_null(base::checked_downcast(p));
|
||||
}
|
||||
};
|
||||
|
||||
template <class T>
|
||||
struct default_object_manager_traits
|
||||
{
|
||||
BOOST_STATIC_CONSTANT(
|
||||
bool, is_specialized = python::detail::is_borrowed_ptr<T>::value
|
||||
);
|
||||
};
|
||||
|
||||
template <class T>
|
||||
struct object_manager_traits
|
||||
: mpl::if_c<
|
||||
is_handle<T>::value
|
||||
, handle_object_manager_traits<T>
|
||||
, default_object_manager_traits<T>
|
||||
>::type
|
||||
{
|
||||
};
|
||||
|
||||
//
|
||||
// Traits for detecting whether a type is an object manager or a
|
||||
// (cv-qualified) reference to an object manager.
|
||||
//
|
||||
|
||||
template <class T>
|
||||
struct is_object_manager
|
||||
{
|
||||
BOOST_STATIC_CONSTANT(
|
||||
bool, value = object_manager_traits<T>::is_specialized);
|
||||
};
|
||||
|
||||
# ifndef BOOST_NO_TEMPLATE_PARTIAL_SPECIALIZATION
|
||||
template <class T>
|
||||
struct is_reference_to_object_manager
|
||||
{
|
||||
BOOST_STATIC_CONSTANT(bool, value = false);
|
||||
};
|
||||
|
||||
template <class T>
|
||||
struct is_reference_to_object_manager<T&>
|
||||
: is_object_manager<T>
|
||||
{
|
||||
};
|
||||
|
||||
template <class T>
|
||||
struct is_reference_to_object_manager<T const&>
|
||||
: is_object_manager<T>
|
||||
{
|
||||
};
|
||||
|
||||
template <class T>
|
||||
struct is_reference_to_object_manager<T volatile&>
|
||||
: is_object_manager<T>
|
||||
{
|
||||
};
|
||||
|
||||
template <class T>
|
||||
struct is_reference_to_object_manager<T const volatile&>
|
||||
: is_object_manager<T>
|
||||
{
|
||||
};
|
||||
# else
|
||||
|
||||
namespace detail
|
||||
{
|
||||
typedef char (&yes_reference_to_object_manager)[1];
|
||||
typedef char (&no_reference_to_object_manager)[2];
|
||||
|
||||
// A number of nastinesses go on here in order to work around MSVC6
|
||||
// bugs.
|
||||
template <class T>
|
||||
struct is_object_manager_help
|
||||
{
|
||||
typedef typename mpl::if_c<
|
||||
is_object_manager<T>::value
|
||||
, yes_reference_to_object_manager
|
||||
, no_reference_to_object_manager
|
||||
>::type type;
|
||||
|
||||
// If we just use the type instead of the result of calling this
|
||||
// function, VC6 will ICE.
|
||||
static type call();
|
||||
};
|
||||
|
||||
// A set of overloads for each cv-qualification. The same argument
|
||||
// is passed twice: the first one is used to unwind the cv*, and the
|
||||
// second one is used to avoid relying on partial ordering for
|
||||
// overload resolution.
|
||||
template <class U>
|
||||
typename is_object_manager_help<U>
|
||||
is_object_manager_helper(U*, void*);
|
||||
|
||||
template <class U>
|
||||
typename is_object_manager_help<U>
|
||||
is_object_manager_helper(U const*, void const*);
|
||||
|
||||
template <class U>
|
||||
typename is_object_manager_help<U>
|
||||
is_object_manager_helper(U volatile*, void volatile*);
|
||||
|
||||
template <class U>
|
||||
typename is_object_manager_help<U>
|
||||
is_object_manager_helper(U const volatile*, void const volatile*);
|
||||
|
||||
template <class T>
|
||||
struct is_reference_to_object_manager_nonref
|
||||
{
|
||||
BOOST_STATIC_CONSTANT(bool, value = false);
|
||||
};
|
||||
|
||||
template <class T>
|
||||
struct is_reference_to_object_manager_ref
|
||||
{
|
||||
static T sample_object;
|
||||
BOOST_STATIC_CONSTANT(
|
||||
bool, value
|
||||
= (sizeof(is_object_manager_helper(&sample_object, &sample_object).call())
|
||||
== sizeof(detail::yes_reference_to_object_manager)
|
||||
)
|
||||
);
|
||||
};
|
||||
}
|
||||
|
||||
template <class T>
|
||||
struct is_reference_to_object_manager
|
||||
{
|
||||
typedef typename mpl::if_c<
|
||||
is_reference<T>::value
|
||||
, detail::is_reference_to_object_manager_ref<T>
|
||||
, detail::is_reference_to_object_manager_nonref<T>
|
||||
> chooser;
|
||||
|
||||
BOOST_STATIC_CONSTANT(bool, value = chooser::type::value);
|
||||
};
|
||||
# endif
|
||||
|
||||
}}} // namespace boost::python::converter
|
||||
|
||||
#endif // OBJECT_MANAGER_DWA2002614_HPP
|
||||
@@ -0,0 +1,51 @@
|
||||
// Copyright David Abrahams 2002. Permission to copy, use,
|
||||
// modify, sell and distribute this software is granted provided this
|
||||
// copyright notice appears in all copies. This software is provided
|
||||
// "as is" without express or implied warranty, and with no claim as
|
||||
// to its suitability for any purpose.
|
||||
#ifndef POINTEE_TO_PYTHON_FUNCTION_DWA2002128_HPP
|
||||
# define POINTEE_TO_PYTHON_FUNCTION_DWA2002128_HPP
|
||||
|
||||
# include <boost/python/detail/wrap_python.hpp>
|
||||
# include <boost/type_traits/transform_traits.hpp>
|
||||
# include <boost/type_traits/cv_traits.hpp>
|
||||
# include <boost/python/converter/type_id.hpp>
|
||||
# include <boost/python/converter/registry.hpp>
|
||||
# include <boost/python/converter/to_python_function_type.hpp>
|
||||
# include <boost/python/converter/pointer_type_id.hpp>
|
||||
|
||||
namespace boost { namespace python { namespace converter {
|
||||
|
||||
// pointee_to_python_function --
|
||||
//
|
||||
// essentially a "templated global reference" which holds the
|
||||
// converter for converting a type to Python by-value. We "normalize"
|
||||
// T by adding "const volatile&" so that fewer global variables and
|
||||
// associated static initializations are generated.
|
||||
namespace detail
|
||||
{
|
||||
template <class T>
|
||||
struct pointee_to_python_function_base
|
||||
{
|
||||
static to_python_function_t const& value;
|
||||
};
|
||||
|
||||
template <class T>
|
||||
to_python_function_t const&
|
||||
pointee_to_python_function_base<T>::value
|
||||
= converter::registry::get_to_python_function(pointer_type_id<T>());
|
||||
}
|
||||
|
||||
template <class T>
|
||||
struct pointee_to_python_function
|
||||
: detail::pointee_to_python_function_base<
|
||||
typename add_reference<
|
||||
typename add_cv<T>::type
|
||||
>::type
|
||||
>
|
||||
{
|
||||
};
|
||||
|
||||
}}} // namespace boost::python::converter
|
||||
|
||||
#endif // POINTEE_TO_PYTHON_FUNCTION_DWA2002128_HPP
|
||||
69
include/boost/python/converter/pointer_type_id.hpp
Normal file
69
include/boost/python/converter/pointer_type_id.hpp
Normal file
@@ -0,0 +1,69 @@
|
||||
// Copyright David Abrahams 2002. Permission to copy, use,
|
||||
// modify, sell and distribute this software is granted provided this
|
||||
// copyright notice appears in all copies. This software is provided
|
||||
// "as is" without express or implied warranty, and with no claim as
|
||||
// to its suitability for any purpose.
|
||||
#ifndef POINTER_TYPE_ID_DWA2002222_HPP
|
||||
# define POINTER_TYPE_ID_DWA2002222_HPP
|
||||
|
||||
# include <boost/python/type_id.hpp>
|
||||
# include <boost/type_traits/composite_traits.hpp>
|
||||
|
||||
namespace boost { namespace python { namespace converter {
|
||||
|
||||
namespace detail
|
||||
{
|
||||
template <bool is_ref = false>
|
||||
struct pointer_typeid_select
|
||||
{
|
||||
template <class T>
|
||||
static inline type_info execute(T*(*)() = 0)
|
||||
{
|
||||
return type_id<T>();
|
||||
}
|
||||
};
|
||||
|
||||
template <>
|
||||
struct pointer_typeid_select<true>
|
||||
{
|
||||
template <class T>
|
||||
static inline type_info execute(T* const volatile&(*)() = 0)
|
||||
{
|
||||
return type_id<T>();
|
||||
}
|
||||
|
||||
template <class T>
|
||||
static inline type_info execute(T*volatile&(*)() = 0)
|
||||
{
|
||||
return type_id<T>();
|
||||
}
|
||||
|
||||
template <class T>
|
||||
static inline type_info execute(T*const&(*)() = 0)
|
||||
{
|
||||
return type_id<T>();
|
||||
}
|
||||
|
||||
template <class T>
|
||||
static inline type_info execute(T*&(*)() = 0)
|
||||
{
|
||||
return type_id<T>();
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
// Usage: pointer_type_id<T>()
|
||||
//
|
||||
// Returns a type_info associated with the type pointed
|
||||
// to by T, which may be a pointer or a reference to a pointer.
|
||||
template <class T>
|
||||
type_info pointer_type_id(T(*)() = 0)
|
||||
{
|
||||
return detail::pointer_typeid_select<
|
||||
is_reference<T>::value
|
||||
>::execute((T(*)())0);
|
||||
}
|
||||
|
||||
}}} // namespace boost::python::converter
|
||||
|
||||
#endif // POINTER_TYPE_ID_DWA2002222_HPP
|
||||
42
include/boost/python/converter/pyobject_traits.hpp
Normal file
42
include/boost/python/converter/pyobject_traits.hpp
Normal file
@@ -0,0 +1,42 @@
|
||||
// Copyright David Abrahams 2002. Permission to copy, use,
|
||||
// modify, sell and distribute this software is granted provided this
|
||||
// copyright notice appears in all copies. This software is provided
|
||||
// "as is" without express or implied warranty, and with no claim as
|
||||
// to its suitability for any purpose.
|
||||
#ifndef PYOBJECT_TRAITS_DWA2002720_HPP
|
||||
# define PYOBJECT_TRAITS_DWA2002720_HPP
|
||||
|
||||
# include <boost/python/detail/wrap_python.hpp>
|
||||
# include <boost/python/converter/pyobject_type.hpp>
|
||||
|
||||
namespace boost { namespace python { namespace converter {
|
||||
|
||||
template <class> struct pyobject_traits;
|
||||
|
||||
template <>
|
||||
struct pyobject_traits<PyObject>
|
||||
{
|
||||
// All objects are convertible to PyObject
|
||||
static bool check(PyObject*) { return true; }
|
||||
static PyObject* checked_downcast(PyObject* x) { return x; }
|
||||
};
|
||||
|
||||
//
|
||||
// Specializations
|
||||
//
|
||||
|
||||
# define BOOST_PYTHON_BUILTIN_OBJECT_TRAITS(T) \
|
||||
template <> struct pyobject_traits<Py##T##Object> \
|
||||
: pyobject_type<Py##T##Object, &Py##T##_Type> {}
|
||||
|
||||
// This is not an exhaustive list; should be expanded.
|
||||
BOOST_PYTHON_BUILTIN_OBJECT_TRAITS(Type);
|
||||
BOOST_PYTHON_BUILTIN_OBJECT_TRAITS(List);
|
||||
BOOST_PYTHON_BUILTIN_OBJECT_TRAITS(Int);
|
||||
BOOST_PYTHON_BUILTIN_OBJECT_TRAITS(Long);
|
||||
BOOST_PYTHON_BUILTIN_OBJECT_TRAITS(Dict);
|
||||
BOOST_PYTHON_BUILTIN_OBJECT_TRAITS(Tuple);
|
||||
|
||||
}}} // namespace boost::python::converter
|
||||
|
||||
#endif // PYOBJECT_TRAITS_DWA2002720_HPP
|
||||
36
include/boost/python/converter/pyobject_type.hpp
Normal file
36
include/boost/python/converter/pyobject_type.hpp
Normal file
@@ -0,0 +1,36 @@
|
||||
// Copyright David Abrahams 2002. Permission to copy, use,
|
||||
// modify, sell and distribute this software is granted provided this
|
||||
// copyright notice appears in all copies. This software is provided
|
||||
// "as is" without express or implied warranty, and with no claim as
|
||||
// to its suitability for any purpose.
|
||||
#ifndef PYOBJECT_TYPE_DWA2002720_HPP
|
||||
# define PYOBJECT_TYPE_DWA2002720_HPP
|
||||
|
||||
# include <boost/python/detail/wrap_python.hpp>
|
||||
# include <boost/python/cast.hpp>
|
||||
|
||||
namespace boost { namespace python { namespace converter {
|
||||
|
||||
BOOST_PYTHON_DECL PyObject* checked_downcast_impl(PyObject*, PyTypeObject*);
|
||||
|
||||
// Used as a base class for specializations which need to provide
|
||||
// Python type checking capability.
|
||||
template <class Object, PyTypeObject* pytype>
|
||||
struct pyobject_type
|
||||
{
|
||||
static bool check(PyObject* x)
|
||||
{
|
||||
return ::PyObject_IsInstance(x, (PyObject*)pytype);
|
||||
}
|
||||
|
||||
static Object* checked_downcast(PyObject* x)
|
||||
{
|
||||
return python::downcast<Object>(
|
||||
(checked_downcast_impl)(x, pytype)
|
||||
);
|
||||
}
|
||||
};
|
||||
|
||||
}}} // namespace boost::python::converter
|
||||
|
||||
#endif // PYOBJECT_TYPE_DWA2002720_HPP
|
||||
99
include/boost/python/converter/pytype_arg_from_python.hpp
Normal file
99
include/boost/python/converter/pytype_arg_from_python.hpp
Normal file
@@ -0,0 +1,99 @@
|
||||
// Copyright David Abrahams 2002. Permission to copy, use,
|
||||
// modify, sell and distribute this software is granted provided this
|
||||
// copyright notice appears in all copies. This software is provided
|
||||
// "as is" without express or implied warranty, and with no claim as
|
||||
// to its suitability for any purpose.
|
||||
#ifndef PYTYPE_ARG_FROM_PYTHON_DWA2002628_HPP
|
||||
# define PYTYPE_ARG_FROM_PYTHON_DWA2002628_HPP
|
||||
|
||||
# include <boost/python/detail/wrap_python.hpp>
|
||||
|
||||
//
|
||||
// arg_from_python converters for Python type wrappers, to be used as
|
||||
// base classes for specializations.
|
||||
//
|
||||
namespace boost { namespace python { namespace converter {
|
||||
|
||||
template <PyTypeObject* python_type>
|
||||
struct pytype_arg_from_python
|
||||
{
|
||||
pytype_arg_from_python(PyObject*);
|
||||
bool convertible() const;
|
||||
private:
|
||||
PyObject* m_src;
|
||||
};
|
||||
|
||||
// rvalue converter base
|
||||
template <class Wrapper, PyTypeObject* python_type>
|
||||
struct pytype_wrapper_value_arg_from_python
|
||||
: pytype_arg_from_python<python_type>
|
||||
{
|
||||
typedef Wrapper result_type;
|
||||
|
||||
pytype_wrapper_value_arg_from_python(PyObject*);
|
||||
Wrapper operator()(PyObject*) const;
|
||||
};
|
||||
|
||||
// Special case for Wrapper& - must store an lvalue internally. This
|
||||
// OK because the entire state of the object is actually in the Python
|
||||
// object.
|
||||
template <class Wrapper, PyTypeObject* python_type>
|
||||
struct pytype_wrapper_ref_arg_from_python
|
||||
: pytype_arg_from_python<python_type>
|
||||
{
|
||||
typedef Wrapper& result_type;
|
||||
|
||||
pytype_wrapper_ref_arg_from_python(PyObject*);
|
||||
Wrapper& operator()(PyObject*) const;
|
||||
private:
|
||||
mutable Wrapper m_result;
|
||||
};
|
||||
|
||||
//
|
||||
// implementations
|
||||
//
|
||||
|
||||
template <PyTypeObject* python_type>
|
||||
inline pytype_arg_from_python<python_type>::pytype_arg_from_python(PyObject* x)
|
||||
: m_src(x)
|
||||
{
|
||||
}
|
||||
|
||||
template <PyTypeObject* python_type>
|
||||
inline bool pytype_arg_from_python<python_type>::convertible() const
|
||||
{
|
||||
return PyObject_IsInstance(m_src, (PyObject*)python_type);
|
||||
}
|
||||
|
||||
template <class Wrapper, PyTypeObject* python_type>
|
||||
pytype_wrapper_value_arg_from_python<Wrapper,python_type>::pytype_wrapper_value_arg_from_python(
|
||||
PyObject* p)
|
||||
: pytype_arg_from_python<python_type>(p)
|
||||
{
|
||||
}
|
||||
|
||||
template <class Wrapper, PyTypeObject* python_type>
|
||||
Wrapper pytype_wrapper_value_arg_from_python<Wrapper,python_type>::operator()(
|
||||
PyObject* x) const
|
||||
{
|
||||
return Wrapper(python::detail::borrowed_reference(x));
|
||||
}
|
||||
|
||||
template <class Wrapper, PyTypeObject* python_type>
|
||||
pytype_wrapper_ref_arg_from_python<Wrapper,python_type>::pytype_wrapper_ref_arg_from_python(
|
||||
PyObject* p)
|
||||
: pytype_arg_from_python<python_type>(p)
|
||||
, m_result(python::detail::borrowed_reference(p))
|
||||
{
|
||||
}
|
||||
|
||||
template <class Wrapper, PyTypeObject* python_type>
|
||||
Wrapper& pytype_wrapper_ref_arg_from_python<Wrapper,python_type>::operator()(
|
||||
PyObject* x) const
|
||||
{
|
||||
return m_result;
|
||||
}
|
||||
|
||||
}}} // namespace boost::python::converter
|
||||
|
||||
#endif // PYTYPE_ARG_FROM_PYTHON_DWA2002628_HPP
|
||||
43
include/boost/python/converter/pytype_object_mgr_traits.hpp
Normal file
43
include/boost/python/converter/pytype_object_mgr_traits.hpp
Normal file
@@ -0,0 +1,43 @@
|
||||
// Copyright David Abrahams 2002. Permission to copy, use,
|
||||
// modify, sell and distribute this software is granted provided this
|
||||
// copyright notice appears in all copies. This software is provided
|
||||
// "as is" without express or implied warranty, and with no claim as
|
||||
// to its suitability for any purpose.
|
||||
#ifndef PYTYPE_OBJECT_MANAGER_TRAITS_DWA2002716_HPP
|
||||
# define PYTYPE_OBJECT_MANAGER_TRAITS_DWA2002716_HPP
|
||||
|
||||
# include <boost/python/detail/raw_pyobject.hpp>
|
||||
# include <boost/python/cast.hpp>
|
||||
# include <boost/python/detail/wrap_python.hpp>
|
||||
# include <boost/python/converter/pyobject_type.hpp>
|
||||
# include <boost/python/errors.hpp>
|
||||
|
||||
namespace boost { namespace python { namespace converter {
|
||||
|
||||
// Provide a forward declaration as a convenience for clients, who all
|
||||
// need it.
|
||||
template <class T> struct object_manager_traits;
|
||||
|
||||
// Derive specializations of object_manager_traits from this class
|
||||
// when T is an object manager for a particular Python type hierarchy.
|
||||
//
|
||||
template <PyTypeObject* pytype, class T>
|
||||
struct pytype_object_manager_traits
|
||||
: pyobject_type<T, pytype> // provides check()
|
||||
{
|
||||
BOOST_STATIC_CONSTANT(bool, is_specialized = true);
|
||||
static inline python::detail::new_reference adopt(PyObject*);
|
||||
};
|
||||
|
||||
//
|
||||
// implementations
|
||||
//
|
||||
template <PyTypeObject* pytype, class T>
|
||||
inline python::detail::new_reference pytype_object_manager_traits<pytype,T>::adopt(PyObject* x)
|
||||
{
|
||||
return python::detail::new_reference(python::pytype_check(pytype, x));
|
||||
}
|
||||
|
||||
}}} // namespace boost::python::converter
|
||||
|
||||
#endif // PYTYPE_OBJECT_MANAGER_TRAITS_DWA2002716_HPP
|
||||
54
include/boost/python/converter/registered.hpp
Normal file
54
include/boost/python/converter/registered.hpp
Normal file
@@ -0,0 +1,54 @@
|
||||
// Copyright David Abrahams 2002. Permission to copy, use,
|
||||
// modify, sell and distribute this software is granted provided this
|
||||
// copyright notice appears in all copies. This software is provided
|
||||
// "as is" without express or implied warranty, and with no claim as
|
||||
// to its suitability for any purpose.
|
||||
#ifndef REGISTERED_DWA2002710_HPP
|
||||
# define REGISTERED_DWA2002710_HPP
|
||||
# include <boost/python/type_id.hpp>
|
||||
# include <boost/python/converter/registry.hpp>
|
||||
# include <boost/python/converter/registrations.hpp>
|
||||
# include <boost/type_traits/transform_traits.hpp>
|
||||
# include <boost/type_traits/cv_traits.hpp>
|
||||
|
||||
namespace boost { namespace python { namespace converter {
|
||||
|
||||
struct registration;
|
||||
|
||||
namespace detail
|
||||
{
|
||||
template <class T>
|
||||
struct registered_base
|
||||
{
|
||||
static registration const& converters;
|
||||
};
|
||||
}
|
||||
|
||||
template <class T>
|
||||
struct registered
|
||||
: detail::registered_base<
|
||||
typename add_reference<
|
||||
typename add_cv<T>::type
|
||||
>::type
|
||||
>
|
||||
{
|
||||
};
|
||||
|
||||
# ifndef BOOST_NO_TEMPLATE_PARTIAL_SPECIALIZATION
|
||||
// collapses a few more types to the same static instance
|
||||
template <class T>
|
||||
struct registered<T&> : registered<T> {};
|
||||
# endif
|
||||
|
||||
//
|
||||
// implementations
|
||||
//
|
||||
namespace detail
|
||||
{
|
||||
template <class T>
|
||||
registration const& registered_base<T>::converters
|
||||
= registry::lookup(type_id<T>());
|
||||
}
|
||||
}}} // namespace boost::python::converter
|
||||
|
||||
#endif // REGISTERED_DWA2002710_HPP
|
||||
63
include/boost/python/converter/registered_pointee.hpp
Normal file
63
include/boost/python/converter/registered_pointee.hpp
Normal file
@@ -0,0 +1,63 @@
|
||||
// Copyright David Abrahams 2002. Permission to copy, use,
|
||||
// modify, sell and distribute this software is granted provided this
|
||||
// copyright notice appears in all copies. This software is provided
|
||||
// "as is" without express or implied warranty, and with no claim as
|
||||
// to its suitability for any purpose.
|
||||
#ifndef REGISTERED_POINTEE_DWA2002710_HPP
|
||||
# define REGISTERED_POINTEE_DWA2002710_HPP
|
||||
# include <boost/python/converter/registered.hpp>
|
||||
# include <boost/python/converter/pointer_type_id.hpp>
|
||||
# include <boost/python/converter/registry.hpp>
|
||||
# include <boost/type_traits/transform_traits.hpp>
|
||||
# include <boost/type_traits/cv_traits.hpp>
|
||||
|
||||
namespace boost { namespace python { namespace converter {
|
||||
|
||||
struct registration;
|
||||
|
||||
# ifndef BOOST_NO_TEMPLATE_PARTIAL_SPECIALIZATION
|
||||
template <class T>
|
||||
struct registered_pointee
|
||||
: registered<
|
||||
typename remove_pointer<
|
||||
typename remove_cv<
|
||||
typename remove_reference<T>::type
|
||||
>::type
|
||||
>::type
|
||||
>
|
||||
{
|
||||
};
|
||||
# else
|
||||
namespace detail
|
||||
{
|
||||
template <class T>
|
||||
struct registered_pointee_base
|
||||
{
|
||||
static registration const& converters;
|
||||
};
|
||||
}
|
||||
|
||||
template <class T>
|
||||
struct registered_pointee
|
||||
: detail::registered_pointee_base<
|
||||
typename add_reference<
|
||||
typename add_cv<T>::type
|
||||
>::type
|
||||
>
|
||||
{
|
||||
};
|
||||
|
||||
//
|
||||
// implementations
|
||||
//
|
||||
namespace detail
|
||||
{
|
||||
template <class T>
|
||||
registration const& registered_pointee_base<T>::converters
|
||||
= registry::lookup(pointer_type_id<T>());
|
||||
}
|
||||
|
||||
# endif
|
||||
}}} // namespace boost::python::converter
|
||||
|
||||
#endif // REGISTERED_POINTEE_DWA2002710_HPP
|
||||
67
include/boost/python/converter/registrations.hpp
Normal file
67
include/boost/python/converter/registrations.hpp
Normal file
@@ -0,0 +1,67 @@
|
||||
// Copyright David Abrahams 2002. Permission to copy, use,
|
||||
// modify, sell and distribute this software is granted provided this
|
||||
// copyright notice appears in all copies. This software is provided
|
||||
// "as is" without express or implied warranty, and with no claim as
|
||||
// to its suitability for any purpose.
|
||||
#ifndef REGISTRATIONS_DWA2002223_HPP
|
||||
# define REGISTRATIONS_DWA2002223_HPP
|
||||
|
||||
# include <boost/python/detail/wrap_python.hpp>
|
||||
# include <boost/python/converter/convertible_function.hpp>
|
||||
# include <boost/python/converter/constructor_function.hpp>
|
||||
# include <boost/python/converter/to_python_function_type.hpp>
|
||||
# include <boost/python/type_id.hpp>
|
||||
|
||||
namespace boost { namespace python { namespace converter {
|
||||
|
||||
struct lvalue_from_python_chain
|
||||
{
|
||||
convertible_function convert;
|
||||
lvalue_from_python_chain* next;
|
||||
};
|
||||
|
||||
struct rvalue_from_python_chain
|
||||
{
|
||||
convertible_function convertible;
|
||||
constructor_function construct;
|
||||
rvalue_from_python_chain* next;
|
||||
};
|
||||
|
||||
struct registration
|
||||
{
|
||||
explicit registration(type_info);
|
||||
|
||||
const python::type_info target_type;
|
||||
|
||||
// The chain of eligible from_python converters when an lvalue is required
|
||||
lvalue_from_python_chain* lvalue_chain;
|
||||
|
||||
// The chain of eligible from_python converters when an rvalue is acceptable
|
||||
rvalue_from_python_chain* rvalue_chain;
|
||||
|
||||
// The unique to_python converter for the associated C++ type.
|
||||
to_python_function_t to_python;
|
||||
|
||||
// The class object associated with this type
|
||||
PyTypeObject* class_object;
|
||||
};
|
||||
|
||||
//
|
||||
// implementations
|
||||
//
|
||||
inline registration::registration(type_info target_type)
|
||||
: target_type(target_type)
|
||||
, lvalue_chain(0)
|
||||
, rvalue_chain(0)
|
||||
, to_python(0)
|
||||
, class_object(0)
|
||||
{}
|
||||
|
||||
inline bool operator<(registration const& lhs, registration const& rhs)
|
||||
{
|
||||
return lhs.target_type < rhs.target_type;
|
||||
}
|
||||
|
||||
}}} // namespace boost::python::converter
|
||||
|
||||
#endif // REGISTRATIONS_DWA2002223_HPP
|
||||
52
include/boost/python/converter/registry.hpp
Normal file
52
include/boost/python/converter/registry.hpp
Normal file
@@ -0,0 +1,52 @@
|
||||
// Copyright David Abrahams 2001. Permission to copy, use,
|
||||
// modify, sell and distribute this software is granted provided this
|
||||
// copyright notice appears in all copies. This software is provided
|
||||
// "as is" without express or implied warranty, and with no claim as
|
||||
// to its suitability for any purpose.
|
||||
#ifndef REGISTRY_DWA20011127_HPP
|
||||
# define REGISTRY_DWA20011127_HPP
|
||||
# include <boost/python/type_id.hpp>
|
||||
# include <boost/python/detail/config.hpp>
|
||||
# include <boost/python/detail/wrap_python.hpp>
|
||||
# include <boost/python/converter/to_python_function_type.hpp>
|
||||
# include <boost/python/converter/rvalue_from_python_data.hpp>
|
||||
# include <boost/python/converter/constructor_function.hpp>
|
||||
# include <boost/python/converter/convertible_function.hpp>
|
||||
|
||||
namespace boost { namespace python { namespace converter {
|
||||
|
||||
struct registration;
|
||||
|
||||
// This namespace acts as a sort of singleton
|
||||
namespace registry
|
||||
{
|
||||
// Get the registration corresponding to the type, creating it if neccessary
|
||||
BOOST_PYTHON_DECL registration const& lookup(type_info);
|
||||
|
||||
// Return a pointer to the corresponding registration, if one exists
|
||||
BOOST_PYTHON_DECL registration const* query(type_info);
|
||||
|
||||
BOOST_PYTHON_DECL void insert(to_python_function_t, type_info);
|
||||
|
||||
// Insert an lvalue from_python converter
|
||||
BOOST_PYTHON_DECL void insert(void* (*convert)(PyObject*), type_info);
|
||||
|
||||
// Insert an rvalue from_python converter
|
||||
BOOST_PYTHON_DECL void insert(
|
||||
convertible_function
|
||||
, constructor_function
|
||||
, type_info
|
||||
);
|
||||
|
||||
// Insert an rvalue from_python converter at the tail of the
|
||||
// chain. Used for implicit conversions
|
||||
BOOST_PYTHON_DECL void push_back(
|
||||
convertible_function
|
||||
, constructor_function
|
||||
, type_info
|
||||
);
|
||||
}
|
||||
|
||||
}}} // namespace boost::python::converter
|
||||
|
||||
#endif // REGISTRY_DWA20011127_HPP
|
||||
151
include/boost/python/converter/return_from_python.hpp
Executable file
151
include/boost/python/converter/return_from_python.hpp
Executable file
@@ -0,0 +1,151 @@
|
||||
// Copyright David Abrahams 2002. Permission to copy, use,
|
||||
// modify, sell and distribute this software is granted provided this
|
||||
// copyright notice appears in all copies. This software is provided
|
||||
// "as is" without express or implied warranty, and with no claim as
|
||||
// to its suitability for any purpose.
|
||||
#ifndef RETURN_FROM_PYTHON_DWA200265_HPP
|
||||
# define RETURN_FROM_PYTHON_DWA200265_HPP
|
||||
|
||||
# include <boost/python/converter/from_python.hpp>
|
||||
# include <boost/python/converter/rvalue_from_python_data.hpp>
|
||||
# include <boost/python/converter/registered.hpp>
|
||||
# include <boost/python/converter/registered_pointee.hpp>
|
||||
# include <boost/python/detail/void_ptr.hpp>
|
||||
# include <boost/call_traits.hpp>
|
||||
# include <boost/python/detail/void_return.hpp>
|
||||
|
||||
namespace boost { namespace python { namespace converter {
|
||||
|
||||
template <class T> struct is_object_manager;
|
||||
|
||||
namespace detail
|
||||
{
|
||||
template <class T>
|
||||
struct return_pointer_from_python
|
||||
{
|
||||
typedef T result_type;
|
||||
T operator()(PyObject*) const;
|
||||
};
|
||||
|
||||
template <class T>
|
||||
struct return_reference_from_python
|
||||
{
|
||||
typedef T result_type;
|
||||
T operator()(PyObject*) const;
|
||||
};
|
||||
|
||||
template <class T>
|
||||
struct return_rvalue_from_python
|
||||
{
|
||||
typedef typename call_traits<T>::param_type result_type;
|
||||
return_rvalue_from_python();
|
||||
result_type operator()(PyObject*);
|
||||
private:
|
||||
rvalue_from_python_data<T> m_data;
|
||||
};
|
||||
|
||||
template <class T>
|
||||
struct return_object_manager_from_python
|
||||
{
|
||||
typedef T result_type;
|
||||
result_type operator()(PyObject*) const;
|
||||
};
|
||||
|
||||
template <class T>
|
||||
struct select_return_from_python
|
||||
{
|
||||
BOOST_STATIC_CONSTANT(
|
||||
bool, obj_mgr = is_object_manager<T>::value);
|
||||
|
||||
BOOST_STATIC_CONSTANT(
|
||||
bool, ptr = is_pointer<T>::value);
|
||||
|
||||
BOOST_STATIC_CONSTANT(
|
||||
bool, ref = is_reference<T>::value);
|
||||
|
||||
typedef typename mpl::if_c<
|
||||
obj_mgr
|
||||
, return_object_manager_from_python<T>
|
||||
, typename mpl::if_c<
|
||||
ptr
|
||||
, return_pointer_from_python<T>
|
||||
, typename mpl::if_c<
|
||||
ref
|
||||
, return_reference_from_python<T>
|
||||
, return_rvalue_from_python<T>
|
||||
>::type
|
||||
>::type
|
||||
>::type type;
|
||||
};
|
||||
}
|
||||
|
||||
template <class T>
|
||||
struct return_from_python
|
||||
: detail::select_return_from_python<T>::type
|
||||
{
|
||||
};
|
||||
|
||||
// Specialization as a convenience for call and call_method
|
||||
template <>
|
||||
struct return_from_python<void>
|
||||
{
|
||||
typedef python::detail::returnable<void>::type result_type;
|
||||
|
||||
result_type operator()(PyObject* x) const
|
||||
{
|
||||
(void_result_from_python)(x);
|
||||
# ifdef BOOST_NO_VOID_RETURNS
|
||||
return result_type();
|
||||
# endif
|
||||
}
|
||||
};
|
||||
|
||||
//
|
||||
// Implementations
|
||||
//
|
||||
namespace detail
|
||||
{
|
||||
template <class T>
|
||||
inline return_rvalue_from_python<T>::return_rvalue_from_python()
|
||||
: m_data(
|
||||
const_cast<registration*>(®istered<T>::converters)
|
||||
)
|
||||
{
|
||||
}
|
||||
|
||||
template <class T>
|
||||
inline typename return_rvalue_from_python<T>::result_type
|
||||
return_rvalue_from_python<T>::operator()(PyObject* obj)
|
||||
{
|
||||
return *(T*)
|
||||
(rvalue_result_from_python)(obj, m_data.stage1);
|
||||
}
|
||||
|
||||
template <class T>
|
||||
inline T return_reference_from_python<T>::operator()(PyObject* obj) const
|
||||
{
|
||||
return python::detail::void_ptr_to_reference(
|
||||
(reference_result_from_python)(obj, registered<T>::converters)
|
||||
, (T(*)())0);
|
||||
}
|
||||
|
||||
template <class T>
|
||||
inline T return_pointer_from_python<T>::operator()(PyObject* obj) const
|
||||
{
|
||||
return T(
|
||||
(pointer_result_from_python)(obj, registered_pointee<T>::converters)
|
||||
);
|
||||
}
|
||||
|
||||
template <class T>
|
||||
inline T return_object_manager_from_python<T>::operator()(PyObject* obj) const
|
||||
{
|
||||
return T(
|
||||
object_manager_traits<T>::adopt(obj)
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
}}} // namespace boost::python::converter
|
||||
|
||||
#endif // RETURN_FROM_PYTHON_DWA200265_HPP
|
||||
39
include/boost/python/converter/rvalue_from_python_chain.hpp
Normal file
39
include/boost/python/converter/rvalue_from_python_chain.hpp
Normal file
@@ -0,0 +1,39 @@
|
||||
// Copyright David Abrahams 2002. Permission to copy, use,
|
||||
// modify, sell and distribute this software is granted provided this
|
||||
// copyright notice appears in all copies. This software is provided
|
||||
// "as is" without express or implied warranty, and with no claim as
|
||||
// to its suitability for any purpose.
|
||||
#ifndef RVALUE_FROM_PYTHON_CHAIN_DWA200237_HPP
|
||||
# define RVALUE_FROM_PYTHON_CHAIN_DWA200237_HPP
|
||||
# include <boost/python/converter/registry.hpp>
|
||||
# include <boost/type_traits/transform_traits.hpp>
|
||||
# include <boost/type_traits/cv_traits.hpp>
|
||||
|
||||
namespace boost { namespace python { namespace converter {
|
||||
|
||||
namespace detail
|
||||
{
|
||||
template <class T>
|
||||
struct rvalue_from_python_chain_impl
|
||||
{
|
||||
static rvalue_from_python_registration*const& value;
|
||||
};
|
||||
|
||||
template <class T>
|
||||
rvalue_from_python_registration*const& rvalue_from_python_chain_impl<T>::value
|
||||
= registry::rvalue_converters(undecorated_type_id<T>());
|
||||
}
|
||||
|
||||
template <class T>
|
||||
struct rvalue_from_python_chain
|
||||
: detail::rvalue_from_python_chain_impl<
|
||||
typename add_reference<
|
||||
typename add_cv<T>::type
|
||||
>::type
|
||||
>
|
||||
{
|
||||
};
|
||||
|
||||
}}} // namespace boost::python::converter
|
||||
|
||||
#endif // RVALUE_FROM_PYTHON_CHAIN_DWA200237_HPP
|
||||
140
include/boost/python/converter/rvalue_from_python_data.hpp
Normal file
140
include/boost/python/converter/rvalue_from_python_data.hpp
Normal file
@@ -0,0 +1,140 @@
|
||||
// Copyright David Abrahams 2002. Permission to copy, use,
|
||||
// modify, sell and distribute this software is granted provided this
|
||||
// copyright notice appears in all copies. This software is provided
|
||||
// "as is" without express or implied warranty, and with no claim as
|
||||
// to its suitability for any purpose.
|
||||
#ifndef FROM_PYTHON_AUX_DATA_DWA2002128_HPP
|
||||
# define FROM_PYTHON_AUX_DATA_DWA2002128_HPP
|
||||
|
||||
# include <boost/python/converter/constructor_function.hpp>
|
||||
# include <boost/python/detail/referent_storage.hpp>
|
||||
# include <boost/python/detail/destroy.hpp>
|
||||
# include <boost/static_assert.hpp>
|
||||
# include <boost/type_traits/add_reference.hpp>
|
||||
# include <boost/type_traits/add_cv.hpp>
|
||||
# include <cstddef>
|
||||
|
||||
// Data management for potential rvalue conversions from Python to C++
|
||||
// types. When a client requests a conversion to T* or T&, we
|
||||
// generally require that an object of type T exists in the source
|
||||
// Python object, and the code here does not apply**. This implements
|
||||
// conversions which may create new temporaries of type T. The classic
|
||||
// example is a conversion which converts a Python tuple to a
|
||||
// std::vector. Since no std::vector lvalue exists in the Python
|
||||
// object -- it must be created "on-the-fly" by the converter, and
|
||||
// which must manage the lifetime of the created object.
|
||||
//
|
||||
// Note that the client is not precluded from using a registered
|
||||
// lvalue conversion to T in this case. In other words, we will
|
||||
// happily accept a Python object which /does/ contain a std::vector
|
||||
// lvalue, provided an appropriate converter is registered. So, while
|
||||
// this is an rvalue conversion from the client's point-of-view, the
|
||||
// converter registry may serve up lvalue or rvalue conversions for
|
||||
// the target type.
|
||||
//
|
||||
// ** C++ argument from_python conversions to T const& are an
|
||||
// exception to the rule for references: since in C++, const
|
||||
// references can bind to temporary rvalues, we allow rvalue
|
||||
// converters to be chosen when the target type is T const& for some
|
||||
// T.
|
||||
namespace boost { namespace python { namespace converter {
|
||||
|
||||
// Conversions begin by filling in and returning a copy of this
|
||||
// structure. The process looks up a converter in the rvalue converter
|
||||
// registry for the target type. It calls the convertible() function
|
||||
// of each registered converter, passing the source PyObject* as an
|
||||
// argument, until a non-null result is returned. This result goes in
|
||||
// the convertible field, and the converter's construct() function is
|
||||
// stored in the construct field.
|
||||
//
|
||||
// If no appropriate converter is found, conversion fails and the
|
||||
// convertible field is null. When used in argument conversion for
|
||||
// wrapped C++ functions, it causes overload resolution to reject the
|
||||
// current function but not to fail completely. If an exception is
|
||||
// thrown, overload resolution stops and the exception propagates back
|
||||
// through the caller.
|
||||
//
|
||||
// If an lvalue converter is matched, its convertible() function is
|
||||
// expected to return a pointer to the stored T object; its
|
||||
// construct() function will be NULL. The convertible() function of
|
||||
// rvalue converters may return any non-singular pointer; the actual
|
||||
// target object will only be available once the converter's
|
||||
// construct() function is called.
|
||||
struct rvalue_from_python_stage1_data
|
||||
{
|
||||
void* convertible;
|
||||
constructor_function construct;
|
||||
};
|
||||
|
||||
// Augments rvalue_from_python_stage1_data by adding storage for
|
||||
// constructing an object of remove_reference<T>::type. The
|
||||
// construct() function of rvalue converters (stored in m_construct
|
||||
// above) will cast the rvalue_from_python_stage1_data to an
|
||||
// appropriate instantiation of this template in order to access that
|
||||
// storage.
|
||||
template <class T>
|
||||
struct rvalue_from_python_storage
|
||||
{
|
||||
rvalue_from_python_stage1_data stage1;
|
||||
|
||||
// Storage for the result, in case an rvalue must be constructed
|
||||
typename python::detail::referent_storage<
|
||||
typename add_reference<T>::type
|
||||
>::type storage;
|
||||
};
|
||||
|
||||
// Augments rvalue_from_python_storage<T> with a destructor. If
|
||||
// stage1.convertible == storage.bytes, it indicates that an object of
|
||||
// remove_reference<T>::type has been constructed in storage and
|
||||
// should will be destroyed in ~rvalue_from_python_data(). It is
|
||||
// crucial that successful rvalue conversions establish this equality
|
||||
// and that unsuccessful ones do not.
|
||||
template <class T>
|
||||
struct rvalue_from_python_data : rvalue_from_python_storage<T>
|
||||
{
|
||||
# if (!defined(__MWERKS__) || __MWERKS__ >= 0x3000) \
|
||||
&& (!defined(__EDG_VERSION__) || __EDG_VERSION__ >= 245) \
|
||||
&& (!defined(__DECCXX_VER) || __DECCXX_VER > 60590014)
|
||||
// This must always be a POD struct with m_data its first member.
|
||||
BOOST_STATIC_ASSERT(offsetof(rvalue_from_python_storage<T>,stage1) == 0);
|
||||
# endif
|
||||
|
||||
// The usual constructor
|
||||
rvalue_from_python_data(rvalue_from_python_stage1_data const&);
|
||||
|
||||
// This constructor just sets m_convertible -- used by
|
||||
// implicitly_convertible<> to perform the final step of the
|
||||
// conversion, where the construct() function is already known.
|
||||
rvalue_from_python_data(void* convertible);
|
||||
|
||||
// Destroys any object constructed in the storage.
|
||||
~rvalue_from_python_data();
|
||||
private:
|
||||
typedef typename add_reference<typename add_cv<T>::type>::type ref_type;
|
||||
};
|
||||
|
||||
//
|
||||
// Implementataions
|
||||
//
|
||||
template <class T>
|
||||
inline rvalue_from_python_data<T>::rvalue_from_python_data(rvalue_from_python_stage1_data const& stage1)
|
||||
{
|
||||
this->stage1 = stage1;
|
||||
}
|
||||
|
||||
template <class T>
|
||||
inline rvalue_from_python_data<T>::rvalue_from_python_data(void* convertible)
|
||||
{
|
||||
this->stage1.convertible = convertible;
|
||||
}
|
||||
|
||||
template <class T>
|
||||
inline rvalue_from_python_data<T>::~rvalue_from_python_data()
|
||||
{
|
||||
if (this->stage1.convertible == this->storage.bytes)
|
||||
python::detail::destroy_referent<ref_type>(this->storage.bytes);
|
||||
}
|
||||
|
||||
}}} // namespace boost::python::converter
|
||||
|
||||
#endif // FROM_PYTHON_AUX_DATA_DWA2002128_HPP
|
||||
70
include/boost/python/converter/smart_ptr.hpp
Normal file
70
include/boost/python/converter/smart_ptr.hpp
Normal file
@@ -0,0 +1,70 @@
|
||||
// Copyright David Abrahams 2002. Permission to copy, use,
|
||||
// modify, sell and distribute this software is granted provided this
|
||||
// copyright notice appears in all copies. This software is provided
|
||||
// "as is" without express or implied warranty, and with no claim as
|
||||
// to its suitability for any purpose.
|
||||
#ifndef SMART_PTR_DWA2002123_HPP
|
||||
# define SMART_PTR_DWA2002123_HPP
|
||||
|
||||
# include <boost/python/converter/class.hpp>
|
||||
# include <boost/python/object/pointer_holder.hpp>
|
||||
namespace boost { namespace python { namespace converter {
|
||||
|
||||
template <class Pointer, class Value>
|
||||
class smart_ptr_wrapper
|
||||
: wrapper<Pointer const&>
|
||||
{
|
||||
smart_ptr_wrapper(ref const& type_)
|
||||
: m_class_object(type_)
|
||||
{
|
||||
assert(type_->ob_type == (PyTypeObject*)class_metatype().get());
|
||||
}
|
||||
|
||||
PyObject* convert(Pointer x) const;
|
||||
|
||||
private:
|
||||
ref m_class_object;
|
||||
|
||||
smart_ptr_converters();
|
||||
}
|
||||
|
||||
|
||||
//
|
||||
// implementations
|
||||
//
|
||||
|
||||
template <class Pointer, class Value>
|
||||
PyObject* smart_ptr_wrapper<Pointer,Value>::convert(Pointer x) const
|
||||
{
|
||||
if (x.operator->() == 0)
|
||||
return detail::none();
|
||||
|
||||
// Don't call the type to do the construction, since that
|
||||
// would require the registration of an __init__ copy
|
||||
// constructor. Instead, just construct the object in place.
|
||||
PyObject* raw_result = (PyObject*)PyObject_New(
|
||||
instance, (PyTypeObject*)m_class_object.get());
|
||||
|
||||
if (raw_result == 0)
|
||||
return 0;
|
||||
|
||||
// Everything's OK; Bypass NULL checks but guard against
|
||||
// exceptions.
|
||||
ref result(raw_result, ref::allow_null());
|
||||
|
||||
// Build a value_holder to contain the object using the copy
|
||||
// constructor
|
||||
objects::pointer_holder<Pointer,Value>*
|
||||
p = new objects::pointer_holder<Pointer,Value>(x);
|
||||
|
||||
// Install it in the instance
|
||||
p->install(raw_result);
|
||||
|
||||
// Return the new result
|
||||
return result.release();
|
||||
}
|
||||
|
||||
|
||||
}}} // namespace boost::python::converter
|
||||
|
||||
#endif // SMART_PTR_DWA2002123_HPP
|
||||
50
include/boost/python/converter/to_python_function.hpp
Normal file
50
include/boost/python/converter/to_python_function.hpp
Normal file
@@ -0,0 +1,50 @@
|
||||
// Copyright David Abrahams 2002. Permission to copy, use,
|
||||
// modify, sell and distribute this software is granted provided this
|
||||
// copyright notice appears in all copies. This software is provided
|
||||
// "as is" without express or implied warranty, and with no claim as
|
||||
// to its suitability for any purpose.
|
||||
#ifndef TO_PYTHON_FUNCTION_DWA2002128_HPP
|
||||
# define TO_PYTHON_FUNCTION_DWA2002128_HPP
|
||||
|
||||
# include <boost/python/detail/wrap_python.hpp>
|
||||
# include <boost/type_traits/transform_traits.hpp>
|
||||
# include <boost/type_traits/cv_traits.hpp>
|
||||
# include <boost/python/converter/type_id.hpp>
|
||||
# include <boost/python/converter/registry.hpp>
|
||||
# include <boost/python/converter/to_python_function_type.hpp>
|
||||
|
||||
namespace boost { namespace python { namespace converter {
|
||||
|
||||
// to_python_function --
|
||||
//
|
||||
// essentially a "templated global reference" which holds the
|
||||
// converter for converting a type to Python by-value. We "normalize"
|
||||
// T by adding "const volatile&" so that fewer global variables and
|
||||
// associated static initializations are generated.
|
||||
namespace detail
|
||||
{
|
||||
template <class T>
|
||||
struct to_python_function_base
|
||||
{
|
||||
static to_python_function_t const& value;
|
||||
};
|
||||
|
||||
template <class T>
|
||||
to_python_function_t const&
|
||||
to_python_function_base<T>::value
|
||||
= converter::registry::get_to_python_function(undecorated_type_id<T>());
|
||||
}
|
||||
|
||||
template <class T>
|
||||
struct to_python_function
|
||||
: detail::to_python_function_base<
|
||||
typename add_reference<
|
||||
typename add_cv<T>::type
|
||||
>::type
|
||||
>
|
||||
{
|
||||
};
|
||||
|
||||
}}} // namespace boost::python::converter
|
||||
|
||||
#endif // TO_PYTHON_FUNCTION_DWA2002128_HPP
|
||||
30
include/boost/python/converter/to_python_function_type.hpp
Normal file
30
include/boost/python/converter/to_python_function_type.hpp
Normal file
@@ -0,0 +1,30 @@
|
||||
// Copyright David Abrahams 2002. Permission to copy, use,
|
||||
// modify, sell and distribute this software is granted provided this
|
||||
// copyright notice appears in all copies. This software is provided
|
||||
// "as is" without express or implied warranty, and with no claim as
|
||||
// to its suitability for any purpose.
|
||||
#ifndef TO_PYTHON_FUNCTION_TYPE_DWA200236_HPP
|
||||
# define TO_PYTHON_FUNCTION_TYPE_DWA200236_HPP
|
||||
# include <boost/python/detail/wrap_python.hpp>
|
||||
|
||||
namespace boost { namespace python { namespace converter {
|
||||
|
||||
// The type of stored function pointers which actually do conversion
|
||||
// by-value. The void* points to the object to be converted, and
|
||||
// type-safety is preserved through runtime registration.
|
||||
typedef PyObject* (*to_python_function_t)(void const*);
|
||||
|
||||
// Given a typesafe to_python conversion function, produces a
|
||||
// to_python_function_t which can be registered in the usual way.
|
||||
template <class T, class ToPython>
|
||||
struct as_to_python_function
|
||||
{
|
||||
static PyObject* convert(void const* x)
|
||||
{
|
||||
return ToPython::convert(*(T const*)x);
|
||||
}
|
||||
};
|
||||
|
||||
}}} // namespace boost::python::converter
|
||||
|
||||
#endif // TO_PYTHON_FUNCTION_TYPE_DWA200236_HPP
|
||||
176
include/boost/python/converter/type_id.hpp
Normal file
176
include/boost/python/converter/type_id.hpp
Normal file
@@ -0,0 +1,176 @@
|
||||
// Copyright David Abrahams 2001. Permission to copy, use,
|
||||
// modify, sell and distribute this software is granted provided this
|
||||
// copyright notice appears in all copies. This software is provided
|
||||
// "as is" without express or implied warranty, and with no claim as
|
||||
// to its suitability for any purpose.
|
||||
#ifndef TYPE_ID_DWA20011127_HPP
|
||||
# define TYPE_ID_DWA20011127_HPP
|
||||
# include <boost/python/detail/config.hpp>
|
||||
# include <boost/python/detail/indirect_traits.hpp>
|
||||
# include <boost/python/detail/msvc_typeinfo.hpp>
|
||||
# include <boost/type_traits/cv_traits.hpp>
|
||||
# include <boost/type_traits/composite_traits.hpp>
|
||||
# include <boost/mpl/select_if.hpp>
|
||||
# include <boost/operators.hpp>
|
||||
# include <boost/type.hpp>
|
||||
# include <typeinfo>
|
||||
# include <iosfwd>
|
||||
# include <cstring>
|
||||
|
||||
|
||||
namespace boost { namespace python { namespace converter {
|
||||
|
||||
// for this compiler at least, cross-shared-library type_info
|
||||
// comparisons don't work, so use typeid(x).name() instead. It's not
|
||||
// yet clear what the best default strategy is.
|
||||
# if defined(__GNUC__) && __GNUC__ >= 3
|
||||
# define BOOST_PYTHON_TYPE_ID_NAME
|
||||
# endif
|
||||
|
||||
// type ids which represent the same information as std::type_info
|
||||
// (i.e. the top-level reference and cv-qualifiers are stripped), but
|
||||
// which works across shared libraries.
|
||||
struct undecorated_type_id_t : totally_ordered<undecorated_type_id_t>
|
||||
{
|
||||
undecorated_type_id_t(std::type_info const&);
|
||||
|
||||
// default constructor needed to build arrays, etc.
|
||||
undecorated_type_id_t();
|
||||
|
||||
bool operator<(undecorated_type_id_t const& rhs) const;
|
||||
bool operator==(undecorated_type_id_t const& rhs) const;
|
||||
|
||||
char const* name() const;
|
||||
friend BOOST_PYTHON_DECL std::ostream& operator<<(
|
||||
std::ostream&, undecorated_type_id_t const&);
|
||||
|
||||
private: // data members
|
||||
# ifdef BOOST_PYTHON_TYPE_ID_NAME
|
||||
typedef char const* base_id_t;
|
||||
# else
|
||||
typedef std::type_info const* base_id_t;
|
||||
# endif
|
||||
|
||||
base_id_t m_base_type;
|
||||
};
|
||||
|
||||
struct type_id_t : totally_ordered<type_id_t>
|
||||
{
|
||||
enum decoration { const_ = 0x1, volatile_ = 0x2, reference = 0x4 };
|
||||
|
||||
type_id_t(undecorated_type_id_t, decoration = decoration());
|
||||
|
||||
bool operator<(type_id_t const& rhs) const;
|
||||
bool operator==(type_id_t const& rhs) const;
|
||||
|
||||
friend BOOST_PYTHON_DECL std::ostream& operator<<(std::ostream&, type_id_t const&);
|
||||
|
||||
operator undecorated_type_id_t const&() const;
|
||||
private: // type
|
||||
typedef undecorated_type_id_t base_id_t;
|
||||
|
||||
private: // data members
|
||||
decoration m_decoration;
|
||||
base_id_t m_base_type;
|
||||
};
|
||||
|
||||
template <class T>
|
||||
inline undecorated_type_id_t undecorated_type_id(boost::type<T>* = 0)
|
||||
{
|
||||
return undecorated_type_id_t(
|
||||
# if (!defined(BOOST_MSVC) || BOOST_MSVC > 1300) && (!defined(BOOST_INTEL_CXX_VERSION) || BOOST_INTEL_CXX_VERSION > 600)
|
||||
typeid(T)
|
||||
# else // strip the decoration which msvc and Intel mistakenly leave in
|
||||
python::detail::msvc_typeid<T>()
|
||||
# endif
|
||||
);
|
||||
}
|
||||
|
||||
template <class T>
|
||||
inline type_id_t type_id(boost::type<T>* = 0)
|
||||
{
|
||||
return type_id_t(
|
||||
undecorated_type_id<T>()
|
||||
, type_id_t::decoration(
|
||||
(is_const<T>::value || python::detail::is_reference_to_const<T>::value
|
||||
? type_id_t::const_ : 0)
|
||||
| (is_volatile<T>::value || python::detail::is_reference_to_volatile<T>::value
|
||||
? type_id_t::volatile_ : 0)
|
||||
| (is_reference<T>::value ? type_id_t::reference : 0)
|
||||
)
|
||||
);
|
||||
}
|
||||
|
||||
inline undecorated_type_id_t::undecorated_type_id_t(std::type_info const& id)
|
||||
: m_base_type(
|
||||
# ifdef BOOST_PYTHON_TYPE_ID_NAME
|
||||
id.name()
|
||||
# else
|
||||
&id
|
||||
# endif
|
||||
)
|
||||
{
|
||||
}
|
||||
|
||||
inline undecorated_type_id_t::undecorated_type_id_t()
|
||||
: m_base_type()
|
||||
{
|
||||
}
|
||||
|
||||
inline type_id_t::type_id_t(undecorated_type_id_t base_t, decoration decoration)
|
||||
: m_decoration(decoration)
|
||||
, m_base_type(base_t)
|
||||
{
|
||||
}
|
||||
|
||||
inline bool undecorated_type_id_t::operator<(undecorated_type_id_t const& rhs) const
|
||||
{
|
||||
# ifdef BOOST_PYTHON_TYPE_ID_NAME
|
||||
return std::strcmp(m_base_type, rhs.m_base_type) < 0;
|
||||
# else
|
||||
return m_base_type->before(*rhs.m_base_type);
|
||||
# endif
|
||||
}
|
||||
|
||||
inline bool type_id_t::operator<(type_id_t const& rhs) const
|
||||
{
|
||||
return m_decoration < rhs.m_decoration
|
||||
|| m_decoration == rhs.m_decoration
|
||||
&& m_base_type < rhs.m_base_type;
|
||||
}
|
||||
|
||||
inline bool undecorated_type_id_t::operator==(undecorated_type_id_t const& rhs) const
|
||||
{
|
||||
# ifdef BOOST_PYTHON_TYPE_ID_NAME
|
||||
return !std::strcmp(m_base_type, rhs.m_base_type);
|
||||
# else
|
||||
return *m_base_type == *rhs.m_base_type;
|
||||
# endif
|
||||
}
|
||||
|
||||
inline bool type_id_t::operator==(type_id_t const& rhs) const
|
||||
{
|
||||
return m_decoration == rhs.m_decoration && m_base_type == rhs.m_base_type;
|
||||
}
|
||||
|
||||
inline type_id_t::operator undecorated_type_id_t const&() const
|
||||
{
|
||||
return m_base_type;
|
||||
}
|
||||
|
||||
inline char const* undecorated_type_id_t::name() const
|
||||
{
|
||||
# ifdef BOOST_PYTHON_TYPE_ID_NAME
|
||||
return m_base_type;
|
||||
# else
|
||||
return m_base_type->name();
|
||||
# endif
|
||||
}
|
||||
|
||||
|
||||
BOOST_PYTHON_DECL std::ostream& operator<<(std::ostream&, undecorated_type_id_t const&);
|
||||
BOOST_PYTHON_DECL std::ostream& operator<<(std::ostream&, type_id_t const&);
|
||||
|
||||
}}} // namespace boost::python::converter
|
||||
|
||||
#endif // TYPE_ID_DWA20011127_HPP
|
||||
42
include/boost/python/copy_const_reference.hpp
Normal file
42
include/boost/python/copy_const_reference.hpp
Normal file
@@ -0,0 +1,42 @@
|
||||
// Copyright David Abrahams 2002. Permission to copy, use,
|
||||
// modify, sell and distribute this software is granted provided this
|
||||
// copyright notice appears in all copies. This software is provided
|
||||
// "as is" without express or implied warranty, and with no claim as
|
||||
// to its suitability for any purpose.
|
||||
#ifndef COPY_CONST_REFERENCE_DWA2002131_HPP
|
||||
# define COPY_CONST_REFERENCE_DWA2002131_HPP
|
||||
# include <boost/python/detail/indirect_traits.hpp>
|
||||
# include <boost/mpl/if.hpp>
|
||||
# include <boost/python/to_python_value.hpp>
|
||||
|
||||
namespace boost { namespace python {
|
||||
|
||||
namespace detail
|
||||
{
|
||||
template <class R>
|
||||
struct copy_const_reference_expects_a_const_reference_return_type
|
||||
# if defined(__GNUC__) && __GNUC__ >= 3 || defined(__EDG__)
|
||||
{}
|
||||
# endif
|
||||
;
|
||||
}
|
||||
|
||||
template <class T> struct to_python_value;
|
||||
|
||||
struct copy_const_reference
|
||||
{
|
||||
template <class T>
|
||||
struct apply
|
||||
{
|
||||
typedef typename mpl::if_c<
|
||||
detail::is_reference_to_const<T>::value
|
||||
, to_python_value<T>
|
||||
, detail::copy_const_reference_expects_a_const_reference_return_type<T>
|
||||
>::type type;
|
||||
};
|
||||
};
|
||||
|
||||
|
||||
}} // namespace boost::python
|
||||
|
||||
#endif // COPY_CONST_REFERENCE_DWA2002131_HPP
|
||||
41
include/boost/python/copy_mutable_reference.hpp
Normal file
41
include/boost/python/copy_mutable_reference.hpp
Normal file
@@ -0,0 +1,41 @@
|
||||
// Copyright David Abrahams 2002. Permission to copy, use,
|
||||
// modify, sell and distribute this software is granted provided this
|
||||
// copyright notice appears in all copies. This software is provided
|
||||
// "as is" without express or implied warranty, and with no claim as
|
||||
// to its suitability for any purpose.
|
||||
#ifndef COPY_MUTABLE_REFERENCE_DWA2002131_HPP
|
||||
# define COPY_MUTABLE_REFERENCE_DWA2002131_HPP
|
||||
# include <boost/python/detail/indirect_traits.hpp>
|
||||
# include <boost/mpl/select_if.hpp>
|
||||
# include <boost/python/to_python_value.hpp>
|
||||
|
||||
namespace boost { namespace python {
|
||||
|
||||
namespace detail
|
||||
{
|
||||
template <class R>
|
||||
struct copy_mutable_reference_expects_a_reference_to_non_const_return_type
|
||||
# if defined(__GNUC__) && __GNUC__ >= 3 || defined(__EDG__)
|
||||
{}
|
||||
# endif
|
||||
;
|
||||
}
|
||||
|
||||
template <class T> struct to_python_value;
|
||||
|
||||
struct copy_mutable_reference
|
||||
{
|
||||
template <class T>
|
||||
struct apply
|
||||
{
|
||||
typedef typename mpl::select_if_c<
|
||||
detail::is_reference_to_non_const<T>::value
|
||||
, to_python_value<T>
|
||||
, detail::copy_mutable_reference_expects_a_reference_to_non_const_return_type<T>
|
||||
>::type type;
|
||||
};
|
||||
};
|
||||
|
||||
}} // namespace boost::python
|
||||
|
||||
#endif // COPY_MUTABLE_REFERENCE_DWA2002131_HPP
|
||||
42
include/boost/python/copy_non_const_reference.hpp
Normal file
42
include/boost/python/copy_non_const_reference.hpp
Normal file
@@ -0,0 +1,42 @@
|
||||
// Copyright David Abrahams 2002. Permission to copy, use,
|
||||
// modify, sell and distribute this software is granted provided this
|
||||
// copyright notice appears in all copies. This software is provided
|
||||
// "as is" without express or implied warranty, and with no claim as
|
||||
// to its suitability for any purpose.
|
||||
#ifndef COPY_NON_CONST_REFERENCE_DWA2002131_HPP
|
||||
# define COPY_NON_CONST_REFERENCE_DWA2002131_HPP
|
||||
# include <boost/python/detail/indirect_traits.hpp>
|
||||
# include <boost/mpl/if.hpp>
|
||||
# include <boost/python/to_python_value.hpp>
|
||||
|
||||
namespace boost { namespace python {
|
||||
|
||||
namespace detail
|
||||
{
|
||||
template <class R>
|
||||
struct copy_non_const_reference_expects_a_non_const_reference_return_type
|
||||
# if defined(__GNUC__) && __GNUC__ >= 3 || defined(__EDG__)
|
||||
{}
|
||||
# endif
|
||||
;
|
||||
}
|
||||
|
||||
template <class T> struct to_python_value;
|
||||
|
||||
struct copy_non_const_reference
|
||||
{
|
||||
template <class T>
|
||||
struct apply
|
||||
{
|
||||
typedef typename mpl::if_c<
|
||||
boost::python::detail::is_reference_to_non_const<T>::value
|
||||
, to_python_value<T>
|
||||
, detail::copy_non_const_reference_expects_a_non_const_reference_return_type<T>
|
||||
>::type type;
|
||||
};
|
||||
};
|
||||
|
||||
|
||||
}} // namespace boost::python
|
||||
|
||||
#endif // COPY_NON_CONST_REFERENCE_DWA2002131_HPP
|
||||
@@ -1,29 +1,49 @@
|
||||
/* (C) Copyright Ralf W. Grosse-Kunstleve 2001. Permission to copy, use,
|
||||
modify, sell and distribute this software is granted provided this
|
||||
copyright notice appears in all copies. This software is provided
|
||||
"as is" without express or implied warranty, and with no claim as to
|
||||
its suitability for any purpose.
|
||||
|
||||
Revision History:
|
||||
17 Apr 01 merged into boost CVS trunk (Ralf W. Grosse-Kunstleve)
|
||||
*/
|
||||
|
||||
/* Implementation of Boost.Python cross-module support.
|
||||
See root/libs/python/doc/cross_module.html for details.
|
||||
*/
|
||||
|
||||
#ifndef CROSS_MODULE_HPP
|
||||
# define CROSS_MODULE_HPP
|
||||
|
||||
# include <boost/python/class_builder.hpp>
|
||||
|
||||
namespace boost { namespace python {
|
||||
struct import_error : error_already_set {};
|
||||
struct export_error : error_already_set {};
|
||||
}}
|
||||
|
||||
namespace boost { namespace python { namespace detail {
|
||||
struct BOOST_PYTHON_DECL import_error: error_already_set {};
|
||||
struct BOOST_PYTHON_DECL export_error : error_already_set {};
|
||||
|
||||
void BOOST_PYTHON_DECL throw_import_error();
|
||||
void BOOST_PYTHON_DECL throw_export_error();
|
||||
|
||||
namespace detail
|
||||
{
|
||||
|
||||
// Concept: throw exception if api_major is changed
|
||||
// show warning on stderr if api_minor is changed
|
||||
const int export_converters_api_major = 2;
|
||||
const int export_converters_api_minor = 1;
|
||||
extern const char* converters_attribute_name;
|
||||
void* import_converter_object(const std::string& module_name,
|
||||
const std::string& py_class_name,
|
||||
const std::string& attribute_name);
|
||||
void check_export_converters_api(const int importing_major,
|
||||
const int importing_minor,
|
||||
const int imported_major,
|
||||
const int imported_minor);
|
||||
const int export_converters_api_major = 4;
|
||||
const int export_converters_api_minor = 1;
|
||||
extern BOOST_PYTHON_DECL const char* converters_attribute_name;
|
||||
BOOST_PYTHON_DECL void* import_converter_object(const std::string& module_name,
|
||||
const std::string& py_class_name,
|
||||
const std::string& attribute_name);
|
||||
BOOST_PYTHON_DECL void check_export_converters_api(const int importing_major,
|
||||
const int importing_minor,
|
||||
const int imported_major,
|
||||
const int imported_minor);
|
||||
|
||||
}}}
|
||||
}
|
||||
|
||||
}} // namespace boost::python
|
||||
|
||||
// forward declaration
|
||||
namespace boost { namespace python { namespace detail {
|
||||
@@ -32,83 +52,75 @@ template <class T> class import_extension_class;
|
||||
|
||||
BOOST_PYTHON_BEGIN_CONVERSION_NAMESPACE
|
||||
|
||||
//QUESTIONMARK
|
||||
// This class is a look-alike of class python_extension_class_converters.
|
||||
// Is there a formal way to ensure that the siblings stay in sync?
|
||||
/* This class template is instantiated by import_converters<T>.
|
||||
This class is a look-alike of class python_extension_class_converters.
|
||||
The converters in this class are wrappers that call converters
|
||||
imported from another module.
|
||||
To ensure that the dynamic loader resolves all symbols in the
|
||||
intended way, the signature of all friend functions is changed with
|
||||
respect to the original functions in class
|
||||
python_extension_class_converters by adding an arbitrary additional
|
||||
parameter with a default value, in this case "bool sig = false".
|
||||
See also: comments for class export_converter_object_base below.
|
||||
*/
|
||||
template <class T>
|
||||
class python_import_extension_class_converters
|
||||
{
|
||||
public:
|
||||
|
||||
friend python_import_extension_class_converters py_extension_class_converters(boost::python::type<T>)
|
||||
{
|
||||
friend python_import_extension_class_converters py_extension_class_converters(boost::python::type<T>, bool sig = false) {
|
||||
return python_import_extension_class_converters();
|
||||
}
|
||||
|
||||
PyObject* to_python(const T& x) const
|
||||
{
|
||||
PyObject* to_python(const T& x) const {
|
||||
return boost::python::detail::import_extension_class<T>::get_converters()->to_python(x);
|
||||
}
|
||||
|
||||
friend T* from_python(PyObject* p, boost::python::type<T*>)
|
||||
{
|
||||
return boost::python::detail::import_extension_class<T>::get_converters()->T_pointer_from_python(p);
|
||||
friend T* from_python(PyObject* p, boost::python::type<T*> t, bool sig = false) {
|
||||
return boost::python::detail::import_extension_class<T>::get_converters()->from_python_Ts(p, t);
|
||||
}
|
||||
friend const T* from_python(PyObject* p, boost::python::type<const T*> t, bool sig = false) {
|
||||
return boost::python::detail::import_extension_class<T>::get_converters()->from_python_cTs(p, t);
|
||||
}
|
||||
friend const T* from_python(PyObject* p, boost::python::type<const T*const&> t, bool sig = false) {
|
||||
return boost::python::detail::import_extension_class<T>::get_converters()->from_python_cTscr(p, t);
|
||||
}
|
||||
friend T* from_python(PyObject* p, boost::python::type<T* const&> t, bool sig = false) {
|
||||
return boost::python::detail::import_extension_class<T>::get_converters()->from_python_Tscr(p, t);
|
||||
}
|
||||
friend T& from_python(PyObject* p, boost::python::type<T&> t, bool sig = false) {
|
||||
return boost::python::detail::import_extension_class<T>::get_converters()->from_python_Tr(p, t);
|
||||
}
|
||||
friend const T& from_python(PyObject* p, boost::python::type<const T&> t, bool sig = false) {
|
||||
return boost::python::detail::import_extension_class<T>::get_converters()->from_python_cTr(p, t);
|
||||
}
|
||||
friend const T& from_python(PyObject* p, boost::python::type<T> t, bool sig = false) {
|
||||
return boost::python::detail::import_extension_class<T>::get_converters()->from_python_T(p, t);
|
||||
}
|
||||
|
||||
// Convert to const T*
|
||||
friend const T* from_python(PyObject* p, boost::python::type<const T*>)
|
||||
{ return from_python(p, boost::python::type<T*>()); }
|
||||
|
||||
// Convert to const T* const&
|
||||
friend const T* from_python(PyObject* p, boost::python::type<const T*const&>)
|
||||
{ return from_python(p, boost::python::type<const T*>()); }
|
||||
|
||||
// Convert to T* const&
|
||||
friend T* from_python(PyObject* p, boost::python::type<T* const&>)
|
||||
{ return from_python(p, boost::python::type<T*>()); }
|
||||
|
||||
// Convert to T&
|
||||
friend T& from_python(PyObject* p, boost::python::type<T&>) {
|
||||
return boost::python::detail::import_extension_class<T>::get_converters()->T_reference_from_python(p);
|
||||
friend std::auto_ptr<T>& from_python(PyObject* p, boost::python::type<std::auto_ptr<T>&> t, bool sig = false) {
|
||||
return boost::python::detail::import_extension_class<T>::get_converters()->from_python_aTr(p, t);
|
||||
}
|
||||
|
||||
// Convert to const T&
|
||||
friend const T& from_python(PyObject* p, boost::python::type<const T&>)
|
||||
{ return from_python(p, boost::python::type<T&>()); }
|
||||
|
||||
// Convert to T
|
||||
friend const T& from_python(PyObject* p, boost::python::type<T>)
|
||||
{ return from_python(p, boost::python::type<T&>()); }
|
||||
|
||||
friend std::auto_ptr<T>& from_python(PyObject* p, boost::python::type<std::auto_ptr<T>&>) {
|
||||
return boost::python::detail::import_extension_class<T>::get_converters()->auto_ptr_reference_from_python(p);
|
||||
friend std::auto_ptr<T> from_python(PyObject* p, boost::python::type<std::auto_ptr<T> > t, bool sig = false) {
|
||||
return boost::python::detail::import_extension_class<T>::get_converters()->from_python_aT(p, t);
|
||||
}
|
||||
|
||||
friend std::auto_ptr<T>& from_python(PyObject* p, boost::python::type<std::auto_ptr<T> >) {
|
||||
return boost::python::detail::import_extension_class<T>::get_converters()->auto_ptr_value_from_python(p);
|
||||
friend const std::auto_ptr<T>& from_python(PyObject* p, boost::python::type<const std::auto_ptr<T>&> t, bool sig = false) {
|
||||
return boost::python::detail::import_extension_class<T>::get_converters()->from_python_caTr(p, t);
|
||||
}
|
||||
|
||||
friend const std::auto_ptr<T>& from_python(PyObject* p, boost::python::type<const std::auto_ptr<T>&>) {
|
||||
return boost::python::detail::import_extension_class<T>::get_converters()->auto_ptr_value_from_python(p);
|
||||
}
|
||||
|
||||
friend PyObject* to_python(std::auto_ptr<T> x) {
|
||||
friend PyObject* to_python(std::auto_ptr<T> x, bool sig = false) {
|
||||
return boost::python::detail::import_extension_class<T>::get_converters()->to_python(x);
|
||||
}
|
||||
|
||||
friend boost::shared_ptr<T>& from_python(PyObject* p, boost::python::type<boost::shared_ptr<T>&>) {
|
||||
return boost::python::detail::import_extension_class<T>::get_converters()->shared_ptr_reference_from_python(p);
|
||||
friend boost::shared_ptr<T>& from_python(PyObject* p, boost::python::type<boost::shared_ptr<T>&> t, bool sig = false) {
|
||||
return boost::python::detail::import_extension_class<T>::get_converters()->from_python_sTr(p, t);
|
||||
}
|
||||
|
||||
friend boost::shared_ptr<T>& from_python(PyObject* p, boost::python::type<boost::shared_ptr<T> >) {
|
||||
return boost::python::detail::import_extension_class<T>::get_converters()->shared_ptr_value_from_python(p);
|
||||
friend const boost::shared_ptr<T>& from_python(PyObject* p, boost::python::type<boost::shared_ptr<T> > t, bool sig = false) {
|
||||
return boost::python::detail::import_extension_class<T>::get_converters()->from_python_sT(p, t);
|
||||
}
|
||||
|
||||
friend const boost::shared_ptr<T>& from_python(PyObject* p, boost::python::type<const boost::shared_ptr<T>&>) {
|
||||
return boost::python::detail::import_extension_class<T>::get_converters()->shared_ptr_value_from_python(p);
|
||||
friend const boost::shared_ptr<T>& from_python(PyObject* p, boost::python::type<const boost::shared_ptr<T>&> t, bool sig = false) {
|
||||
return boost::python::detail::import_extension_class<T>::get_converters()->from_python_csTr(p, t);
|
||||
}
|
||||
|
||||
friend PyObject* to_python(boost::shared_ptr<T> x) {
|
||||
friend PyObject* to_python(boost::shared_ptr<T> x, bool sig = false) {
|
||||
return boost::python::detail::import_extension_class<T>::get_converters()->to_python(x);
|
||||
}
|
||||
};
|
||||
@@ -119,124 +131,166 @@ namespace boost { namespace python {
|
||||
|
||||
BOOST_PYTHON_IMPORT_CONVERSION(python_import_extension_class_converters);
|
||||
|
||||
// A pointer to this class is exported/imported via the Python API.
|
||||
// All functions are virtual. This is, what we really export/import
|
||||
// is essentially just a pointer to a vtbl.
|
||||
/* This class template is instantiated by export_converters().
|
||||
A pointer to this class is exported/imported via the Python API.
|
||||
Using the Python API ensures maximum portability.
|
||||
All member functions are virtual. This is, what we export/import
|
||||
is essentially just a pointer to a vtbl.
|
||||
To work around a deficiency of Visual C++ 6.0, the name of each
|
||||
from_python() member functions is made unique by appending a few
|
||||
characters (derived in a ad-hoc manner from the corresponding type).
|
||||
*/
|
||||
template <class T>
|
||||
struct export_converter_object_base
|
||||
{
|
||||
virtual const int get_api_major() const {
|
||||
return detail::export_converters_api_major; }
|
||||
virtual const int get_api_minor() const {
|
||||
return detail::export_converters_api_minor; }
|
||||
virtual PyObject* to_python(const T& x) = 0;
|
||||
virtual PyObject* to_python(std::auto_ptr<T> x) = 0;
|
||||
virtual PyObject* to_python(boost::shared_ptr<T> x) = 0;
|
||||
virtual T* T_pointer_from_python(PyObject* obj) = 0;
|
||||
virtual T& T_reference_from_python(PyObject* obj) = 0;
|
||||
virtual std::auto_ptr<T>& auto_ptr_reference_from_python(PyObject* obj) = 0;
|
||||
virtual std::auto_ptr<T> auto_ptr_value_from_python(PyObject* obj) = 0;
|
||||
virtual boost::shared_ptr<T>& shared_ptr_reference_from_python(PyObject* obj) = 0;
|
||||
virtual boost::shared_ptr<T> shared_ptr_value_from_python(PyObject* obj) = 0;
|
||||
virtual int get_api_major() const { return detail::export_converters_api_major; }
|
||||
virtual int get_api_minor() const { return detail::export_converters_api_minor; }
|
||||
|
||||
virtual PyObject* to_python(const T& x) = 0;
|
||||
|
||||
virtual T* from_python_Ts(PyObject* p, boost::python::type<T*> t) = 0;
|
||||
virtual const T* from_python_cTs(PyObject* p, boost::python::type<const T*> t) = 0;
|
||||
virtual const T* from_python_cTscr(PyObject* p, boost::python::type<const T*const&> t) = 0;
|
||||
virtual T* from_python_Tscr(PyObject* p, boost::python::type<T* const&> t) = 0;
|
||||
virtual T& from_python_Tr(PyObject* p, boost::python::type<T&> t) = 0;
|
||||
virtual const T& from_python_cTr(PyObject* p, boost::python::type<const T&> t) = 0;
|
||||
virtual const T& from_python_T(PyObject* p, boost::python::type<T> t) = 0;
|
||||
|
||||
virtual std::auto_ptr<T>& from_python_aTr(PyObject* p, boost::python::type<std::auto_ptr<T>&> t) = 0;
|
||||
virtual std::auto_ptr<T> from_python_aT(PyObject* p, boost::python::type<std::auto_ptr<T> > t) = 0;
|
||||
virtual const std::auto_ptr<T>& from_python_caTr(PyObject* p, boost::python::type<const std::auto_ptr<T>&> t) = 0;
|
||||
virtual PyObject* to_python(std::auto_ptr<T> x) = 0;
|
||||
|
||||
virtual boost::shared_ptr<T>& from_python_sTr(PyObject* p, boost::python::type<boost::shared_ptr<T>&> t) = 0;
|
||||
virtual const boost::shared_ptr<T>& from_python_sT(PyObject* p, boost::python::type<boost::shared_ptr<T> > t) = 0;
|
||||
virtual const boost::shared_ptr<T>& from_python_csTr(PyObject* p, boost::python::type<const boost::shared_ptr<T>&> t) = 0;
|
||||
virtual PyObject* to_python(boost::shared_ptr<T> x) = 0;
|
||||
};
|
||||
|
||||
// Converters to be used if T is not copyable.
|
||||
template <class T>
|
||||
struct export_converter_object_noncopyable : export_converter_object_base<T>
|
||||
{
|
||||
virtual PyObject* to_python(const T& x) {
|
||||
PyErr_SetString(PyExc_RuntimeError,
|
||||
"to_python(const T&) converter not exported");
|
||||
throw import_error();
|
||||
}
|
||||
virtual PyObject* to_python(std::auto_ptr<T> x) {
|
||||
return BOOST_PYTHON_CONVERSION::to_python(x);
|
||||
}
|
||||
virtual PyObject* to_python(boost::shared_ptr<T> x) {
|
||||
return BOOST_PYTHON_CONVERSION::to_python(x);
|
||||
}
|
||||
virtual T* T_pointer_from_python(PyObject* obj) {
|
||||
return BOOST_PYTHON_CONVERSION::from_python(obj, boost::python::type<T*>());
|
||||
}
|
||||
virtual T& T_reference_from_python(PyObject* obj) {
|
||||
return BOOST_PYTHON_CONVERSION::from_python(obj, boost::python::type<T&>());
|
||||
}
|
||||
virtual std::auto_ptr<T>& auto_ptr_reference_from_python(PyObject* obj) {
|
||||
return BOOST_PYTHON_CONVERSION::python_extension_class_converters<T>::smart_ptr_reference(obj, boost::python::type<std::auto_ptr<T> >());
|
||||
}
|
||||
virtual std::auto_ptr<T> auto_ptr_value_from_python(PyObject* obj) {
|
||||
return BOOST_PYTHON_CONVERSION::python_extension_class_converters<T>::smart_ptr_value(obj, boost::python::type<std::auto_ptr<T> >());
|
||||
}
|
||||
virtual boost::shared_ptr<T>& shared_ptr_reference_from_python(PyObject* obj) {
|
||||
return BOOST_PYTHON_CONVERSION::python_extension_class_converters<T>::smart_ptr_reference(obj, boost::python::type<boost::shared_ptr<T> >());
|
||||
}
|
||||
virtual boost::shared_ptr<T> shared_ptr_value_from_python(PyObject* obj) {
|
||||
return BOOST_PYTHON_CONVERSION::python_extension_class_converters<T>::smart_ptr_value(obj, boost::python::type<boost::shared_ptr<T> >());
|
||||
}
|
||||
virtual PyObject* to_python(const T& x) {
|
||||
PyErr_SetString(PyExc_RuntimeError,
|
||||
"to_python(const T&) converter not exported");
|
||||
throw_import_error();
|
||||
return 0;
|
||||
}
|
||||
|
||||
virtual T* from_python_Ts(PyObject* p, boost::python::type<T*> t) {
|
||||
return BOOST_PYTHON_CONVERSION::from_python(p, t);
|
||||
}
|
||||
virtual const T* from_python_cTs(PyObject* p, boost::python::type<const T*> t) {
|
||||
return BOOST_PYTHON_CONVERSION::from_python(p, t);
|
||||
}
|
||||
virtual const T* from_python_cTscr(PyObject* p, boost::python::type<const T*const&> t) {
|
||||
return BOOST_PYTHON_CONVERSION::from_python(p, t);
|
||||
}
|
||||
virtual T* from_python_Tscr(PyObject* p, boost::python::type<T* const&> t) {
|
||||
return BOOST_PYTHON_CONVERSION::from_python(p, t);
|
||||
}
|
||||
virtual T& from_python_Tr(PyObject* p, boost::python::type<T&> t) {
|
||||
return BOOST_PYTHON_CONVERSION::from_python(p, t);
|
||||
}
|
||||
virtual const T& from_python_cTr(PyObject* p, boost::python::type<const T&> t) {
|
||||
return BOOST_PYTHON_CONVERSION::from_python(p, t);
|
||||
}
|
||||
virtual const T& from_python_T(PyObject* p, boost::python::type<T> t) {
|
||||
return BOOST_PYTHON_CONVERSION::from_python(p, t);
|
||||
}
|
||||
|
||||
virtual std::auto_ptr<T>& from_python_aTr(PyObject* p, boost::python::type<std::auto_ptr<T>&> t) {
|
||||
return BOOST_PYTHON_CONVERSION::from_python(p, t);
|
||||
}
|
||||
virtual std::auto_ptr<T> from_python_aT(PyObject* p, boost::python::type<std::auto_ptr<T> > t) {
|
||||
return BOOST_PYTHON_CONVERSION::from_python(p, t);
|
||||
}
|
||||
virtual const std::auto_ptr<T>& from_python_caTr(PyObject* p, boost::python::type<const std::auto_ptr<T>&> t) {
|
||||
return BOOST_PYTHON_CONVERSION::from_python(p, t);
|
||||
}
|
||||
virtual PyObject* to_python(std::auto_ptr<T> x) {
|
||||
return BOOST_PYTHON_CONVERSION::to_python(x);
|
||||
}
|
||||
|
||||
virtual boost::shared_ptr<T>& from_python_sTr(PyObject* p, boost::python::type<boost::shared_ptr<T>&> t) {
|
||||
return BOOST_PYTHON_CONVERSION::from_python(p, t);
|
||||
}
|
||||
virtual const boost::shared_ptr<T>& from_python_sT(PyObject* p, boost::python::type<boost::shared_ptr<T> > t) {
|
||||
return BOOST_PYTHON_CONVERSION::from_python(p, t);
|
||||
}
|
||||
virtual const boost::shared_ptr<T>& from_python_csTr(PyObject* p, boost::python::type<const boost::shared_ptr<T>&> t) {
|
||||
return BOOST_PYTHON_CONVERSION::from_python(p, t);
|
||||
}
|
||||
virtual PyObject* to_python(boost::shared_ptr<T> x) {
|
||||
return BOOST_PYTHON_CONVERSION::to_python(x);
|
||||
}
|
||||
};
|
||||
|
||||
// The addditional to_python() converter that can be used if T is copyable.
|
||||
template <class T>
|
||||
struct export_converter_object : export_converter_object_noncopyable<T>
|
||||
{
|
||||
virtual PyObject* to_python(const T& x) {
|
||||
BOOST_PYTHON_CONVERSION::python_extension_class_converters<T> cv;
|
||||
return cv.to_python(x);
|
||||
}
|
||||
};
|
||||
|
||||
namespace detail {
|
||||
|
||||
//QUESTIONMARK
|
||||
// A stripped-down, modified version of class extension_class.
|
||||
// Would it make sense to establish a formal relationship
|
||||
// between the two classes?
|
||||
template <class T>
|
||||
class import_extension_class
|
||||
: public python_import_extension_class_converters<T>
|
||||
{
|
||||
public:
|
||||
inline import_extension_class(const char* module, const char* py_class) {
|
||||
m_module = module;
|
||||
m_py_class = py_class;
|
||||
virtual PyObject* to_python(const T& x) {
|
||||
return BOOST_PYTHON_CONVERSION::py_extension_class_converters(boost::python::type<T>()).to_python(x);
|
||||
}
|
||||
|
||||
static boost::python::export_converter_object_base<T>* get_converters();
|
||||
|
||||
private:
|
||||
static std::string m_module;
|
||||
static std::string m_py_class;
|
||||
static boost::python::export_converter_object_base<T>* imported_converters;
|
||||
};
|
||||
|
||||
template <class T> std::string import_extension_class<T>::m_module;
|
||||
template <class T> std::string import_extension_class<T>::m_py_class;
|
||||
template <class T>
|
||||
boost::python::export_converter_object_base<T>*
|
||||
import_extension_class<T>::imported_converters = 0;
|
||||
namespace detail
|
||||
{
|
||||
|
||||
template <class T>
|
||||
boost::python::export_converter_object_base<T>*
|
||||
import_extension_class<T>::get_converters() {
|
||||
if (imported_converters == 0) {
|
||||
void* cobject
|
||||
= import_converter_object(m_module, m_py_class,
|
||||
converters_attribute_name);
|
||||
imported_converters
|
||||
= static_cast<boost::python::export_converter_object_base<T>*>(cobject);
|
||||
check_export_converters_api(
|
||||
export_converters_api_major,
|
||||
export_converters_api_minor,
|
||||
imported_converters->get_api_major(),
|
||||
imported_converters->get_api_minor());
|
||||
/* This class template is instantiated by import_converters<T>.
|
||||
Its purpose is to import the converter_object via the Python API.
|
||||
The actual import is only done once. The pointer to the
|
||||
imported converter object is kept in the static data member
|
||||
imported_converters.
|
||||
*/
|
||||
template <class T>
|
||||
class import_extension_class
|
||||
: public python_import_extension_class_converters<T>
|
||||
{
|
||||
public:
|
||||
inline import_extension_class(const char* module, const char* py_class) {
|
||||
m_module = module;
|
||||
m_py_class = py_class;
|
||||
}
|
||||
|
||||
static boost::python::export_converter_object_base<T>* get_converters();
|
||||
|
||||
private:
|
||||
static std::string m_module;
|
||||
static std::string m_py_class;
|
||||
static boost::python::export_converter_object_base<T>* imported_converters;
|
||||
};
|
||||
|
||||
template <class T> std::string import_extension_class<T>::m_module;
|
||||
template <class T> std::string import_extension_class<T>::m_py_class;
|
||||
template <class T>
|
||||
boost::python::export_converter_object_base<T>*
|
||||
import_extension_class<T>::imported_converters = 0;
|
||||
|
||||
template <class T>
|
||||
boost::python::export_converter_object_base<T>*
|
||||
import_extension_class<T>::get_converters() {
|
||||
if (imported_converters == 0) {
|
||||
void* cobject
|
||||
= import_converter_object(m_module, m_py_class,
|
||||
converters_attribute_name);
|
||||
imported_converters
|
||||
= static_cast<boost::python::export_converter_object_base<T>*>(cobject);
|
||||
check_export_converters_api(
|
||||
export_converters_api_major,
|
||||
export_converters_api_minor,
|
||||
imported_converters->get_api_major(),
|
||||
imported_converters->get_api_minor());
|
||||
}
|
||||
return imported_converters;
|
||||
}
|
||||
return imported_converters;
|
||||
}
|
||||
|
||||
}}} // namespace boost::python::detail
|
||||
|
||||
namespace boost { namespace python {
|
||||
|
||||
// Implementation of export_converters().
|
||||
template <class T, class U>
|
||||
void export_converters(class_builder<T, U>& cb)
|
||||
{
|
||||
@@ -246,6 +300,7 @@ void export_converters(class_builder<T, U>& cb)
|
||||
detail::converters_attribute_name);
|
||||
}
|
||||
|
||||
// Implementation of export_converters_noncopyable().
|
||||
template <class T, class U>
|
||||
void export_converters_noncopyable(class_builder<T, U>& cb)
|
||||
{
|
||||
@@ -255,17 +310,17 @@ void export_converters_noncopyable(class_builder<T, U>& cb)
|
||||
detail::converters_attribute_name);
|
||||
}
|
||||
|
||||
// Implementation of import_converters<T>.
|
||||
template <class T>
|
||||
class import_converters
|
||||
: python_import_extension_class_converters<T>
|
||||
: python_import_extension_class_converters<T> // Works around MSVC6.x/GCC2.95.2 bug described
|
||||
// at the bottom of class_builder.hpp.
|
||||
{
|
||||
public:
|
||||
import_converters(const char* module, const char* py_class)
|
||||
: m_class(new detail::import_extension_class<T>(module, py_class))
|
||||
{ }
|
||||
private:
|
||||
//QUESTIONMARK
|
||||
//reference<detail::import_extension_class<T> > m_class;
|
||||
boost::shared_ptr<detail::import_extension_class<T> > m_class;
|
||||
};
|
||||
|
||||
|
||||
111
include/boost/python/data_members.hpp
Normal file
111
include/boost/python/data_members.hpp
Normal file
@@ -0,0 +1,111 @@
|
||||
// Copyright David Abrahams 2002. Permission to copy, use,
|
||||
// modify, sell and distribute this software is granted provided this
|
||||
// copyright notice appears in all copies. This software is provided
|
||||
// "as is" without express or implied warranty, and with no claim as
|
||||
// to its suitability for any purpose.
|
||||
#ifndef DATA_MEMBERS_DWA2002328_HPP
|
||||
# define DATA_MEMBERS_DWA2002328_HPP
|
||||
|
||||
# include <boost/python/detail/config.hpp>
|
||||
# include <boost/python/detail/wrap_python.hpp>
|
||||
# include <boost/type_traits/transform_traits.hpp>
|
||||
# include <boost/type_traits/cv_traits.hpp>
|
||||
# include <boost/python/return_value_policy.hpp>
|
||||
# include <boost/python/copy_non_const_reference.hpp>
|
||||
# include <boost/python/object/function_object.hpp>
|
||||
# include <boost/python/arg_from_python.hpp>
|
||||
# include <boost/bind.hpp>
|
||||
|
||||
namespace boost { namespace python {
|
||||
|
||||
namespace detail
|
||||
{
|
||||
template <class Data, class Class, class Policies>
|
||||
struct member
|
||||
{
|
||||
static PyObject* get(Data Class::*pm, PyObject* args_, PyObject*, Policies const& policies)
|
||||
{
|
||||
arg_from_python<Class*> c0(PyTuple_GET_ITEM(args_, 0));
|
||||
if (!c0.convertible()) return 0;
|
||||
|
||||
// find the result converter
|
||||
typedef typename Policies::result_converter result_converter;
|
||||
typedef typename boost::add_reference<Data>::type source;
|
||||
typename mpl::apply1<result_converter,source>::type cr;
|
||||
if (!cr.convertible()) return 0;
|
||||
|
||||
if (!policies.precall(args_)) return 0;
|
||||
|
||||
PyObject* result = cr( (c0(PyTuple_GET_ITEM(args_, 0)))->*pm );
|
||||
|
||||
return policies.postcall(args_, result);
|
||||
}
|
||||
|
||||
static PyObject* set(Data Class::*pm, PyObject* args_, PyObject*, Policies const& policies)
|
||||
{
|
||||
// check that each of the arguments is convertible
|
||||
arg_from_python<Class*> c0(PyTuple_GET_ITEM(args_, 0));
|
||||
if (!c0.convertible()) return 0;
|
||||
|
||||
typedef typename add_const<Data>::type target1;
|
||||
typedef typename add_reference<target1>::type target;
|
||||
arg_from_python<target> c1(PyTuple_GET_ITEM(args_, 1));
|
||||
|
||||
if (!c1.convertible()) return 0;
|
||||
|
||||
if (!policies.precall(args_)) return 0;
|
||||
|
||||
(c0(PyTuple_GET_ITEM(args_, 0)))->*pm = c1(PyTuple_GET_ITEM(args_, 1));
|
||||
|
||||
return policies.postcall(args_, detail::none());
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
template <class C, class D>
|
||||
object make_getter(D C::*pm)
|
||||
{
|
||||
typedef return_value_policy<copy_non_const_reference> default_policy;
|
||||
|
||||
return objects::function_object(
|
||||
::boost::bind(
|
||||
&detail::member<D,C,default_policy>::get, pm, _1, _2
|
||||
, default_policy())
|
||||
, 1);
|
||||
|
||||
}
|
||||
|
||||
template <class C, class D, class Policies>
|
||||
object make_getter(D C::*pm, Policies const& policies)
|
||||
{
|
||||
return objects::function_object(
|
||||
::boost::bind(
|
||||
&detail::member<D,C,Policies>::get, pm, _1, _2
|
||||
, policies)
|
||||
, 1);
|
||||
}
|
||||
|
||||
template <class C, class D>
|
||||
object make_setter(D C::*pm)
|
||||
{
|
||||
return objects::function_object(
|
||||
::boost::bind(
|
||||
&detail::member<D,C,default_call_policies>::set, pm, _1, _2
|
||||
, default_call_policies())
|
||||
, 2);
|
||||
}
|
||||
|
||||
template <class C, class D, class Policies>
|
||||
object make_setter(D C::*pm, Policies const& policies)
|
||||
{
|
||||
return objects::function_object(
|
||||
::boost::bind(
|
||||
&detail::member<D,C,Policies>::set, pm, _1, _2
|
||||
, policies)
|
||||
, 2);
|
||||
}
|
||||
|
||||
|
||||
}} // namespace boost::python
|
||||
|
||||
#endif // DATA_MEMBERS_DWA2002328_HPP
|
||||
94
include/boost/python/def.hpp
Normal file
94
include/boost/python/def.hpp
Normal file
@@ -0,0 +1,94 @@
|
||||
// Copyright David Abrahams 2002. Permission to copy, use,
|
||||
// modify, sell and distribute this software is granted provided this
|
||||
// copyright notice appears in all copies. This software is provided
|
||||
// "as is" without express or implied warranty, and with no claim as
|
||||
// to its suitability for any purpose.
|
||||
#ifndef DEF_DWA200292_HPP
|
||||
# define DEF_DWA200292_HPP
|
||||
|
||||
# include <boost/python/object_fwd.hpp>
|
||||
# include <boost/python/make_function.hpp>
|
||||
# include <boost/python/detail/def_helper.hpp>
|
||||
# include <boost/python/detail/defaults_def.hpp>
|
||||
# include <boost/python/scope.hpp>
|
||||
# include <boost/python/signature.hpp>
|
||||
|
||||
namespace boost { namespace python {
|
||||
|
||||
namespace detail
|
||||
{
|
||||
void BOOST_PYTHON_DECL scope_setattr_doc(char const* name, object const& obj, char const* doc);
|
||||
|
||||
template <class Fn, class CallPolicyOrDoc>
|
||||
void
|
||||
dispatch_def(
|
||||
void const*,
|
||||
char const* name,
|
||||
Fn fn,
|
||||
CallPolicyOrDoc const& policy_or_doc,
|
||||
char const* doc = 0)
|
||||
{
|
||||
typedef detail::def_helper<CallPolicyOrDoc> helper;
|
||||
|
||||
detail::scope_setattr_doc(
|
||||
name, boost::python::make_function(fn, helper::get_policy(policy_or_doc)),
|
||||
helper::get_doc(policy_or_doc, doc));
|
||||
}
|
||||
|
||||
template <class StubsT, class SigT>
|
||||
void dispatch_def(
|
||||
detail::func_stubs_base const*,
|
||||
char const* name,
|
||||
SigT sig,
|
||||
StubsT const& stubs)
|
||||
{
|
||||
// convert sig to a type_list (see detail::get_signature in signature.hpp)
|
||||
// before calling detail::define_with_defaults.
|
||||
|
||||
scope current;
|
||||
detail::define_with_defaults(
|
||||
name, stubs, current, detail::get_signature(sig));
|
||||
}
|
||||
}
|
||||
|
||||
template <class Fn>
|
||||
void def(char const* name, Fn fn)
|
||||
{
|
||||
detail::scope_setattr_doc(name, boost::python::make_function(fn), 0);
|
||||
}
|
||||
|
||||
template <class Arg1T, class Arg2T>
|
||||
void def(char const* name, Arg1T arg1, Arg2T const& arg2)
|
||||
{
|
||||
// The arguments may be:
|
||||
// def(name, function)
|
||||
// def(name, function, policy)
|
||||
// def(name, function, doc_string)
|
||||
// def(name, signature, stubs)
|
||||
|
||||
detail::dispatch_def(&arg2, name, arg1, arg2);
|
||||
}
|
||||
|
||||
template <class Arg1T, class Arg2T, class Arg3T>
|
||||
void def(char const* name, Arg1T arg1, Arg2T const& arg2, Arg3T const& arg3)
|
||||
{
|
||||
// The arguments are definitely:
|
||||
// def(name, function, policy, doc_string) // TODO: exchange policy, doc_string position
|
||||
|
||||
detail::dispatch_def(&arg2, name, arg1, arg2, arg3);
|
||||
}
|
||||
|
||||
//template <class Arg1T, class Arg2T, class Arg3T>
|
||||
//void def(char const* name, Arg1T arg1, Arg2T const& arg2, Arg3T const& arg3, char const* doc)
|
||||
//{
|
||||
// // The arguments are definitely:
|
||||
// // arg1: signature
|
||||
// // arg2: stubs
|
||||
// // arg3: policy
|
||||
//
|
||||
// detail::dispatch_def(&arg2, name, arg1, arg2, arg3, doc);
|
||||
//}
|
||||
|
||||
}} // namespace boost::python
|
||||
|
||||
#endif // DEF_DWA200292_HPP
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user