Compare commits
2995 Commits
timing_viz
...
master
Author | SHA1 | Date | |
---|---|---|---|
![]() |
0c060512c1 | ||
![]() |
d673d04ff3 | ||
![]() |
e12093201a | ||
![]() |
1623243d50 | ||
![]() |
90d746f79e | ||
![]() |
fac934bd2d | ||
![]() |
6855b558ac | ||
![]() |
17943a51cb | ||
![]() |
dbba1328bf | ||
![]() |
cd7f7c12f1 | ||
![]() |
bb2336ad73 | ||
![]() |
dcfb7d8c33 | ||
![]() |
f5776a6d64 | ||
![]() |
a951faa16d | ||
![]() |
43b2f38520 | ||
![]() |
284fb3e874 | ||
![]() |
155adc3f5d | ||
![]() |
d214308f5f | ||
![]() |
c48157aa4b | ||
![]() |
574f504787 | ||
![]() |
ab7a372491 | ||
![]() |
92694d7db7 | ||
![]() |
5fe680390f | ||
![]() |
55bd760808 | ||
![]() |
c565e364bc | ||
![]() |
0345b6e803 | ||
![]() |
3d350c21c5 | ||
![]() |
f01465f628 | ||
![]() |
d810aac867 | ||
![]() |
5a807110de | ||
![]() |
5eaa1b3f1f | ||
![]() |
2b8a235776 | ||
![]() |
0e69425794 | ||
![]() |
55035465aa | ||
![]() |
9c2d96f86e | ||
![]() |
f36a6571c1 | ||
![]() |
cf42baa43b | ||
![]() |
7c459805f6 | ||
![]() |
028be1462a | ||
![]() |
d27993f019 | ||
![]() |
0e5b1348e6 | ||
![]() |
854549a5ab | ||
![]() |
75d2ce6a92 | ||
![]() |
65cf6d8da7 | ||
![]() |
268b32c341 | ||
![]() |
b3b2392893 | ||
![]() |
7f33329fe1 | ||
![]() |
3d00b97e0a | ||
![]() |
a9cc7f453d | ||
![]() |
ff9ba9e090 | ||
![]() |
cc04882b17 | ||
![]() |
9b51c6e337 | ||
![]() |
fcdaf3f86c | ||
![]() |
1967db170d | ||
![]() |
24fc33c014 | ||
![]() |
d3c0f945da | ||
![]() |
38e5faca85 | ||
![]() |
e4dfd4e622 | ||
![]() |
7516b8950a | ||
![]() |
118ecbc6b3 | ||
![]() |
c90d872e35 | ||
![]() |
437fb70ed3 | ||
![]() |
cd51a0c2fc | ||
![]() |
9da05b6001 | ||
![]() |
2031a067a0 | ||
![]() |
81bf92a855 | ||
![]() |
8a0e062520 | ||
![]() |
a08229d6b6 | ||
![]() |
9bea22ed1e | ||
![]() |
ad9a54cc69 | ||
![]() |
04f5f80766 | ||
![]() |
db0c99199e | ||
![]() |
bbdf7aacb0 | ||
![]() |
0af42f1218 | ||
![]() |
93e233dad9 | ||
![]() |
098dcaedec | ||
![]() |
0fce4b8f4e | ||
![]() |
25d64b2105 | ||
![]() |
5488cd994b | ||
![]() |
8ee2c5612c | ||
![]() |
a7f79fd681 | ||
![]() |
bca6f6394a | ||
![]() |
eb0bf9ea9c | ||
![]() |
3b7fec8c4f | ||
![]() |
4488d42368 | ||
![]() |
8e12dfc693 | ||
![]() |
86106cb49a | ||
![]() |
fc3b2de8da | ||
![]() |
60ee682d58 | ||
![]() |
82ea65d984 | ||
![]() |
7aeed52c06 | ||
![]() |
c25da06d03 | ||
![]() |
44665a9c4d | ||
![]() |
2d542eb63a | ||
![]() |
4b63b1115e | ||
![]() |
6ca64526bb | ||
![]() |
2627d4e0ad | ||
![]() |
50bd8d09b0 | ||
![]() |
ff7b8535bc | ||
![]() |
8d0f52fbf9 | ||
![]() |
4d1de4532a | ||
![]() |
4cf7afedf7 | ||
![]() |
2dc712130c | ||
![]() |
32e2d9223c | ||
![]() |
01737a400c | ||
![]() |
ccdc2f6f13 | ||
![]() |
fa55e93848 | ||
![]() |
0d5d32951c | ||
![]() |
f199c3e576 | ||
![]() |
e9e7dce23d | ||
![]() |
11d335c7ce | ||
![]() |
10a5a44b81 | ||
![]() |
f17caa2379 | ||
![]() |
eb099a9244 | ||
![]() |
1871afe9b9 | ||
![]() |
cecd6b3f4d | ||
![]() |
6b5b21e165 | ||
![]() |
7dd4a8c1d5 | ||
![]() |
ba293437e0 | ||
![]() |
0639681b73 | ||
![]() |
2e8280a949 | ||
![]() |
8f87918230 | ||
![]() |
a29a17f8f2 | ||
![]() |
c89037db49 | ||
![]() |
945cf48c6c | ||
![]() |
61cc5259d9 | ||
![]() |
b7f91e57a0 | ||
![]() |
59a29e5f42 | ||
![]() |
423f1b7159 | ||
![]() |
09703c7f35 | ||
![]() |
eb0554319f | ||
![]() |
f99346ba61 | ||
![]() |
0dc4bcb203 | ||
![]() |
3f2451f8d7 | ||
![]() |
89e3b7d23d | ||
![]() |
7a00e76cb1 | ||
![]() |
f085950383 | ||
![]() |
edcafcf085 | ||
![]() |
4d5c48ad83 | ||
![]() |
d3b53d8e1a | ||
![]() |
6b7723e4c1 | ||
![]() |
9bb46b98b4 | ||
![]() |
1f25f2067a | ||
![]() |
ac725465a9 | ||
![]() |
75af8ccfd2 | ||
![]() |
465cbfaf19 | ||
![]() |
7f9f75c0d3 | ||
![]() |
b4da57598e | ||
![]() |
693058abb7 | ||
![]() |
5ecb669a41 | ||
![]() |
210e0fa33b | ||
![]() |
ff96fc5af1 | ||
![]() |
4e8436a1fc | ||
![]() |
4981ebb698 | ||
![]() |
05ed9308d6 | ||
![]() |
aa26ba7ea1 | ||
![]() |
255633c9f3 | ||
![]() |
cc273c1257 | ||
![]() |
833cb86b51 | ||
![]() |
4eeb56c0e0 | ||
![]() |
b05cb86291 | ||
![]() |
a65ddff8ba | ||
![]() |
325985e055 | ||
![]() |
e7192cd375 | ||
![]() |
9dcd0eff16 | ||
![]() |
73b7de74a5 | ||
![]() |
91b0c4f90a | ||
![]() |
97f5c3ca2c | ||
![]() |
8968c84ce6 | ||
![]() |
4220ce1007 | ||
![]() |
a0e360fd9f | ||
![]() |
14a09061a5 | ||
![]() |
dfd651a132 | ||
![]() |
d0e01661a5 | ||
![]() |
6e4e81429c | ||
![]() |
c8e1cbc5f2 | ||
![]() |
c5fc34f11a | ||
![]() |
f12e76479c | ||
![]() |
2afb1f632e | ||
![]() |
d00fdc8f7a | ||
![]() |
257fbe549d | ||
![]() |
d557e3e35f | ||
![]() |
2c8ad5fa1d | ||
![]() |
d867019dcb | ||
![]() |
5013392841 | ||
![]() |
6a9ad61051 | ||
![]() |
cb269b46d6 | ||
![]() |
3e46fbc655 | ||
![]() |
cfeb588d32 | ||
![]() |
7d0c4eaf1b | ||
![]() |
e9c69ac00c | ||
![]() |
cb4db2d368 | ||
![]() |
7fd80c5a92 | ||
![]() |
50d43742ce | ||
![]() |
e12ab86c75 | ||
![]() |
1bbcc5f2c4 | ||
![]() |
49d505831d | ||
![]() |
1dbd81067a | ||
![]() |
d2297b1ba0 | ||
![]() |
4a4025192a | ||
![]() |
41914876ef | ||
![]() |
56587859d3 | ||
![]() |
535709a9a9 | ||
![]() |
d1083fd348 | ||
![]() |
b4ca68c8ef | ||
![]() |
6d9322457e | ||
![]() |
c13b34f20e | ||
![]() |
90d4863dd4 | ||
![]() |
f2c280feda | ||
![]() |
e3f4578b3b | ||
![]() |
ec60542ffd | ||
![]() |
1ec8e411d7 | ||
![]() |
0b8a93eed5 | ||
![]() |
de3d5be8f0 | ||
![]() |
7814f44883 | ||
![]() |
6683fd4ada | ||
![]() |
55635cf2cd | ||
![]() |
e2a887ef0d | ||
![]() |
5bfe0dd1b1 | ||
![]() |
a32ad13a86 | ||
![]() |
a4d2244300 | ||
![]() |
0106c3d299 | ||
![]() |
506d5f9422 | ||
![]() |
4c6003ac0b | ||
![]() |
7b0e082000 | ||
![]() |
cf647463e4 | ||
![]() |
fe52840054 | ||
![]() |
e3c44dd20a | ||
![]() |
214cc4315e | ||
![]() |
d6f54fd9df | ||
![]() |
d40c6e850d | ||
![]() |
74d7ebc71f | ||
![]() |
6bae89b8b7 | ||
![]() |
7cac0249a1 | ||
![]() |
95f0a19391 | ||
![]() |
1238b69d74 | ||
![]() |
4a7e58a938 | ||
![]() |
5a2eff2120 | ||
![]() |
0eb9a9ad02 | ||
![]() |
95e7598cc6 | ||
![]() |
e4cb7ea337 | ||
![]() |
f0325730a8 | ||
![]() |
c2e7d3d611 | ||
![]() |
1811c71438 | ||
![]() |
1a92c83c3a | ||
![]() |
ed7064b210 | ||
![]() |
72546a2186 | ||
![]() |
657d2898cf | ||
![]() |
c2b75b355f | ||
![]() |
40313eacf0 | ||
![]() |
1edb449601 | ||
![]() |
58cb8a830a | ||
![]() |
e8602fb56d | ||
![]() |
c07ca64ebe | ||
![]() |
3f2e550f51 | ||
![]() |
38d2a4b844 | ||
![]() |
8e84006ee7 | ||
![]() |
682c91476f | ||
![]() |
f5996ff4a1 | ||
![]() |
8a54e5ec1c | ||
![]() |
165e89f49a | ||
![]() |
565927dfcc | ||
![]() |
3cac90a30a | ||
![]() |
3e1e783873 | ||
![]() |
890d7f7617 | ||
![]() |
78ee20b5da | ||
![]() |
f9825c3130 | ||
![]() |
eef5243fba | ||
![]() |
732b329e7d | ||
![]() |
9994ba1d19 | ||
![]() |
79c6840fef | ||
![]() |
a9a9251e42 | ||
![]() |
98b09c369f | ||
![]() |
3e0b9826b5 | ||
![]() |
aca14cc420 | ||
![]() |
6513299126 | ||
![]() |
f42805984c | ||
![]() |
fdd45d12fd | ||
![]() |
1b926b2703 | ||
![]() |
84a27c3ebf | ||
![]() |
09b7cad7f1 | ||
![]() |
e85bb1c28c | ||
![]() |
4d0afdfd60 | ||
![]() |
0994e11b73 | ||
![]() |
a823543932 | ||
![]() |
87ae77fbc6 | ||
![]() |
3a073540c2 | ||
![]() |
dfb701b5ab | ||
![]() |
5e9a96d358 | ||
![]() |
01044cc910 | ||
![]() |
03c413a27a | ||
![]() |
df13104384 | ||
![]() |
49f8620ac9 | ||
![]() |
6eeac1cabf | ||
![]() |
b2ec06dfe8 | ||
![]() |
6cac19c055 | ||
![]() |
3d3039e25c | ||
![]() |
2930d80627 | ||
![]() |
c4b3268e90 | ||
![]() |
c9b23a01db | ||
![]() |
c82654d003 | ||
![]() |
f7fbe0db04 | ||
![]() |
e4d2e1bd85 | ||
![]() |
ae89430075 | ||
![]() |
fb5f764b85 | ||
![]() |
24e1734999 | ||
![]() |
bc7cd4f20e | ||
![]() |
b9592093b5 | ||
![]() |
5497a37de1 | ||
![]() |
688f1ba983 | ||
![]() |
e08471dfaf | ||
![]() |
977180524a | ||
![]() |
a01e2c9068 | ||
![]() |
053dfc98f0 | ||
![]() |
1fdd683344 | ||
![]() |
240f89081f | ||
![]() |
d2a489d5e9 | ||
![]() |
b0820eeaaa | ||
![]() |
cfd3a52a3c | ||
![]() |
596873c302 | ||
![]() |
8b51674a6b | ||
![]() |
d9f009b570 | ||
![]() |
88714c54ec | ||
![]() |
053d89570f | ||
![]() |
adacaf65f4 | ||
![]() |
83f65169a3 | ||
![]() |
679b662a2b | ||
![]() |
54b2045726 | ||
![]() |
914999673c | ||
![]() |
77afaf23a5 | ||
![]() |
1260f2f7d7 | ||
![]() |
cbd6496d35 | ||
![]() |
6c0b4443d5 | ||
![]() |
bbe9ea9d65 | ||
![]() |
787fac7649 | ||
![]() |
71a6b99633 | ||
![]() |
8935c1867f | ||
![]() |
863ad4cee8 | ||
![]() |
68a2b2710f | ||
![]() |
8a79a3522c | ||
![]() |
cb4846a58d | ||
![]() |
0f947ee693 | ||
![]() |
5b958c4d80 | ||
![]() |
119b47acf3 | ||
![]() |
c5666c47fe | ||
![]() |
e5a5de53c1 | ||
![]() |
5936464967 | ||
![]() |
7912a61ce3 | ||
![]() |
7dafd4da58 | ||
![]() |
f03da6568b | ||
![]() |
1d3e5151ba | ||
![]() |
354b7daf12 | ||
![]() |
7a827b1c78 | ||
![]() |
ea925f39fb | ||
![]() |
98121308e0 | ||
![]() |
bc7b8b63ed | ||
![]() |
ca2e328a5f | ||
![]() |
57b923a603 | ||
![]() |
e3529d3356 | ||
![]() |
91771895b6 | ||
![]() |
0067bcc615 | ||
![]() |
10595726c1 | ||
![]() |
e012f7b4f8 | ||
![]() |
8fd4735292 | ||
![]() |
655aee1f9d | ||
![]() |
582cd526ac | ||
![]() |
909917cb61 | ||
![]() |
90a6578c53 | ||
![]() |
a2d08dc79e | ||
![]() |
01c631870e | ||
![]() |
d7c2eb3fae | ||
![]() |
8c19e6f83a | ||
![]() |
7ac3d0d901 | ||
![]() |
2a35f0292a | ||
![]() |
c6f1f124f2 | ||
![]() |
3281ca6717 | ||
![]() |
437b57a510 | ||
![]() |
8c38e7ba61 | ||
![]() |
3a7770dca2 | ||
![]() |
19176ab597 | ||
![]() |
1b3283fb7c | ||
![]() |
a79c2f3209 | ||
![]() |
4b3ae70ca8 | ||
![]() |
c04c961949 | ||
![]() |
9121880c5f | ||
![]() |
5e3fe3a4dc | ||
![]() |
55518011e3 | ||
![]() |
6ec3423405 | ||
![]() |
510d92e01b | ||
![]() |
b6bb0cd5b8 | ||
![]() |
80c461bddd | ||
![]() |
05a191a014 | ||
![]() |
a0ba9afcba | ||
![]() |
aacb36bf15 | ||
![]() |
a00f810093 | ||
![]() |
6f85053b03 | ||
![]() |
3624fe90b2 | ||
![]() |
6508a0c267 | ||
![]() |
153144022f | ||
![]() |
ca3d32e5ac | ||
![]() |
62ace58204 | ||
![]() |
7f8518d938 | ||
![]() |
442142a47a | ||
![]() |
398b2ab569 | ||
![]() |
235a575267 | ||
![]() |
b033b915a6 | ||
![]() |
89c71bc8ac | ||
![]() |
80705e9bbb | ||
![]() |
051bdb12b3 | ||
![]() |
729757d55e | ||
![]() |
fdc2769259 | ||
![]() |
71192dc7a3 | ||
![]() |
b0a78de78f | ||
![]() |
62b8baa959 | ||
![]() |
fddacb3dc1 | ||
![]() |
7557d33dc6 | ||
![]() |
6455b5dd26 | ||
![]() |
9bcefe46a8 | ||
![]() |
23f2877dde | ||
![]() |
20b7f760d9 | ||
![]() |
b36e8a3013 | ||
![]() |
c52906e8bc | ||
![]() |
38eb1f05ff | ||
![]() |
95ace0fade | ||
![]() |
b3c33bd0ab | ||
![]() |
d7e450b7b6 | ||
![]() |
35eeaa7cc5 | ||
![]() |
3f4c8d15d9 | ||
![]() |
0ce72e1a31 | ||
![]() |
ad5f6fccaa | ||
![]() |
e4fcd3740d | ||
![]() |
4111cc25d6 | ||
![]() |
656bfdb819 | ||
![]() |
d337ab93e6 | ||
![]() |
11a90aff83 | ||
![]() |
f008d7c4d8 | ||
![]() |
6eb5f2a77e | ||
![]() |
1f115ddd32 | ||
![]() |
26798038fe | ||
![]() |
7ad9914e51 | ||
![]() |
d5b5f7e4b2 | ||
![]() |
4396a646a7 | ||
![]() |
26f23e3121 | ||
![]() |
18ad718e53 | ||
![]() |
12911a7470 | ||
![]() |
ff14547601 | ||
![]() |
39b6584274 | ||
![]() |
132a98a91d | ||
![]() |
2f509734df | ||
![]() |
cdd7bb676f | ||
![]() |
1dcc2f777d | ||
![]() |
5d0aa77861 | ||
![]() |
26fcf349ad | ||
![]() |
14050f991b | ||
![]() |
1809e18c7b | ||
![]() |
ebbaf8c08d | ||
![]() |
8f0731edc9 | ||
![]() |
088c822e28 | ||
![]() |
e94479ccd5 | ||
![]() |
4b4f4a7da1 | ||
![]() |
0c4e0d4312 | ||
![]() |
0ed964247e | ||
![]() |
03b6fb3ddb | ||
![]() |
19fec70aa3 | ||
![]() |
61021a22ee | ||
![]() |
825d646196 | ||
![]() |
16bcc51ffb | ||
![]() |
2275ff78e2 | ||
![]() |
c65762b5c2 | ||
![]() |
32e818204e | ||
![]() |
06b675b345 | ||
![]() |
78dabb7b8f | ||
![]() |
57693bcb7f | ||
![]() |
dd9426606a | ||
![]() |
52b02f7377 | ||
![]() |
3608c3eb02 | ||
![]() |
b5125aac31 | ||
![]() |
ba3801e010 | ||
![]() |
eb70e95079 | ||
![]() |
1226fad4f6 | ||
![]() |
a8a88d4813 | ||
![]() |
a93f49eb04 | ||
![]() |
69fe654f02 | ||
![]() |
9e8f8b7b45 | ||
![]() |
d2bf44ba45 | ||
![]() |
48b0025732 | ||
![]() |
2edc77836d | ||
![]() |
a38ee0786a | ||
![]() |
f328130c0a | ||
![]() |
582410629b | ||
![]() |
49ae495344 | ||
![]() |
235e0d28e9 | ||
![]() |
803c57d052 | ||
![]() |
5d5ea57e21 | ||
![]() |
aac36ecf3f | ||
![]() |
bfa3e047ce | ||
![]() |
2829a7d70a | ||
![]() |
6a1212a1e1 | ||
![]() |
f50d4c1ed1 | ||
![]() |
0cf5006e3b | ||
![]() |
f80b871dd5 | ||
![]() |
d661d117af | ||
![]() |
2d45d57b32 | ||
![]() |
9b5e5f124c | ||
![]() |
c8cb063656 | ||
![]() |
b9ed39bc1c | ||
![]() |
4c7e805f18 | ||
![]() |
985c688bf6 | ||
![]() |
7845b66512 | ||
![]() |
06eaffc57c | ||
![]() |
cc45f5ec48 | ||
![]() |
ba4d7b1e9a | ||
![]() |
dc2dac1f9e | ||
![]() |
6079326633 | ||
![]() |
b22eebac30 | ||
![]() |
a46afc6ff8 | ||
![]() |
8d8c244e00 | ||
![]() |
174848b4b3 | ||
![]() |
f89b959b5f | ||
![]() |
5cea801a2f | ||
![]() |
d210a5aded | ||
![]() |
3338227ef7 | ||
![]() |
7c4f44c783 | ||
![]() |
eaf2bc8bdd | ||
![]() |
b8ab3116b2 | ||
![]() |
8424dc79d2 | ||
![]() |
0004cd54db | ||
![]() |
2e5c799566 | ||
![]() |
76fea8268c | ||
![]() |
64f7306b24 | ||
![]() |
4af8964069 | ||
![]() |
bd628ce591 | ||
![]() |
a80d63b268 | ||
![]() |
b101f0092c | ||
![]() |
d6cbe4b7f8 | ||
![]() |
be1f700b0b | ||
![]() |
923458a2c9 | ||
![]() |
d5299f144f | ||
![]() |
2712cbf6e4 | ||
![]() |
3ea3a931ca | ||
![]() |
6e0311efca | ||
![]() |
78926b31db | ||
![]() |
ccb573298c | ||
![]() |
bc18d18a95 | ||
![]() |
16ffd02a9d | ||
![]() |
bc3d9f3108 | ||
![]() |
b5d30c7387 | ||
![]() |
aa8359c73e | ||
![]() |
0eb53d59d8 | ||
![]() |
df99b4ff6c | ||
![]() |
603b60da8d | ||
![]() |
519011533a | ||
![]() |
d1afd6c0f1 | ||
![]() |
e260ac33ab | ||
![]() |
a342b96bb0 | ||
![]() |
150a482b77 | ||
![]() |
cd3b76e3f7 | ||
![]() |
3a61bb4119 | ||
![]() |
e6a8d0f4fc | ||
![]() |
db25c5c889 | ||
![]() |
2e68962a02 | ||
![]() |
91454515f4 | ||
![]() |
c62a947a28 | ||
![]() |
f07d9a1835 | ||
![]() |
b0791a01c9 | ||
![]() |
7638146782 | ||
![]() |
719f89806a | ||
![]() |
6ee3daf06a | ||
![]() |
ec53ae0c3b | ||
![]() |
c61d490bd4 | ||
![]() |
378ca60a2f | ||
![]() |
c8406b71fe | ||
![]() |
d4642d918c | ||
![]() |
1aa9cda77a | ||
![]() |
9013b2de50 | ||
![]() |
79cb2f9e20 | ||
![]() |
8a69bd0735 | ||
![]() |
6930ab3acd | ||
![]() |
a84ded4793 | ||
![]() |
ac17c36bec | ||
![]() |
4ffa47d897 | ||
![]() |
010b2e5ecf | ||
![]() |
445d32497d | ||
![]() |
bd082132ce | ||
![]() |
c2dbaa2b11 | ||
![]() |
613d84fb72 | ||
![]() |
a7acda95f0 | ||
![]() |
0d1ea9e6ed | ||
![]() |
1602774d27 | ||
![]() |
41709dac8f | ||
![]() |
3826a31ad3 | ||
![]() |
124c0fc812 | ||
![]() |
c44b034fc3 | ||
![]() |
a16d184956 | ||
![]() |
f0f9070adb | ||
![]() |
9572f6f032 | ||
![]() |
c702e15a3f | ||
![]() |
78f67ae5bc | ||
![]() |
f4e6bbd383 | ||
![]() |
9000c41c4b | ||
![]() |
136ab81cbd | ||
![]() |
a920ffcf70 | ||
![]() |
415c097df8 | ||
![]() |
376cedd558 | ||
![]() |
a3a641f449 | ||
![]() |
d58e85f297 | ||
![]() |
e5da8be4f8 | ||
![]() |
9e272810d8 | ||
![]() |
7ca3ba3835 | ||
![]() |
79aad0988a | ||
![]() |
3983d4fe53 | ||
![]() |
a72f898ff4 | ||
![]() |
0a8c411692 | ||
![]() |
f423055390 | ||
![]() |
1f1bae3e23 | ||
![]() |
60a6e8b070 | ||
![]() |
9a61ad9234 | ||
![]() |
8b6be09809 | ||
![]() |
f1349e114f | ||
![]() |
e0539f0ed7 | ||
![]() |
0f4166fedb | ||
![]() |
a00b997cf1 | ||
![]() |
1aa797b820 | ||
![]() |
ccf4367209 | ||
![]() |
19160f10ae | ||
![]() |
05167fcb8b | ||
![]() |
5c93d71c2a | ||
![]() |
ae8966040b | ||
![]() |
b9b16eaa53 | ||
![]() |
47da562600 | ||
![]() |
b653e39991 | ||
![]() |
c60fb94b6c | ||
![]() |
a20d21bd13 | ||
![]() |
f7354d092d | ||
![]() |
66722096ed | ||
![]() |
77c82b0fbf | ||
![]() |
06ce27ed38 | ||
![]() |
37f0886cb9 | ||
![]() |
1b54fa2a1c | ||
![]() |
0285d47138 | ||
![]() |
ce2335bc00 | ||
![]() |
dfea954754 | ||
![]() |
ad502bf64b | ||
![]() |
6969782a4b | ||
![]() |
5667113f8a | ||
![]() |
ecddac7b18 | ||
![]() |
664cec54b9 | ||
![]() |
09e388f453 | ||
![]() |
1ebfe67daf | ||
![]() |
3364a3b674 | ||
![]() |
86396c41d6 | ||
![]() |
cc1d78a3d4 | ||
![]() |
7e64c326e0 | ||
![]() |
9914f56137 | ||
![]() |
e1ba379fb7 | ||
![]() |
5d915a550b | ||
![]() |
3172a38dae | ||
![]() |
6d85de43ee | ||
![]() |
6f56ad298c | ||
![]() |
0641ff47d9 | ||
![]() |
b4337d99fd | ||
![]() |
6122f172e3 | ||
![]() |
63f2acd42a | ||
![]() |
f11225360b | ||
![]() |
590b9050ff | ||
![]() |
b502499a1e | ||
![]() |
b950f5cb6d | ||
![]() |
b7992ec772 | ||
![]() |
8d063d38b1 | ||
![]() |
eac864ebdc | ||
![]() |
aeece7d278 | ||
![]() |
bd0af4052c | ||
![]() |
2da7caf657 | ||
![]() |
de1bee9352 | ||
![]() |
490dddf636 | ||
![]() |
db696af2fe | ||
![]() |
997af6d720 | ||
![]() |
8c4e3e91cc | ||
![]() |
48f9daf867 | ||
![]() |
447b5b905c | ||
![]() |
e900494394 | ||
![]() |
ae67c98f11 | ||
![]() |
4ecbf6c6e9 | ||
![]() |
d75c45c63f | ||
![]() |
7c7a4f0959 | ||
![]() |
aafe1a176c | ||
![]() |
41936fefac | ||
![]() |
1aa693732c | ||
![]() |
769a1f263a | ||
![]() |
27966f101f | ||
![]() |
a494982646 | ||
![]() |
15413de359 | ||
![]() |
f0d4e4fbc3 | ||
![]() |
20cfafa109 | ||
![]() |
a35c80cc10 | ||
![]() |
b8f9f2daa2 | ||
![]() |
19cade3b3b | ||
![]() |
d76a6093ae | ||
![]() |
61b3e2e1ff | ||
![]() |
895aa01e39 | ||
![]() |
d3ba259db2 | ||
![]() |
9067d954f4 | ||
![]() |
92a58a2631 | ||
![]() |
57681e69ce | ||
![]() |
49f178ed94 | ||
![]() |
e42e22575f | ||
![]() |
efb58711b0 | ||
![]() |
d5ec421d98 | ||
![]() |
03074cdbc2 | ||
![]() |
c4e47ba1a8 | ||
![]() |
fcf2bf6a95 | ||
![]() |
85e8570a73 | ||
![]() |
2ed68a21db | ||
![]() |
219310b203 | ||
![]() |
336124b879 | ||
![]() |
e96ec9a102 | ||
![]() |
601b32948b | ||
![]() |
5850cb6336 | ||
![]() |
b9e76d1bcd | ||
![]() |
84c5b578d4 | ||
![]() |
6f6b502f7a | ||
![]() |
bd81dcc8f9 | ||
![]() |
5a9ddc0675 | ||
![]() |
12b38bab6d | ||
![]() |
3ed53153ca | ||
![]() |
be8d3fd74d | ||
![]() |
374ac6d162 | ||
![]() |
07c8506372 | ||
![]() |
69b4461f55 | ||
![]() |
b234828125 | ||
![]() |
bb923c7732 | ||
![]() |
774d3944b3 | ||
![]() |
7703cf61d0 | ||
![]() |
5e9236f9d4 | ||
![]() |
051228c49a | ||
![]() |
49cc4ca30b | ||
![]() |
8e9d0a6e09 | ||
![]() |
29654c52be | ||
![]() |
14d53dfec8 | ||
![]() |
d8244bb62d | ||
![]() |
2635bab2f1 | ||
![]() |
c278a29a38 | ||
![]() |
c9fd41c529 | ||
![]() |
237391c1b8 | ||
![]() |
43861c0ee2 | ||
![]() |
74783c0c09 | ||
![]() |
c898587b87 | ||
![]() |
e3b9c971f9 | ||
![]() |
2df9d3537b | ||
![]() |
53ddbbaa85 | ||
![]() |
e327050bd1 | ||
![]() |
81b48b414b | ||
![]() |
ad00f3fdeb | ||
![]() |
1cc71c7846 | ||
![]() |
6ed625be8e | ||
![]() |
badef293eb | ||
![]() |
e9ce55bfd0 | ||
![]() |
25d7e3ae8b | ||
![]() |
b852df3260 | ||
![]() |
4736acb3d5 | ||
![]() |
e0f55e6d69 | ||
![]() |
c0fd0374ad | ||
![]() |
851007b4a1 | ||
![]() |
883f274802 | ||
![]() |
233ea62c13 | ||
![]() |
4a2aa6deb4 | ||
![]() |
9f53bd4278 | ||
![]() |
2a3d0c1d29 | ||
![]() |
20e595e211 | ||
![]() |
8c0dbdb218 | ||
![]() |
1911a9523c | ||
![]() |
3e688a3ac9 | ||
![]() |
9be65cd67c | ||
![]() |
da65afc83b | ||
![]() |
78474a5dec | ||
![]() |
34b7cdb533 | ||
![]() |
33e031a284 | ||
![]() |
af6735bdf4 | ||
![]() |
df7e26c1aa | ||
![]() |
5ff701d45e | ||
![]() |
191be632e2 | ||
![]() |
1af997a074 | ||
![]() |
626eccdb89 | ||
![]() |
81e970867d | ||
![]() |
aee35768f4 | ||
![]() |
285325ad5b | ||
![]() |
2c8062bdb3 | ||
![]() |
b5d6fc8ed7 | ||
![]() |
c93a3f35ac | ||
![]() |
2c6ca4836f | ||
![]() |
cc9f99a80c | ||
![]() |
0a70b9c992 | ||
![]() |
d8bea3ccfc | ||
![]() |
9b3e687eda | ||
![]() |
86699b42f6 | ||
![]() |
434a9737bb | ||
![]() |
0b4f1e2b51 | ||
![]() |
fbb02e2860 | ||
![]() |
33ca747b1f | ||
![]() |
3894a36ddb | ||
![]() |
440d7e394e | ||
![]() |
ad49b7c78d | ||
![]() |
4666ea7051 | ||
![]() |
4812f9707a | ||
![]() |
75c45dbef1 | ||
![]() |
347ba3afb3 | ||
![]() |
6a32aca4ac | ||
![]() |
61d1db16be | ||
![]() |
76683a1e3c | ||
![]() |
9ef0bc3d3a | ||
![]() |
25c47e5b7e | ||
![]() |
30fd86ce69 | ||
![]() |
02e6d2dbca | ||
![]() |
f3ee0d51a9 | ||
![]() |
bdea5a1f6f | ||
![]() |
a9228095ee | ||
![]() |
05c41ae224 | ||
![]() |
e90f5b72f7 | ||
![]() |
6047112753 | ||
![]() |
5c30093360 | ||
![]() |
74c99f9195 | ||
![]() |
dad0ef4ab7 | ||
![]() |
cd97ef6536 | ||
![]() |
230de1e68a | ||
![]() |
e5bfff6e9f | ||
![]() |
4b72f02255 | ||
![]() |
5ef5c33e9e | ||
![]() |
69625564ca | ||
![]() |
d13a4f4c7a | ||
![]() |
0675b98437 | ||
![]() |
1152c9f2f8 | ||
![]() |
eb5d3b3197 | ||
![]() |
5007cd3603 | ||
![]() |
84399caebe | ||
![]() |
a78719ecc1 | ||
![]() |
d446a29987 | ||
![]() |
604260a0d7 | ||
![]() |
368299d143 | ||
![]() |
7ba1466333 | ||
![]() |
6fceac95c0 | ||
![]() |
3042f9e792 | ||
![]() |
370e98a248 | ||
![]() |
c306ef12bc | ||
![]() |
676e56e5d4 | ||
![]() |
22e4081c73 | ||
![]() |
e069b3bc6a | ||
![]() |
e51e82d6a9 | ||
![]() |
1301feb4ad | ||
![]() |
18f71ace8c | ||
![]() |
fbeef2b8c2 | ||
![]() |
27d38de612 | ||
![]() |
91a0eb9367 | ||
![]() |
b5fc788153 | ||
![]() |
58a1b473b8 | ||
![]() |
2ab08a872d | ||
![]() |
ae7c2261be | ||
![]() |
3d24583b91 | ||
![]() |
e88bd34c02 | ||
![]() |
089ca8258e | ||
![]() |
045ce3f148 | ||
![]() |
3266c51d85 | ||
![]() |
69a4e3e544 | ||
![]() |
d65c629fb0 | ||
![]() |
59874188a6 | ||
![]() |
c272d28e57 | ||
![]() |
fdeb86809f | ||
![]() |
5b6961edd0 | ||
![]() |
4dbf1c1ca4 | ||
![]() |
e6b7879542 | ||
![]() |
643b697178 | ||
![]() |
fa1ef15e47 | ||
![]() |
b53a921e42 | ||
![]() |
de63b5b09a | ||
![]() |
2c43ac992f | ||
![]() |
d2e193f257 | ||
![]() |
500fa6f442 | ||
![]() |
5a76b3cb4d | ||
![]() |
62a3e09385 | ||
![]() |
ddb084e9a8 | ||
![]() |
56d5507333 | ||
![]() |
4a3847765c | ||
![]() |
f670de7b52 | ||
![]() |
9b2d6c5a67 | ||
![]() |
673faea230 | ||
![]() |
53ce8f3736 | ||
![]() |
f80f56d69f | ||
![]() |
cc603a612b | ||
![]() |
a306860144 | ||
![]() |
4451a562ef | ||
![]() |
a120577773 | ||
![]() |
064b6d808e | ||
![]() |
78ce9971ff | ||
![]() |
4d75792257 | ||
![]() |
be3788fa30 | ||
![]() |
365a871908 | ||
![]() |
d2ac6dffbc | ||
![]() |
d04cfd5f0f | ||
![]() |
120ed0c42d | ||
![]() |
762125d3cf | ||
![]() |
a946ed0206 | ||
![]() |
a120ae1fa7 | ||
![]() |
256134d615 | ||
![]() |
73a7406211 | ||
![]() |
fdf26e698f | ||
![]() |
f36188f2e1 | ||
![]() |
8720d79f21 | ||
![]() |
90b0e90bbe | ||
![]() |
a933f82845 | ||
![]() |
0dafcc44ff | ||
![]() |
c76e1be397 | ||
![]() |
cb362c2256 | ||
![]() |
fc5b34254f | ||
![]() |
80dd442412 | ||
![]() |
61597e14a7 | ||
![]() |
78905c3ecf | ||
![]() |
1c8d4d6460 | ||
![]() |
35feb7ebba | ||
![]() |
21fc372a9d | ||
![]() |
3c8af04ca5 | ||
![]() |
ecf3027a4d | ||
![]() |
62fcf944f9 | ||
![]() |
df061b1a9c | ||
![]() |
e0ab7bf6c1 | ||
![]() |
fd2d4a8f99 | ||
![]() |
41accf84ce | ||
![]() |
238da79e52 | ||
![]() |
5bc97c94ae | ||
![]() |
086bcf0615 | ||
![]() |
d97f93ee88 | ||
![]() |
f5cc959c4e | ||
![]() |
b3edf81f6c | ||
![]() |
b7207b0885 | ||
![]() |
deb14762aa | ||
![]() |
2a27085ecb | ||
![]() |
19911ae3a7 | ||
![]() |
1615b0a500 | ||
![]() |
ce030a474c | ||
![]() |
74b4f69728 | ||
![]() |
0e8a2999bd | ||
![]() |
06d58e6eed | ||
![]() |
d51c559ab8 | ||
![]() |
80a14592a0 | ||
![]() |
e9f3946d58 | ||
![]() |
f52fd6a272 | ||
![]() |
013f3e0b39 | ||
![]() |
840aee7e0e | ||
![]() |
a0f1522167 | ||
![]() |
8d330f1dc7 | ||
![]() |
3b99db294f | ||
![]() |
d90de7f696 | ||
![]() |
6bd1ab41b7 | ||
![]() |
f88c119461 | ||
![]() |
60833abd3b | ||
![]() |
c71a20e805 | ||
![]() |
bfd61411e7 | ||
![]() |
206bb07506 | ||
![]() |
4e1f2d7deb | ||
![]() |
15c10796bd | ||
![]() |
dd2c5942a4 | ||
![]() |
349cbdf9da | ||
![]() |
0a0c9393c1 | ||
![]() |
9963f76583 | ||
![]() |
603f44e947 | ||
![]() |
e546cd00de | ||
![]() |
8ad74edd66 | ||
![]() |
95217e7dd2 | ||
![]() |
bfe9cd548a | ||
![]() |
520aec3ef4 | ||
![]() |
4c8a8003d3 | ||
![]() |
b749ef5f56 | ||
![]() |
74e7beb5e1 | ||
![]() |
c72ea15472 | ||
![]() |
4f17a1711a | ||
![]() |
f5f7ef6864 | ||
![]() |
9c32e2d852 | ||
![]() |
fe31fba623 | ||
![]() |
4d97e29999 | ||
![]() |
211b6b6b06 | ||
![]() |
5ae9eeba18 | ||
![]() |
a3ba83fce3 | ||
![]() |
7550b60069 | ||
![]() |
bd137a8b50 | ||
![]() |
1db3a87c62 | ||
![]() |
76f5874ffc | ||
![]() |
8b3e6711bc | ||
![]() |
ddc368f0dd | ||
![]() |
1ed692aca9 | ||
![]() |
9018782eaa | ||
![]() |
a9df3b425f | ||
![]() |
6deff56e83 | ||
![]() |
c6dc1f535a | ||
![]() |
d8571b6c00 | ||
![]() |
12adbb81b1 | ||
![]() |
99ae5ef38e | ||
![]() |
19afb07370 | ||
![]() |
d89afc2aa6 | ||
![]() |
9d8d3bdbc4 | ||
![]() |
0b0baf3446 | ||
![]() |
535b2490c4 | ||
![]() |
ea489f6d93 | ||
![]() |
9782a46a9b | ||
![]() |
d44b6acaa9 | ||
![]() |
718ee441a0 | ||
![]() |
ab6990f908 | ||
![]() |
502fcff765 | ||
![]() |
439ae9609b | ||
![]() |
2de1ecfabe | ||
![]() |
44def159cc | ||
![]() |
b12119d8e8 | ||
![]() |
94acf7a797 | ||
![]() |
3cd459912a | ||
![]() |
fdcfe8cd81 | ||
![]() |
d9a71083e1 | ||
![]() |
24f13ec942 | ||
![]() |
a886904540 | ||
![]() |
8c97cbe341 | ||
![]() |
b2e9ce46f1 | ||
![]() |
562d02196c | ||
![]() |
41c07126ec | ||
![]() |
f395ad3e27 | ||
![]() |
fed682ee5f | ||
![]() |
4d90850676 | ||
![]() |
53e94653f3 | ||
![]() |
035452d938 | ||
![]() |
80e2f8a791 | ||
![]() |
e926cddca2 | ||
![]() |
4730a4f339 | ||
![]() |
287a860283 | ||
![]() |
d17b5faf76 | ||
![]() |
f119f56e63 | ||
![]() |
8ffd30cb2d | ||
![]() |
ef9eee6b15 | ||
![]() |
6948d41616 | ||
![]() |
7c82a04df5 | ||
![]() |
1e4f706ace | ||
![]() |
67bd349e8f | ||
![]() |
95845b47b5 | ||
![]() |
258b46125f | ||
![]() |
544d6073bc | ||
![]() |
675a96fc5a | ||
![]() |
46fc902bcf | ||
![]() |
9368671ca9 | ||
![]() |
d4a14a0d04 | ||
![]() |
d08fb255a2 | ||
![]() |
d6fdd6c7ce | ||
![]() |
e4701f2da1 | ||
![]() |
fd6366f027 | ||
![]() |
01b51fb715 | ||
![]() |
e82d49e13a | ||
![]() |
0c40bed425 | ||
![]() |
e0950408d5 | ||
![]() |
2df931f7db | ||
![]() |
85cf6562b6 | ||
![]() |
f3899696a7 | ||
![]() |
23a5e91858 | ||
![]() |
78bf5796db | ||
![]() |
0e83db47a0 | ||
![]() |
7f8e467acd | ||
![]() |
b85fe12234 | ||
![]() |
6fc41692d6 | ||
![]() |
0367719eea | ||
![]() |
e15f0db408 | ||
![]() |
86393c8c8e | ||
![]() |
42166f2e3e | ||
![]() |
de311e052f | ||
![]() |
e4196f32d3 | ||
![]() |
897a2fccb6 | ||
![]() |
6ae9b47155 | ||
![]() |
df67783dd3 | ||
![]() |
e6006805ce | ||
![]() |
b88e86f366 | ||
![]() |
b37d133c43 | ||
![]() |
f207068ee2 | ||
![]() |
42522c492c | ||
![]() |
2a856db72c | ||
![]() |
64f6b8bc67 | ||
![]() |
4d54b62e63 | ||
![]() |
f7be385230 | ||
![]() |
e7db15d6a4 | ||
![]() |
a66cd0200b | ||
![]() |
b0a4f1b86e | ||
![]() |
200c57f475 | ||
![]() |
dd63764331 | ||
![]() |
3f959c7421 | ||
![]() |
0c1ee5fad1 | ||
![]() |
5482b9a0c6 | ||
![]() |
ef1fbfc651 | ||
![]() |
8466985bc7 | ||
![]() |
b5a31d2e4e | ||
![]() |
42f48b6dc0 | ||
![]() |
d2007a386c | ||
![]() |
4ac00af6fa | ||
![]() |
0991003de9 | ||
![]() |
504199e70e | ||
![]() |
39a7381928 | ||
![]() |
efd3252d08 | ||
![]() |
5686fdcf1c | ||
![]() |
d0acb1b239 | ||
![]() |
ce92cdf8e4 | ||
![]() |
14c676ab49 | ||
![]() |
eb6817c259 | ||
![]() |
0b36616940 | ||
![]() |
b4602ae5bf | ||
![]() |
c74f0d3239 | ||
![]() |
6be26fbde7 | ||
![]() |
ef3be26a69 | ||
![]() |
bbb1ea26b6 | ||
![]() |
0e3b25468c | ||
![]() |
f61fa73b77 | ||
![]() |
5212e38512 | ||
![]() |
580a45485a | ||
![]() |
8fc16a57c9 | ||
![]() |
8733cce5fa | ||
![]() |
0e838c3cea | ||
![]() |
391248e031 | ||
![]() |
86a91ccf1b | ||
![]() |
1a5bb7b8ab | ||
![]() |
ef08c4a91d | ||
![]() |
8f722a0d35 | ||
![]() |
08bbe173ce | ||
![]() |
41eecd7ce2 | ||
![]() |
f3be638ea9 | ||
![]() |
ffd97945ba | ||
![]() |
c6aa51a2de | ||
![]() |
916ae180ac | ||
![]() |
811f5b4d18 | ||
![]() |
ccf2bb123c | ||
![]() |
c95aa86a8e | ||
![]() |
857961a6bb | ||
![]() |
0336f55b16 | ||
![]() |
044c9ba2d4 | ||
![]() |
d52516756c | ||
![]() |
2c4599612c | ||
![]() |
7edfcc3bfa | ||
![]() |
084e15f9cf | ||
![]() |
9190bda27d | ||
![]() |
034467ff61 | ||
![]() |
7abfeb11c3 | ||
![]() |
3de0be7c06 | ||
![]() |
d9668df818 | ||
![]() |
24b7084feb | ||
![]() |
f03abe14d1 | ||
![]() |
8604b03008 | ||
![]() |
96a5885051 | ||
![]() |
a63e7b3db8 | ||
![]() |
c89c14b6bf | ||
![]() |
eecc6147df | ||
![]() |
76070a7647 | ||
![]() |
8531658019 | ||
![]() |
d290766101 | ||
![]() |
478456e6e9 | ||
![]() |
7b62c7fa50 | ||
![]() |
b64642fc99 | ||
![]() |
fbd291deaf | ||
![]() |
dc0819b01a | ||
![]() |
6829e4c197 | ||
![]() |
881fd97c5a | ||
![]() |
d613626ab9 | ||
![]() |
5d8b27710d | ||
![]() |
5f018df4e4 | ||
![]() |
fd7734f000 | ||
![]() |
c696e88573 | ||
![]() |
bf542f07b0 | ||
![]() |
027d54e771 | ||
![]() |
5b2db015a9 | ||
![]() |
81c549549d | ||
![]() |
c0bb2fb76a | ||
![]() |
3d0facf119 | ||
![]() |
96263058c3 | ||
![]() |
31abefc8e4 | ||
![]() |
6fe071ad1d | ||
![]() |
f64d06fa02 | ||
![]() |
6edc11de4d | ||
![]() |
baa68fa4c1 | ||
![]() |
1aae331ddc | ||
![]() |
5c5982c50a | ||
![]() |
8a9fb81036 | ||
![]() |
888a2462af | ||
![]() |
9443267717 | ||
![]() |
a65f0e57b9 | ||
![]() |
fe38e70dc1 | ||
![]() |
55c663f7ac | ||
![]() |
344cfe6216 | ||
![]() |
41d09f7187 | ||
![]() |
e625876949 | ||
![]() |
45c33e9dcf | ||
![]() |
ec239c8c35 | ||
![]() |
b1f25d4b33 | ||
![]() |
74ffe2c543 | ||
![]() |
f17643bc08 | ||
![]() |
86bc708299 | ||
![]() |
ddff2e2e5e | ||
![]() |
79ab283890 | ||
![]() |
8b4e880827 | ||
![]() |
006a40a353 | ||
![]() |
dd7cfccbae | ||
![]() |
523ffbaa37 | ||
![]() |
2124da44d8 | ||
![]() |
cfbd1dfa4d | ||
![]() |
152c41c3ac | ||
![]() |
b3882f8324 | ||
![]() |
ef18590043 | ||
![]() |
91b998bb11 | ||
![]() |
5c6b8a5f04 | ||
![]() |
6c23fe202c | ||
![]() |
2476f116bb | ||
![]() |
78c965141f | ||
![]() |
7115dd3393 | ||
![]() |
65a4bce9ad | ||
![]() |
980a7013d2 | ||
![]() |
454617f0cb | ||
![]() |
721e760f1a | ||
![]() |
c73d4cf6dd | ||
![]() |
0344fdcf8d | ||
![]() |
0f9a88b2cd | ||
![]() |
889c295baf | ||
![]() |
167867ff7c | ||
![]() |
3d528adfdc | ||
![]() |
84fc2877c6 | ||
![]() |
ded32f3390 | ||
![]() |
9df05c4f98 | ||
![]() |
b77119e1a3 | ||
![]() |
f9054190fd | ||
![]() |
3e8f08895b | ||
![]() |
f42ad6b90c | ||
![]() |
f4bfc2af5b | ||
![]() |
377f56c151 | ||
![]() |
ee65e6f32d | ||
![]() |
c1d35c1bce | ||
![]() |
c401ca3d1e | ||
![]() |
1941d1aa81 | ||
![]() |
2ffb081442 | ||
![]() |
f9d3b99e63 | ||
![]() |
1c7efdc02c | ||
![]() |
aa1784c5d9 | ||
![]() |
b65dbd5c9e | ||
![]() |
af520f0f92 | ||
![]() |
64b45848d7 | ||
![]() |
d72c10cb6c | ||
![]() |
e8191dc061 | ||
![]() |
490ca794c5 | ||
![]() |
104536b7aa | ||
![]() |
7278d3c0ed | ||
![]() |
3cc58b3918 | ||
![]() |
ba502e6e9f | ||
![]() |
e9d5b75d1d | ||
![]() |
13c037cc08 | ||
![]() |
5e18bb1735 | ||
![]() |
8fa3088057 | ||
![]() |
875004d300 | ||
![]() |
d946cfd265 | ||
![]() |
4e85203a13 | ||
![]() |
bcc5158eab | ||
![]() |
6fbc9e8159 | ||
![]() |
47f24a7024 | ||
![]() |
a3d8b4f9d1 | ||
![]() |
dcbb322447 | ||
![]() |
897e2c2fdc | ||
![]() |
eca1a4cee4 | ||
![]() |
b8a68f5f35 | ||
![]() |
ecc19c2c08 | ||
![]() |
f4fed62c05 | ||
![]() |
dfe0ce599a | ||
![]() |
43b8dde923 | ||
![]() |
579b98c596 | ||
![]() |
ff72454f83 | ||
![]() |
76ef768864 | ||
![]() |
589ca8ded5 | ||
![]() |
cbedf52342 | ||
![]() |
2bef7b5f7b | ||
![]() |
e5c8214f2c | ||
![]() |
665ab09d20 | ||
![]() |
315a5733d2 | ||
![]() |
0426ba4e87 | ||
![]() |
24ae205f20 | ||
![]() |
473723b24a | ||
![]() |
bf67845df6 | ||
![]() |
eb2265a2bf | ||
![]() |
e2b838a10a | ||
![]() |
ba69b35501 | ||
![]() |
e19d44ee20 | ||
![]() |
ff48ad83be | ||
![]() |
bae83857a3 | ||
![]() |
64f5b1d031 | ||
![]() |
a146dbdb03 | ||
![]() |
2759480cb5 | ||
![]() |
237b27e50b | ||
![]() |
012b60c9ca | ||
![]() |
81818fd38c | ||
![]() |
54b8364cea | ||
![]() |
9dce00a4e7 | ||
![]() |
6e22a9ea97 | ||
![]() |
1595c07260 | ||
![]() |
84359f39c5 | ||
![]() |
5a41d2070c | ||
![]() |
179ae683cc | ||
![]() |
b81ba2d6c2 | ||
![]() |
47b4e42b1c | ||
![]() |
3eeb2b20eb | ||
![]() |
9d7f90dd89 | ||
![]() |
6cef569155 | ||
![]() |
3bb94192d5 | ||
![]() |
b1e1492dac | ||
![]() |
f318898474 | ||
![]() |
7fbfd98b8a | ||
![]() |
34677d3883 | ||
![]() |
9221acc9e2 | ||
![]() |
4d32c4f2fc | ||
![]() |
511e46c40f | ||
![]() |
e1aaf715c6 | ||
![]() |
87ebada258 | ||
![]() |
8bc9732d49 | ||
![]() |
757a10c247 | ||
![]() |
dce847b2f3 | ||
![]() |
b29fa1d24c | ||
![]() |
66b3a192f8 | ||
![]() |
b2f45b1aab | ||
![]() |
bd525d3548 | ||
![]() |
8c7fa8e6c9 | ||
![]() |
6ad329c540 | ||
![]() |
e688ee0e89 | ||
![]() |
3313d5267a | ||
![]() |
09a867310b | ||
![]() |
3d1bb4f1b2 | ||
![]() |
2f2fde7e6c | ||
![]() |
d39e67da7e | ||
![]() |
7574eab2b6 | ||
![]() |
18e05ec852 | ||
![]() |
bacba274a2 | ||
![]() |
d1f635242d | ||
![]() |
dea4c6f53f | ||
![]() |
27eb3be7da | ||
![]() |
ad5e5f80ca | ||
![]() |
a581526528 | ||
![]() |
386b5b901c | ||
![]() |
c5d983066d | ||
![]() |
2612853238 | ||
![]() |
5d191f8297 | ||
![]() |
96f16c8635 | ||
![]() |
595b354184 | ||
![]() |
3fc5396063 | ||
![]() |
1b729d90d0 | ||
![]() |
d38ff14264 | ||
![]() |
e5e2f7bc62 | ||
![]() |
879ac39e53 | ||
![]() |
2938682295 | ||
![]() |
9eb0bc482e | ||
![]() |
a6ea72fd84 | ||
![]() |
fbdcfa9c42 | ||
![]() |
1cd22b81da | ||
![]() |
9bd7ef5f5f | ||
![]() |
24af19b58d | ||
![]() |
431c4cec9f | ||
![]() |
86ce6abf6a | ||
![]() |
c671961c18 | ||
![]() |
b1d3eb07c3 | ||
![]() |
8677d59b92 | ||
![]() |
5d1b8bf744 | ||
![]() |
af0bffbae9 | ||
![]() |
c3cb9aa3f6 | ||
![]() |
9901a5fafc | ||
![]() |
7e57196cf9 | ||
![]() |
0533818cee | ||
![]() |
9f2cbe1762 | ||
![]() |
170d6cffdd | ||
![]() |
fcdf1e0bfd | ||
![]() |
189164e7c8 | ||
![]() |
b8f58d558c | ||
![]() |
6ffbb9ed87 | ||
![]() |
1b5767928d | ||
![]() |
428b56570d | ||
![]() |
21d594a150 | ||
![]() |
8c468acff8 | ||
![]() |
fd93697a2d | ||
![]() |
ced31aa917 | ||
![]() |
ee60e9c71c | ||
![]() |
ea45971dcc | ||
![]() |
7e3bb72049 | ||
![]() |
e9fdbf618c | ||
![]() |
7a1a95a2d6 | ||
![]() |
744e91dda8 | ||
![]() |
b3b79122e1 | ||
![]() |
466de95312 | ||
![]() |
45618faf36 | ||
![]() |
beff2b912c | ||
![]() |
432b9d8bde | ||
![]() |
51949d95c3 | ||
![]() |
9a1cad85fe | ||
![]() |
9b3fb00908 | ||
![]() |
b8c8200683 | ||
![]() |
3144e83950 | ||
![]() |
65c611da02 | ||
![]() |
62613cb266 | ||
![]() |
ae8a910339 | ||
![]() |
c322cda3f8 | ||
![]() |
0d6be6f474 | ||
![]() |
c6fa1a179a | ||
![]() |
1bf202adcd | ||
![]() |
c82df9e40d | ||
![]() |
14863bc04e | ||
![]() |
6a3eacddd6 | ||
![]() |
e1717bd771 | ||
![]() |
b62dcc4bcc | ||
![]() |
ed17091e6a | ||
![]() |
f5c2547952 | ||
![]() |
4bdf4582f0 | ||
![]() |
3dd8986322 | ||
![]() |
49caad0b7b | ||
![]() |
0461cc8c3a | ||
![]() |
5225550b5b | ||
![]() |
dcb09ec8de | ||
![]() |
ecf24201ec | ||
![]() |
d718ccaa78 | ||
![]() |
d3a6cf3ae7 | ||
![]() |
b6c608e038 | ||
![]() |
d4c688297c | ||
![]() |
9538954cc6 | ||
![]() |
b7bf7c11a8 | ||
![]() |
0abe425675 | ||
![]() |
3fd1ee7757 | ||
![]() |
d1548ed317 | ||
![]() |
95698827b8 | ||
![]() |
0e6955a08d | ||
![]() |
18459a9e4c | ||
![]() |
872b3aa63d | ||
![]() |
6fbefb8f13 | ||
![]() |
1631cdffb8 | ||
![]() |
d4aac6586c | ||
![]() |
d14db5c98f | ||
![]() |
8f5185c381 | ||
![]() |
ea9e12b6ae | ||
![]() |
dfc9c3df8c | ||
![]() |
b26088f940 | ||
![]() |
b0f57d234f | ||
![]() |
4e346ecfba | ||
![]() |
2912860c97 | ||
![]() |
06e54f08e6 | ||
![]() |
423da76ff2 | ||
![]() |
ece10c3e04 | ||
![]() |
5cd2a7f9c2 | ||
![]() |
dc6453b720 | ||
![]() |
2fdf41ac01 | ||
![]() |
fc15105643 | ||
![]() |
5b35329abb | ||
![]() |
b5731cee02 | ||
![]() |
9cc09207fc | ||
![]() |
7acef00443 | ||
![]() |
93e34b8754 | ||
![]() |
581682a08e | ||
![]() |
157cc1b60c | ||
![]() |
883ece6034 | ||
![]() |
2cb2985539 | ||
![]() |
31eda82b3f | ||
![]() |
8501098c16 | ||
![]() |
ae2f7551c1 | ||
![]() |
c43ad2fab6 | ||
![]() |
3200026e1f | ||
![]() |
c2a6f6ce62 | ||
![]() |
8773c645ca | ||
![]() |
c11ad31393 | ||
![]() |
9b82ded77b | ||
![]() |
90aa1d3b7e | ||
![]() |
0d41fff3a7 | ||
![]() |
a519341112 | ||
![]() |
ff449ca997 | ||
![]() |
cf6833b9cd | ||
![]() |
8e0d8df791 | ||
![]() |
d399d3ae1b | ||
![]() |
4301e4705b | ||
![]() |
bb6079133c | ||
![]() |
3a85088d66 | ||
![]() |
009d3b64b6 | ||
![]() |
366f8782cb | ||
![]() |
ec98fee1ee | ||
![]() |
3678eff5dc | ||
![]() |
edecc06fcf | ||
![]() |
8675945b26 | ||
![]() |
4dc45ffdc8 | ||
![]() |
7e47af1085 | ||
![]() |
9259763599 | ||
![]() |
a003aae7c2 | ||
![]() |
ecfaae7f9e | ||
![]() |
b6b8959397 | ||
![]() |
3cb5e81d50 | ||
![]() |
7a9082e698 | ||
![]() |
8863b962fd | ||
![]() |
99298d0aba | ||
![]() |
7ae3f636ef | ||
![]() |
a6a92f6b6b | ||
![]() |
0b1e089547 | ||
![]() |
df339f4f3c | ||
![]() |
d2579282a6 | ||
![]() |
692d7dc26d | ||
![]() |
4419c36db5 | ||
![]() |
d0bc033ab8 | ||
![]() |
b5ba3ee9ee | ||
![]() |
0e9a1abc7e | ||
![]() |
0f425aff5a | ||
![]() |
f33d02dca9 | ||
![]() |
55c9d43c70 | ||
![]() |
c8dccd3e7b | ||
![]() |
cc4f2b4516 | ||
![]() |
bbe1881293 | ||
![]() |
91ca5f110b | ||
![]() |
5dda3a14ff | ||
![]() |
77bc2f9130 | ||
![]() |
5e96740451 | ||
![]() |
22fb2c1548 | ||
![]() |
7b1df27c1a | ||
![]() |
c388cebf7f | ||
![]() |
f233bee970 | ||
![]() |
c4cb86efe9 | ||
![]() |
9f28fa4e75 | ||
![]() |
1a774a0526 | ||
![]() |
b6d2a59fc2 | ||
![]() |
15e945aa1c | ||
![]() |
2956a0ca03 | ||
![]() |
4812092cdb | ||
![]() |
658dadaa70 | ||
![]() |
336d31cbcf | ||
![]() |
3cc50a5744 | ||
![]() |
323da87dec | ||
![]() |
2300d81c3c | ||
![]() |
8c85e648df | ||
![]() |
720f64ea60 | ||
![]() |
0dd93035e4 | ||
![]() |
b7bf2c706f | ||
![]() |
831b94cdac | ||
![]() |
ae71206e1f | ||
![]() |
8a50b02b9b | ||
![]() |
af1fba9f52 | ||
![]() |
4d8dcab1d3 | ||
![]() |
79400756f5 | ||
![]() |
8d1eb0a195 | ||
![]() |
9ef412c2cc | ||
![]() |
a3ed97c0db | ||
![]() |
e8d36bf5bd | ||
![]() |
f6ae068cb2 | ||
![]() |
32f2ec86c4 | ||
![]() |
0f4014615c | ||
![]() |
06bcde6243 | ||
![]() |
4cd74bba2c | ||
![]() |
e7d81913a4 | ||
![]() |
53ed6979a9 | ||
![]() |
694f9ec3a5 | ||
![]() |
db12a83ced | ||
![]() |
68ca923bfe | ||
![]() |
22c6754bcd | ||
![]() |
2cd5bacca0 | ||
![]() |
f52b522964 | ||
![]() |
bac2a8ba02 | ||
![]() |
aa8b12db6f | ||
![]() |
bc3fe7d014 | ||
![]() |
76c6e1248c | ||
![]() |
d5021e7ed5 | ||
![]() |
f4dc67879e | ||
![]() |
a3dd5b33bc | ||
![]() |
b8678e778e | ||
![]() |
965ba00e0f | ||
![]() |
5feea4497f | ||
![]() |
01a95faf21 | ||
![]() |
f6583f7ecc | ||
![]() |
c1e668f823 | ||
![]() |
f9e9fadbc8 | ||
![]() |
83544cdf6a | ||
![]() |
c68dfb09c4 | ||
![]() |
f63a9a48a4 | ||
![]() |
f52b5b39ed | ||
![]() |
3f3cabea2d | ||
![]() |
0b62e540a3 | ||
![]() |
bd2da27e4e | ||
![]() |
e5cc03965e | ||
![]() |
490fdb0a1c | ||
![]() |
77ffdd7fd4 | ||
![]() |
6a08b0d733 | ||
![]() |
d77d0ff34a | ||
![]() |
701587241f | ||
![]() |
e1cd98ba15 | ||
![]() |
bf5f0fc58f | ||
![]() |
351ca3b5ea | ||
![]() |
a8e35062c6 | ||
![]() |
3cf4a33666 | ||
![]() |
3c71911c26 | ||
![]() |
fe4608386e | ||
![]() |
035b797ec2 | ||
![]() |
a342ae56e0 | ||
![]() |
bffaad477a | ||
![]() |
bdf13ddcfb | ||
![]() |
cc367d7e67 | ||
![]() |
7168cf8657 | ||
![]() |
7f0c23dff3 | ||
![]() |
979e7b8709 | ||
![]() |
d1f44fe91a | ||
![]() |
326b34887c | ||
![]() |
0f17e80eef | ||
![]() |
08c7f97b1e | ||
![]() |
91064c7ec8 | ||
![]() |
e1534e1dec | ||
![]() |
da88d3d825 | ||
![]() |
55fa8b7745 | ||
![]() |
f0e30abf62 | ||
![]() |
8a4bf3a780 | ||
![]() |
98d1c5a411 | ||
![]() |
1ff2023f32 | ||
![]() |
5f6aaa2475 | ||
![]() |
ebc2527368 | ||
![]() |
bbf5a7d461 | ||
![]() |
e681e0f14c | ||
![]() |
296e6d10c2 | ||
![]() |
541376f8cc | ||
![]() |
16e7bba87b | ||
![]() |
0528ceead1 | ||
![]() |
9c8d1bd6e3 | ||
![]() |
534e69fbff | ||
![]() |
7a546b1554 | ||
![]() |
d0772ce1e3 | ||
![]() |
fac6a6c068 | ||
![]() |
1aab019f1e | ||
![]() |
685cc23b94 | ||
![]() |
fba71bd182 | ||
![]() |
6e38e236f8 | ||
![]() |
27fbee5233 | ||
![]() |
392156c250 | ||
![]() |
0afa0da19f | ||
![]() |
99a2262d61 | ||
![]() |
6ff02248a3 | ||
![]() |
354d497a57 | ||
![]() |
6689bfe923 | ||
![]() |
77a5a60a66 | ||
![]() |
7878561970 | ||
![]() |
71b92cb813 | ||
![]() |
78748a67be | ||
![]() |
cfa449c3f3 | ||
![]() |
9cbfd0b967 | ||
![]() |
c65ba121e0 | ||
![]() |
396af7470b | ||
![]() |
b64f45a8ba | ||
![]() |
89928a0e6b | ||
![]() |
49fae99063 | ||
![]() |
a0af4d8768 | ||
![]() |
c64a910151 | ||
![]() |
de107da5b3 | ||
![]() |
23413a4d12 | ||
![]() |
17183fff05 | ||
![]() |
ab8dfcfba4 | ||
![]() |
e2cdaa653c | ||
![]() |
e0a4af09ed | ||
![]() |
6d193ffd8b | ||
![]() |
4026082470 | ||
![]() |
3650294e51 | ||
![]() |
19ae97afd1 | ||
![]() |
5de1978632 | ||
![]() |
a30043c8da | ||
![]() |
184665652e | ||
![]() |
5574455d2a | ||
![]() |
2fc353d559 | ||
![]() |
cd8297f54d | ||
![]() |
5c6e231412 | ||
![]() |
46b38f8a40 | ||
![]() |
3ccb164f2a | ||
![]() |
15459cae91 | ||
![]() |
cf554f9338 | ||
![]() |
3e5a23ed5b | ||
![]() |
761d9d9229 | ||
![]() |
40df4f4f65 | ||
![]() |
0758f68020 | ||
![]() |
423a10bc31 | ||
![]() |
bf458cbc5a | ||
![]() |
85af066d4f | ||
![]() |
162793aa87 | ||
![]() |
72b7a2e107 | ||
![]() |
20f0ba9526 | ||
![]() |
3b45174375 | ||
![]() |
c0a7cff304 | ||
![]() |
6672f17d0a | ||
![]() |
e571c707b5 | ||
![]() |
130c5cc768 | ||
![]() |
8ab36b4a05 | ||
![]() |
7922b3bfc4 | ||
![]() |
8376db94a7 | ||
![]() |
5dcb59b13d | ||
![]() |
c21e23b3eb | ||
![]() |
e138a6c56d | ||
![]() |
4766e889c0 | ||
![]() |
532954847a | ||
![]() |
b4a97efe4d | ||
![]() |
cbff1e1371 | ||
![]() |
456688a49d | ||
![]() |
7ecfd98b2d | ||
![]() |
8ef5411f70 | ||
![]() |
b3dcc9d507 | ||
![]() |
5833c90210 | ||
![]() |
8f668f06ca | ||
![]() |
558a753d3d | ||
![]() |
9e0ca72827 | ||
![]() |
f9bd692f75 | ||
![]() |
cc687b3b72 | ||
![]() |
5a7f83c705 | ||
![]() |
7c1544f4d8 | ||
![]() |
6f1c835221 | ||
![]() |
c385321248 | ||
![]() |
a7421399f7 | ||
![]() |
f6dc2dd198 | ||
![]() |
782747cc0c | ||
![]() |
e189666a2d | ||
![]() |
a8c55728e2 | ||
![]() |
18113ff43d | ||
![]() |
09535a95ca | ||
![]() |
cb957795a3 | ||
![]() |
d83259828e | ||
![]() |
399c24c805 | ||
![]() |
6b4bd0993f | ||
![]() |
da1ecf0813 | ||
![]() |
a77ceec5cf | ||
![]() |
26a187e5eb | ||
![]() |
bb4fa7af5b | ||
![]() |
a74d1a8b32 | ||
![]() |
c7c13cd95f | ||
![]() |
815b57b9e1 | ||
![]() |
1be70320b9 | ||
![]() |
2c7ee44046 | ||
![]() |
6b04fd1524 | ||
![]() |
e60dda57f3 | ||
![]() |
664407089b | ||
![]() |
5e11e29ba2 | ||
![]() |
9fc02041fe | ||
![]() |
f0b2a91bda | ||
![]() |
a8a5153873 | ||
![]() |
a002ccfbc1 | ||
![]() |
065f46daeb | ||
![]() |
1b6cdce925 | ||
![]() |
f1ccc0e205 | ||
![]() |
033cc6731b | ||
![]() |
5312945757 | ||
![]() |
82ab3c1aad | ||
![]() |
8a860857ea | ||
![]() |
c96d0f225c | ||
![]() |
d987bd2997 | ||
![]() |
a0bd313139 | ||
![]() |
cede682585 | ||
![]() |
e28dedbbe3 | ||
![]() |
9c9a02628d | ||
![]() |
d3688982ac | ||
![]() |
6de733b38c | ||
![]() |
33eca9a3d2 | ||
![]() |
8f5133d811 | ||
![]() |
b539363cd0 | ||
![]() |
3f7618283d | ||
![]() |
32433db7ae | ||
![]() |
3dbd5b0932 | ||
![]() |
730e543ca6 | ||
![]() |
0b0faa2f1c | ||
![]() |
73c851d8e0 | ||
![]() |
74b5e846a5 | ||
![]() |
77bb3e73cd | ||
![]() |
2b54e87548 | ||
![]() |
a3a38b0536 | ||
![]() |
0aa472fb3a | ||
![]() |
b9eb443e54 | ||
![]() |
4948e8d914 | ||
![]() |
086bca18b8 | ||
![]() |
3ab300a28e | ||
![]() |
f18df5ed59 | ||
![]() |
da1b15d6f5 | ||
![]() |
8629d7b692 | ||
![]() |
07bc6bac53 | ||
![]() |
c9487293e9 | ||
![]() |
d0b822c036 | ||
![]() |
0250aaaddd | ||
![]() |
2c9d4ba9ae | ||
![]() |
0d00c10e2f | ||
![]() |
884e7d9a98 | ||
![]() |
d485dc6ef6 | ||
![]() |
5415194b39 | ||
![]() |
cf2db7a4c4 | ||
![]() |
56656b2b24 | ||
![]() |
695fb7e569 | ||
![]() |
75f33e0c55 | ||
![]() |
e1f72318e0 | ||
![]() |
447b3a060c | ||
![]() |
385917059b | ||
![]() |
722d1f2542 | ||
![]() |
861c12e6eb | ||
![]() |
0adde4aede | ||
![]() |
19a9554bda | ||
![]() |
9a9054188c | ||
![]() |
e4a6fd3571 | ||
![]() |
31ea8f8719 | ||
![]() |
9c37aef499 | ||
![]() |
8417470276 | ||
![]() |
0e63178fe1 | ||
![]() |
91ad064249 | ||
![]() |
a7917c9c63 | ||
![]() |
bbc683dd75 | ||
![]() |
138519d820 | ||
![]() |
8a94a3451f | ||
![]() |
5f748272fc | ||
![]() |
682de724a8 | ||
![]() |
3e6be4bbfd | ||
![]() |
094233a4ab | ||
![]() |
52b424c385 | ||
![]() |
dc07054ee8 | ||
![]() |
ec4a9685ab | ||
![]() |
6f6aaa4a97 | ||
![]() |
a3a3a91b72 | ||
![]() |
c5292e0db5 | ||
![]() |
3d287adbcf | ||
![]() |
b739513894 | ||
![]() |
dfedef5772 | ||
![]() |
e0b14ba98e | ||
![]() |
6ce2edc2f1 | ||
![]() |
4f042eac53 | ||
![]() |
5838662b2f | ||
![]() |
da6204442f | ||
![]() |
f2a240550e | ||
![]() |
42214b226f | ||
![]() |
3424badeff | ||
![]() |
5c30f95c42 | ||
![]() |
1cde40792f | ||
![]() |
ade94efbff | ||
![]() |
59efba2fc0 | ||
![]() |
88b7dfce58 | ||
![]() |
e5576448ea | ||
![]() |
512daf2c89 | ||
![]() |
9704f422dc | ||
![]() |
98214865be | ||
![]() |
78880e1fdf | ||
![]() |
539651609c | ||
![]() |
c38762f91f | ||
![]() |
81d6bc3614 | ||
![]() |
510969ab97 | ||
![]() |
c956cae824 | ||
![]() |
ad7bb51030 | ||
![]() |
5dfbe703ae | ||
![]() |
99e397000c | ||
![]() |
96293ab25e | ||
![]() |
73710416b4 | ||
![]() |
7c7d69e1d2 | ||
![]() |
7dafc64f78 | ||
![]() |
535723f414 | ||
![]() |
85bb108ba4 | ||
![]() |
e376f950fe | ||
![]() |
6bd3dba1e3 | ||
![]() |
f67d474edc | ||
![]() |
11db5a2f1d | ||
![]() |
1febb80a1e | ||
![]() |
bcf81f0e71 | ||
![]() |
2932dc3985 | ||
![]() |
f501ba0c77 | ||
![]() |
23edefa0b5 | ||
![]() |
0d444bfc6e | ||
![]() |
697c4fd08b | ||
![]() |
9deb9e6e85 | ||
![]() |
efca63862c | ||
![]() |
3e631fe2f4 | ||
![]() |
6575bfac3e | ||
![]() |
c7ef7e1902 | ||
![]() |
f5d2e245e1 | ||
![]() |
59c3db46ca | ||
![]() |
a8a27299ae | ||
![]() |
b4227f586c | ||
![]() |
297cd026b9 | ||
![]() |
ed8e3c83d9 | ||
![]() |
6d794abf49 | ||
![]() |
d4363b7ee5 | ||
![]() |
b866601b63 | ||
![]() |
ba5568d501 | ||
![]() |
cfa9a9daec | ||
![]() |
8f76af40db | ||
![]() |
8b4163b77c | ||
![]() |
a0ee42833b | ||
![]() |
9557047e5e | ||
![]() |
b0f9b7834e | ||
![]() |
450bfae86c | ||
![]() |
ca32e935a6 | ||
![]() |
f1ee2fde58 | ||
![]() |
9afa8a9bea | ||
![]() |
22c3c9c303 | ||
![]() |
58c90184f6 | ||
![]() |
d8fa9d7f36 | ||
![]() |
d4f66a73c1 | ||
![]() |
90ece77f8d | ||
![]() |
dc47c6d9ec | ||
![]() |
0b911e484c | ||
![]() |
149087b880 | ||
![]() |
78737ab01d | ||
![]() |
083f6afb1c | ||
![]() |
4a62c8c2eb | ||
![]() |
5c16c5024d | ||
![]() |
cd41c4001e | ||
![]() |
67dc19bb57 | ||
![]() |
5a89dc58e1 | ||
![]() |
1dd24f6461 | ||
![]() |
6e68e8f097 | ||
![]() |
561b519716 | ||
![]() |
c99fbde0eb | ||
![]() |
40d026e6fc | ||
![]() |
235a8e07e3 | ||
![]() |
155e0b9c42 | ||
![]() |
0865198a9e | ||
![]() |
f05d024666 | ||
![]() |
a09a62bc4a | ||
![]() |
9a79163eab | ||
![]() |
15bf9e4f74 | ||
![]() |
7cff69f945 | ||
![]() |
2a9584ea31 | ||
![]() |
6566a011b4 | ||
![]() |
b31b21fd51 | ||
![]() |
3ae96bff88 | ||
![]() |
d792bce0fb | ||
![]() |
9614d37229 | ||
![]() |
9388df19d3 | ||
![]() |
6d23461bcd | ||
![]() |
0dbe7f96a3 | ||
![]() |
ff92d19fed | ||
![]() |
90edf33c95 | ||
![]() |
9c5d13a630 | ||
![]() |
d1ef3ae1ba | ||
![]() |
a4369afae5 | ||
![]() |
da74a425d2 | ||
![]() |
01509ec7c9 | ||
![]() |
1deab29b05 | ||
![]() |
9089ee2d16 | ||
![]() |
9fe546f279 | ||
![]() |
11c80c048b | ||
![]() |
310f9f7b84 | ||
![]() |
8d9390fc46 | ||
![]() |
16394d3158 | ||
![]() |
0338368afa | ||
![]() |
d03d9d839b | ||
![]() |
71e210dd4b | ||
![]() |
878fcdd22d | ||
![]() |
b4160c228e | ||
![]() |
f3a7c691a3 | ||
![]() |
2285c8dbbd | ||
![]() |
efc98c517e | ||
![]() |
5cf2f8d1ea | ||
![]() |
7d0b134b48 | ||
![]() |
b8c823ef99 | ||
![]() |
15b2852b91 | ||
![]() |
94e8847d67 | ||
![]() |
5fc3e8e4d2 | ||
![]() |
6ecf7f86c8 | ||
![]() |
0d97904216 | ||
![]() |
b671d8f59d | ||
![]() |
a95d6678b1 | ||
![]() |
6a7fa4b402 | ||
![]() |
bf8a14252b | ||
![]() |
b8770915ad | ||
![]() |
a5472bc5c1 | ||
![]() |
b87ab0ee9d | ||
![]() |
75ee2fc4e6 | ||
![]() |
3fc5455ec5 | ||
![]() |
c10238de8c | ||
![]() |
e049d5f2fc | ||
![]() |
dc46d84c35 | ||
![]() |
2700687c00 | ||
![]() |
9b9628047c | ||
![]() |
61b07bc9a6 | ||
![]() |
e76cdab6dd | ||
![]() |
c6cdf30501 | ||
![]() |
60276e3447 | ||
![]() |
818faa78aa | ||
![]() |
3611f54902 | ||
![]() |
5e53a18292 | ||
![]() |
74c4fa6751 | ||
![]() |
a40829fef3 | ||
![]() |
84c55f8931 | ||
![]() |
c667c56bd9 | ||
![]() |
c967f8e434 | ||
![]() |
c8cb9895a3 | ||
![]() |
2c6caf4a9a | ||
![]() |
bdaa9f0eae | ||
![]() |
0a54ffdd44 | ||
![]() |
ca08add9c9 | ||
![]() |
588042dc99 | ||
![]() |
f923d32620 | ||
![]() |
92ef01830c | ||
![]() |
c73b4bec8f | ||
![]() |
940b7efa15 | ||
![]() |
270efdca85 | ||
![]() |
f937982754 | ||
![]() |
86e6a2225c | ||
![]() |
b666c85824 | ||
![]() |
5a291e4622 | ||
![]() |
868902fbdf | ||
![]() |
62dde576e0 | ||
![]() |
402819c64b | ||
![]() |
3503f4e907 | ||
![]() |
b6c91d1621 | ||
![]() |
8b5c0dc1e4 | ||
![]() |
2fe8bebc6c | ||
![]() |
567166aece | ||
![]() |
bb50b54d80 | ||
![]() |
ca73e14cf9 | ||
![]() |
f84850064f | ||
![]() |
df3c6dfe3e | ||
![]() |
76543d05e7 | ||
![]() |
e3b3201d53 | ||
![]() |
5cf7f01169 | ||
![]() |
f795527454 | ||
![]() |
edd719c5c5 | ||
![]() |
91d746cfc8 | ||
![]() |
fcde8e2d56 | ||
![]() |
54539b8519 | ||
![]() |
6b5277638b | ||
![]() |
160045a058 | ||
![]() |
d8e748bc58 | ||
![]() |
30c65931b2 | ||
![]() |
9203181625 | ||
![]() |
d9a19897c4 | ||
![]() |
094bf419d4 | ||
![]() |
90608f2c89 | ||
![]() |
c7ad3cece6 | ||
![]() |
a69c595802 | ||
![]() |
530d6ce9e9 | ||
![]() |
9b89a82573 | ||
![]() |
8c1f25cf31 | ||
![]() |
6457b4ca7b | ||
![]() |
fa9194e3e2 | ||
![]() |
963fd175ad | ||
![]() |
4e5ad7feac | ||
![]() |
629a06b0ae | ||
![]() |
f41b4045d4 | ||
![]() |
3d41656168 | ||
![]() |
0a59cbb8ce | ||
![]() |
e6c2887773 | ||
![]() |
c89d830e16 | ||
![]() |
00ff7c6cfe | ||
![]() |
5e90086d4f | ||
![]() |
f8dca82a71 | ||
![]() |
f749038959 | ||
![]() |
e8e6316f88 | ||
![]() |
27ecaf3e88 | ||
![]() |
4503608c7c | ||
![]() |
8d1678f0ef | ||
![]() |
70749b37d0 | ||
![]() |
1e4eb5ec39 | ||
![]() |
cbf99d5e53 | ||
![]() |
dfd6b6e39e | ||
![]() |
40441d83cd | ||
![]() |
c80144b7f0 | ||
![]() |
901bf2bb1e | ||
![]() |
9affda5626 | ||
![]() |
7645354917 | ||
![]() |
2df4d212c3 | ||
![]() |
da1e3c8612 | ||
![]() |
1bb509897c | ||
![]() |
0eb5c72cc5 | ||
![]() |
7f03f4d896 | ||
![]() |
d849e2f8b4 | ||
![]() |
af3af59df4 | ||
![]() |
10ad7d9cfe | ||
![]() |
df3866a800 | ||
![]() |
518ead2e2d | ||
![]() |
69b449c875 | ||
![]() |
12013b4c1f | ||
![]() |
e2de234ef1 | ||
![]() |
e203bd3a2b | ||
![]() |
0a1afe1f79 | ||
![]() |
2f822a3b79 | ||
![]() |
46536773f4 | ||
![]() |
acb4cf9ead | ||
![]() |
75040cdbdf | ||
![]() |
53d1c2c309 | ||
![]() |
682351df7f | ||
![]() |
e54aa836a4 | ||
![]() |
2b13b24cbe | ||
![]() |
a586bfc290 | ||
![]() |
84d5426242 | ||
![]() |
887d7c717b | ||
![]() |
46010f33ad | ||
![]() |
b5d46a0235 | ||
![]() |
a280f893d4 | ||
![]() |
f8f3ee06c7 | ||
![]() |
44f98c545b | ||
![]() |
140baf7037 | ||
![]() |
3c8a740374 | ||
![]() |
2fc75bae79 | ||
![]() |
ee4e30ce8b | ||
![]() |
1ff42e9936 | ||
![]() |
cef0e1db8f | ||
![]() |
689922bc21 | ||
![]() |
2c49f812d9 | ||
![]() |
eb15463406 | ||
![]() |
8e53b35fcc | ||
![]() |
871f3c66bc | ||
![]() |
b00595f3da | ||
![]() |
1e940323b0 | ||
![]() |
259659c838 | ||
![]() |
65a59e9dcc | ||
![]() |
ae1a486520 | ||
![]() |
35de36dd59 | ||
![]() |
c7f00b4760 | ||
![]() |
60c6510b3b | ||
![]() |
54e0ef9cf7 | ||
![]() |
1afa494e69 | ||
![]() |
839fbb3fe9 | ||
![]() |
70de8b3a03 | ||
![]() |
8955230712 | ||
![]() |
996b4100b9 | ||
![]() |
6514471a3b | ||
![]() |
da4ff1c40a | ||
![]() |
fe8a011629 | ||
![]() |
b015ee825c | ||
![]() |
93faa752f5 | ||
![]() |
15f35c19b8 | ||
![]() |
bb16fdb4bb | ||
![]() |
06555aa003 | ||
![]() |
b8d0e622fd | ||
![]() |
8686b6dada | ||
![]() |
319046fed7 | ||
![]() |
e15b339d41 | ||
![]() |
cf331ca2a7 | ||
![]() |
bdc95b8dc0 | ||
![]() |
76ffdbbbde | ||
![]() |
9916525418 | ||
![]() |
d5dde5df46 | ||
![]() |
b18ea204c2 | ||
![]() |
576baa994f | ||
![]() |
b5054f0d77 | ||
![]() |
c4244d967d | ||
![]() |
3c7c95ecce | ||
![]() |
b2438caec3 | ||
![]() |
9aff6aa55c | ||
![]() |
587bfab2a6 | ||
![]() |
84ce3ed43e | ||
![]() |
d927878024 | ||
![]() |
13c2e8ceba | ||
![]() |
26dfe6f23d | ||
![]() |
8f96417bcf | ||
![]() |
9e597e0dda | ||
![]() |
f7da7c26aa | ||
![]() |
b5e5f8d85f | ||
![]() |
48cd40773a | ||
![]() |
717bcfa19e | ||
![]() |
4512a9de19 | ||
![]() |
c30cadd19c | ||
![]() |
cba4753c22 | ||
![]() |
a8c110b045 | ||
![]() |
f6d436d58b | ||
![]() |
c8ecb8341c | ||
![]() |
e63270f918 | ||
![]() |
109aa63474 | ||
![]() |
be607c10a8 | ||
![]() |
fd5d95320b | ||
![]() |
b0dedf1a22 | ||
![]() |
b299c64973 | ||
![]() |
3611b7120c | ||
![]() |
e475490992 | ||
![]() |
e313d051a8 | ||
![]() |
fbe486df45 | ||
![]() |
1168d1ff90 | ||
![]() |
b39a2a5020 | ||
![]() |
fe398ab983 | ||
![]() |
bb6e6a15f1 | ||
![]() |
8a7c3c9802 | ||
![]() |
597f4a1495 | ||
![]() |
598ef014e6 | ||
![]() |
770bb40eb3 | ||
![]() |
8a90328ab7 | ||
![]() |
cca7d3aef7 | ||
![]() |
6bb457be69 | ||
![]() |
8f2b707d02 | ||
![]() |
444e535f00 | ||
![]() |
e6991ad5dc | ||
![]() |
70afb97f61 | ||
![]() |
44007eab6f | ||
![]() |
467d26d9e6 | ||
![]() |
5f241f6baa | ||
![]() |
00d702086a | ||
![]() |
9a621cf49c | ||
![]() |
19a4ddf2f0 | ||
![]() |
6016e54d6c | ||
![]() |
33067130e5 | ||
![]() |
3cafb16aa6 | ||
![]() |
2726f3af91 | ||
![]() |
451d56051b | ||
![]() |
1fae965cbb | ||
![]() |
32ddc94b4f | ||
![]() |
b45b375ff2 | ||
![]() |
6991a53d68 | ||
![]() |
3be76a837d | ||
![]() |
bb3dad7ce7 | ||
![]() |
137241cfef | ||
![]() |
4a2964c915 | ||
![]() |
18bb70afca | ||
![]() |
f6e30f22f4 | ||
![]() |
c0901fb972 | ||
![]() |
72786e249a | ||
![]() |
43ad5614bd | ||
![]() |
2c4ae853f2 | ||
![]() |
c7fbdc7877 | ||
![]() |
b24e0a609b | ||
![]() |
32e655d0af | ||
![]() |
929a1cc7e4 | ||
![]() |
7a95629aff | ||
![]() |
901ad4e917 | ||
![]() |
9eb6e549c5 | ||
![]() |
4f4aa53120 | ||
![]() |
89e0cc8078 | ||
![]() |
2873133479 | ||
![]() |
1df8ac805a | ||
![]() |
19a3095ecb | ||
![]() |
dc209f6344 | ||
![]() |
bf8d4c428e | ||
![]() |
1dc1164dce | ||
![]() |
23d19a254d | ||
![]() |
7decb6526b | ||
![]() |
1f061b5a97 | ||
![]() |
93dbb53371 | ||
![]() |
4c7aedcf4e | ||
![]() |
c9e7d1448e | ||
![]() |
3c078f6090 | ||
![]() |
43fd9e6779 | ||
![]() |
be50947fa6 | ||
![]() |
9b71bba747 | ||
![]() |
5e2b6bcef9 | ||
![]() |
f44498a530 | ||
![]() |
e7bb04769d | ||
![]() |
2d406f3e27 | ||
![]() |
ddf546c2cc | ||
![]() |
0fb7746c20 | ||
![]() |
f8cf206826 | ||
![]() |
34bc421626 | ||
![]() |
e6b85f1bc0 | ||
![]() |
163dee1e1a | ||
![]() |
3c60ea383d | ||
![]() |
2aaef61547 | ||
![]() |
2cebd40f2e | ||
![]() |
7b84ed94b5 | ||
![]() |
08f68518f2 | ||
![]() |
2692c6f6cc | ||
![]() |
5b660e3432 | ||
![]() |
e431d1a33f | ||
![]() |
0faf07aac8 | ||
![]() |
84327b634c | ||
![]() |
a1160068c8 | ||
![]() |
de6ddc470b | ||
![]() |
6e8082860e | ||
![]() |
0043ae0807 | ||
![]() |
6625284950 | ||
![]() |
a4fa953740 | ||
![]() |
5e763b1afc | ||
![]() |
5c6b2cbafe | ||
![]() |
25938500d6 | ||
![]() |
8f1683246e | ||
![]() |
5024fc0690 | ||
![]() |
fd099cef52 | ||
![]() |
5e40589114 | ||
![]() |
3573fcca80 | ||
![]() |
5cc8fe6c18 | ||
![]() |
93228f78d7 | ||
![]() |
de00c00aac | ||
![]() |
4458251765 | ||
![]() |
64d3e3e1e8 | ||
![]() |
96c14abd1f | ||
![]() |
3eff12a2a0 | ||
![]() |
bdea5d072d | ||
![]() |
a8111bba83 | ||
![]() |
ced336492c | ||
![]() |
396dfb7d5e | ||
![]() |
3aecb3b08c | ||
![]() |
fc591421f9 | ||
![]() |
e46b990251 | ||
![]() |
3257bdc8a1 | ||
![]() |
0bdf1e05f1 | ||
![]() |
c007463168 | ||
![]() |
e8933f8519 | ||
![]() |
571ad7d604 | ||
![]() |
ec1eea9990 | ||
![]() |
70ccab4765 | ||
![]() |
ef4a699b72 | ||
![]() |
31e9fffadd | ||
![]() |
f9a76c56f7 | ||
![]() |
f09dfb028a | ||
![]() |
8cc6a2fae5 | ||
![]() |
38efbf5dea | ||
![]() |
707289c8d6 | ||
![]() |
98e2f9ea81 | ||
![]() |
3d3b222e2a | ||
![]() |
bd68d6035c | ||
![]() |
a3ede0293a | ||
![]() |
4b54253c24 | ||
![]() |
a621e04062 | ||
![]() |
d20ce45c1b | ||
![]() |
564f40f6db | ||
![]() |
54b15ed201 | ||
![]() |
3b49c20f43 | ||
![]() |
bb73580209 | ||
![]() |
751f4556fd | ||
![]() |
7ac1735395 | ||
![]() |
af7be21591 | ||
![]() |
b4aaae2c5f | ||
![]() |
050cb6914f | ||
![]() |
5a26e0f0d3 | ||
![]() |
a957e90396 | ||
![]() |
c06827cd50 | ||
![]() |
4a9981ee77 | ||
![]() |
054be6fb67 | ||
![]() |
5fa10e1a95 | ||
![]() |
6566b5da73 | ||
![]() |
7e54d2c305 | ||
![]() |
34cc1bd41f | ||
![]() |
bb754441c8 | ||
![]() |
3e95c57317 | ||
![]() |
9aa22433ff | ||
![]() |
affb12cc27 | ||
![]() |
b6158f94f6 | ||
![]() |
e0b4f0ee63 | ||
![]() |
bb8af6ff8b | ||
![]() |
d570163116 | ||
![]() |
2c7d2f9e0c | ||
![]() |
9125698cb0 | ||
![]() |
1cb0e3af03 | ||
![]() |
7db1484c75 | ||
![]() |
d1f5cdcb93 | ||
![]() |
1ff060c5ad | ||
![]() |
7bda6f15a9 | ||
![]() |
ca73356187 | ||
![]() |
a3b74f009c | ||
![]() |
2c938e0e8b | ||
![]() |
1b560ae44c | ||
![]() |
c95b140dec | ||
![]() |
1ceffbe0bc | ||
![]() |
b4d029a55c | ||
![]() |
a1c902dadc | ||
![]() |
2248e07b66 | ||
![]() |
a8206ed170 | ||
![]() |
ce144addb3 | ||
![]() |
7123209324 | ||
![]() |
25f57a1e38 | ||
![]() |
ad1cc12df1 | ||
![]() |
5e1aac67db | ||
![]() |
f82e133c7c | ||
![]() |
d2c77fd9ae | ||
![]() |
c27e7780d1 | ||
![]() |
3b043432f5 | ||
![]() |
2de98386a7 | ||
![]() |
7ac43e5f00 | ||
![]() |
72367e6cfd | ||
![]() |
900fe98f0d | ||
![]() |
3b6d9c952a | ||
![]() |
a1c703729c | ||
![]() |
37543ad003 | ||
![]() |
17256c680a | ||
![]() |
3d739b5916 | ||
![]() |
50b120528a | ||
![]() |
bbc9c9b0ba | ||
![]() |
59c554b50a | ||
![]() |
363d664f27 | ||
![]() |
ffd679cd36 | ||
![]() |
3b28ba2f76 | ||
![]() |
39b75244da | ||
![]() |
72f4721167 | ||
![]() |
c21db8a0c1 | ||
![]() |
010e7ba8cb | ||
![]() |
a8351b265f | ||
![]() |
abdaa9c8a1 | ||
![]() |
385380401a | ||
![]() |
fa217a50a5 | ||
![]() |
599236bbc6 | ||
![]() |
a4ab9b19d7 | ||
![]() |
54ca2e9b9c | ||
![]() |
d5f6661bfb | ||
![]() |
1c686101fc | ||
![]() |
0ca07e5a6b | ||
![]() |
37d5775694 | ||
![]() |
dbb771dfe4 | ||
![]() |
a0ac9d62f2 | ||
![]() |
51c0642ee0 | ||
![]() |
aed93a9390 | ||
![]() |
d5f50070d7 | ||
![]() |
f81bd6b1fc | ||
![]() |
531b739180 | ||
![]() |
a0091eb44b | ||
![]() |
24e3f8417e | ||
![]() |
85f4452b0a | ||
![]() |
ab7078d574 | ||
![]() |
9185c85a54 | ||
![]() |
f1dbb0c4f2 | ||
![]() |
3b5e64e8c6 | ||
![]() |
4754ab3894 | ||
![]() |
7c81d4e630 | ||
![]() |
9dc8e1e35d | ||
![]() |
4ff19c8260 | ||
![]() |
84fec7e82f | ||
![]() |
714769e1b8 | ||
![]() |
d281e18113 | ||
![]() |
38e3b6338c | ||
![]() |
b67ba18590 | ||
![]() |
54c1bc1538 | ||
![]() |
44cbc5121b | ||
![]() |
f513d5fff4 | ||
![]() |
eba6ea53f8 | ||
![]() |
92a2109f0c | ||
![]() |
4cdf002557 | ||
![]() |
b6a7b607fd | ||
![]() |
56918e5596 | ||
![]() |
0bf8fa23d9 | ||
![]() |
659c4fad56 | ||
![]() |
3f439c1ef2 | ||
![]() |
abfe31d5d2 | ||
![]() |
247e18cf02 | ||
![]() |
fb5480cde3 | ||
![]() |
59f4755e8f | ||
![]() |
6cca93543b | ||
![]() |
6ebe2fd034 | ||
![]() |
796d648995 | ||
![]() |
50f87a6024 | ||
![]() |
0d43aff268 | ||
![]() |
4e0ca50db1 | ||
![]() |
5774b13984 | ||
![]() |
0ea7f153a1 | ||
![]() |
fe40094216 | ||
![]() |
b100087024 | ||
![]() |
9f6031cda1 | ||
![]() |
6bf3c261fa | ||
![]() |
035bfb0fe5 | ||
![]() |
14b18cb6fa | ||
![]() |
28279b18fe | ||
![]() |
c9a0033c5c | ||
![]() |
3e21f894f4 | ||
![]() |
9e6770af90 | ||
![]() |
eb14cf09f4 | ||
![]() |
a26b1a276d | ||
![]() |
98f93f39be | ||
![]() |
bed053251e | ||
![]() |
21b4965966 | ||
![]() |
77cbd70a72 | ||
![]() |
240561c370 | ||
![]() |
25867e3f23 | ||
![]() |
6aaa9f5a3d | ||
![]() |
fffc3b8447 | ||
![]() |
fa7317f594 | ||
![]() |
b6e2159cec | ||
![]() |
cea27dc84a | ||
![]() |
346998caed | ||
![]() |
98cc243b5f | ||
![]() |
d399346de0 | ||
![]() |
a05954249a | ||
![]() |
c26c5e7b8e | ||
![]() |
e4210e7fd3 | ||
![]() |
16e28f002e | ||
![]() |
b271e59472 | ||
![]() |
d5174110fa | ||
![]() |
f2b8e347a9 | ||
![]() |
2872b500e3 | ||
![]() |
bbc05f3113 | ||
![]() |
3d42097e9d | ||
![]() |
fa55a826b2 | ||
![]() |
436260e47e | ||
![]() |
fb27f1a031 | ||
![]() |
cce27e72f0 | ||
![]() |
abf9bc3bb9 | ||
![]() |
d42ecc081e | ||
![]() |
7e7e20742d | ||
![]() |
601360b73a | ||
![]() |
e118e418e5 | ||
![]() |
ebbfb6375d | ||
![]() |
19eb16045f | ||
![]() |
6d005f38b5 | ||
![]() |
2a5f0bbd28 | ||
![]() |
c0585e98eb | ||
![]() |
16f6aaa68c | ||
![]() |
dd7f7a53bd | ||
![]() |
992c9acd56 | ||
![]() |
dd73a7ff9f | ||
![]() |
7fd856b866 | ||
![]() |
275805d78f | ||
![]() |
401bee6111 | ||
![]() |
76d2a3f0db | ||
![]() |
b764f9b13a | ||
![]() |
349be76d26 | ||
![]() |
f0887427da | ||
![]() |
7220f456ef | ||
![]() |
a28786097d | ||
![]() |
b8636902e3 | ||
![]() |
5897a6a963 | ||
![]() |
be37a39ecb | ||
![]() |
f57c2bcebb | ||
![]() |
89e15d488a | ||
![]() |
0c77eed07d | ||
![]() |
0392cd3a5b | ||
![]() |
1c1c096861 | ||
![]() |
ff30bc87fe | ||
![]() |
befc994806 | ||
![]() |
29d4192f6f | ||
![]() |
2f56b98959 | ||
![]() |
6562edc98e | ||
![]() |
2b3dda7535 | ||
![]() |
2957eb7cc9 | ||
![]() |
b4e9f5c3a6 | ||
![]() |
2f7c7ccf80 | ||
![]() |
b7079d159b | ||
![]() |
1e4feed383 | ||
![]() |
4916eb9bb1 | ||
![]() |
98fe4438f1 | ||
![]() |
523ed4cfb2 | ||
![]() |
defafcf5fe | ||
![]() |
ff9d6b4f89 | ||
![]() |
75f403db60 | ||
![]() |
aee2e01983 | ||
![]() |
08cf545d9b | ||
![]() |
6a7d1fe53d | ||
![]() |
67e216f8fb | ||
![]() |
c3d4117a21 | ||
![]() |
f28186bb1b | ||
![]() |
36c0ff2dbc | ||
![]() |
9a848d9d76 | ||
![]() |
0a8e9b0fbd | ||
![]() |
d08e2ade88 | ||
![]() |
e270fcd1db | ||
![]() |
ea05c48032 | ||
![]() |
da8b5758cd | ||
![]() |
2827731210 | ||
![]() |
2898d8182d | ||
![]() |
0cbc25f74a | ||
![]() |
522bbbc1f2 | ||
![]() |
6e349db55b | ||
![]() |
afea345cc7 | ||
![]() |
74f2c4a73b | ||
![]() |
43c7b4fa21 | ||
![]() |
9a9265f4d2 | ||
![]() |
f6d74cb7a9 | ||
![]() |
6a335411da | ||
![]() |
a4848f6902 | ||
![]() |
5dd1e5e51e | ||
![]() |
7c362f292c | ||
![]() |
caf7abdb8d | ||
![]() |
21c09c8b8f | ||
![]() |
58b7cb920f | ||
![]() |
5cf0ed5ede | ||
![]() |
bac8335222 | ||
![]() |
475fcd4425 | ||
![]() |
371d33146f | ||
![]() |
36c07a0f45 | ||
![]() |
49760a9ea8 | ||
![]() |
ae1e7837bb | ||
![]() |
f2b9cc6d23 | ||
![]() |
8343488bdf | ||
![]() |
5b99382002 | ||
![]() |
d1feb2aa2d | ||
![]() |
b582ba810c | ||
![]() |
0d2ae5cc9d | ||
![]() |
847910d986 | ||
![]() |
e9ae0cf7ce | ||
![]() |
eaf760768b | ||
![]() |
e69bb4c077 | ||
![]() |
3b01d2fbce | ||
![]() |
399a137a77 | ||
![]() |
8c79044d43 | ||
![]() |
4cbdc388b8 | ||
![]() |
28d0313ccc | ||
![]() |
966d0dec19 | ||
![]() |
74da9cc424 | ||
![]() |
4b79050ef4 | ||
![]() |
a59faa8df0 | ||
![]() |
07a8022a1f | ||
![]() |
a11cc8791b | ||
![]() |
3da7af9f02 | ||
![]() |
0b4ced96ec | ||
![]() |
3e117ce792 | ||
![]() |
49b12a828a | ||
![]() |
1ae64d7bf5 | ||
![]() |
d1dc2c3a5f | ||
![]() |
f7a6d4dc06 | ||
![]() |
eafc0e4e9e | ||
![]() |
bfbb6dbf69 | ||
![]() |
4775930e49 | ||
![]() |
c0484a317d | ||
![]() |
a22f86f861 | ||
![]() |
cf5cbd1153 | ||
![]() |
872e296f7b | ||
![]() |
0db8995e81 | ||
![]() |
c365dd1cab | ||
![]() |
8c0610e84f | ||
![]() |
ee769420e3 | ||
![]() |
8f86ccc412 | ||
![]() |
58db38c746 | ||
![]() |
f2fd1bf80a | ||
![]() |
c6401413a4 | ||
![]() |
a14555c8d1 | ||
![]() |
21847a55e0 | ||
![]() |
9b83e67460 | ||
![]() |
cc8eaf7206 | ||
![]() |
e9cced57bf | ||
![]() |
cba36239a4 | ||
![]() |
a00d6c75aa | ||
![]() |
2c59ce9df5 | ||
![]() |
d04e5954a6 | ||
![]() |
cb8d90bcbf | ||
![]() |
137d9d33c1 | ||
![]() |
72244066bb | ||
![]() |
cfe86dfd15 | ||
![]() |
7cd1e04951 | ||
![]() |
30e3c8469b | ||
![]() |
395db49b21 | ||
![]() |
fac998ddcb | ||
![]() |
cb71b488ec | ||
![]() |
f8b3c13a53 | ||
![]() |
8351ae275e | ||
![]() |
f8719a5717 | ||
![]() |
6bb098b476 | ||
![]() |
7cda79f9b7 | ||
![]() |
96130efc34 | ||
![]() |
062091e9e4 | ||
![]() |
5cd2b55f1f | ||
![]() |
d5e4986e1b | ||
![]() |
c2299c8972 | ||
![]() |
2f9b04fd56 | ||
![]() |
3d9ce8836c | ||
![]() |
dd40c41ffc | ||
![]() |
bc6b47efe0 | ||
![]() |
3975424ff5 | ||
![]() |
95540763b9 | ||
![]() |
9e8976996e | ||
![]() |
2ace9b5ad3 | ||
![]() |
927077e03b | ||
![]() |
0d0056a043 | ||
![]() |
f98960b936 | ||
![]() |
c0f02563e8 | ||
![]() |
de5d22fbd8 | ||
![]() |
4d8fa13033 | ||
![]() |
c0b7379e86 | ||
![]() |
04be9a71f9 | ||
![]() |
cce5cb65c1 | ||
![]() |
9f9920f92b | ||
![]() |
c06d7390b6 | ||
![]() |
78f86ce67a | ||
![]() |
ccd9ca2a30 | ||
![]() |
a26c9bb6d9 | ||
![]() |
a947f09bfb | ||
![]() |
c192ba261d | ||
![]() |
2d66f8e6c9 | ||
![]() |
a6a4349bd6 | ||
![]() |
ace5ad09f8 | ||
![]() |
8b63de9e55 | ||
![]() |
aa7e20357f | ||
![]() |
0b5c0bd94e | ||
![]() |
ac0d0fc241 | ||
![]() |
541451dc62 | ||
![]() |
6e932f5a2d | ||
![]() |
3f26cf5076 | ||
![]() |
82ce89e315 | ||
![]() |
c70f87e4c5 | ||
![]() |
67488f780c | ||
![]() |
c9969c1593 | ||
![]() |
dc565b11c7 | ||
![]() |
f0abbc71b5 | ||
![]() |
eed85cda83 | ||
![]() |
e0a114fcb3 | ||
![]() |
bb0b6e85ce | ||
![]() |
fba7c2caef | ||
![]() |
b8455f20e2 | ||
![]() |
e55946bec7 | ||
![]() |
661237eb64 | ||
![]() |
90364fc3fa | ||
![]() |
eaef3b600e | ||
![]() |
8eef6ac55e | ||
![]() |
7126dacccd | ||
![]() |
c9ba81ab50 | ||
![]() |
7b5b5524c4 | ||
![]() |
ebcdfc1ae8 | ||
![]() |
ec48f8f464 | ||
![]() |
1839a3a770 | ||
![]() |
1ecf271cb3 | ||
![]() |
1727662f10 | ||
![]() |
ba050c21b9 | ||
![]() |
d297a96dc1 | ||
![]() |
2da41a66c7 | ||
![]() |
19cb4ca554 | ||
![]() |
bd694bda19 | ||
![]() |
8f2813279c | ||
![]() |
e27dc41a76 | ||
![]() |
831c7f2ef1 | ||
![]() |
ff958830d1 | ||
![]() |
c57137e17d | ||
![]() |
6f38731009 | ||
![]() |
4f87bb5f99 | ||
![]() |
e78ed11421 | ||
![]() |
1b3c8ea9c1 | ||
![]() |
640285755e | ||
![]() |
be47fc3e9a | ||
![]() |
ec47ce2320 | ||
![]() |
76ff791913 | ||
![]() |
138d7308dc | ||
![]() |
fa77a5ae4a | ||
![]() |
678cffb9c7 | ||
![]() |
560e3899d8 | ||
![]() |
e5c21afc7c | ||
![]() |
bc1450a5cd | ||
![]() |
5cb9735735 | ||
![]() |
9affcf82d9 | ||
![]() |
0c3093fe49 | ||
![]() |
df8688c227 | ||
![]() |
87ecd49295 | ||
![]() |
7ae64b9477 | ||
![]() |
92da4a91de | ||
![]() |
ff257a0929 | ||
![]() |
226885a58f | ||
![]() |
8d5724f4fd | ||
![]() |
95280060b8 | ||
![]() |
66ea9f39f7 | ||
![]() |
aca372de99 | ||
![]() |
903391a9e4 | ||
![]() |
0d8c80ad5d | ||
![]() |
053bd48bef | ||
![]() |
36ccc22fc9 | ||
![]() |
ca7e944d7a | ||
![]() |
c6057abd00 | ||
![]() |
03dff10cbd | ||
![]() |
4de147d9e4 | ||
![]() |
c760b03261 | ||
![]() |
1cd4a4d17a | ||
![]() |
856760599e | ||
![]() |
29adacf18e | ||
![]() |
88eeafae12 | ||
![]() |
187db92b05 | ||
![]() |
d9b0bac248 | ||
![]() |
ef1a5fa606 | ||
![]() |
5b62f33dd5 | ||
![]() |
07b21c5129 | ||
![]() |
78e6631f76 | ||
![]() |
54175f9187 | ||
![]() |
a8871ea8aa | ||
![]() |
729e6c1ee9 | ||
![]() |
15a1d4f582 | ||
![]() |
1093d7e122 | ||
![]() |
3ae50f85b1 | ||
![]() |
206761b415 | ||
![]() |
f3339961fe | ||
![]() |
d5f804832f | ||
![]() |
44d6f16b66 | ||
![]() |
82ed1803c7 | ||
![]() |
7c65da417b | ||
![]() |
1894cb549c | ||
![]() |
d0273f7faa | ||
![]() |
5c47b6034e | ||
![]() |
eff1a1341a | ||
![]() |
bab6c9a09f | ||
![]() |
d5d8213871 | ||
![]() |
ccbe2dd18d | ||
![]() |
aa0568628f | ||
![]() |
5013724c0a | ||
![]() |
f1b3a14bc2 | ||
![]() |
1657479c81 | ||
![]() |
545068dec4 | ||
![]() |
eb2c50b135 | ||
![]() |
150004e393 | ||
![]() |
a0c9a70a5e | ||
![]() |
2ea1ccf2e6 | ||
![]() |
68c16c2db7 | ||
![]() |
9b8d3b7546 | ||
![]() |
0d1c7118e3 | ||
![]() |
95f3d4cc6e | ||
![]() |
3d4f1dc60b | ||
![]() |
bfe4c50d88 | ||
![]() |
c9ba65e7b2 | ||
![]() |
1b6a81a8cc | ||
![]() |
e17299a1ca | ||
![]() |
ea91ea163e | ||
![]() |
643d7dec4c | ||
![]() |
12f375a239 | ||
![]() |
d00288198f | ||
![]() |
5344bc3b65 | ||
![]() |
d49eb2ba40 | ||
![]() |
0be844e6a8 | ||
![]() |
e7bb262e96 | ||
![]() |
66b64f928b | ||
![]() |
c4cb0c5e49 | ||
![]() |
87a2446081 | ||
![]() |
6387a3d33e | ||
![]() |
c33da42365 | ||
![]() |
9fa13b5adc | ||
![]() |
ede81dc095 | ||
![]() |
48c4c1ed05 | ||
![]() |
90ceb829f3 | ||
![]() |
037e13b883 | ||
![]() |
c1cc356bb0 | ||
![]() |
9dd68aa0e2 | ||
![]() |
250c914763 | ||
![]() |
003619e91c | ||
![]() |
db7e850ee8 | ||
![]() |
6cb4e2e83b | ||
![]() |
22da6c8a65 | ||
![]() |
cfcd657e32 | ||
![]() |
ad9bc627e6 | ||
![]() |
65b2a76159 | ||
![]() |
659c932559 | ||
![]() |
f12a209391 | ||
![]() |
f0cd51e6bc | ||
![]() |
3f98084021 | ||
![]() |
6fffe24177 | ||
![]() |
6adf37e3c1 | ||
![]() |
587b022b0a | ||
![]() |
a05593da62 | ||
![]() |
f2c911bf07 | ||
![]() |
32327b761a | ||
![]() |
6a383cd4c5 | ||
![]() |
ca918078bf | ||
![]() |
99c3713293 | ||
![]() |
f88ddf85b2 | ||
![]() |
50fd8aa01f | ||
![]() |
fd3ad75598 | ||
![]() |
30f0c582e4 | ||
![]() |
f5bfd557b6 | ||
![]() |
2e246c1968 | ||
![]() |
638f84a622 | ||
![]() |
d27ec2cd15 | ||
![]() |
db152b332b | ||
![]() |
ed4fc888de | ||
![]() |
d401e3e1a0 | ||
![]() |
c2d87846d8 | ||
![]() |
818165031c | ||
![]() |
c67b8259bb | ||
![]() |
25e3350675 | ||
![]() |
49e827a9b4 | ||
![]() |
efc6872341 | ||
![]() |
00b09fbb43 | ||
![]() |
02ae21d8fc | ||
![]() |
52e05f4a07 | ||
![]() |
e04efa8c6e | ||
![]() |
81a7b5d2a1 | ||
![]() |
23f2fff1c8 | ||
![]() |
801675a2c6 | ||
![]() |
fcc3bb1495 | ||
![]() |
f8a38c59f8 | ||
![]() |
bd12c0a486 | ||
![]() |
7142db28a8 | ||
![]() |
1c824709e2 | ||
![]() |
589b267a93 | ||
![]() |
8e4e03d980 | ||
![]() |
6cf001d355 | ||
![]() |
352f15e96b | ||
![]() |
70a6379bf6 | ||
![]() |
87edf6305f | ||
![]() |
2e2f44c82e | ||
![]() |
fb02fc69c6 | ||
![]() |
8295f997ae | ||
![]() |
ba1e05f16b | ||
![]() |
3dedc62593 | ||
![]() |
05e9ae183d | ||
![]() |
eb638c47b3 | ||
![]() |
2a0c117662 | ||
![]() |
f3d9b45387 | ||
![]() |
0570cb7ae9 | ||
![]() |
030b02588b | ||
![]() |
b483008cdf | ||
![]() |
8a791e8309 | ||
![]() |
4d2906378f | ||
![]() |
d1808c2594 | ||
![]() |
d5cfd38179 | ||
![]() |
ea56dc9d08 | ||
![]() |
e36460b83e | ||
![]() |
4cf8549f5c | ||
![]() |
9cd5980d35 | ||
![]() |
bd0a33022b | ||
![]() |
1780f42b9a | ||
![]() |
0118ac00c4 | ||
![]() |
a8289b699f | ||
![]() |
493d6c3fb9 | ||
![]() |
ae33ff397f | ||
![]() |
ade72de02f | ||
![]() |
0cb351df52 | ||
![]() |
222abb5be2 | ||
![]() |
c926b273de | ||
![]() |
23306c163f | ||
![]() |
3650c8a0e7 | ||
![]() |
0d80181c5e | ||
![]() |
a218c27305 | ||
![]() |
3938ea41fc | ||
![]() |
2ef2d2b2cb | ||
![]() |
f8f89cea71 | ||
![]() |
3e40f0b9c3 | ||
![]() |
0d064c05f9 | ||
![]() |
85bff66393 | ||
![]() |
997a66791e | ||
![]() |
1060810d7a | ||
![]() |
cadbf42054 | ||
![]() |
b1d345c233 | ||
![]() |
a0ad5bc306 | ||
![]() |
97993e76ea | ||
![]() |
661857fe8e | ||
![]() |
0bcf57bd47 | ||
![]() |
cc5edfd97e | ||
![]() |
d0ee4cef04 | ||
![]() |
203e46aee3 | ||
![]() |
0279f63710 | ||
![]() |
9aadfef8c1 | ||
![]() |
8744c46ea0 | ||
![]() |
a2d906a3fd | ||
![]() |
ba4150aecc | ||
![]() |
81b176e150 | ||
![]() |
031725c80e | ||
![]() |
df79d94944 | ||
![]() |
95a85c8ea7 | ||
![]() |
a0fa164399 | ||
![]() |
f363dd2d3c | ||
![]() |
89de4caf6c | ||
![]() |
4ec2bd1e5d | ||
![]() |
55b0b60d9d | ||
![]() |
f5b11ce075 | ||
![]() |
af3ff143be | ||
![]() |
998d055ea7 | ||
![]() |
e87fb69665 | ||
![]() |
7a5699891a | ||
![]() |
8c70501912 | ||
![]() |
64dc453f12 | ||
![]() |
15314538f8 | ||
![]() |
0d83f3fcfe | ||
![]() |
ab50a6ef54 | ||
![]() |
0bc88e622c | ||
![]() |
ae6c1170ef | ||
![]() |
e50ab2106f | ||
![]() |
3b50b57f05 | ||
![]() |
f960139768 | ||
![]() |
817ba5a4b9 | ||
![]() |
fd52db813f | ||
![]() |
491d64293d | ||
![]() |
68abcb365a | ||
![]() |
49e9453820 | ||
![]() |
82ad10a395 | ||
![]() |
6e8fbe8cdf | ||
![]() |
4e49ab1625 | ||
![]() |
6f203dfd7b | ||
![]() |
4402361246 | ||
![]() |
eb45956d0e | ||
![]() |
fe2375324d | ||
![]() |
8a64a72a21 | ||
![]() |
52d1954d96 | ||
![]() |
63e1f02c65 | ||
![]() |
db1666fc3d | ||
![]() |
5cfc7674c1 | ||
![]() |
92a4a48f47 | ||
![]() |
7044f56246 | ||
![]() |
9539f57c74 | ||
![]() |
a05f6b261e | ||
![]() |
e8d3aaaf34 | ||
![]() |
a7ea3f58e3 | ||
![]() |
4c7306185e | ||
![]() |
9026ab8886 | ||
![]() |
4b6505df9e | ||
![]() |
e649b1e4ed | ||
![]() |
e9e9b9469c | ||
![]() |
cf7baeec55 | ||
![]() |
c52202233a | ||
![]() |
d24d85a6e4 | ||
![]() |
565d5eed17 | ||
![]() |
6fed51ee3d | ||
![]() |
6d2594d95b | ||
![]() |
b35090d77c | ||
![]() |
ef8105bfba | ||
![]() |
7bd4fa99a1 | ||
![]() |
63a7f57b01 | ||
![]() |
6cd0b8a123 | ||
![]() |
1b28bdd121 | ||
![]() |
8b0af0e48d | ||
![]() |
4ac505701e | ||
![]() |
fcb6362279 | ||
![]() |
4a2560b0d3 | ||
![]() |
9238f1cfd7 | ||
![]() |
859f105e76 | ||
![]() |
054be887ae | ||
![]() |
366151ad61 | ||
![]() |
d964ea911c | ||
![]() |
a520b38424 | ||
![]() |
54820974bb | ||
![]() |
73f200fe74 | ||
![]() |
170bf8a5ec | ||
![]() |
0639be7966 | ||
![]() |
4b7ec5cecb | ||
![]() |
882775acef | ||
![]() |
db990d2175 | ||
![]() |
c900bcc949 | ||
![]() |
e929d221f3 | ||
![]() |
f3f404e81c | ||
![]() |
3e18260815 | ||
![]() |
3927f8c9c0 | ||
![]() |
09207cf91f | ||
![]() |
1c5dab9d47 | ||
![]() |
a65d2e425c | ||
![]() |
dea61e604f | ||
![]() |
f9f15e79cd | ||
![]() |
bfc96cc962 | ||
![]() |
c6604a4582 | ||
![]() |
564a7e27b1 | ||
![]() |
8e8c103b34 | ||
![]() |
0ca0af6c72 | ||
![]() |
6d664046d3 | ||
![]() |
77bb5ea63a | ||
![]() |
f4d8a25fb7 | ||
![]() |
7f950a1852 | ||
![]() |
3cdd83a3be | ||
![]() |
38f80b1048 |
12
.cirrus.yml
12
.cirrus.yml
@ -1,12 +0,0 @@
|
|||||||
task:
|
|
||||||
name: build-test-ubuntu1604
|
|
||||||
container:
|
|
||||||
cpu: 4
|
|
||||||
memory: 16
|
|
||||||
dockerfile: .cirrus/Dockerfile.ubuntu16.04
|
|
||||||
|
|
||||||
build_script: mkdir build && cd build && cmake .. -DARCH=all -DTRELLIS_ROOT=/usr/local/src/prjtrellis -DBUILD_TESTS=on && make -j $(nproc)
|
|
||||||
test_generic_script: cd build && ./nextpnr-generic-test
|
|
||||||
test_ice40_script: cd build && ./nextpnr-ice40-test
|
|
||||||
smoketest_ice40_script: export NEXTPNR=$(pwd)/build/nextpnr-ice40 && cd ice40/smoketest/attosoc && ./smoketest.sh
|
|
||||||
test_ecp5_script: cd build && ./nextpnr-ecp5-test
|
|
@ -1,55 +0,0 @@
|
|||||||
FROM ubuntu:xenial-20181113
|
|
||||||
|
|
||||||
ENV DEBIAN_FRONTEND=noninteractive
|
|
||||||
|
|
||||||
RUN set -e -x ;\
|
|
||||||
apt-get -y update ;\
|
|
||||||
apt-get -y upgrade ;\
|
|
||||||
apt-get -y install \
|
|
||||||
build-essential autoconf cmake clang bison wget flex gperf \
|
|
||||||
libreadline-dev gawk tcl-dev libffi-dev graphviz xdot python3-dev \
|
|
||||||
libboost-all-dev qt5-default git libftdi-dev pkg-config
|
|
||||||
|
|
||||||
RUN set -e -x ;\
|
|
||||||
mkdir -p /usr/local/src ;\
|
|
||||||
cd /usr/local/src ;\
|
|
||||||
git clone --recursive https://github.com/steveicarus/iverilog.git ;\
|
|
||||||
cd iverilog ;\
|
|
||||||
git reset --hard 172d7eb0a3665f89b91d601b5912c33acedc81e5 ;\
|
|
||||||
sh autoconf.sh ;\
|
|
||||||
./configure ;\
|
|
||||||
make -j $(nproc) ;\
|
|
||||||
make install ;\
|
|
||||||
rm -rf /usr/local/src/iverilog
|
|
||||||
|
|
||||||
RUN set -e -x ;\
|
|
||||||
mkdir -p /usr/local/src ;\
|
|
||||||
cd /usr/local/src ;\
|
|
||||||
git clone --recursive https://github.com/cliffordwolf/icestorm.git ;\
|
|
||||||
cd icestorm ;\
|
|
||||||
git reset --hard 9671b760f84ca4006f0ef101a3e3b201df4eabb5 ;\
|
|
||||||
make -j $(nproc) ;\
|
|
||||||
make install
|
|
||||||
|
|
||||||
RUN set -e -x ;\
|
|
||||||
mkdir -p /usr/local/src ;\
|
|
||||||
cd /usr/local/src ;\
|
|
||||||
git clone --recursive https://github.com/YosysHQ/yosys.git ;\
|
|
||||||
cd yosys ;\
|
|
||||||
git reset --hard 47a5dfdaa4bd7d400c6e3d58476de80904df460d ;\
|
|
||||||
make -j $(nproc) ;\
|
|
||||||
make install ;\
|
|
||||||
rm -rf /usr/local/src/yosys
|
|
||||||
|
|
||||||
RUN set -e -x ;\
|
|
||||||
mkdir -p /usr/local/src ;\
|
|
||||||
cd /usr/local/src ;\
|
|
||||||
git clone --recursive https://github.com/SymbiFlow/prjtrellis.git ;\
|
|
||||||
cd prjtrellis ;\
|
|
||||||
git reset --hard de035a6e5e5818804a66b9408f0ad381b10957db ;\
|
|
||||||
cd libtrellis ;\
|
|
||||||
cmake -DCMAKE_INSTALL_PREFIX=/usr . ;\
|
|
||||||
make -j $(nproc) ;\
|
|
||||||
make install
|
|
||||||
|
|
||||||
|
|
55
.github/ci/build_common.sh
vendored
Normal file
55
.github/ci/build_common.sh
vendored
Normal file
@ -0,0 +1,55 @@
|
|||||||
|
#!/bin/bash
|
||||||
|
|
||||||
|
# Install latest Yosys
|
||||||
|
function build_yosys {
|
||||||
|
PREFIX=`pwd`/.yosys
|
||||||
|
YOSYS_PATH=${DEPS_PATH}/yosys
|
||||||
|
mkdir -p ${YOSYS_PATH}
|
||||||
|
git clone --recursive https://github.com/YosysHQ/yosys ${YOSYS_PATH}
|
||||||
|
pushd ${YOSYS_PATH}
|
||||||
|
git reset --hard ${YOSYS_REVISION}
|
||||||
|
make -j`nproc` PREFIX=$PREFIX
|
||||||
|
make install PREFIX=$PREFIX
|
||||||
|
popd
|
||||||
|
}
|
||||||
|
|
||||||
|
function build_icestorm {
|
||||||
|
PREFIX=`pwd`/.icestorm
|
||||||
|
ICESTORM_PATH=${DEPS_PATH}/icestorm
|
||||||
|
mkdir -p ${ICESTORM_PATH}
|
||||||
|
git clone --recursive https://github.com/YosysHQ/icestorm ${ICESTORM_PATH}
|
||||||
|
pushd ${ICESTORM_PATH}
|
||||||
|
git reset --hard ${ICESTORM_REVISION}
|
||||||
|
make -j`nproc` PREFIX=${PREFIX}
|
||||||
|
make install PREFIX=${PREFIX}
|
||||||
|
popd
|
||||||
|
}
|
||||||
|
|
||||||
|
function build_trellis {
|
||||||
|
PREFIX=`pwd`/.trellis
|
||||||
|
TRELLIS_PATH=${DEPS_PATH}/prjtrellis
|
||||||
|
mkdir -p ${TRELLIS_PATH}
|
||||||
|
git clone --recursive https://github.com/YosysHQ/prjtrellis ${TRELLIS_PATH}
|
||||||
|
pushd ${TRELLIS_PATH}
|
||||||
|
git reset --hard ${TRELLIS_REVISION}
|
||||||
|
mkdir -p libtrellis/build
|
||||||
|
pushd libtrellis/build
|
||||||
|
cmake -DCMAKE_INSTALL_PREFIX=${PREFIX} ..
|
||||||
|
make -j`nproc`
|
||||||
|
make install
|
||||||
|
popd
|
||||||
|
popd
|
||||||
|
}
|
||||||
|
|
||||||
|
function build_prjoxide {
|
||||||
|
PREFIX=`pwd`/.prjoxide
|
||||||
|
PRJOXIDE_PATH=${DEPS_PATH}/prjoxide
|
||||||
|
curl --proto '=https' --tlsv1.2 -sSf https://sh.rustup.rs | sh -s -- -y ;\
|
||||||
|
mkdir -p ${PRJOXIDE_PATH}
|
||||||
|
git clone --recursive https://github.com/gatecat/prjoxide ${PRJOXIDE_PATH}
|
||||||
|
pushd ${PRJOXIDE_PATH}
|
||||||
|
git reset --hard ${PRJOXIDE_REVISION}
|
||||||
|
cd libprjoxide
|
||||||
|
PATH=$PATH:$HOME/.cargo/bin cargo install --root $PREFIX --path prjoxide
|
||||||
|
popd
|
||||||
|
}
|
24
.github/ci/build_ecp5.sh
vendored
Normal file
24
.github/ci/build_ecp5.sh
vendored
Normal file
@ -0,0 +1,24 @@
|
|||||||
|
#!/bin/bash
|
||||||
|
|
||||||
|
function get_dependencies {
|
||||||
|
:
|
||||||
|
}
|
||||||
|
|
||||||
|
function build_nextpnr {
|
||||||
|
mkdir build
|
||||||
|
pushd build
|
||||||
|
cmake .. -DARCH=ecp5 -DTRELLIS_INSTALL_PREFIX=${GITHUB_WORKSPACE}/.trellis -DWERROR=on -DBUILD_GUI=on -DUSE_IPO=off
|
||||||
|
make nextpnr-ecp5 -j`nproc`
|
||||||
|
popd
|
||||||
|
}
|
||||||
|
|
||||||
|
function run_tests {
|
||||||
|
export PATH=${GITHUB_WORKSPACE}/.trellis/bin:${GITHUB_WORKSPACE}/.yosys/bin:$PATH
|
||||||
|
make -j $(nproc) -C tests/ecp5/regressions NPNR=$(pwd)/build/nextpnr-ecp5
|
||||||
|
}
|
||||||
|
|
||||||
|
function run_archcheck {
|
||||||
|
pushd build
|
||||||
|
./nextpnr-ecp5 --um5g-25k --package CABGA381 --test
|
||||||
|
popd
|
||||||
|
}
|
25
.github/ci/build_generic.sh
vendored
Normal file
25
.github/ci/build_generic.sh
vendored
Normal file
@ -0,0 +1,25 @@
|
|||||||
|
#!/bin/bash
|
||||||
|
|
||||||
|
function get_dependencies {
|
||||||
|
:
|
||||||
|
}
|
||||||
|
|
||||||
|
function build_nextpnr {
|
||||||
|
mkdir build
|
||||||
|
pushd build
|
||||||
|
cmake .. -DARCH=generic -DWERROR=on
|
||||||
|
make nextpnr-generic -j`nproc`
|
||||||
|
popd
|
||||||
|
}
|
||||||
|
|
||||||
|
function run_tests {
|
||||||
|
export PATH=${GITHUB_WORKSPACE}/.yosys/bin:$PATH
|
||||||
|
( export NPNR=$(pwd)/build/nextpnr-generic && cd tests/generic/flow && ./run.sh )
|
||||||
|
}
|
||||||
|
|
||||||
|
function run_archcheck {
|
||||||
|
pushd build
|
||||||
|
# TODO
|
||||||
|
# ./nextpnr-generic --uarch example --test
|
||||||
|
popd
|
||||||
|
}
|
23
.github/ci/build_gowin.sh
vendored
Normal file
23
.github/ci/build_gowin.sh
vendored
Normal file
@ -0,0 +1,23 @@
|
|||||||
|
#!/bin/bash
|
||||||
|
|
||||||
|
function get_dependencies {
|
||||||
|
pip3 install apycula==${APYCULA_REVISION}
|
||||||
|
}
|
||||||
|
|
||||||
|
function build_nextpnr {
|
||||||
|
mkdir build
|
||||||
|
pushd build
|
||||||
|
cmake .. -DARCH=gowin -DWERROR=on -DBUILD_GUI=on -DUSE_IPO=off
|
||||||
|
make nextpnr-gowin -j`nproc`
|
||||||
|
popd
|
||||||
|
}
|
||||||
|
|
||||||
|
function run_tests {
|
||||||
|
:
|
||||||
|
}
|
||||||
|
|
||||||
|
function run_archcheck {
|
||||||
|
pushd build
|
||||||
|
./nextpnr-gowin --device GW1N-UV4LQ144C6/I5 --test
|
||||||
|
popd
|
||||||
|
}
|
23
.github/ci/build_himbaechel.sh
vendored
Normal file
23
.github/ci/build_himbaechel.sh
vendored
Normal file
@ -0,0 +1,23 @@
|
|||||||
|
#!/bin/bash
|
||||||
|
|
||||||
|
function get_dependencies {
|
||||||
|
:
|
||||||
|
}
|
||||||
|
|
||||||
|
function build_nextpnr {
|
||||||
|
mkdir build
|
||||||
|
pushd build
|
||||||
|
cmake .. -DARCH=himbaechel -DHIMBAECHEL_UARCH=example -DHIMBAECHEL_EXAMPLE_DEVICES=example
|
||||||
|
make nextpnr-himbaechel -j`nproc`
|
||||||
|
popd
|
||||||
|
}
|
||||||
|
|
||||||
|
function run_tests {
|
||||||
|
:
|
||||||
|
}
|
||||||
|
|
||||||
|
function run_archcheck {
|
||||||
|
pushd build
|
||||||
|
./nextpnr-himbaechel --device EXAMPLE --test
|
||||||
|
popd
|
||||||
|
}
|
27
.github/ci/build_ice40.sh
vendored
Normal file
27
.github/ci/build_ice40.sh
vendored
Normal file
@ -0,0 +1,27 @@
|
|||||||
|
#!/bin/bash
|
||||||
|
|
||||||
|
function get_dependencies {
|
||||||
|
:
|
||||||
|
}
|
||||||
|
|
||||||
|
function build_nextpnr {
|
||||||
|
mkdir build
|
||||||
|
pushd build
|
||||||
|
cmake .. -DARCH=ice40 -DICESTORM_INSTALL_PREFIX=${GITHUB_WORKSPACE}/.icestorm -DWERROR=on -DBUILD_TESTS=on -DBUILD_GUI=on
|
||||||
|
make nextpnr-ice40 nextpnr-ice40-test -j`nproc`
|
||||||
|
popd
|
||||||
|
}
|
||||||
|
|
||||||
|
function run_tests {
|
||||||
|
export PATH=${GITHUB_WORKSPACE}/.yosys/bin:${GITHUB_WORKSPACE}/.icestorm/bin:$PATH
|
||||||
|
(cd build && ./nextpnr-ice40-test)
|
||||||
|
(export NEXTPNR=$(pwd)/build/nextpnr-ice40 && cd ice40/smoketest/attosoc && ./smoketest.sh)
|
||||||
|
make -j $(nproc) -C tests/ice40/regressions NPNR=$(pwd)/build/nextpnr-ice40
|
||||||
|
}
|
||||||
|
|
||||||
|
function run_archcheck {
|
||||||
|
pushd build
|
||||||
|
./nextpnr-ice40 --hx8k --package ct256 --test
|
||||||
|
./nextpnr-ice40 --up5k --package sg48 --test
|
||||||
|
popd
|
||||||
|
}
|
24
.github/ci/build_machxo2.sh
vendored
Normal file
24
.github/ci/build_machxo2.sh
vendored
Normal file
@ -0,0 +1,24 @@
|
|||||||
|
#!/bin/bash
|
||||||
|
|
||||||
|
function get_dependencies {
|
||||||
|
:
|
||||||
|
}
|
||||||
|
|
||||||
|
function build_nextpnr {
|
||||||
|
mkdir build
|
||||||
|
pushd build
|
||||||
|
cmake .. -DARCH=machxo2 -DTRELLIS_INSTALL_PREFIX=${GITHUB_WORKSPACE}/.trellis -DWERROR=on -DUSE_IPO=off
|
||||||
|
make nextpnr-machxo2 -j`nproc`
|
||||||
|
popd
|
||||||
|
}
|
||||||
|
|
||||||
|
function run_tests {
|
||||||
|
:
|
||||||
|
}
|
||||||
|
|
||||||
|
function run_archcheck {
|
||||||
|
pushd build
|
||||||
|
./nextpnr-machxo2 --device LCMXO2-1200HC-4SG32C --test
|
||||||
|
./nextpnr-machxo2 --device LCMXO3LF-6900C-6BG256C --test
|
||||||
|
popd
|
||||||
|
}
|
30
.github/ci/build_mistral.sh
vendored
Normal file
30
.github/ci/build_mistral.sh
vendored
Normal file
@ -0,0 +1,30 @@
|
|||||||
|
#!/bin/bash
|
||||||
|
|
||||||
|
export MISTRAL_PATH=${DEPS_PATH}/mistral
|
||||||
|
|
||||||
|
function get_dependencies {
|
||||||
|
# Fetch mistral
|
||||||
|
mkdir -p ${MISTRAL_PATH}
|
||||||
|
git clone --recursive https://github.com/Ravenslofty/mistral.git ${MISTRAL_PATH}
|
||||||
|
pushd ${MISTRAL_PATH}
|
||||||
|
git reset --hard ${MISTRAL_REVISION}
|
||||||
|
popd
|
||||||
|
}
|
||||||
|
|
||||||
|
function build_nextpnr {
|
||||||
|
mkdir build
|
||||||
|
pushd build
|
||||||
|
cmake .. -DARCH=mistral -DMISTRAL_ROOT=${MISTRAL_PATH}
|
||||||
|
make nextpnr-mistral -j`nproc`
|
||||||
|
popd
|
||||||
|
}
|
||||||
|
|
||||||
|
function run_tests {
|
||||||
|
:
|
||||||
|
}
|
||||||
|
|
||||||
|
function run_archcheck {
|
||||||
|
pushd build
|
||||||
|
./nextpnr-mistral --device 5CEBA2F17A7 --test
|
||||||
|
popd
|
||||||
|
}
|
23
.github/ci/build_nexus.sh
vendored
Normal file
23
.github/ci/build_nexus.sh
vendored
Normal file
@ -0,0 +1,23 @@
|
|||||||
|
#!/bin/bash
|
||||||
|
|
||||||
|
function get_dependencies {
|
||||||
|
:
|
||||||
|
}
|
||||||
|
|
||||||
|
function build_nextpnr {
|
||||||
|
mkdir build
|
||||||
|
pushd build
|
||||||
|
cmake .. -DARCH=nexus -DOXIDE_INSTALL_PREFIX=${GITHUB_WORKSPACE}/.prjoxide
|
||||||
|
make nextpnr-nexus -j`nproc`
|
||||||
|
popd
|
||||||
|
}
|
||||||
|
|
||||||
|
function run_tests {
|
||||||
|
:
|
||||||
|
}
|
||||||
|
|
||||||
|
function run_archcheck {
|
||||||
|
pushd build
|
||||||
|
./nextpnr-nexus --device LIFCL-40-9BG400CES --test
|
||||||
|
popd
|
||||||
|
}
|
96
.github/workflows/arch_ci.yml
vendored
Normal file
96
.github/workflows/arch_ci.yml
vendored
Normal file
@ -0,0 +1,96 @@
|
|||||||
|
# CI for everything other than the sui generis FPGA interchange arrangements
|
||||||
|
|
||||||
|
name: Arch CI tests
|
||||||
|
|
||||||
|
on: [push, pull_request]
|
||||||
|
|
||||||
|
jobs:
|
||||||
|
Build-nextpnr:
|
||||||
|
strategy:
|
||||||
|
fail-fast: false
|
||||||
|
matrix:
|
||||||
|
arch: [mistral, ice40, ecp5, generic, nexus, machxo2, gowin, himbaechel]
|
||||||
|
runs-on: ubuntu-latest
|
||||||
|
env:
|
||||||
|
DEPS_PATH: ${{ github.workspace }}/deps
|
||||||
|
YOSYS_REVISION: 7045cf509e1d95cbc973746674cf2d7c73c02e50
|
||||||
|
ICESTORM_REVISION: 68044cc4dac829729ccd0ee88d0780525b515746
|
||||||
|
TRELLIS_REVISION: 36c615d1740473cc3574464c7f0bed44da20e5b6
|
||||||
|
PRJOXIDE_REVISION: c3fb1526cf4a2165e15b74f4a994d153c7695fe4
|
||||||
|
MISTRAL_REVISION: ebfc0dd2cc7d6d2159b641a397c88554840e93c9
|
||||||
|
APYCULA_REVISION: 0.8.2a1
|
||||||
|
steps:
|
||||||
|
- uses: actions/checkout@v4
|
||||||
|
with:
|
||||||
|
submodules: recursive
|
||||||
|
|
||||||
|
- uses: actions/setup-python@v5
|
||||||
|
with:
|
||||||
|
python-version: '3.12'
|
||||||
|
- name: Install
|
||||||
|
run: |
|
||||||
|
sudo apt-get update
|
||||||
|
sudo apt-get install git make cmake libboost-all-dev python3-dev pypy3 libeigen3-dev tcl-dev lzma-dev libftdi-dev clang bison flex swig qtbase5-dev qtchooser qt5-qmake qtbase5-dev-tools iverilog libreadline-dev liblzma-dev
|
||||||
|
|
||||||
|
- name: Cache yosys installation
|
||||||
|
uses: actions/cache@v4
|
||||||
|
id: cache-yosys
|
||||||
|
with:
|
||||||
|
path: .yosys
|
||||||
|
key: cache-yosys-${{ env.YOSYS_REVISION }}-r3
|
||||||
|
|
||||||
|
- name: Build yosys
|
||||||
|
run: |
|
||||||
|
source ./.github/ci/build_common.sh
|
||||||
|
build_yosys
|
||||||
|
if: steps.cache-yosys.outputs.cache-hit != 'true'
|
||||||
|
|
||||||
|
- name: Cache icestorm installation
|
||||||
|
uses: actions/cache@v4
|
||||||
|
id: cache-icestorm
|
||||||
|
with:
|
||||||
|
path: .icestorm
|
||||||
|
key: cache-icestorm-${{ env.ICESTORM_REVISION }}-r3
|
||||||
|
if: matrix.arch == 'ice40'
|
||||||
|
|
||||||
|
- name: Build icestorm
|
||||||
|
run: |
|
||||||
|
source ./.github/ci/build_common.sh
|
||||||
|
build_icestorm
|
||||||
|
if: matrix.arch == 'ice40' && steps.cache-icestorm.outputs.cache-hit != 'true'
|
||||||
|
|
||||||
|
- name: Cache trellis installation
|
||||||
|
uses: actions/cache@v4
|
||||||
|
id: cache-trellis
|
||||||
|
with:
|
||||||
|
path: .trellis
|
||||||
|
key: cache-trellis-${{ env.TRELLIS_REVISION }}-r3
|
||||||
|
if: matrix.arch == 'ecp5' || matrix.arch == 'machxo2'
|
||||||
|
|
||||||
|
- name: Build trellis
|
||||||
|
run: |
|
||||||
|
source ./.github/ci/build_common.sh
|
||||||
|
build_trellis
|
||||||
|
if: (matrix.arch == 'ecp5' || matrix.arch == 'machxo2') && steps.cache-trellis.outputs.cache-hit != 'true'
|
||||||
|
|
||||||
|
- name: Cache prjoxide installation
|
||||||
|
uses: actions/cache@v4
|
||||||
|
id: cache-prjoxide
|
||||||
|
with:
|
||||||
|
path: .prjoxide
|
||||||
|
key: cache-prjoxide-${{ env.PRJOXIDE_REVISION }}-r3
|
||||||
|
if: matrix.arch == 'nexus'
|
||||||
|
|
||||||
|
- name: Build prjoxide
|
||||||
|
run: |
|
||||||
|
source ./.github/ci/build_common.sh
|
||||||
|
build_prjoxide
|
||||||
|
if: matrix.arch == 'nexus' && steps.cache-prjoxide.outputs.cache-hit != 'true'
|
||||||
|
|
||||||
|
- name: Execute build nextpnr
|
||||||
|
run: |
|
||||||
|
source ./.github/ci/build_${{ matrix.arch }}.sh
|
||||||
|
get_dependencies
|
||||||
|
build_nextpnr
|
||||||
|
run_tests
|
||||||
|
run_archcheck
|
18
.gitignore
vendored
18
.gitignore
vendored
@ -1,8 +1,13 @@
|
|||||||
/generated/
|
|
||||||
/objs/
|
/objs/
|
||||||
/nextpnr-generic*
|
/nextpnr-generic*
|
||||||
/nextpnr-ice40*
|
/nextpnr-ice40*
|
||||||
/nextpnr-ecp5*
|
/nextpnr-ecp5*
|
||||||
|
/nextpnr-nexus*
|
||||||
|
/nextpnr-fpga_interchange*
|
||||||
|
/nextpnr-gowin*
|
||||||
|
/nextpnr-machxo2*
|
||||||
|
/nextpnr-himbaechel*
|
||||||
|
.cache
|
||||||
cmake-build-*/
|
cmake-build-*/
|
||||||
Makefile
|
Makefile
|
||||||
cmake_install.cmake
|
cmake_install.cmake
|
||||||
@ -19,13 +24,22 @@ CMakeCache.txt
|
|||||||
.*.swp
|
.*.swp
|
||||||
a.out
|
a.out
|
||||||
*.json
|
*.json
|
||||||
|
*.dot
|
||||||
|
*.il
|
||||||
|
/generic/examples/blinky.png
|
||||||
build/
|
build/
|
||||||
|
share/
|
||||||
*.asc
|
*.asc
|
||||||
*.bin
|
*.bin
|
||||||
/Testing/*
|
/Testing/*
|
||||||
CTestTestfile.cmake
|
CTestTestfile.cmake
|
||||||
install_manifest.txt
|
install_manifest.txt
|
||||||
/bbasm
|
/bba/bbasm
|
||||||
|
/bba-export.cmake
|
||||||
/ImportExecutables.cmake
|
/ImportExecutables.cmake
|
||||||
*-coverage/
|
*-coverage/
|
||||||
*-coverage.info
|
*-coverage.info
|
||||||
|
*.netlist
|
||||||
|
*.phys
|
||||||
|
*.dcp
|
||||||
|
*.bit
|
||||||
|
9
.gitmodules
vendored
Normal file
9
.gitmodules
vendored
Normal file
@ -0,0 +1,9 @@
|
|||||||
|
[submodule "tests"]
|
||||||
|
path = tests
|
||||||
|
url = https://github.com/YosysHQ/nextpnr-tests
|
||||||
|
[submodule "himbaechel/uarch/xilinx/meta"]
|
||||||
|
path = himbaechel/uarch/xilinx/meta
|
||||||
|
url = https://github.com/gatecat/nextpnr-xilinx-meta
|
||||||
|
[submodule "3rdparty/corrosion"]
|
||||||
|
path = 3rdparty/corrosion
|
||||||
|
url = https://github.com/corrosion-rs/corrosion
|
3
3rdparty/QtPropertyBrowser/CMakeLists.txt
vendored
3
3rdparty/QtPropertyBrowser/CMakeLists.txt
vendored
@ -1,4 +1,5 @@
|
|||||||
CMAKE_MINIMUM_REQUIRED(VERSION 2.8.11)
|
CMAKE_MINIMUM_REQUIRED(VERSION 3.13)
|
||||||
|
|
||||||
PROJECT(QtPropertyBrowser)
|
PROJECT(QtPropertyBrowser)
|
||||||
|
|
||||||
##################### Look for required libraries ######################
|
##################### Look for required libraries ######################
|
||||||
|
@ -2205,11 +2205,10 @@ void QtColorEditWidget::setValue(const QColor &c)
|
|||||||
|
|
||||||
void QtColorEditWidget::buttonClicked()
|
void QtColorEditWidget::buttonClicked()
|
||||||
{
|
{
|
||||||
bool ok = false;
|
|
||||||
QRgb oldRgba = m_color.rgba();
|
QRgb oldRgba = m_color.rgba();
|
||||||
QRgb newRgba = QColorDialog::getRgba(oldRgba, &ok, this);
|
QColor newRgba = QColorDialog::getColor(oldRgba, this).rgba();
|
||||||
if (ok && newRgba != oldRgba) {
|
if (newRgba.isValid() && newRgba.rgba() != oldRgba) {
|
||||||
setValue(QColor::fromRgba(newRgba));
|
setValue(newRgba);
|
||||||
emit valueChanged(m_color);
|
emit valueChanged(m_color);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -132,9 +132,9 @@ public:
|
|||||||
protected:
|
protected:
|
||||||
void mouseMoveEvent(QMouseEvent *event) override;
|
void mouseMoveEvent(QMouseEvent *event) override;
|
||||||
void leaveEvent(QEvent *event) override;
|
void leaveEvent(QEvent *event) override;
|
||||||
void keyPressEvent(QKeyEvent *event);
|
void keyPressEvent(QKeyEvent *event) override;
|
||||||
void mousePressEvent(QMouseEvent *event);
|
void mousePressEvent(QMouseEvent *event) override;
|
||||||
void drawRow(QPainter *painter, const QStyleOptionViewItem &option, const QModelIndex &index) const;
|
void drawRow(QPainter *painter, const QStyleOptionViewItem &option, const QModelIndex &index) const override;
|
||||||
|
|
||||||
Q_SIGNALS:
|
Q_SIGNALS:
|
||||||
void hoverPropertyChanged(QtBrowserItem *item);
|
void hoverPropertyChanged(QtBrowserItem *item);
|
||||||
@ -383,7 +383,7 @@ void QtPropertyEditorDelegate::paint(QPainter *painter, const QStyleOptionViewIt
|
|||||||
opt.palette.setColor(QPalette::Text, opt.palette.color(QPalette::BrightText));
|
opt.palette.setColor(QPalette::Text, opt.palette.color(QPalette::BrightText));
|
||||||
} else {
|
} else {
|
||||||
c = m_editorPrivate->calculatedBackgroundColor(m_editorPrivate->indexToBrowserItem(index));
|
c = m_editorPrivate->calculatedBackgroundColor(m_editorPrivate->indexToBrowserItem(index));
|
||||||
if (c.isValid() && (opt.features & QStyleOptionViewItemV2::Alternate))
|
if (c.isValid() && (opt.features & QStyleOptionViewItem::Alternate))
|
||||||
c = c.lighter(112);
|
c = c.lighter(112);
|
||||||
}
|
}
|
||||||
if (c.isValid())
|
if (c.isValid())
|
||||||
@ -609,7 +609,7 @@ void QtTreePropertyBrowserPrivate::propertyInserted(QtBrowserItem *index, QtBrow
|
|||||||
m_indexToItem[index] = newItem;
|
m_indexToItem[index] = newItem;
|
||||||
|
|
||||||
newItem->setFlags(newItem->flags() | Qt::ItemIsEditable);
|
newItem->setFlags(newItem->flags() | Qt::ItemIsEditable);
|
||||||
m_treeWidget->setItemExpanded(newItem, true);
|
newItem->setExpanded(true);
|
||||||
|
|
||||||
updateItem(newItem);
|
updateItem(newItem);
|
||||||
}
|
}
|
||||||
|
@ -145,7 +145,6 @@ static QtProperty *wrappedProperty(QtProperty *property)
|
|||||||
|
|
||||||
class QtVariantPropertyPrivate
|
class QtVariantPropertyPrivate
|
||||||
{
|
{
|
||||||
QtVariantProperty *q_ptr;
|
|
||||||
public:
|
public:
|
||||||
QtVariantPropertyPrivate(QtVariantPropertyManager *m) : manager(m) {}
|
QtVariantPropertyPrivate(QtVariantPropertyManager *m) : manager(m) {}
|
||||||
|
|
||||||
@ -576,7 +575,7 @@ void QtVariantPropertyManagerPrivate::slotValueChanged(QtProperty *property, con
|
|||||||
void QtVariantPropertyManagerPrivate::slotValueChanged(QtProperty *property, const QKeySequence &val)
|
void QtVariantPropertyManagerPrivate::slotValueChanged(QtProperty *property, const QKeySequence &val)
|
||||||
{
|
{
|
||||||
QVariant v;
|
QVariant v;
|
||||||
qVariantSetValue(v, val);
|
v.setValue(val);
|
||||||
valueChanged(property, v);
|
valueChanged(property, v);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -663,7 +662,7 @@ void QtVariantPropertyManagerPrivate::slotEnumIconsChanged(QtProperty *property,
|
|||||||
{
|
{
|
||||||
if (QtVariantProperty *varProp = m_internalToProperty.value(property, 0)) {
|
if (QtVariantProperty *varProp = m_internalToProperty.value(property, 0)) {
|
||||||
QVariant v;
|
QVariant v;
|
||||||
qVariantSetValue(v, enumIcons);
|
v.setValue(enumIcons);
|
||||||
emit q_ptr->attributeChanged(varProp, m_enumIconsAttribute, v);
|
emit q_ptr->attributeChanged(varProp, m_enumIconsAttribute, v);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -1567,7 +1566,7 @@ QVariant QtVariantPropertyManager::attributeValue(const QtProperty *property, co
|
|||||||
return enumManager->enumNames(internProp);
|
return enumManager->enumNames(internProp);
|
||||||
if (attribute == d_ptr->m_enumIconsAttribute) {
|
if (attribute == d_ptr->m_enumIconsAttribute) {
|
||||||
QVariant v;
|
QVariant v;
|
||||||
qVariantSetValue(v, enumManager->enumIcons(internProp));
|
v.setValue(enumManager->enumIcons(internProp));
|
||||||
return v;
|
return v;
|
||||||
}
|
}
|
||||||
return QVariant();
|
return QVariant();
|
||||||
|
1
3rdparty/corrosion
vendored
Submodule
1
3rdparty/corrosion
vendored
Submodule
@ -0,0 +1 @@
|
|||||||
|
Subproject commit be76480232216a64f65e3b1d9794d68cbac6c690
|
@ -95,6 +95,7 @@ template <typename T1, typename T2>
|
|||||||
class ValueArray2 {
|
class ValueArray2 {
|
||||||
public:
|
public:
|
||||||
ValueArray2(T1 v1, T2 v2) : v1_(v1), v2_(v2) {}
|
ValueArray2(T1 v1, T2 v2) : v1_(v1), v2_(v2) {}
|
||||||
|
ValueArray2(const ValueArray2& other) = default;
|
||||||
|
|
||||||
template <typename T>
|
template <typename T>
|
||||||
operator ParamGenerator<T>() const {
|
operator ParamGenerator<T>() const {
|
||||||
|
@ -1004,7 +1004,7 @@ void StackLowerThanAddress(const void* ptr, bool* result) {
|
|||||||
// Make sure AddressSanitizer does not tamper with the stack here.
|
// Make sure AddressSanitizer does not tamper with the stack here.
|
||||||
GTEST_ATTRIBUTE_NO_SANITIZE_ADDRESS_
|
GTEST_ATTRIBUTE_NO_SANITIZE_ADDRESS_
|
||||||
bool StackGrowsDown() {
|
bool StackGrowsDown() {
|
||||||
int dummy;
|
int dummy = 0;
|
||||||
bool result;
|
bool result;
|
||||||
StackLowerThanAddress(&dummy, &result);
|
StackLowerThanAddress(&dummy, &result);
|
||||||
return result;
|
return result;
|
||||||
|
1
3rdparty/imgui/examples/imgui_impl_win32.cpp
vendored
1
3rdparty/imgui/examples/imgui_impl_win32.cpp
vendored
@ -13,6 +13,7 @@
|
|||||||
#ifndef WIN32_LEAN_AND_MEAN
|
#ifndef WIN32_LEAN_AND_MEAN
|
||||||
#define WIN32_LEAN_AND_MEAN
|
#define WIN32_LEAN_AND_MEAN
|
||||||
#endif
|
#endif
|
||||||
|
#define NOMINMAX
|
||||||
#include <windows.h>
|
#include <windows.h>
|
||||||
#include <tchar.h>
|
#include <tchar.h>
|
||||||
|
|
||||||
|
1
3rdparty/imgui/examples/libs/gl3w/GL/gl3w.c
vendored
1
3rdparty/imgui/examples/libs/gl3w/GL/gl3w.c
vendored
@ -7,6 +7,7 @@
|
|||||||
|
|
||||||
#ifdef _WIN32
|
#ifdef _WIN32
|
||||||
#define WIN32_LEAN_AND_MEAN 1
|
#define WIN32_LEAN_AND_MEAN 1
|
||||||
|
#define NOMINMAX
|
||||||
#include <windows.h>
|
#include <windows.h>
|
||||||
|
|
||||||
static HMODULE libgl;
|
static HMODULE libgl;
|
||||||
|
@ -57,6 +57,7 @@ extern "C" {
|
|||||||
|
|
||||||
#if defined(_WIN32) && !defined(APIENTRY) && !defined(__CYGWIN__) && !defined(__SCITECH_SNAP__)
|
#if defined(_WIN32) && !defined(APIENTRY) && !defined(__CYGWIN__) && !defined(__SCITECH_SNAP__)
|
||||||
#define WIN32_LEAN_AND_MEAN 1
|
#define WIN32_LEAN_AND_MEAN 1
|
||||||
|
#define NOMINMAX
|
||||||
#include <windows.h>
|
#include <windows.h>
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
@ -85,7 +85,8 @@ extern "C" {
|
|||||||
// example to allow applications to correctly declare a GL_ARB_debug_output
|
// example to allow applications to correctly declare a GL_ARB_debug_output
|
||||||
// callback) but windows.h assumes no one will define APIENTRY before it does
|
// callback) but windows.h assumes no one will define APIENTRY before it does
|
||||||
#undef APIENTRY
|
#undef APIENTRY
|
||||||
#include <windows.h>
|
#define NOMINMAX
|
||||||
|
#include <windows.h>
|
||||||
#elif defined(GLFW_EXPOSE_NATIVE_COCOA)
|
#elif defined(GLFW_EXPOSE_NATIVE_COCOA)
|
||||||
#include <ApplicationServices/ApplicationServices.h>
|
#include <ApplicationServices/ApplicationServices.h>
|
||||||
#if defined(__OBJC__)
|
#if defined(__OBJC__)
|
||||||
|
4
3rdparty/imgui/imgui.cpp
vendored
4
3rdparty/imgui/imgui.cpp
vendored
@ -8723,8 +8723,10 @@ static void SettingsHandlerWindow_WriteAll(ImGuiContext* imgui_ctx, ImGuiSetting
|
|||||||
#define WIN32_LEAN_AND_MEAN
|
#define WIN32_LEAN_AND_MEAN
|
||||||
#endif
|
#endif
|
||||||
#ifndef __MINGW32__
|
#ifndef __MINGW32__
|
||||||
#include <Windows.h>
|
#define NOMINMAX
|
||||||
|
#include <windows.h>
|
||||||
#else
|
#else
|
||||||
|
#define NOMINMAX
|
||||||
#include <windows.h>
|
#include <windows.h>
|
||||||
#endif
|
#endif
|
||||||
#endif
|
#endif
|
||||||
|
3
3rdparty/imgui/imgui_internal.h
vendored
3
3rdparty/imgui/imgui_internal.h
vendored
@ -27,6 +27,9 @@
|
|||||||
#pragma clang diagnostic ignored "-Wunused-function" // for stb_textedit.h
|
#pragma clang diagnostic ignored "-Wunused-function" // for stb_textedit.h
|
||||||
#pragma clang diagnostic ignored "-Wmissing-prototypes" // for stb_textedit.h
|
#pragma clang diagnostic ignored "-Wmissing-prototypes" // for stb_textedit.h
|
||||||
#pragma clang diagnostic ignored "-Wold-style-cast"
|
#pragma clang diagnostic ignored "-Wold-style-cast"
|
||||||
|
#elif defined(__GNUC__) && __GNUC__ >= 8
|
||||||
|
#pragma GCC diagnostic push
|
||||||
|
#pragma GCC diagnostic ignored "-Wclass-memaccess"
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
//-----------------------------------------------------------------------------
|
//-----------------------------------------------------------------------------
|
||||||
|
5
3rdparty/json11/CMakeLists.txt
vendored
Normal file
5
3rdparty/json11/CMakeLists.txt
vendored
Normal file
@ -0,0 +1,5 @@
|
|||||||
|
add_library(json11 STATIC
|
||||||
|
json11.cpp
|
||||||
|
json11.hpp
|
||||||
|
)
|
||||||
|
target_include_directories(json11 PUBLIC .)
|
19
3rdparty/json11/LICENSE.txt
vendored
Normal file
19
3rdparty/json11/LICENSE.txt
vendored
Normal file
@ -0,0 +1,19 @@
|
|||||||
|
Copyright (c) 2013 Dropbox, Inc.
|
||||||
|
|
||||||
|
Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||||
|
of this software and associated documentation files (the "Software"), to deal
|
||||||
|
in the Software without restriction, including without limitation the rights
|
||||||
|
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||||
|
copies of the Software, and to permit persons to whom the Software is
|
||||||
|
furnished to do so, subject to the following conditions:
|
||||||
|
|
||||||
|
The above copyright notice and this permission notice shall be included in
|
||||||
|
all copies or substantial portions of the Software.
|
||||||
|
|
||||||
|
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||||
|
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||||
|
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||||
|
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||||
|
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||||
|
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
||||||
|
THE SOFTWARE.
|
794
3rdparty/json11/json11.cpp
vendored
Normal file
794
3rdparty/json11/json11.cpp
vendored
Normal file
@ -0,0 +1,794 @@
|
|||||||
|
/* Copyright (c) 2013 Dropbox, Inc.
|
||||||
|
*
|
||||||
|
* Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||||
|
* of this software and associated documentation files (the "Software"), to deal
|
||||||
|
* in the Software without restriction, including without limitation the rights
|
||||||
|
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||||
|
* copies of the Software, and to permit persons to whom the Software is
|
||||||
|
* furnished to do so, subject to the following conditions:
|
||||||
|
*
|
||||||
|
* The above copyright notice and this permission notice shall be included in
|
||||||
|
* all copies or substantial portions of the Software.
|
||||||
|
*
|
||||||
|
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||||
|
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||||
|
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||||
|
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||||
|
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||||
|
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
||||||
|
* THE SOFTWARE.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include "json11.hpp"
|
||||||
|
#include <cassert>
|
||||||
|
#include <cmath>
|
||||||
|
#include <cstdlib>
|
||||||
|
#include <cstdint>
|
||||||
|
#include <cstdio>
|
||||||
|
#include <climits>
|
||||||
|
#include <cerrno>
|
||||||
|
|
||||||
|
namespace json11 {
|
||||||
|
|
||||||
|
static const int max_depth = 200;
|
||||||
|
|
||||||
|
using std::string;
|
||||||
|
using std::vector;
|
||||||
|
using std::map;
|
||||||
|
using std::make_shared;
|
||||||
|
using std::initializer_list;
|
||||||
|
using std::move;
|
||||||
|
|
||||||
|
/* Helper for representing null - just a do-nothing struct, plus comparison
|
||||||
|
* operators so the helpers in JsonValue work. We can't use nullptr_t because
|
||||||
|
* it may not be orderable.
|
||||||
|
*/
|
||||||
|
struct NullStruct {
|
||||||
|
bool operator==(NullStruct) const { return true; }
|
||||||
|
bool operator<(NullStruct) const { return false; }
|
||||||
|
};
|
||||||
|
|
||||||
|
/* * * * * * * * * * * * * * * * * * * *
|
||||||
|
* Serialization
|
||||||
|
*/
|
||||||
|
|
||||||
|
static void dump(NullStruct, string &out) {
|
||||||
|
out += "null";
|
||||||
|
}
|
||||||
|
|
||||||
|
static void dump(double value, string &out) {
|
||||||
|
if (std::isfinite(value)) {
|
||||||
|
char buf[32];
|
||||||
|
snprintf(buf, sizeof buf, "%.17g", value);
|
||||||
|
out += buf;
|
||||||
|
} else {
|
||||||
|
out += "null";
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
static void dump(int value, string &out) {
|
||||||
|
char buf[32];
|
||||||
|
snprintf(buf, sizeof buf, "%d", value);
|
||||||
|
out += buf;
|
||||||
|
}
|
||||||
|
|
||||||
|
static void dump(bool value, string &out) {
|
||||||
|
out += value ? "true" : "false";
|
||||||
|
}
|
||||||
|
|
||||||
|
static void dump(const string &value, string &out) {
|
||||||
|
out += '"';
|
||||||
|
for (size_t i = 0; i < value.length(); i++) {
|
||||||
|
const char ch = value[i];
|
||||||
|
if (ch == '\\') {
|
||||||
|
out += "\\\\";
|
||||||
|
} else if (ch == '"') {
|
||||||
|
out += "\\\"";
|
||||||
|
} else if (ch == '\b') {
|
||||||
|
out += "\\b";
|
||||||
|
} else if (ch == '\f') {
|
||||||
|
out += "\\f";
|
||||||
|
} else if (ch == '\n') {
|
||||||
|
out += "\\n";
|
||||||
|
} else if (ch == '\r') {
|
||||||
|
out += "\\r";
|
||||||
|
} else if (ch == '\t') {
|
||||||
|
out += "\\t";
|
||||||
|
} else if (static_cast<uint8_t>(ch) <= 0x1f) {
|
||||||
|
char buf[8];
|
||||||
|
snprintf(buf, sizeof buf, "\\u%04x", ch);
|
||||||
|
out += buf;
|
||||||
|
} else if (static_cast<uint8_t>(ch) == 0xe2 && static_cast<uint8_t>(value[i+1]) == 0x80
|
||||||
|
&& static_cast<uint8_t>(value[i+2]) == 0xa8) {
|
||||||
|
out += "\\u2028";
|
||||||
|
i += 2;
|
||||||
|
} else if (static_cast<uint8_t>(ch) == 0xe2 && static_cast<uint8_t>(value[i+1]) == 0x80
|
||||||
|
&& static_cast<uint8_t>(value[i+2]) == 0xa9) {
|
||||||
|
out += "\\u2029";
|
||||||
|
i += 2;
|
||||||
|
} else {
|
||||||
|
out += ch;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
out += '"';
|
||||||
|
}
|
||||||
|
|
||||||
|
static void dump(const Json::array &values, string &out) {
|
||||||
|
bool first = true;
|
||||||
|
out += "[";
|
||||||
|
for (const auto &value : values) {
|
||||||
|
if (!first)
|
||||||
|
out += ", ";
|
||||||
|
value.dump(out);
|
||||||
|
first = false;
|
||||||
|
}
|
||||||
|
out += "]";
|
||||||
|
}
|
||||||
|
|
||||||
|
static void dump(const Json::object &values, string &out) {
|
||||||
|
bool first = true;
|
||||||
|
out += "{";
|
||||||
|
for (const auto &kv : values) {
|
||||||
|
if (!first)
|
||||||
|
out += ", ";
|
||||||
|
dump(kv.first, out);
|
||||||
|
out += ": ";
|
||||||
|
kv.second.dump(out);
|
||||||
|
first = false;
|
||||||
|
}
|
||||||
|
out += "}";
|
||||||
|
}
|
||||||
|
|
||||||
|
void Json::dump(string &out) const {
|
||||||
|
m_ptr->dump(out);
|
||||||
|
}
|
||||||
|
|
||||||
|
/* * * * * * * * * * * * * * * * * * * *
|
||||||
|
* Value wrappers
|
||||||
|
*/
|
||||||
|
|
||||||
|
template <Json::Type tag, typename T>
|
||||||
|
class Value : public JsonValue {
|
||||||
|
protected:
|
||||||
|
|
||||||
|
// Constructors
|
||||||
|
explicit Value(const T &value) : m_value(value) {}
|
||||||
|
explicit Value(T &&value) : m_value(std::move(value)) {}
|
||||||
|
|
||||||
|
// Get type tag
|
||||||
|
Json::Type type() const override {
|
||||||
|
return tag;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Comparisons
|
||||||
|
bool equals(const JsonValue * other) const override {
|
||||||
|
return m_value == static_cast<const Value<tag, T> *>(other)->m_value;
|
||||||
|
}
|
||||||
|
bool less(const JsonValue * other) const override {
|
||||||
|
return m_value < static_cast<const Value<tag, T> *>(other)->m_value;
|
||||||
|
}
|
||||||
|
|
||||||
|
const T m_value;
|
||||||
|
void dump(string &out) const override { json11::dump(m_value, out); }
|
||||||
|
};
|
||||||
|
|
||||||
|
class JsonDouble final : public Value<Json::NUMBER, double> {
|
||||||
|
double number_value() const override { return m_value; }
|
||||||
|
int int_value() const override { return static_cast<int>(m_value); }
|
||||||
|
bool equals(const JsonValue * other) const override { return m_value == other->number_value(); }
|
||||||
|
bool less(const JsonValue * other) const override { return m_value < other->number_value(); }
|
||||||
|
public:
|
||||||
|
explicit JsonDouble(double value) : Value(value) {}
|
||||||
|
};
|
||||||
|
|
||||||
|
class JsonInt final : public Value<Json::NUMBER, int> {
|
||||||
|
double number_value() const override { return m_value; }
|
||||||
|
int int_value() const override { return m_value; }
|
||||||
|
bool equals(const JsonValue * other) const override { return m_value == other->number_value(); }
|
||||||
|
bool less(const JsonValue * other) const override { return m_value < other->number_value(); }
|
||||||
|
public:
|
||||||
|
explicit JsonInt(int value) : Value(value) {}
|
||||||
|
};
|
||||||
|
|
||||||
|
class JsonBoolean final : public Value<Json::BOOL, bool> {
|
||||||
|
bool bool_value() const override { return m_value; }
|
||||||
|
public:
|
||||||
|
explicit JsonBoolean(bool value) : Value(value) {}
|
||||||
|
};
|
||||||
|
|
||||||
|
class JsonString final : public Value<Json::STRING, string> {
|
||||||
|
const string &string_value() const override { return m_value; }
|
||||||
|
public:
|
||||||
|
explicit JsonString(const string &value) : Value(value) {}
|
||||||
|
explicit JsonString(string &&value) : Value(std::move(value)) {}
|
||||||
|
};
|
||||||
|
|
||||||
|
class JsonArray final : public Value<Json::ARRAY, Json::array> {
|
||||||
|
const Json::array &array_items() const override { return m_value; }
|
||||||
|
const Json & operator[](size_t i) const override;
|
||||||
|
public:
|
||||||
|
explicit JsonArray(const Json::array &value) : Value(value) {}
|
||||||
|
explicit JsonArray(Json::array &&value) : Value(std::move(value)) {}
|
||||||
|
};
|
||||||
|
|
||||||
|
class JsonObject final : public Value<Json::OBJECT, Json::object> {
|
||||||
|
const Json::object &object_items() const override { return m_value; }
|
||||||
|
const Json & operator[](const string &key) const override;
|
||||||
|
public:
|
||||||
|
explicit JsonObject(const Json::object &value) : Value(value) {}
|
||||||
|
explicit JsonObject(Json::object &&value) : Value(std::move(value)) {}
|
||||||
|
};
|
||||||
|
|
||||||
|
class JsonNull final : public Value<Json::NUL, NullStruct> {
|
||||||
|
public:
|
||||||
|
JsonNull() : Value({}) {}
|
||||||
|
};
|
||||||
|
|
||||||
|
/* * * * * * * * * * * * * * * * * * * *
|
||||||
|
* Static globals - static-init-safe
|
||||||
|
*/
|
||||||
|
struct Statics {
|
||||||
|
const std::shared_ptr<JsonValue> null = make_shared<JsonNull>();
|
||||||
|
const std::shared_ptr<JsonValue> t = make_shared<JsonBoolean>(true);
|
||||||
|
const std::shared_ptr<JsonValue> f = make_shared<JsonBoolean>(false);
|
||||||
|
const string empty_string;
|
||||||
|
const vector<Json> empty_vector;
|
||||||
|
const map<string, Json> empty_map;
|
||||||
|
Statics() {}
|
||||||
|
};
|
||||||
|
|
||||||
|
static const Statics & statics() {
|
||||||
|
static const Statics s {};
|
||||||
|
return s;
|
||||||
|
}
|
||||||
|
|
||||||
|
static const Json & static_null() {
|
||||||
|
// This has to be separate, not in Statics, because Json() accesses statics().null.
|
||||||
|
static const Json json_null;
|
||||||
|
return json_null;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* * * * * * * * * * * * * * * * * * * *
|
||||||
|
* Constructors
|
||||||
|
*/
|
||||||
|
|
||||||
|
Json::Json() noexcept : m_ptr(statics().null) {}
|
||||||
|
Json::Json(std::nullptr_t) noexcept : m_ptr(statics().null) {}
|
||||||
|
Json::Json(double value) : m_ptr(make_shared<JsonDouble>(value)) {}
|
||||||
|
Json::Json(int value) : m_ptr(make_shared<JsonInt>(value)) {}
|
||||||
|
Json::Json(bool value) : m_ptr(value ? statics().t : statics().f) {}
|
||||||
|
Json::Json(const string &value) : m_ptr(make_shared<JsonString>(value)) {}
|
||||||
|
Json::Json(string &&value) : m_ptr(make_shared<JsonString>(std::move(value))) {}
|
||||||
|
Json::Json(const char * value) : m_ptr(make_shared<JsonString>(value)) {}
|
||||||
|
Json::Json(const Json::array &values) : m_ptr(make_shared<JsonArray>(values)) {}
|
||||||
|
Json::Json(Json::array &&values) : m_ptr(make_shared<JsonArray>(std::move(values))) {}
|
||||||
|
Json::Json(const Json::object &values) : m_ptr(make_shared<JsonObject>(values)) {}
|
||||||
|
Json::Json(Json::object &&values) : m_ptr(make_shared<JsonObject>(std::move(values))) {}
|
||||||
|
|
||||||
|
/* * * * * * * * * * * * * * * * * * * *
|
||||||
|
* Accessors
|
||||||
|
*/
|
||||||
|
|
||||||
|
Json::Type Json::type() const { return m_ptr->type(); }
|
||||||
|
double Json::number_value() const { return m_ptr->number_value(); }
|
||||||
|
int Json::int_value() const { return m_ptr->int_value(); }
|
||||||
|
bool Json::bool_value() const { return m_ptr->bool_value(); }
|
||||||
|
const string & Json::string_value() const { return m_ptr->string_value(); }
|
||||||
|
const vector<Json> & Json::array_items() const { return m_ptr->array_items(); }
|
||||||
|
const map<string, Json> & Json::object_items() const { return m_ptr->object_items(); }
|
||||||
|
const Json & Json::operator[] (size_t i) const { return (*m_ptr)[i]; }
|
||||||
|
const Json & Json::operator[] (const string &key) const { return (*m_ptr)[key]; }
|
||||||
|
|
||||||
|
double JsonValue::number_value() const { return 0; }
|
||||||
|
int JsonValue::int_value() const { return 0; }
|
||||||
|
bool JsonValue::bool_value() const { return false; }
|
||||||
|
const string & JsonValue::string_value() const { return statics().empty_string; }
|
||||||
|
const vector<Json> & JsonValue::array_items() const { return statics().empty_vector; }
|
||||||
|
const map<string, Json> & JsonValue::object_items() const { return statics().empty_map; }
|
||||||
|
const Json & JsonValue::operator[] (size_t) const { return static_null(); }
|
||||||
|
const Json & JsonValue::operator[] (const string &) const { return static_null(); }
|
||||||
|
|
||||||
|
const Json & JsonObject::operator[] (const string &key) const {
|
||||||
|
auto iter = m_value.find(key);
|
||||||
|
return (iter == m_value.end()) ? static_null() : iter->second;
|
||||||
|
}
|
||||||
|
const Json & JsonArray::operator[] (size_t i) const {
|
||||||
|
if (i >= m_value.size()) return static_null();
|
||||||
|
else return m_value[i];
|
||||||
|
}
|
||||||
|
|
||||||
|
/* * * * * * * * * * * * * * * * * * * *
|
||||||
|
* Comparison
|
||||||
|
*/
|
||||||
|
|
||||||
|
bool Json::operator== (const Json &other) const {
|
||||||
|
if (m_ptr == other.m_ptr)
|
||||||
|
return true;
|
||||||
|
if (m_ptr->type() != other.m_ptr->type())
|
||||||
|
return false;
|
||||||
|
|
||||||
|
return m_ptr->equals(other.m_ptr.get());
|
||||||
|
}
|
||||||
|
|
||||||
|
bool Json::operator< (const Json &other) const {
|
||||||
|
if (m_ptr == other.m_ptr)
|
||||||
|
return false;
|
||||||
|
if (m_ptr->type() != other.m_ptr->type())
|
||||||
|
return m_ptr->type() < other.m_ptr->type();
|
||||||
|
|
||||||
|
return m_ptr->less(other.m_ptr.get());
|
||||||
|
}
|
||||||
|
|
||||||
|
/* * * * * * * * * * * * * * * * * * * *
|
||||||
|
* Parsing
|
||||||
|
*/
|
||||||
|
|
||||||
|
/* esc(c)
|
||||||
|
*
|
||||||
|
* Format char c suitable for printing in an error message.
|
||||||
|
*/
|
||||||
|
static inline string esc(char c) {
|
||||||
|
char buf[12];
|
||||||
|
if (static_cast<uint8_t>(c) >= 0x20 && static_cast<uint8_t>(c) <= 0x7f) {
|
||||||
|
snprintf(buf, sizeof buf, "'%c' (%d)", c, c);
|
||||||
|
} else {
|
||||||
|
snprintf(buf, sizeof buf, "(%d)", c);
|
||||||
|
}
|
||||||
|
return string(buf);
|
||||||
|
}
|
||||||
|
|
||||||
|
static inline bool in_range(long x, long lower, long upper) {
|
||||||
|
return (x >= lower && x <= upper);
|
||||||
|
}
|
||||||
|
|
||||||
|
namespace {
|
||||||
|
/* JsonParser
|
||||||
|
*
|
||||||
|
* Object that tracks all state of an in-progress parse.
|
||||||
|
*/
|
||||||
|
struct JsonParser final {
|
||||||
|
|
||||||
|
/* State
|
||||||
|
*/
|
||||||
|
const string &str;
|
||||||
|
size_t i;
|
||||||
|
string &err;
|
||||||
|
bool failed;
|
||||||
|
const JsonParse strategy;
|
||||||
|
|
||||||
|
/* fail(msg, err_ret = Json())
|
||||||
|
*
|
||||||
|
* Mark this parse as failed.
|
||||||
|
*/
|
||||||
|
Json fail(string &&msg) {
|
||||||
|
return fail(std::move(msg), Json());
|
||||||
|
}
|
||||||
|
|
||||||
|
template <typename T>
|
||||||
|
T fail(string &&msg, const T err_ret) {
|
||||||
|
if (!failed)
|
||||||
|
err = std::move(msg);
|
||||||
|
failed = true;
|
||||||
|
return err_ret;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* consume_whitespace()
|
||||||
|
*
|
||||||
|
* Advance until the current character is non-whitespace.
|
||||||
|
*/
|
||||||
|
void consume_whitespace() {
|
||||||
|
while (str[i] == ' ' || str[i] == '\r' || str[i] == '\n' || str[i] == '\t')
|
||||||
|
i++;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* consume_comment()
|
||||||
|
*
|
||||||
|
* Advance comments (c-style inline and multiline).
|
||||||
|
*/
|
||||||
|
bool consume_comment() {
|
||||||
|
bool comment_found = false;
|
||||||
|
if (str[i] == '/') {
|
||||||
|
i++;
|
||||||
|
if (i == str.size())
|
||||||
|
return fail("unexpected end of input after start of comment", false);
|
||||||
|
if (str[i] == '/') { // inline comment
|
||||||
|
i++;
|
||||||
|
// advance until next line, or end of input
|
||||||
|
while (i < str.size() && str[i] != '\n') {
|
||||||
|
i++;
|
||||||
|
}
|
||||||
|
comment_found = true;
|
||||||
|
}
|
||||||
|
else if (str[i] == '*') { // multiline comment
|
||||||
|
i++;
|
||||||
|
if (i > str.size()-2)
|
||||||
|
return fail("unexpected end of input inside multi-line comment", false);
|
||||||
|
// advance until closing tokens
|
||||||
|
while (!(str[i] == '*' && str[i+1] == '/')) {
|
||||||
|
i++;
|
||||||
|
if (i > str.size()-2)
|
||||||
|
return fail(
|
||||||
|
"unexpected end of input inside multi-line comment", false);
|
||||||
|
}
|
||||||
|
i += 2;
|
||||||
|
comment_found = true;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
return fail("malformed comment", false);
|
||||||
|
}
|
||||||
|
return comment_found;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* consume_garbage()
|
||||||
|
*
|
||||||
|
* Advance until the current character is non-whitespace and non-comment.
|
||||||
|
*/
|
||||||
|
void consume_garbage() {
|
||||||
|
consume_whitespace();
|
||||||
|
if(strategy == JsonParse::COMMENTS) {
|
||||||
|
bool comment_found = false;
|
||||||
|
do {
|
||||||
|
comment_found = consume_comment();
|
||||||
|
if (failed) return;
|
||||||
|
consume_whitespace();
|
||||||
|
}
|
||||||
|
while(comment_found);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/* get_next_token()
|
||||||
|
*
|
||||||
|
* Return the next non-whitespace character. If the end of the input is reached,
|
||||||
|
* flag an error and return 0.
|
||||||
|
*/
|
||||||
|
char get_next_token() {
|
||||||
|
consume_garbage();
|
||||||
|
if (failed) return static_cast<char>(0);
|
||||||
|
if (i == str.size())
|
||||||
|
return fail("unexpected end of input", static_cast<char>(0));
|
||||||
|
|
||||||
|
return str[i++];
|
||||||
|
}
|
||||||
|
|
||||||
|
/* encode_utf8(pt, out)
|
||||||
|
*
|
||||||
|
* Encode pt as UTF-8 and add it to out.
|
||||||
|
*/
|
||||||
|
void encode_utf8(long pt, string & out) {
|
||||||
|
if (pt < 0)
|
||||||
|
return;
|
||||||
|
|
||||||
|
if (pt < 0x80) {
|
||||||
|
out += static_cast<char>(pt);
|
||||||
|
} else if (pt < 0x800) {
|
||||||
|
out += static_cast<char>((pt >> 6) | 0xC0);
|
||||||
|
out += static_cast<char>((pt & 0x3F) | 0x80);
|
||||||
|
} else if (pt < 0x10000) {
|
||||||
|
out += static_cast<char>((pt >> 12) | 0xE0);
|
||||||
|
out += static_cast<char>(((pt >> 6) & 0x3F) | 0x80);
|
||||||
|
out += static_cast<char>((pt & 0x3F) | 0x80);
|
||||||
|
} else {
|
||||||
|
out += static_cast<char>((pt >> 18) | 0xF0);
|
||||||
|
out += static_cast<char>(((pt >> 12) & 0x3F) | 0x80);
|
||||||
|
out += static_cast<char>(((pt >> 6) & 0x3F) | 0x80);
|
||||||
|
out += static_cast<char>((pt & 0x3F) | 0x80);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/* parse_string()
|
||||||
|
*
|
||||||
|
* Parse a string, starting at the current position.
|
||||||
|
*/
|
||||||
|
string parse_string() {
|
||||||
|
string out;
|
||||||
|
long last_escaped_codepoint = -1;
|
||||||
|
while (true) {
|
||||||
|
if (i == str.size())
|
||||||
|
return fail("unexpected end of input in string", "");
|
||||||
|
|
||||||
|
char ch = str[i++];
|
||||||
|
|
||||||
|
if (ch == '"') {
|
||||||
|
encode_utf8(last_escaped_codepoint, out);
|
||||||
|
return out;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (in_range(ch, 0, 0x1f))
|
||||||
|
return fail("unescaped " + esc(ch) + " in string", "");
|
||||||
|
|
||||||
|
// The usual case: non-escaped characters
|
||||||
|
if (ch != '\\') {
|
||||||
|
encode_utf8(last_escaped_codepoint, out);
|
||||||
|
last_escaped_codepoint = -1;
|
||||||
|
out += ch;
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Handle escapes
|
||||||
|
if (i == str.size())
|
||||||
|
return fail("unexpected end of input in string", "");
|
||||||
|
|
||||||
|
ch = str[i++];
|
||||||
|
|
||||||
|
if (ch == 'u') {
|
||||||
|
// Extract 4-byte escape sequence
|
||||||
|
string esc = str.substr(i, 4);
|
||||||
|
// Explicitly check length of the substring. The following loop
|
||||||
|
// relies on std::string returning the terminating NUL when
|
||||||
|
// accessing str[length]. Checking here reduces brittleness.
|
||||||
|
if (esc.length() < 4) {
|
||||||
|
return fail("bad \\u escape: " + esc, "");
|
||||||
|
}
|
||||||
|
for (size_t j = 0; j < 4; j++) {
|
||||||
|
if (!in_range(esc[j], 'a', 'f') && !in_range(esc[j], 'A', 'F')
|
||||||
|
&& !in_range(esc[j], '0', '9'))
|
||||||
|
return fail("bad \\u escape: " + esc, "");
|
||||||
|
}
|
||||||
|
|
||||||
|
long codepoint = strtol(esc.data(), nullptr, 16);
|
||||||
|
|
||||||
|
// JSON specifies that characters outside the BMP shall be encoded as a pair
|
||||||
|
// of 4-hex-digit \u escapes encoding their surrogate pair components. Check
|
||||||
|
// whether we're in the middle of such a beast: the previous codepoint was an
|
||||||
|
// escaped lead (high) surrogate, and this is a trail (low) surrogate.
|
||||||
|
if (in_range(last_escaped_codepoint, 0xD800, 0xDBFF)
|
||||||
|
&& in_range(codepoint, 0xDC00, 0xDFFF)) {
|
||||||
|
// Reassemble the two surrogate pairs into one astral-plane character, per
|
||||||
|
// the UTF-16 algorithm.
|
||||||
|
encode_utf8((((last_escaped_codepoint - 0xD800) << 10)
|
||||||
|
| (codepoint - 0xDC00)) + 0x10000, out);
|
||||||
|
last_escaped_codepoint = -1;
|
||||||
|
} else {
|
||||||
|
encode_utf8(last_escaped_codepoint, out);
|
||||||
|
last_escaped_codepoint = codepoint;
|
||||||
|
}
|
||||||
|
|
||||||
|
i += 4;
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
encode_utf8(last_escaped_codepoint, out);
|
||||||
|
last_escaped_codepoint = -1;
|
||||||
|
|
||||||
|
if (ch == 'b') {
|
||||||
|
out += '\b';
|
||||||
|
} else if (ch == 'f') {
|
||||||
|
out += '\f';
|
||||||
|
} else if (ch == 'n') {
|
||||||
|
out += '\n';
|
||||||
|
} else if (ch == 'r') {
|
||||||
|
out += '\r';
|
||||||
|
} else if (ch == 't') {
|
||||||
|
out += '\t';
|
||||||
|
} else if (ch == '"' || ch == '\\' || ch == '/') {
|
||||||
|
out += ch;
|
||||||
|
} else {
|
||||||
|
return fail("invalid escape character " + esc(ch), "");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/* parse_number()
|
||||||
|
*
|
||||||
|
* Parse a double.
|
||||||
|
*/
|
||||||
|
Json parse_number() {
|
||||||
|
size_t start_pos = i;
|
||||||
|
|
||||||
|
if (str[i] == '-')
|
||||||
|
i++;
|
||||||
|
|
||||||
|
// Integer part
|
||||||
|
if (str[i] == '0') {
|
||||||
|
i++;
|
||||||
|
if (in_range(str[i], '0', '9'))
|
||||||
|
return fail("leading 0s not permitted in numbers");
|
||||||
|
} else if (in_range(str[i], '1', '9')) {
|
||||||
|
i++;
|
||||||
|
while (in_range(str[i], '0', '9'))
|
||||||
|
i++;
|
||||||
|
} else {
|
||||||
|
return fail("invalid " + esc(str[i]) + " in number");
|
||||||
|
}
|
||||||
|
|
||||||
|
if (str[i] != '.' && str[i] != 'e' && str[i] != 'E') {
|
||||||
|
errno = 0;
|
||||||
|
long val = std::strtol(str.c_str() + start_pos, nullptr, 0);
|
||||||
|
if (!errno && val >= INT_MIN && val <= INT_MAX)
|
||||||
|
return int(val);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Decimal part
|
||||||
|
if (str[i] == '.') {
|
||||||
|
i++;
|
||||||
|
if (!in_range(str[i], '0', '9'))
|
||||||
|
return fail("at least one digit required in fractional part");
|
||||||
|
|
||||||
|
while (in_range(str[i], '0', '9'))
|
||||||
|
i++;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Exponent part
|
||||||
|
if (str[i] == 'e' || str[i] == 'E') {
|
||||||
|
i++;
|
||||||
|
|
||||||
|
if (str[i] == '+' || str[i] == '-')
|
||||||
|
i++;
|
||||||
|
|
||||||
|
if (!in_range(str[i], '0', '9'))
|
||||||
|
return fail("at least one digit required in exponent");
|
||||||
|
|
||||||
|
while (in_range(str[i], '0', '9'))
|
||||||
|
i++;
|
||||||
|
}
|
||||||
|
|
||||||
|
return std::strtod(str.c_str() + start_pos, nullptr);
|
||||||
|
}
|
||||||
|
|
||||||
|
/* expect(str, res)
|
||||||
|
*
|
||||||
|
* Expect that 'str' starts at the character that was just read. If it does, advance
|
||||||
|
* the input and return res. If not, flag an error.
|
||||||
|
*/
|
||||||
|
Json expect(const string &expected, Json res) {
|
||||||
|
assert(i != 0);
|
||||||
|
i--;
|
||||||
|
if (str.compare(i, expected.length(), expected) == 0) {
|
||||||
|
i += expected.length();
|
||||||
|
return res;
|
||||||
|
} else {
|
||||||
|
return fail("parse error: expected " + expected + ", got " + str.substr(i, expected.length()));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/* parse_json()
|
||||||
|
*
|
||||||
|
* Parse a JSON object.
|
||||||
|
*/
|
||||||
|
Json parse_json(int depth) {
|
||||||
|
if (depth > max_depth) {
|
||||||
|
return fail("exceeded maximum nesting depth");
|
||||||
|
}
|
||||||
|
|
||||||
|
char ch = get_next_token();
|
||||||
|
if (failed)
|
||||||
|
return Json();
|
||||||
|
|
||||||
|
if (ch == '-' || (ch >= '0' && ch <= '9')) {
|
||||||
|
i--;
|
||||||
|
return parse_number();
|
||||||
|
}
|
||||||
|
|
||||||
|
if (ch == 't')
|
||||||
|
return expect("true", true);
|
||||||
|
|
||||||
|
if (ch == 'f')
|
||||||
|
return expect("false", false);
|
||||||
|
|
||||||
|
if (ch == 'n')
|
||||||
|
return expect("null", Json());
|
||||||
|
|
||||||
|
if (ch == '"')
|
||||||
|
return parse_string();
|
||||||
|
|
||||||
|
if (ch == '{') {
|
||||||
|
map<string, Json> data;
|
||||||
|
ch = get_next_token();
|
||||||
|
if (ch == '}')
|
||||||
|
return data;
|
||||||
|
|
||||||
|
while (1) {
|
||||||
|
if (ch != '"')
|
||||||
|
return fail("expected '\"' in object, got " + esc(ch));
|
||||||
|
|
||||||
|
string key = parse_string();
|
||||||
|
if (failed)
|
||||||
|
return Json();
|
||||||
|
|
||||||
|
ch = get_next_token();
|
||||||
|
if (ch != ':')
|
||||||
|
return fail("expected ':' in object, got " + esc(ch));
|
||||||
|
|
||||||
|
data[std::move(key)] = parse_json(depth + 1);
|
||||||
|
if (failed)
|
||||||
|
return Json();
|
||||||
|
|
||||||
|
ch = get_next_token();
|
||||||
|
if (ch == '}')
|
||||||
|
break;
|
||||||
|
if (ch != ',')
|
||||||
|
return fail("expected ',' in object, got " + esc(ch));
|
||||||
|
|
||||||
|
ch = get_next_token();
|
||||||
|
}
|
||||||
|
return data;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (ch == '[') {
|
||||||
|
vector<Json> data;
|
||||||
|
ch = get_next_token();
|
||||||
|
if (ch == ']')
|
||||||
|
return data;
|
||||||
|
|
||||||
|
while (1) {
|
||||||
|
i--;
|
||||||
|
data.push_back(parse_json(depth + 1));
|
||||||
|
if (failed)
|
||||||
|
return Json();
|
||||||
|
|
||||||
|
ch = get_next_token();
|
||||||
|
if (ch == ']')
|
||||||
|
break;
|
||||||
|
if (ch != ',')
|
||||||
|
return fail("expected ',' in list, got " + esc(ch));
|
||||||
|
|
||||||
|
ch = get_next_token();
|
||||||
|
(void)ch;
|
||||||
|
}
|
||||||
|
return data;
|
||||||
|
}
|
||||||
|
|
||||||
|
return fail("expected value, got " + esc(ch));
|
||||||
|
}
|
||||||
|
};
|
||||||
|
}//namespace {
|
||||||
|
|
||||||
|
Json Json::parse(const string &in, string &err, JsonParse strategy) {
|
||||||
|
JsonParser parser { in, 0, err, false, strategy };
|
||||||
|
Json result = parser.parse_json(0);
|
||||||
|
|
||||||
|
// Check for any trailing garbage
|
||||||
|
parser.consume_garbage();
|
||||||
|
if (parser.failed)
|
||||||
|
return Json();
|
||||||
|
if (parser.i != in.size())
|
||||||
|
return parser.fail("unexpected trailing " + esc(in[parser.i]));
|
||||||
|
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Documented in json11.hpp
|
||||||
|
vector<Json> Json::parse_multi(const string &in,
|
||||||
|
std::string::size_type &parser_stop_pos,
|
||||||
|
string &err,
|
||||||
|
JsonParse strategy) {
|
||||||
|
JsonParser parser { in, 0, err, false, strategy };
|
||||||
|
parser_stop_pos = 0;
|
||||||
|
vector<Json> json_vec;
|
||||||
|
while (parser.i != in.size() && !parser.failed) {
|
||||||
|
json_vec.push_back(parser.parse_json(0));
|
||||||
|
if (parser.failed)
|
||||||
|
break;
|
||||||
|
|
||||||
|
// Check for another object
|
||||||
|
parser.consume_garbage();
|
||||||
|
if (parser.failed)
|
||||||
|
break;
|
||||||
|
parser_stop_pos = parser.i;
|
||||||
|
}
|
||||||
|
return json_vec;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* * * * * * * * * * * * * * * * * * * *
|
||||||
|
* Shape-checking
|
||||||
|
*/
|
||||||
|
|
||||||
|
bool Json::has_shape(const shape & types, string & err) const {
|
||||||
|
if (!is_object()) {
|
||||||
|
err = "expected JSON object, got " + dump();
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
const auto& obj_items = object_items();
|
||||||
|
for (auto & item : types) {
|
||||||
|
const auto it = obj_items.find(item.first);
|
||||||
|
if (it == obj_items.cend() || it->second.type() != item.second) {
|
||||||
|
err = "bad type for " + item.first + " in " + dump();
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
} // namespace json11
|
232
3rdparty/json11/json11.hpp
vendored
Normal file
232
3rdparty/json11/json11.hpp
vendored
Normal file
@ -0,0 +1,232 @@
|
|||||||
|
/* json11
|
||||||
|
*
|
||||||
|
* json11 is a tiny JSON library for C++11, providing JSON parsing and serialization.
|
||||||
|
*
|
||||||
|
* The core object provided by the library is json11::Json. A Json object represents any JSON
|
||||||
|
* value: null, bool, number (int or double), string (std::string), array (std::vector), or
|
||||||
|
* object (std::map).
|
||||||
|
*
|
||||||
|
* Json objects act like values: they can be assigned, copied, moved, compared for equality or
|
||||||
|
* order, etc. There are also helper methods Json::dump, to serialize a Json to a string, and
|
||||||
|
* Json::parse (static) to parse a std::string as a Json object.
|
||||||
|
*
|
||||||
|
* Internally, the various types of Json object are represented by the JsonValue class
|
||||||
|
* hierarchy.
|
||||||
|
*
|
||||||
|
* A note on numbers - JSON specifies the syntax of number formatting but not its semantics,
|
||||||
|
* so some JSON implementations distinguish between integers and floating-point numbers, while
|
||||||
|
* some don't. In json11, we choose the latter. Because some JSON implementations (namely
|
||||||
|
* Javascript itself) treat all numbers as the same type, distinguishing the two leads
|
||||||
|
* to JSON that will be *silently* changed by a round-trip through those implementations.
|
||||||
|
* Dangerous! To avoid that risk, json11 stores all numbers as double internally, but also
|
||||||
|
* provides integer helpers.
|
||||||
|
*
|
||||||
|
* Fortunately, double-precision IEEE754 ('double') can precisely store any integer in the
|
||||||
|
* range +/-2^53, which includes every 'int' on most systems. (Timestamps often use int64
|
||||||
|
* or long long to avoid the Y2038K problem; a double storing microseconds since some epoch
|
||||||
|
* will be exact for +/- 275 years.)
|
||||||
|
*/
|
||||||
|
|
||||||
|
/* Copyright (c) 2013 Dropbox, Inc.
|
||||||
|
*
|
||||||
|
* Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||||
|
* of this software and associated documentation files (the "Software"), to deal
|
||||||
|
* in the Software without restriction, including without limitation the rights
|
||||||
|
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||||
|
* copies of the Software, and to permit persons to whom the Software is
|
||||||
|
* furnished to do so, subject to the following conditions:
|
||||||
|
*
|
||||||
|
* The above copyright notice and this permission notice shall be included in
|
||||||
|
* all copies or substantial portions of the Software.
|
||||||
|
*
|
||||||
|
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||||
|
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||||
|
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||||
|
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||||
|
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||||
|
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
||||||
|
* THE SOFTWARE.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#pragma once
|
||||||
|
|
||||||
|
#include <string>
|
||||||
|
#include <vector>
|
||||||
|
#include <map>
|
||||||
|
#include <memory>
|
||||||
|
#include <initializer_list>
|
||||||
|
|
||||||
|
#ifdef _MSC_VER
|
||||||
|
#if _MSC_VER <= 1800 // VS 2013
|
||||||
|
#ifndef noexcept
|
||||||
|
#define noexcept throw()
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#ifndef snprintf
|
||||||
|
#define snprintf _snprintf_s
|
||||||
|
#endif
|
||||||
|
#endif
|
||||||
|
#endif
|
||||||
|
|
||||||
|
namespace json11 {
|
||||||
|
|
||||||
|
enum JsonParse {
|
||||||
|
STANDARD, COMMENTS
|
||||||
|
};
|
||||||
|
|
||||||
|
class JsonValue;
|
||||||
|
|
||||||
|
class Json final {
|
||||||
|
public:
|
||||||
|
// Types
|
||||||
|
enum Type {
|
||||||
|
NUL, NUMBER, BOOL, STRING, ARRAY, OBJECT
|
||||||
|
};
|
||||||
|
|
||||||
|
// Array and object typedefs
|
||||||
|
typedef std::vector<Json> array;
|
||||||
|
typedef std::map<std::string, Json> object;
|
||||||
|
|
||||||
|
// Constructors for the various types of JSON value.
|
||||||
|
Json() noexcept; // NUL
|
||||||
|
Json(std::nullptr_t) noexcept; // NUL
|
||||||
|
Json(double value); // NUMBER
|
||||||
|
Json(int value); // NUMBER
|
||||||
|
Json(bool value); // BOOL
|
||||||
|
Json(const std::string &value); // STRING
|
||||||
|
Json(std::string &&value); // STRING
|
||||||
|
Json(const char * value); // STRING
|
||||||
|
Json(const array &values); // ARRAY
|
||||||
|
Json(array &&values); // ARRAY
|
||||||
|
Json(const object &values); // OBJECT
|
||||||
|
Json(object &&values); // OBJECT
|
||||||
|
|
||||||
|
// Implicit constructor: anything with a to_json() function.
|
||||||
|
template <class T, class = decltype(&T::to_json)>
|
||||||
|
Json(const T & t) : Json(t.to_json()) {}
|
||||||
|
|
||||||
|
// Implicit constructor: map-like objects (std::map, std::unordered_map, etc)
|
||||||
|
template <class M, typename std::enable_if<
|
||||||
|
std::is_constructible<std::string, decltype(std::declval<M>().begin()->first)>::value
|
||||||
|
&& std::is_constructible<Json, decltype(std::declval<M>().begin()->second)>::value,
|
||||||
|
int>::type = 0>
|
||||||
|
Json(const M & m) : Json(object(m.begin(), m.end())) {}
|
||||||
|
|
||||||
|
// Implicit constructor: vector-like objects (std::list, std::vector, std::set, etc)
|
||||||
|
template <class V, typename std::enable_if<
|
||||||
|
std::is_constructible<Json, decltype(*std::declval<V>().begin())>::value,
|
||||||
|
int>::type = 0>
|
||||||
|
Json(const V & v) : Json(array(v.begin(), v.end())) {}
|
||||||
|
|
||||||
|
// This prevents Json(some_pointer) from accidentally producing a bool. Use
|
||||||
|
// Json(bool(some_pointer)) if that behavior is desired.
|
||||||
|
Json(void *) = delete;
|
||||||
|
|
||||||
|
// Accessors
|
||||||
|
Type type() const;
|
||||||
|
|
||||||
|
bool is_null() const { return type() == NUL; }
|
||||||
|
bool is_number() const { return type() == NUMBER; }
|
||||||
|
bool is_bool() const { return type() == BOOL; }
|
||||||
|
bool is_string() const { return type() == STRING; }
|
||||||
|
bool is_array() const { return type() == ARRAY; }
|
||||||
|
bool is_object() const { return type() == OBJECT; }
|
||||||
|
|
||||||
|
// Return the enclosed value if this is a number, 0 otherwise. Note that json11 does not
|
||||||
|
// distinguish between integer and non-integer numbers - number_value() and int_value()
|
||||||
|
// can both be applied to a NUMBER-typed object.
|
||||||
|
double number_value() const;
|
||||||
|
int int_value() const;
|
||||||
|
|
||||||
|
// Return the enclosed value if this is a boolean, false otherwise.
|
||||||
|
bool bool_value() const;
|
||||||
|
// Return the enclosed string if this is a string, "" otherwise.
|
||||||
|
const std::string &string_value() const;
|
||||||
|
// Return the enclosed std::vector if this is an array, or an empty vector otherwise.
|
||||||
|
const array &array_items() const;
|
||||||
|
// Return the enclosed std::map if this is an object, or an empty map otherwise.
|
||||||
|
const object &object_items() const;
|
||||||
|
|
||||||
|
// Return a reference to arr[i] if this is an array, Json() otherwise.
|
||||||
|
const Json & operator[](size_t i) const;
|
||||||
|
// Return a reference to obj[key] if this is an object, Json() otherwise.
|
||||||
|
const Json & operator[](const std::string &key) const;
|
||||||
|
|
||||||
|
// Serialize.
|
||||||
|
void dump(std::string &out) const;
|
||||||
|
std::string dump() const {
|
||||||
|
std::string out;
|
||||||
|
dump(out);
|
||||||
|
return out;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Parse. If parse fails, return Json() and assign an error message to err.
|
||||||
|
static Json parse(const std::string & in,
|
||||||
|
std::string & err,
|
||||||
|
JsonParse strategy = JsonParse::STANDARD);
|
||||||
|
static Json parse(const char * in,
|
||||||
|
std::string & err,
|
||||||
|
JsonParse strategy = JsonParse::STANDARD) {
|
||||||
|
if (in) {
|
||||||
|
return parse(std::string(in), err, strategy);
|
||||||
|
} else {
|
||||||
|
err = "null input";
|
||||||
|
return nullptr;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
// Parse multiple objects, concatenated or separated by whitespace
|
||||||
|
static std::vector<Json> parse_multi(
|
||||||
|
const std::string & in,
|
||||||
|
std::string::size_type & parser_stop_pos,
|
||||||
|
std::string & err,
|
||||||
|
JsonParse strategy = JsonParse::STANDARD);
|
||||||
|
|
||||||
|
static inline std::vector<Json> parse_multi(
|
||||||
|
const std::string & in,
|
||||||
|
std::string & err,
|
||||||
|
JsonParse strategy = JsonParse::STANDARD) {
|
||||||
|
std::string::size_type parser_stop_pos;
|
||||||
|
return parse_multi(in, parser_stop_pos, err, strategy);
|
||||||
|
}
|
||||||
|
|
||||||
|
bool operator== (const Json &rhs) const;
|
||||||
|
bool operator< (const Json &rhs) const;
|
||||||
|
bool operator!= (const Json &rhs) const { return !(*this == rhs); }
|
||||||
|
bool operator<= (const Json &rhs) const { return !(rhs < *this); }
|
||||||
|
bool operator> (const Json &rhs) const { return (rhs < *this); }
|
||||||
|
bool operator>= (const Json &rhs) const { return !(*this < rhs); }
|
||||||
|
|
||||||
|
/* has_shape(types, err)
|
||||||
|
*
|
||||||
|
* Return true if this is a JSON object and, for each item in types, has a field of
|
||||||
|
* the given type. If not, return false and set err to a descriptive message.
|
||||||
|
*/
|
||||||
|
typedef std::initializer_list<std::pair<std::string, Type>> shape;
|
||||||
|
bool has_shape(const shape & types, std::string & err) const;
|
||||||
|
|
||||||
|
private:
|
||||||
|
std::shared_ptr<JsonValue> m_ptr;
|
||||||
|
};
|
||||||
|
|
||||||
|
// Internal class hierarchy - JsonValue objects are not exposed to users of this API.
|
||||||
|
class JsonValue {
|
||||||
|
protected:
|
||||||
|
friend class Json;
|
||||||
|
friend class JsonInt;
|
||||||
|
friend class JsonDouble;
|
||||||
|
virtual Json::Type type() const = 0;
|
||||||
|
virtual bool equals(const JsonValue * other) const = 0;
|
||||||
|
virtual bool less(const JsonValue * other) const = 0;
|
||||||
|
virtual void dump(std::string &out) const = 0;
|
||||||
|
virtual double number_value() const;
|
||||||
|
virtual int int_value() const;
|
||||||
|
virtual bool bool_value() const;
|
||||||
|
virtual const std::string &string_value() const;
|
||||||
|
virtual const Json::array &array_items() const;
|
||||||
|
virtual const Json &operator[](size_t i) const;
|
||||||
|
virtual const Json::object &object_items() const;
|
||||||
|
virtual const Json &operator[](const std::string &key) const;
|
||||||
|
virtual ~JsonValue() {}
|
||||||
|
};
|
||||||
|
|
||||||
|
} // namespace json11
|
9
3rdparty/oourafft/CMakeLists.txt
vendored
Normal file
9
3rdparty/oourafft/CMakeLists.txt
vendored
Normal file
@ -0,0 +1,9 @@
|
|||||||
|
add_library(oourafft INTERFACE)
|
||||||
|
|
||||||
|
target_include_directories(oourafft INTERFACE .)
|
||||||
|
|
||||||
|
target_sources(oourafft PUBLIC
|
||||||
|
fftsg.cc
|
||||||
|
fftsg.h
|
||||||
|
fftsg2d.cc
|
||||||
|
)
|
3259
3rdparty/oourafft/fftsg.cc
vendored
Normal file
3259
3rdparty/oourafft/fftsg.cc
vendored
Normal file
File diff suppressed because it is too large
Load Diff
24
3rdparty/oourafft/fftsg.h
vendored
Normal file
24
3rdparty/oourafft/fftsg.h
vendored
Normal file
@ -0,0 +1,24 @@
|
|||||||
|
#ifndef FFTSG_H
|
||||||
|
#define FFTSG_H
|
||||||
|
#include "nextpnr_namespaces.h"
|
||||||
|
|
||||||
|
NEXTPNR_NAMESPACE_BEGIN
|
||||||
|
|
||||||
|
//
|
||||||
|
// The following FFT library came from
|
||||||
|
// http://www.kurims.kyoto-u.ac.jp/~ooura/fft.html
|
||||||
|
//
|
||||||
|
//
|
||||||
|
/// 1D FFT ////////////////////////////////////////////////////////////////
|
||||||
|
void ddct(int n, int isgn, float *a, int *ip, float *w);
|
||||||
|
void ddst(int n, int isgn, float *a, int *ip, float *w);
|
||||||
|
|
||||||
|
/// 2D FFT ////////////////////////////////////////////////////////////////
|
||||||
|
void ddct2d(int n1, int n2, int isgn, float **a, float *t, int *ip, float *w);
|
||||||
|
void ddsct2d(int n1, int n2, int isgn, float **a, float *t, int *ip, float *w);
|
||||||
|
void ddcst2d(int n1, int n2, int isgn, float **a, float *t, int *ip, float *w);
|
||||||
|
|
||||||
|
|
||||||
|
NEXTPNR_NAMESPACE_END
|
||||||
|
|
||||||
|
#endif
|
1310
3rdparty/oourafft/fftsg2d.cc
vendored
Normal file
1310
3rdparty/oourafft/fftsg2d.cc
vendored
Normal file
File diff suppressed because it is too large
Load Diff
167
3rdparty/oourafft/readme.txt
vendored
Normal file
167
3rdparty/oourafft/readme.txt
vendored
Normal file
@ -0,0 +1,167 @@
|
|||||||
|
General Purpose FFT (Fast Fourier/Cosine/Sine Transform) Package
|
||||||
|
|
||||||
|
Description:
|
||||||
|
A package to calculate Discrete Fourier/Cosine/Sine Transforms of
|
||||||
|
1-dimensional sequences of length 2^N.
|
||||||
|
|
||||||
|
Files:
|
||||||
|
fft4g.c : FFT Package in C - Fast Version I (radix 4,2)
|
||||||
|
fft4g.f : FFT Package in Fortran - Fast Version I (radix 4,2)
|
||||||
|
fft4g_h.c : FFT Package in C - Simple Version I (radix 4,2)
|
||||||
|
fft8g.c : FFT Package in C - Fast Version II (radix 8,4,2)
|
||||||
|
fft8g.f : FFT Package in Fortran - Fast Version II (radix 8,4,2)
|
||||||
|
fft8g_h.c : FFT Package in C - Simple Version II (radix 8,4,2)
|
||||||
|
fftsg.c : FFT Package in C - Fast Version III (Split-Radix)
|
||||||
|
fftsg.f : FFT Package in Fortran - Fast Version III (Split-Radix)
|
||||||
|
fftsg_h.c : FFT Package in C - Simple Version III (Split-Radix)
|
||||||
|
readme.txt : Readme File
|
||||||
|
sample1/ : Test Directory
|
||||||
|
Makefile : for gcc, cc
|
||||||
|
Makefile.f77: for Fortran
|
||||||
|
testxg.c : Test Program for "fft*g.c"
|
||||||
|
testxg.f : Test Program for "fft*g.f"
|
||||||
|
testxg_h.c : Test Program for "fft*g_h.c"
|
||||||
|
sample2/ : Benchmark Directory
|
||||||
|
Makefile : for gcc, cc
|
||||||
|
Makefile.pth: POSIX Thread version
|
||||||
|
pi_fft.c : PI(= 3.1415926535897932384626...) Calculation Program
|
||||||
|
for a Benchmark Test for "fft*g.c"
|
||||||
|
|
||||||
|
Difference of the Files:
|
||||||
|
C and Fortran versions are equal and
|
||||||
|
the same routines are in each version.
|
||||||
|
"fft4g*.*" are optimized for most machines.
|
||||||
|
"fft8g*.*" are fast on the UltraSPARC.
|
||||||
|
"fftsg*.*" are optimized for the machines that
|
||||||
|
have the multi-level (L1,L2,etc) cache.
|
||||||
|
The simple versions "fft*g_h.c" use no work area, but
|
||||||
|
the fast versions "fft*g.*" use work areas.
|
||||||
|
The fast versions "fft*g.*" have the same specification.
|
||||||
|
|
||||||
|
Routines in the Package:
|
||||||
|
cdft: Complex Discrete Fourier Transform
|
||||||
|
rdft: Real Discrete Fourier Transform
|
||||||
|
ddct: Discrete Cosine Transform
|
||||||
|
ddst: Discrete Sine Transform
|
||||||
|
dfct: Cosine Transform of RDFT (Real Symmetric DFT)
|
||||||
|
dfst: Sine Transform of RDFT (Real Anti-symmetric DFT)
|
||||||
|
|
||||||
|
Usage:
|
||||||
|
Please refer to the comments in the "fft**.*" file which
|
||||||
|
you want to use. Brief explanations are in the block
|
||||||
|
comments of each package. The examples are also given in
|
||||||
|
the test programs.
|
||||||
|
|
||||||
|
Method:
|
||||||
|
-------- cdft --------
|
||||||
|
fft4g*.*, fft8g*.*:
|
||||||
|
A method of in-place, radix 2^M, Sande-Tukey (decimation in
|
||||||
|
frequency). Index of the butterfly loop is in bit
|
||||||
|
reverse order to keep continuous memory access.
|
||||||
|
fftsg*.*:
|
||||||
|
A method of in-place, Split-Radix, recursive fast
|
||||||
|
algorithm.
|
||||||
|
-------- rdft --------
|
||||||
|
A method with a following butterfly operation appended to "cdft".
|
||||||
|
In forward transform :
|
||||||
|
A[k] = sum_j=0^n-1 a[j]*W(n)^(j*k), 0<=k<=n/2,
|
||||||
|
W(n) = exp(2*pi*i/n),
|
||||||
|
this routine makes an array x[] :
|
||||||
|
x[j] = a[2*j] + i*a[2*j+1], 0<=j<n/2
|
||||||
|
and calls "cdft" of length n/2 :
|
||||||
|
X[k] = sum_j=0^n/2-1 x[j] * W(n/2)^(j*k), 0<=k<n.
|
||||||
|
The result A[k] are :
|
||||||
|
A[k] = X[k] - (1+i*W(n)^k)/2 * (X[k]-conjg(X[n/2-k])),
|
||||||
|
A[n/2-k] = X[n/2-k] +
|
||||||
|
conjg((1+i*W(n)^k)/2 * (X[k]-conjg(X[n/2-k]))),
|
||||||
|
0<=k<=n/2
|
||||||
|
(notes: conjg() is a complex conjugate, X[n/2]=X[0]).
|
||||||
|
-------- ddct --------
|
||||||
|
A method with a following butterfly operation appended to "rdft".
|
||||||
|
In backward transform :
|
||||||
|
C[k] = sum_j=0^n-1 a[j]*cos(pi*j*(k+1/2)/n), 0<=k<n,
|
||||||
|
this routine makes an array r[] :
|
||||||
|
r[0] = a[0],
|
||||||
|
r[j] = Re((a[j] - i*a[n-j]) * W(4*n)^j*(1+i)/2),
|
||||||
|
r[n-j] = Im((a[j] - i*a[n-j]) * W(4*n)^j*(1+i)/2),
|
||||||
|
0<j<=n/2
|
||||||
|
and calls "rdft" of length n :
|
||||||
|
A[k] = sum_j=0^n-1 r[j]*W(n)^(j*k), 0<=k<=n/2,
|
||||||
|
W(n) = exp(2*pi*i/n).
|
||||||
|
The result C[k] are :
|
||||||
|
C[2*k] = Re(A[k] * (1-i)),
|
||||||
|
C[2*k-1] = -Im(A[k] * (1-i)).
|
||||||
|
-------- ddst --------
|
||||||
|
A method with a following butterfly operation appended to "rdft".
|
||||||
|
In backward transform :
|
||||||
|
S[k] = sum_j=1^n A[j]*sin(pi*j*(k+1/2)/n), 0<=k<n,
|
||||||
|
this routine makes an array r[] :
|
||||||
|
r[0] = a[0],
|
||||||
|
r[j] = Im((a[n-j] - i*a[j]) * W(4*n)^j*(1+i)/2),
|
||||||
|
r[n-j] = Re((a[n-j] - i*a[j]) * W(4*n)^j*(1+i)/2),
|
||||||
|
0<j<=n/2
|
||||||
|
and calls "rdft" of length n :
|
||||||
|
A[k] = sum_j=0^n-1 r[j]*W(n)^(j*k), 0<=k<=n/2,
|
||||||
|
W(n) = exp(2*pi*i/n).
|
||||||
|
The result S[k] are :
|
||||||
|
S[2*k] = Re(A[k] * (1+i)),
|
||||||
|
S[2*k-1] = -Im(A[k] * (1+i)).
|
||||||
|
-------- dfct --------
|
||||||
|
A method to split into "dfct" and "ddct" of half length.
|
||||||
|
The transform :
|
||||||
|
C[k] = sum_j=0^n a[j]*cos(pi*j*k/n), 0<=k<=n
|
||||||
|
is divided into :
|
||||||
|
C[2*k] = sum'_j=0^n/2 (a[j]+a[n-j])*cos(pi*j*k/(n/2)),
|
||||||
|
C[2*k+1] = sum_j=0^n/2-1 (a[j]-a[n-j])*cos(pi*j*(k+1/2)/(n/2))
|
||||||
|
(sum' is a summation whose last term multiplies 1/2).
|
||||||
|
This routine uses "ddct" recursively.
|
||||||
|
To keep the in-place operation, the data in fft*g_h.*
|
||||||
|
are sorted in bit reversal order.
|
||||||
|
-------- dfst --------
|
||||||
|
A method to split into "dfst" and "ddst" of half length.
|
||||||
|
The transform :
|
||||||
|
S[k] = sum_j=1^n-1 a[j]*sin(pi*j*k/n), 0<k<n
|
||||||
|
is divided into :
|
||||||
|
S[2*k] = sum_j=1^n/2-1 (a[j]-a[n-j])*sin(pi*j*k/(n/2)),
|
||||||
|
S[2*k+1] = sum'_j=1^n/2 (a[j]+a[n-j])*sin(pi*j*(k+1/2)/(n/2))
|
||||||
|
(sum' is a summation whose last term multiplies 1/2).
|
||||||
|
This routine uses "ddst" recursively.
|
||||||
|
To keep the in-place operation, the data in fft*g_h.*
|
||||||
|
are sorted in bit reversal order.
|
||||||
|
|
||||||
|
Reference:
|
||||||
|
* Masatake MORI, Makoto NATORI, Tatuo TORII: Suchikeisan,
|
||||||
|
Iwanamikouzajyouhoukagaku18, Iwanami, 1982 (Japanese)
|
||||||
|
* Henri J. Nussbaumer: Fast Fourier Transform and Convolution
|
||||||
|
Algorithms, Springer Verlag, 1982
|
||||||
|
* C. S. Burrus, Notes on the FFT (with large FFT paper list)
|
||||||
|
http://www-dsp.rice.edu/research/fft/fftnote.asc
|
||||||
|
|
||||||
|
Copyright:
|
||||||
|
Copyright(C) 1996-2001 Takuya OOURA
|
||||||
|
email: ooura@mmm.t.u-tokyo.ac.jp
|
||||||
|
download: http://momonga.t.u-tokyo.ac.jp/~ooura/fft.html
|
||||||
|
You may use, copy, modify this code for any purpose and
|
||||||
|
without fee. You may distribute this ORIGINAL package.
|
||||||
|
|
||||||
|
History:
|
||||||
|
...
|
||||||
|
Dec. 1995 : Edit the General Purpose FFT
|
||||||
|
Mar. 1996 : Change the specification
|
||||||
|
Jun. 1996 : Change the method of trigonometric function table
|
||||||
|
Sep. 1996 : Modify the documents
|
||||||
|
Feb. 1997 : Change the butterfly loops
|
||||||
|
Dec. 1997 : Modify the documents
|
||||||
|
Dec. 1997 : Add "fft4g.*"
|
||||||
|
Jul. 1998 : Fix some bugs in the documents
|
||||||
|
Jul. 1998 : Add "fft8g.*" and delete "fft4f.*"
|
||||||
|
Jul. 1998 : Add a benchmark program "pi_fft.c"
|
||||||
|
Jul. 1999 : Add a simple version "fft*g_h.c"
|
||||||
|
Jul. 1999 : Add a Split-Radix FFT package "fftsg*.c"
|
||||||
|
Sep. 1999 : Reduce the memory operation (minor optimization)
|
||||||
|
Oct. 1999 : Change the butterfly structure of "fftsg*.c"
|
||||||
|
Oct. 1999 : Save the code size
|
||||||
|
Sep. 2001 : Add "fftsg.f"
|
||||||
|
Sep. 2001 : Add Pthread & Win32thread routines to "fftsg*.c"
|
||||||
|
Dec. 2006 : Fix a minor bug in "fftsg.f"
|
||||||
|
|
77
3rdparty/oourafft/readme2d.txt
vendored
Normal file
77
3rdparty/oourafft/readme2d.txt
vendored
Normal file
@ -0,0 +1,77 @@
|
|||||||
|
General Purpose 2D,3D FFT (Fast Fourier Transform) Package
|
||||||
|
|
||||||
|
Files
|
||||||
|
alloc.c : 2D-array Allocation
|
||||||
|
alloc.h : 2D-array Allocation
|
||||||
|
fft4f2d.c : 2D FFT Package in C - Version I (radix 4, 2)
|
||||||
|
fft4f2d.f : 2D FFT Package in Fortran - Version I (radix 4, 2)
|
||||||
|
fftsg.c : 1D FFT Package in C - Fast Version (Split-Radix)
|
||||||
|
fftsg.f : 1D FFT Package in Fortran - Fast Version (Split-Radix)
|
||||||
|
fftsg2d.c : 2D FFT Package in C - Version II (Split-Radix)
|
||||||
|
fftsg2d.f : 2D FFT Package in Fortran - Version II (Split-Radix)
|
||||||
|
fftsg3d.c : 3D FFT Package in C - Version II (Split-Radix)
|
||||||
|
fftsg3d.f : 3D FFT Package in Fortran - Version II (Split-Radix)
|
||||||
|
shrtdct.c : 8x8, 16x16 DCT Package
|
||||||
|
sample2d/
|
||||||
|
Makefile : for gcc, cc
|
||||||
|
Makefile.f77: for Fortran
|
||||||
|
Makefile.pth: Pthread version
|
||||||
|
fft4f2dt.c : Test Program for "fft4f2d.c"
|
||||||
|
fft4f2dt.f : Test Program for "fft4f2d.f"
|
||||||
|
fftsg2dt.c : Test Program for "fftsg2d.c"
|
||||||
|
fftsg2dt.f : Test Program for "fftsg2d.f"
|
||||||
|
fftsg3dt.c : Test Program for "fftsg3d.c"
|
||||||
|
fftsg3dt.f : Test Program for "fftsg3d.f"
|
||||||
|
shrtdctt.c : Test Program for "shrtdct.c"
|
||||||
|
|
||||||
|
Difference of Files
|
||||||
|
C and Fortran versions are equal and
|
||||||
|
the same routines are in each version.
|
||||||
|
---- Difference between "fft4f2d.*" and "fftsg2d.*" ----
|
||||||
|
"fft4f2d.*" are optimized for the old machines that
|
||||||
|
don't have the large size CPU cache.
|
||||||
|
"fftsg2d.*", "fftsg3d.*" use 1D FFT routines in "fftsg.*".
|
||||||
|
"fftsg2d.*", "fftsg3d.*" are optimized for the machines that
|
||||||
|
have the multi-level (L1,L2,etc) cache.
|
||||||
|
|
||||||
|
Routines in the Package
|
||||||
|
in fft4f2d.*, fftsg2d.*
|
||||||
|
cdft2d: 2-dim Complex Discrete Fourier Transform
|
||||||
|
rdft2d: 2-dim Real Discrete Fourier Transform
|
||||||
|
ddct2d: 2-dim Discrete Cosine Transform
|
||||||
|
ddst2d: 2-dim Discrete Sine Transform
|
||||||
|
rdft2dsort: rdft2d input/output ordering (fftsg2d.*)
|
||||||
|
in fftsg3d.*
|
||||||
|
cdft3d: 3-dim Complex Discrete Fourier Transform
|
||||||
|
rdft3d: 3-dim Real Discrete Fourier Transform
|
||||||
|
ddct3d: 3-dim Discrete Cosine Transform
|
||||||
|
ddst3d: 3-dim Discrete Sine Transform
|
||||||
|
rdft3dsort: rdft3d input/output ordering
|
||||||
|
in fftsg.*
|
||||||
|
cdft: 1-dim Complex Discrete Fourier Transform
|
||||||
|
rdft: 1-dim Real Discrete Fourier Transform
|
||||||
|
ddct: 1-dim Discrete Cosine Transform
|
||||||
|
ddst: 1-dim Discrete Sine Transform
|
||||||
|
dfct: 1-dim Real Symmetric DFT
|
||||||
|
dfst: 1-dim Real Anti-symmetric DFT
|
||||||
|
(these routines are called by fftsg2d.*, fftsg3d.*)
|
||||||
|
in shrtdct.c
|
||||||
|
ddct8x8s : Normalized 8x8 DCT
|
||||||
|
ddct16x16s: Normalized 16x16 DCT
|
||||||
|
(faster than ddct2d())
|
||||||
|
|
||||||
|
Usage
|
||||||
|
Brief explanations are in block comments of each packages.
|
||||||
|
The examples are given in the test programs.
|
||||||
|
|
||||||
|
Copyright
|
||||||
|
Copyright(C) 1997,2001 Takuya OOURA (email: ooura@kurims.kyoto-u.ac.jp).
|
||||||
|
You may use, copy, modify this code for any purpose and
|
||||||
|
without fee. You may distribute this ORIGINAL package.
|
||||||
|
|
||||||
|
History
|
||||||
|
...
|
||||||
|
Nov. 2001 : Add 3D-FFT routines
|
||||||
|
Dec. 2006 : Fix a documentation bug in "fftsg3d.*"
|
||||||
|
Dec. 2006 : Fix a minor bug in "fftsg.f"
|
||||||
|
|
35
3rdparty/pybind11/.appveyor.yml
vendored
Normal file
35
3rdparty/pybind11/.appveyor.yml
vendored
Normal file
@ -0,0 +1,35 @@
|
|||||||
|
version: 1.0.{build}
|
||||||
|
image:
|
||||||
|
- Visual Studio 2017
|
||||||
|
test: off
|
||||||
|
skip_branch_with_pr: true
|
||||||
|
build:
|
||||||
|
parallel: true
|
||||||
|
platform:
|
||||||
|
- x86
|
||||||
|
environment:
|
||||||
|
matrix:
|
||||||
|
- PYTHON: 36
|
||||||
|
CONFIG: Debug
|
||||||
|
install:
|
||||||
|
- ps: |
|
||||||
|
$env:CMAKE_GENERATOR = "Visual Studio 15 2017"
|
||||||
|
if ($env:PLATFORM -eq "x64") { $env:PYTHON = "$env:PYTHON-x64" }
|
||||||
|
$env:PATH = "C:\Python$env:PYTHON\;C:\Python$env:PYTHON\Scripts\;$env:PATH"
|
||||||
|
python -W ignore -m pip install --upgrade pip wheel
|
||||||
|
python -W ignore -m pip install pytest numpy --no-warn-script-location pytest-timeout
|
||||||
|
- ps: |
|
||||||
|
Start-FileDownload 'https://gitlab.com/libeigen/eigen/-/archive/3.3.7/eigen-3.3.7.zip'
|
||||||
|
7z x eigen-3.3.7.zip -y > $null
|
||||||
|
$env:CMAKE_INCLUDE_PATH = "eigen-3.3.7;$env:CMAKE_INCLUDE_PATH"
|
||||||
|
build_script:
|
||||||
|
- cmake -G "%CMAKE_GENERATOR%" -A "%CMAKE_ARCH%"
|
||||||
|
-DCMAKE_CXX_STANDARD=14
|
||||||
|
-DPYBIND11_WERROR=ON
|
||||||
|
-DDOWNLOAD_CATCH=ON
|
||||||
|
-DCMAKE_SUPPRESS_REGENERATION=1
|
||||||
|
.
|
||||||
|
- set MSBuildLogger="C:\Program Files\AppVeyor\BuildAgent\Appveyor.MSBuildLogger.dll"
|
||||||
|
- cmake --build . --config %CONFIG% --target pytest -- /m /v:m /logger:%MSBuildLogger%
|
||||||
|
- cmake --build . --config %CONFIG% --target cpptest -- /m /v:m /logger:%MSBuildLogger%
|
||||||
|
on_failure: if exist "tests\test_cmake_build" type tests\test_cmake_build\*.log*
|
38
3rdparty/pybind11/.clang-format
vendored
Normal file
38
3rdparty/pybind11/.clang-format
vendored
Normal file
@ -0,0 +1,38 @@
|
|||||||
|
---
|
||||||
|
# See all possible options and defaults with:
|
||||||
|
# clang-format --style=llvm --dump-config
|
||||||
|
BasedOnStyle: LLVM
|
||||||
|
AccessModifierOffset: -4
|
||||||
|
AllowShortLambdasOnASingleLine: true
|
||||||
|
AlwaysBreakTemplateDeclarations: Yes
|
||||||
|
BinPackArguments: false
|
||||||
|
BinPackParameters: false
|
||||||
|
BreakBeforeBinaryOperators: All
|
||||||
|
BreakConstructorInitializers: BeforeColon
|
||||||
|
ColumnLimit: 99
|
||||||
|
CommentPragmas: 'NOLINT:.*|^ IWYU pragma:'
|
||||||
|
IncludeBlocks: Regroup
|
||||||
|
IndentCaseLabels: true
|
||||||
|
IndentPPDirectives: AfterHash
|
||||||
|
IndentWidth: 4
|
||||||
|
Language: Cpp
|
||||||
|
SpaceAfterCStyleCast: true
|
||||||
|
Standard: Cpp11
|
||||||
|
StatementMacros: ['PyObject_HEAD']
|
||||||
|
TabWidth: 4
|
||||||
|
IncludeCategories:
|
||||||
|
- Regex: '<pybind11/.*'
|
||||||
|
Priority: -1
|
||||||
|
- Regex: 'pybind11.h"$'
|
||||||
|
Priority: 1
|
||||||
|
- Regex: '^".*/?detail/'
|
||||||
|
Priority: 1
|
||||||
|
SortPriority: 2
|
||||||
|
- Regex: '^"'
|
||||||
|
Priority: 1
|
||||||
|
SortPriority: 3
|
||||||
|
- Regex: '<[[:alnum:]._]+>'
|
||||||
|
Priority: 4
|
||||||
|
- Regex: '.*'
|
||||||
|
Priority: 5
|
||||||
|
...
|
77
3rdparty/pybind11/.clang-tidy
vendored
Normal file
77
3rdparty/pybind11/.clang-tidy
vendored
Normal file
@ -0,0 +1,77 @@
|
|||||||
|
FormatStyle: file
|
||||||
|
|
||||||
|
Checks: |
|
||||||
|
*bugprone*,
|
||||||
|
*performance*,
|
||||||
|
clang-analyzer-optin.cplusplus.VirtualCall,
|
||||||
|
clang-analyzer-optin.performance.Padding,
|
||||||
|
cppcoreguidelines-init-variables,
|
||||||
|
cppcoreguidelines-prefer-member-initializer,
|
||||||
|
cppcoreguidelines-pro-type-static-cast-downcast,
|
||||||
|
cppcoreguidelines-slicing,
|
||||||
|
google-explicit-constructor,
|
||||||
|
llvm-namespace-comment,
|
||||||
|
misc-definitions-in-headers,
|
||||||
|
misc-misplaced-const,
|
||||||
|
misc-non-copyable-objects,
|
||||||
|
misc-static-assert,
|
||||||
|
misc-throw-by-value-catch-by-reference,
|
||||||
|
misc-uniqueptr-reset-release,
|
||||||
|
misc-unused-parameters,
|
||||||
|
modernize-avoid-bind,
|
||||||
|
modernize-loop-convert,
|
||||||
|
modernize-make-shared,
|
||||||
|
modernize-redundant-void-arg,
|
||||||
|
modernize-replace-auto-ptr,
|
||||||
|
modernize-replace-disallow-copy-and-assign-macro,
|
||||||
|
modernize-replace-random-shuffle,
|
||||||
|
modernize-shrink-to-fit,
|
||||||
|
modernize-use-auto,
|
||||||
|
modernize-use-bool-literals,
|
||||||
|
modernize-use-default-member-init,
|
||||||
|
modernize-use-emplace,
|
||||||
|
modernize-use-equals-default,
|
||||||
|
modernize-use-equals-delete,
|
||||||
|
modernize-use-noexcept,
|
||||||
|
modernize-use-nullptr,
|
||||||
|
modernize-use-override,
|
||||||
|
modernize-use-using,
|
||||||
|
readability-avoid-const-params-in-decls,
|
||||||
|
readability-braces-around-statements,
|
||||||
|
readability-const-return-type,
|
||||||
|
readability-container-size-empty,
|
||||||
|
readability-delete-null-pointer,
|
||||||
|
readability-else-after-return,
|
||||||
|
readability-implicit-bool-conversion,
|
||||||
|
readability-inconsistent-declaration-parameter-name,
|
||||||
|
readability-make-member-function-const,
|
||||||
|
readability-misplaced-array-index,
|
||||||
|
readability-non-const-parameter,
|
||||||
|
readability-qualified-auto,
|
||||||
|
readability-redundant-function-ptr-dereference,
|
||||||
|
readability-redundant-smartptr-get,
|
||||||
|
readability-redundant-string-cstr,
|
||||||
|
readability-simplify-subscript-expr,
|
||||||
|
readability-static-accessed-through-instance,
|
||||||
|
readability-static-definition-in-anonymous-namespace,
|
||||||
|
readability-string-compare,
|
||||||
|
readability-suspicious-call-argument,
|
||||||
|
readability-uniqueptr-delete-release,
|
||||||
|
-bugprone-easily-swappable-parameters,
|
||||||
|
-bugprone-exception-escape,
|
||||||
|
-bugprone-reserved-identifier,
|
||||||
|
-bugprone-unused-raii,
|
||||||
|
|
||||||
|
CheckOptions:
|
||||||
|
- key: modernize-use-equals-default.IgnoreMacros
|
||||||
|
value: false
|
||||||
|
- key: performance-for-range-copy.WarnOnAllAutoCopies
|
||||||
|
value: true
|
||||||
|
- key: performance-inefficient-string-concatenation.StrictMode
|
||||||
|
value: true
|
||||||
|
- key: performance-unnecessary-value-param.AllowedTypes
|
||||||
|
value: 'exception_ptr$;'
|
||||||
|
- key: readability-implicit-bool-conversion.AllowPointerConditions
|
||||||
|
value: true
|
||||||
|
|
||||||
|
HeaderFilterRegex: 'pybind11/.*h'
|
73
3rdparty/pybind11/.cmake-format.yaml
vendored
Normal file
73
3rdparty/pybind11/.cmake-format.yaml
vendored
Normal file
@ -0,0 +1,73 @@
|
|||||||
|
parse:
|
||||||
|
additional_commands:
|
||||||
|
pybind11_add_module:
|
||||||
|
flags:
|
||||||
|
- THIN_LTO
|
||||||
|
- MODULE
|
||||||
|
- SHARED
|
||||||
|
- NO_EXTRAS
|
||||||
|
- EXCLUDE_FROM_ALL
|
||||||
|
- SYSTEM
|
||||||
|
|
||||||
|
format:
|
||||||
|
line_width: 99
|
||||||
|
tab_size: 2
|
||||||
|
|
||||||
|
# If an argument group contains more than this many sub-groups
|
||||||
|
# (parg or kwarg groups) then force it to a vertical layout.
|
||||||
|
max_subgroups_hwrap: 2
|
||||||
|
|
||||||
|
# If a positional argument group contains more than this many
|
||||||
|
# arguments, then force it to a vertical layout.
|
||||||
|
max_pargs_hwrap: 6
|
||||||
|
|
||||||
|
# If a cmdline positional group consumes more than this many
|
||||||
|
# lines without nesting, then invalidate the layout (and nest)
|
||||||
|
max_rows_cmdline: 2
|
||||||
|
separate_ctrl_name_with_space: false
|
||||||
|
separate_fn_name_with_space: false
|
||||||
|
dangle_parens: false
|
||||||
|
|
||||||
|
# If the trailing parenthesis must be 'dangled' on its on
|
||||||
|
# 'line, then align it to this reference: `prefix`: the start'
|
||||||
|
# 'of the statement, `prefix-indent`: the start of the'
|
||||||
|
# 'statement, plus one indentation level, `child`: align to'
|
||||||
|
# the column of the arguments
|
||||||
|
dangle_align: prefix
|
||||||
|
# If the statement spelling length (including space and
|
||||||
|
# parenthesis) is smaller than this amount, then force reject
|
||||||
|
# nested layouts.
|
||||||
|
min_prefix_chars: 4
|
||||||
|
|
||||||
|
# If the statement spelling length (including space and
|
||||||
|
# parenthesis) is larger than the tab width by more than this
|
||||||
|
# amount, then force reject un-nested layouts.
|
||||||
|
max_prefix_chars: 10
|
||||||
|
|
||||||
|
# If a candidate layout is wrapped horizontally but it exceeds
|
||||||
|
# this many lines, then reject the layout.
|
||||||
|
max_lines_hwrap: 2
|
||||||
|
|
||||||
|
line_ending: unix
|
||||||
|
|
||||||
|
# Format command names consistently as 'lower' or 'upper' case
|
||||||
|
command_case: canonical
|
||||||
|
|
||||||
|
# Format keywords consistently as 'lower' or 'upper' case
|
||||||
|
# unchanged is valid too
|
||||||
|
keyword_case: 'upper'
|
||||||
|
|
||||||
|
# A list of command names which should always be wrapped
|
||||||
|
always_wrap: []
|
||||||
|
|
||||||
|
# If true, the argument lists which are known to be sortable
|
||||||
|
# will be sorted lexicographically
|
||||||
|
enable_sort: true
|
||||||
|
|
||||||
|
# If true, the parsers may infer whether or not an argument
|
||||||
|
# list is sortable (without annotation).
|
||||||
|
autosort: false
|
||||||
|
|
||||||
|
# Causes a few issues - can be solved later, possibly.
|
||||||
|
markup:
|
||||||
|
enable_markup: false
|
24
3rdparty/pybind11/.codespell-ignore-lines
vendored
Normal file
24
3rdparty/pybind11/.codespell-ignore-lines
vendored
Normal file
@ -0,0 +1,24 @@
|
|||||||
|
template <op_id id, op_type ot, typename L = undefined_t, typename R = undefined_t>
|
||||||
|
template <typename ThisT>
|
||||||
|
auto &this_ = static_cast<ThisT &>(*this);
|
||||||
|
if (load_impl<ThisT>(temp, false)) {
|
||||||
|
ssize_t nd = 0;
|
||||||
|
auto trivial = broadcast(buffers, nd, shape);
|
||||||
|
auto ndim = (size_t) nd;
|
||||||
|
int nd;
|
||||||
|
ssize_t ndim() const { return detail::array_proxy(m_ptr)->nd; }
|
||||||
|
using op = op_impl<id, ot, Base, L_type, R_type>;
|
||||||
|
template <op_id id, op_type ot, typename L, typename R>
|
||||||
|
template <detail::op_id id, detail::op_type ot, typename L, typename R, typename... Extra>
|
||||||
|
class_ &def(const detail::op_<id, ot, L, R> &op, const Extra &...extra) {
|
||||||
|
class_ &def_cast(const detail::op_<id, ot, L, R> &op, const Extra &...extra) {
|
||||||
|
@pytest.mark.parametrize("access", ["ro", "rw", "static_ro", "static_rw"])
|
||||||
|
struct IntStruct {
|
||||||
|
explicit IntStruct(int v) : value(v){};
|
||||||
|
~IntStruct() { value = -value; }
|
||||||
|
IntStruct(const IntStruct &) = default;
|
||||||
|
IntStruct &operator=(const IntStruct &) = default;
|
||||||
|
py::class_<IntStruct>(m, "IntStruct").def(py::init([](const int i) { return IntStruct(i); }));
|
||||||
|
py::implicitly_convertible<int, IntStruct>();
|
||||||
|
m.def("test", [](int expected, const IntStruct &in) {
|
||||||
|
[](int expected, const IntStruct &in) {
|
1
3rdparty/pybind11/.gitattributes
vendored
Normal file
1
3rdparty/pybind11/.gitattributes
vendored
Normal file
@ -0,0 +1 @@
|
|||||||
|
docs/*.svg binary
|
9
3rdparty/pybind11/.github/CODEOWNERS
vendored
Normal file
9
3rdparty/pybind11/.github/CODEOWNERS
vendored
Normal file
@ -0,0 +1,9 @@
|
|||||||
|
*.cmake @henryiii
|
||||||
|
CMakeLists.txt @henryiii
|
||||||
|
*.yml @henryiii
|
||||||
|
*.yaml @henryiii
|
||||||
|
/tools/ @henryiii
|
||||||
|
/pybind11/ @henryiii
|
||||||
|
noxfile.py @henryiii
|
||||||
|
.clang-format @henryiii
|
||||||
|
.clang-tidy @henryiii
|
388
3rdparty/pybind11/.github/CONTRIBUTING.md
vendored
Normal file
388
3rdparty/pybind11/.github/CONTRIBUTING.md
vendored
Normal file
@ -0,0 +1,388 @@
|
|||||||
|
Thank you for your interest in this project! Please refer to the following
|
||||||
|
sections on how to contribute code and bug reports.
|
||||||
|
|
||||||
|
### Reporting bugs
|
||||||
|
|
||||||
|
Before submitting a question or bug report, please take a moment of your time
|
||||||
|
and ensure that your issue isn't already discussed in the project documentation
|
||||||
|
provided at [pybind11.readthedocs.org][] or in the [issue tracker][]. You can
|
||||||
|
also check [gitter][] to see if it came up before.
|
||||||
|
|
||||||
|
Assuming that you have identified a previously unknown problem or an important
|
||||||
|
question, it's essential that you submit a self-contained and minimal piece of
|
||||||
|
code that reproduces the problem. In other words: no external dependencies,
|
||||||
|
isolate the function(s) that cause breakage, submit matched and complete C++
|
||||||
|
and Python snippets that can be easily compiled and run in isolation; or
|
||||||
|
ideally make a small PR with a failing test case that can be used as a starting
|
||||||
|
point.
|
||||||
|
|
||||||
|
## Pull requests
|
||||||
|
|
||||||
|
Contributions are submitted, reviewed, and accepted using GitHub pull requests.
|
||||||
|
Please refer to [this article][using pull requests] for details and adhere to
|
||||||
|
the following rules to make the process as smooth as possible:
|
||||||
|
|
||||||
|
* Make a new branch for every feature you're working on.
|
||||||
|
* Make small and clean pull requests that are easy to review but make sure they
|
||||||
|
do add value by themselves.
|
||||||
|
* Add tests for any new functionality and run the test suite (`cmake --build
|
||||||
|
build --target pytest`) to ensure that no existing features break.
|
||||||
|
* Please run [`pre-commit`][pre-commit] to check your code matches the
|
||||||
|
project style. (Note that `gawk` is required.) Use `pre-commit run
|
||||||
|
--all-files` before committing (or use installed-mode, check pre-commit docs)
|
||||||
|
to verify your code passes before pushing to save time.
|
||||||
|
* This project has a strong focus on providing general solutions using a
|
||||||
|
minimal amount of code, thus small pull requests are greatly preferred.
|
||||||
|
|
||||||
|
### Licensing of contributions
|
||||||
|
|
||||||
|
pybind11 is provided under a BSD-style license that can be found in the
|
||||||
|
``LICENSE`` file. By using, distributing, or contributing to this project, you
|
||||||
|
agree to the terms and conditions of this license.
|
||||||
|
|
||||||
|
You are under no obligation whatsoever to provide any bug fixes, patches, or
|
||||||
|
upgrades to the features, functionality or performance of the source code
|
||||||
|
("Enhancements") to anyone; however, if you choose to make your Enhancements
|
||||||
|
available either publicly, or directly to the author of this software, without
|
||||||
|
imposing a separate written license agreement for such Enhancements, then you
|
||||||
|
hereby grant the following license: a non-exclusive, royalty-free perpetual
|
||||||
|
license to install, use, modify, prepare derivative works, incorporate into
|
||||||
|
other computer software, distribute, and sublicense such enhancements or
|
||||||
|
derivative works thereof, in binary and source code form.
|
||||||
|
|
||||||
|
|
||||||
|
## Development of pybind11
|
||||||
|
|
||||||
|
### Quick setup
|
||||||
|
|
||||||
|
To setup a quick development environment, use [`nox`](https://nox.thea.codes).
|
||||||
|
This will allow you to do some common tasks with minimal setup effort, but will
|
||||||
|
take more time to run and be less flexible than a full development environment.
|
||||||
|
If you use [`pipx run nox`](https://pipx.pypa.io), you don't even need to
|
||||||
|
install `nox`. Examples:
|
||||||
|
|
||||||
|
```bash
|
||||||
|
# List all available sessions
|
||||||
|
nox -l
|
||||||
|
|
||||||
|
# Run linters
|
||||||
|
nox -s lint
|
||||||
|
|
||||||
|
# Run tests on Python 3.9
|
||||||
|
nox -s tests-3.9
|
||||||
|
|
||||||
|
# Build and preview docs
|
||||||
|
nox -s docs -- serve
|
||||||
|
|
||||||
|
# Build SDists and wheels
|
||||||
|
nox -s build
|
||||||
|
```
|
||||||
|
|
||||||
|
### Full setup
|
||||||
|
|
||||||
|
To setup an ideal development environment, run the following commands on a
|
||||||
|
system with CMake 3.14+:
|
||||||
|
|
||||||
|
```bash
|
||||||
|
python3 -m venv venv
|
||||||
|
source venv/bin/activate
|
||||||
|
pip install -r tests/requirements.txt
|
||||||
|
cmake -S . -B build -DDOWNLOAD_CATCH=ON -DDOWNLOAD_EIGEN=ON
|
||||||
|
cmake --build build -j4
|
||||||
|
```
|
||||||
|
|
||||||
|
Tips:
|
||||||
|
|
||||||
|
* You can use `virtualenv` (faster, from PyPI) instead of `venv`.
|
||||||
|
* You can select any name for your environment folder; if it contains "env" it
|
||||||
|
will be ignored by git.
|
||||||
|
* If you don't have CMake 3.14+, just add "cmake" to the pip install command.
|
||||||
|
* You can use `-DPYBIND11_FINDPYTHON=ON` to use FindPython on CMake 3.12+
|
||||||
|
* In classic mode, you may need to set `-DPYTHON_EXECUTABLE=/path/to/python`.
|
||||||
|
FindPython uses `-DPython_ROOT_DIR=/path/to` or
|
||||||
|
`-DPython_EXECUTABLE=/path/to/python`.
|
||||||
|
|
||||||
|
### Configuration options
|
||||||
|
|
||||||
|
In CMake, configuration options are given with "-D". Options are stored in the
|
||||||
|
build directory, in the `CMakeCache.txt` file, so they are remembered for each
|
||||||
|
build directory. Two selections are special - the generator, given with `-G`,
|
||||||
|
and the compiler, which is selected based on environment variables `CXX` and
|
||||||
|
similar, or `-DCMAKE_CXX_COMPILER=`. Unlike the others, these cannot be changed
|
||||||
|
after the initial run.
|
||||||
|
|
||||||
|
The valid options are:
|
||||||
|
|
||||||
|
* `-DCMAKE_BUILD_TYPE`: Release, Debug, MinSizeRel, RelWithDebInfo
|
||||||
|
* `-DPYBIND11_FINDPYTHON=ON`: Use CMake 3.12+'s FindPython instead of the
|
||||||
|
classic, deprecated, custom FindPythonLibs
|
||||||
|
* `-DPYBIND11_NOPYTHON=ON`: Disable all Python searching (disables tests)
|
||||||
|
* `-DBUILD_TESTING=ON`: Enable the tests
|
||||||
|
* `-DDOWNLOAD_CATCH=ON`: Download catch to build the C++ tests
|
||||||
|
* `-DDOWNLOAD_EIGEN=ON`: Download Eigen for the NumPy tests
|
||||||
|
* `-DPYBIND11_INSTALL=ON/OFF`: Enable the install target (on by default for the
|
||||||
|
master project)
|
||||||
|
* `-DUSE_PYTHON_INSTALL_DIR=ON`: Try to install into the python dir
|
||||||
|
|
||||||
|
|
||||||
|
<details><summary>A few standard CMake tricks: (click to expand)</summary><p>
|
||||||
|
|
||||||
|
* Use `cmake --build build -v` to see the commands used to build the files.
|
||||||
|
* Use `cmake build -LH` to list the CMake options with help.
|
||||||
|
* Use `ccmake` if available to see a curses (terminal) gui, or `cmake-gui` for
|
||||||
|
a completely graphical interface (not present in the PyPI package).
|
||||||
|
* Use `cmake --build build -j12` to build with 12 cores (for example).
|
||||||
|
* Use `-G` and the name of a generator to use something different. `cmake
|
||||||
|
--help` lists the generators available.
|
||||||
|
- On Unix, setting `CMAKE_GENERATER=Ninja` in your environment will give
|
||||||
|
you automatic multithreading on all your CMake projects!
|
||||||
|
* Open the `CMakeLists.txt` with QtCreator to generate for that IDE.
|
||||||
|
* You can use `-DCMAKE_EXPORT_COMPILE_COMMANDS=ON` to generate the `.json` file
|
||||||
|
that some tools expect.
|
||||||
|
|
||||||
|
</p></details>
|
||||||
|
|
||||||
|
|
||||||
|
To run the tests, you can "build" the check target:
|
||||||
|
|
||||||
|
```bash
|
||||||
|
cmake --build build --target check
|
||||||
|
```
|
||||||
|
|
||||||
|
`--target` can be spelled `-t` in CMake 3.15+. You can also run individual
|
||||||
|
tests with these targets:
|
||||||
|
|
||||||
|
* `pytest`: Python tests only, using the
|
||||||
|
[pytest](https://docs.pytest.org/en/stable/) framework
|
||||||
|
* `cpptest`: C++ tests only
|
||||||
|
* `test_cmake_build`: Install / subdirectory tests
|
||||||
|
|
||||||
|
If you want to build just a subset of tests, use
|
||||||
|
`-DPYBIND11_TEST_OVERRIDE="test_callbacks;test_pickling"`. If this is
|
||||||
|
empty, all tests will be built. Tests are specified without an extension if they need both a .py and
|
||||||
|
.cpp file.
|
||||||
|
|
||||||
|
You may also pass flags to the `pytest` target by editing `tests/pytest.ini` or
|
||||||
|
by using the `PYTEST_ADDOPTS` environment variable
|
||||||
|
(see [`pytest` docs](https://docs.pytest.org/en/2.7.3/customize.html#adding-default-options)). As an example:
|
||||||
|
|
||||||
|
```bash
|
||||||
|
env PYTEST_ADDOPTS="--capture=no --exitfirst" \
|
||||||
|
cmake --build build --target pytest
|
||||||
|
# Or using abbreviated flags
|
||||||
|
env PYTEST_ADDOPTS="-s -x" cmake --build build --target pytest
|
||||||
|
```
|
||||||
|
|
||||||
|
### Formatting
|
||||||
|
|
||||||
|
All formatting is handled by pre-commit.
|
||||||
|
|
||||||
|
Install with brew (macOS) or pip (any OS):
|
||||||
|
|
||||||
|
```bash
|
||||||
|
# Any OS
|
||||||
|
python3 -m pip install pre-commit
|
||||||
|
|
||||||
|
# OR macOS with homebrew:
|
||||||
|
brew install pre-commit
|
||||||
|
```
|
||||||
|
|
||||||
|
Then, you can run it on the items you've added to your staging area, or all
|
||||||
|
files:
|
||||||
|
|
||||||
|
```bash
|
||||||
|
pre-commit run
|
||||||
|
# OR
|
||||||
|
pre-commit run --all-files
|
||||||
|
```
|
||||||
|
|
||||||
|
And, if you want to always use it, you can install it as a git hook (hence the
|
||||||
|
name, pre-commit):
|
||||||
|
|
||||||
|
```bash
|
||||||
|
pre-commit install
|
||||||
|
```
|
||||||
|
|
||||||
|
### Clang-Format
|
||||||
|
|
||||||
|
As of v2.6.2, pybind11 ships with a [`clang-format`][clang-format]
|
||||||
|
configuration file at the top level of the repo (the filename is
|
||||||
|
`.clang-format`). Currently, formatting is NOT applied automatically, but
|
||||||
|
manually using `clang-format` for newly developed files is highly encouraged.
|
||||||
|
To check if a file needs formatting:
|
||||||
|
|
||||||
|
```bash
|
||||||
|
clang-format -style=file --dry-run some.cpp
|
||||||
|
```
|
||||||
|
|
||||||
|
The output will show things to be fixed, if any. To actually format the file:
|
||||||
|
|
||||||
|
```bash
|
||||||
|
clang-format -style=file -i some.cpp
|
||||||
|
```
|
||||||
|
|
||||||
|
Note that the `-style-file` option searches the parent directories for the
|
||||||
|
`.clang-format` file, i.e. the commands above can be run in any subdirectory
|
||||||
|
of the pybind11 repo.
|
||||||
|
|
||||||
|
### Clang-Tidy
|
||||||
|
|
||||||
|
[`clang-tidy`][clang-tidy] performs deeper static code analyses and is
|
||||||
|
more complex to run, compared to `clang-format`, but support for `clang-tidy`
|
||||||
|
is built into the pybind11 CMake configuration. To run `clang-tidy`, the
|
||||||
|
following recipe should work. Run the `docker` command from the top-level
|
||||||
|
directory inside your pybind11 git clone. Files will be modified in place,
|
||||||
|
so you can use git to monitor the changes.
|
||||||
|
|
||||||
|
```bash
|
||||||
|
docker run --rm -v $PWD:/mounted_pybind11 -it silkeh/clang:15-bullseye
|
||||||
|
apt-get update && apt-get install -y git python3-dev python3-pytest
|
||||||
|
cmake -S /mounted_pybind11/ -B build -DCMAKE_CXX_CLANG_TIDY="$(which clang-tidy);--use-color" -DDOWNLOAD_EIGEN=ON -DDOWNLOAD_CATCH=ON -DCMAKE_CXX_STANDARD=17
|
||||||
|
cmake --build build -j 2
|
||||||
|
```
|
||||||
|
|
||||||
|
You can add `--fix` to the options list if you want.
|
||||||
|
|
||||||
|
### Include what you use
|
||||||
|
|
||||||
|
To run include what you use, install (`brew install include-what-you-use` on
|
||||||
|
macOS), then run:
|
||||||
|
|
||||||
|
```bash
|
||||||
|
cmake -S . -B build-iwyu -DCMAKE_CXX_INCLUDE_WHAT_YOU_USE=$(which include-what-you-use)
|
||||||
|
cmake --build build
|
||||||
|
```
|
||||||
|
|
||||||
|
The report is sent to stderr; you can pipe it into a file if you wish.
|
||||||
|
|
||||||
|
### Build recipes
|
||||||
|
|
||||||
|
This builds with the Intel compiler (assuming it is in your path, along with a
|
||||||
|
recent CMake and Python):
|
||||||
|
|
||||||
|
```bash
|
||||||
|
python3 -m venv venv
|
||||||
|
. venv/bin/activate
|
||||||
|
pip install pytest
|
||||||
|
cmake -S . -B build-intel -DCMAKE_CXX_COMPILER=$(which icpc) -DDOWNLOAD_CATCH=ON -DDOWNLOAD_EIGEN=ON -DPYBIND11_WERROR=ON
|
||||||
|
```
|
||||||
|
|
||||||
|
This will test the PGI compilers:
|
||||||
|
|
||||||
|
```bash
|
||||||
|
docker run --rm -it -v $PWD:/pybind11 nvcr.io/hpc/pgi-compilers:ce
|
||||||
|
apt-get update && apt-get install -y python3-dev python3-pip python3-pytest
|
||||||
|
wget -qO- "https://cmake.org/files/v3.18/cmake-3.18.2-Linux-x86_64.tar.gz" | tar --strip-components=1 -xz -C /usr/local
|
||||||
|
cmake -S pybind11/ -B build
|
||||||
|
cmake --build build
|
||||||
|
```
|
||||||
|
|
||||||
|
### Explanation of the SDist/wheel building design
|
||||||
|
|
||||||
|
> These details below are _only_ for packaging the Python sources from git. The
|
||||||
|
> SDists and wheels created do not have any extra requirements at all and are
|
||||||
|
> completely normal.
|
||||||
|
|
||||||
|
The main objective of the packaging system is to create SDists (Python's source
|
||||||
|
distribution packages) and wheels (Python's binary distribution packages) that
|
||||||
|
include everything that is needed to work with pybind11, and which can be
|
||||||
|
installed without any additional dependencies. This is more complex than it
|
||||||
|
appears: in order to support CMake as a first class language even when using
|
||||||
|
the PyPI package, they must include the _generated_ CMake files (so as not to
|
||||||
|
require CMake when installing the `pybind11` package itself). They should also
|
||||||
|
provide the option to install to the "standard" location
|
||||||
|
(`<ENVROOT>/include/pybind11` and `<ENVROOT>/share/cmake/pybind11`) so they are
|
||||||
|
easy to find with CMake, but this can cause problems if you are not an
|
||||||
|
environment or using ``pyproject.toml`` requirements. This was solved by having
|
||||||
|
two packages; the "nice" pybind11 package that stores the includes and CMake
|
||||||
|
files inside the package, that you get access to via functions in the package,
|
||||||
|
and a `pybind11-global` package that can be included via `pybind11[global]` if
|
||||||
|
you want the more invasive but discoverable file locations.
|
||||||
|
|
||||||
|
If you want to install or package the GitHub source, it is best to have Pip 10
|
||||||
|
or newer on Windows, macOS, or Linux (manylinux1 compatible, includes most
|
||||||
|
distributions). You can then build the SDists, or run any procedure that makes
|
||||||
|
SDists internally, like making wheels or installing.
|
||||||
|
|
||||||
|
|
||||||
|
```bash
|
||||||
|
# Editable development install example
|
||||||
|
python3 -m pip install -e .
|
||||||
|
```
|
||||||
|
|
||||||
|
Since Pip itself does not have an `sdist` command (it does have `wheel` and
|
||||||
|
`install`), you may want to use the upcoming `build` package:
|
||||||
|
|
||||||
|
```bash
|
||||||
|
python3 -m pip install build
|
||||||
|
|
||||||
|
# Normal package
|
||||||
|
python3 -m build -s .
|
||||||
|
|
||||||
|
# Global extra
|
||||||
|
PYBIND11_GLOBAL_SDIST=1 python3 -m build -s .
|
||||||
|
```
|
||||||
|
|
||||||
|
If you want to use the classic "direct" usage of `python setup.py`, you will
|
||||||
|
need CMake 3.15+ and either `make` or `ninja` preinstalled (possibly via `pip
|
||||||
|
install cmake ninja`), since directly running Python on `setup.py` cannot pick
|
||||||
|
up and install `pyproject.toml` requirements. As long as you have those two
|
||||||
|
things, though, everything works the way you would expect:
|
||||||
|
|
||||||
|
```bash
|
||||||
|
# Normal package
|
||||||
|
python3 setup.py sdist
|
||||||
|
|
||||||
|
# Global extra
|
||||||
|
PYBIND11_GLOBAL_SDIST=1 python3 setup.py sdist
|
||||||
|
```
|
||||||
|
|
||||||
|
A detailed explanation of the build procedure design for developers wanting to
|
||||||
|
work on or maintain the packaging system is as follows:
|
||||||
|
|
||||||
|
#### 1. Building from the source directory
|
||||||
|
|
||||||
|
When you invoke any `setup.py` command from the source directory, including
|
||||||
|
`pip wheel .` and `pip install .`, you will activate a full source build. This
|
||||||
|
is made of the following steps:
|
||||||
|
|
||||||
|
1. If the tool is PEP 518 compliant, like Pip 10+, it will create a temporary
|
||||||
|
virtual environment and install the build requirements (mostly CMake) into
|
||||||
|
it. (if you are not on Windows, macOS, or a manylinux compliant system, you
|
||||||
|
can disable this with `--no-build-isolation` as long as you have CMake 3.15+
|
||||||
|
installed)
|
||||||
|
2. The environment variable `PYBIND11_GLOBAL_SDIST` is checked - if it is set
|
||||||
|
and truthy, this will be make the accessory `pybind11-global` package,
|
||||||
|
instead of the normal `pybind11` package. This package is used for
|
||||||
|
installing the files directly to your environment root directory, using
|
||||||
|
`pybind11[global]`.
|
||||||
|
2. `setup.py` reads the version from `pybind11/_version.py` and verifies it
|
||||||
|
matches `includes/pybind11/detail/common.h`.
|
||||||
|
3. CMake is run with `-DCMAKE_INSTALL_PREIFX=pybind11`. Since the CMake install
|
||||||
|
procedure uses only relative paths and is identical on all platforms, these
|
||||||
|
files are valid as long as they stay in the correct relative position to the
|
||||||
|
includes. `pybind11/share/cmake/pybind11` has the CMake files, and
|
||||||
|
`pybind11/include` has the includes. The build directory is discarded.
|
||||||
|
4. Simpler files are placed in the SDist: `tools/setup_*.py.in`,
|
||||||
|
`tools/pyproject.toml` (`main` or `global`)
|
||||||
|
5. The package is created by running the setup function in the
|
||||||
|
`tools/setup_*.py`. `setup_main.py` fills in Python packages, and
|
||||||
|
`setup_global.py` fills in only the data/header slots.
|
||||||
|
6. A context manager cleans up the temporary CMake install directory (even if
|
||||||
|
an error is thrown).
|
||||||
|
|
||||||
|
### 2. Building from SDist
|
||||||
|
|
||||||
|
Since the SDist has the rendered template files in `tools` along with the
|
||||||
|
includes and CMake files in the correct locations, the builds are completely
|
||||||
|
trivial and simple. No extra requirements are required. You can even use Pip 9
|
||||||
|
if you really want to.
|
||||||
|
|
||||||
|
|
||||||
|
[pre-commit]: https://pre-commit.com
|
||||||
|
[clang-format]: https://clang.llvm.org/docs/ClangFormat.html
|
||||||
|
[clang-tidy]: https://clang.llvm.org/extra/clang-tidy/
|
||||||
|
[pybind11.readthedocs.org]: http://pybind11.readthedocs.org/en/latest
|
||||||
|
[issue tracker]: https://github.com/pybind/pybind11/issues
|
||||||
|
[gitter]: https://gitter.im/pybind/Lobby
|
||||||
|
[using pull requests]: https://help.github.com/articles/using-pull-requests
|
61
3rdparty/pybind11/.github/ISSUE_TEMPLATE/bug-report.yml
vendored
Normal file
61
3rdparty/pybind11/.github/ISSUE_TEMPLATE/bug-report.yml
vendored
Normal file
@ -0,0 +1,61 @@
|
|||||||
|
name: Bug Report
|
||||||
|
description: File an issue about a bug
|
||||||
|
title: "[BUG]: "
|
||||||
|
labels: [triage]
|
||||||
|
body:
|
||||||
|
- type: markdown
|
||||||
|
attributes:
|
||||||
|
value: |
|
||||||
|
Please do your best to make the issue as easy to act on as possible, and only submit here if there is clearly a problem with pybind11 (ask first if unsure). **Note that a reproducer in a PR is much more likely to get immediate attention.**
|
||||||
|
|
||||||
|
- type: checkboxes
|
||||||
|
id: steps
|
||||||
|
attributes:
|
||||||
|
label: Required prerequisites
|
||||||
|
description: Make sure you've completed the following steps before submitting your issue -- thank you!
|
||||||
|
options:
|
||||||
|
- label: Make sure you've read the [documentation](https://pybind11.readthedocs.io). Your issue may be addressed there.
|
||||||
|
required: true
|
||||||
|
- label: Search the [issue tracker](https://github.com/pybind/pybind11/issues) and [Discussions](https:/pybind/pybind11/discussions) to verify that this hasn't already been reported. +1 or comment there if it has.
|
||||||
|
required: true
|
||||||
|
- label: Consider asking first in the [Gitter chat room](https://gitter.im/pybind/Lobby) or in a [Discussion](https:/pybind/pybind11/discussions/new).
|
||||||
|
required: false
|
||||||
|
|
||||||
|
- type: input
|
||||||
|
id: version
|
||||||
|
attributes:
|
||||||
|
label: What version (or hash if on master) of pybind11 are you using?
|
||||||
|
validations:
|
||||||
|
required: true
|
||||||
|
|
||||||
|
- type: textarea
|
||||||
|
id: description
|
||||||
|
attributes:
|
||||||
|
label: Problem description
|
||||||
|
placeholder: >-
|
||||||
|
Provide a short description, state the expected behavior and what
|
||||||
|
actually happens. Include relevant information like what version of
|
||||||
|
pybind11 you are using, what system you are on, and any useful commands
|
||||||
|
/ output.
|
||||||
|
validations:
|
||||||
|
required: true
|
||||||
|
|
||||||
|
- type: textarea
|
||||||
|
id: code
|
||||||
|
attributes:
|
||||||
|
label: Reproducible example code
|
||||||
|
placeholder: >-
|
||||||
|
The code should be minimal, have no external dependencies, isolate the
|
||||||
|
function(s) that cause breakage. Submit matched and complete C++ and
|
||||||
|
Python snippets that can be easily compiled and run to diagnose the
|
||||||
|
issue. — Note that a reproducer in a PR is much more likely to get
|
||||||
|
immediate attention: failing tests in the pybind11 CI are the best
|
||||||
|
starting point for working out fixes.
|
||||||
|
render: text
|
||||||
|
|
||||||
|
- type: input
|
||||||
|
id: regression
|
||||||
|
attributes:
|
||||||
|
label: Is this a regression? Put the last known working version here if it is.
|
||||||
|
description: Put the last known working version here if this is a regression.
|
||||||
|
value: Not a regression
|
8
3rdparty/pybind11/.github/ISSUE_TEMPLATE/config.yml
vendored
Normal file
8
3rdparty/pybind11/.github/ISSUE_TEMPLATE/config.yml
vendored
Normal file
@ -0,0 +1,8 @@
|
|||||||
|
blank_issues_enabled: false
|
||||||
|
contact_links:
|
||||||
|
- name: Ask a question
|
||||||
|
url: https://github.com/pybind/pybind11/discussions/new
|
||||||
|
about: Please ask and answer questions here, or propose new ideas.
|
||||||
|
- name: Gitter room
|
||||||
|
url: https://gitter.im/pybind/Lobby
|
||||||
|
about: A room for discussing pybind11 with an active community
|
15
3rdparty/pybind11/.github/dependabot.yml
vendored
Normal file
15
3rdparty/pybind11/.github/dependabot.yml
vendored
Normal file
@ -0,0 +1,15 @@
|
|||||||
|
version: 2
|
||||||
|
updates:
|
||||||
|
# Maintain dependencies for GitHub Actions
|
||||||
|
- package-ecosystem: "github-actions"
|
||||||
|
directory: "/"
|
||||||
|
schedule:
|
||||||
|
interval: "weekly"
|
||||||
|
groups:
|
||||||
|
actions:
|
||||||
|
patterns:
|
||||||
|
- "*"
|
||||||
|
ignore:
|
||||||
|
- dependency-name: actions/checkout
|
||||||
|
versions:
|
||||||
|
- "<5"
|
8
3rdparty/pybind11/.github/labeler.yml
vendored
Normal file
8
3rdparty/pybind11/.github/labeler.yml
vendored
Normal file
@ -0,0 +1,8 @@
|
|||||||
|
docs:
|
||||||
|
- any:
|
||||||
|
- 'docs/**/*.rst'
|
||||||
|
- '!docs/changelog.rst'
|
||||||
|
- '!docs/upgrade.rst'
|
||||||
|
|
||||||
|
ci:
|
||||||
|
- '.github/workflows/*.yml'
|
3
3rdparty/pybind11/.github/labeler_merged.yml
vendored
Normal file
3
3rdparty/pybind11/.github/labeler_merged.yml
vendored
Normal file
@ -0,0 +1,3 @@
|
|||||||
|
needs changelog:
|
||||||
|
- all:
|
||||||
|
- '!docs/changelog.rst'
|
19
3rdparty/pybind11/.github/pull_request_template.md
vendored
Normal file
19
3rdparty/pybind11/.github/pull_request_template.md
vendored
Normal file
@ -0,0 +1,19 @@
|
|||||||
|
<!--
|
||||||
|
Title (above): please place [branch_name] at the beginning if you are targeting a branch other than master. *Do not target stable*.
|
||||||
|
It is recommended to use conventional commit format, see conventionalcommits.org, but not required.
|
||||||
|
-->
|
||||||
|
## Description
|
||||||
|
|
||||||
|
<!-- Include relevant issues or PRs here, describe what changed and why -->
|
||||||
|
|
||||||
|
|
||||||
|
## Suggested changelog entry:
|
||||||
|
|
||||||
|
<!-- Fill in the below block with the expected RestructuredText entry. Delete if no entry needed;
|
||||||
|
but do not delete header or rst block if an entry is needed! Will be collected via a script. -->
|
||||||
|
|
||||||
|
```rst
|
||||||
|
|
||||||
|
```
|
||||||
|
|
||||||
|
<!-- If the upgrade guide needs updating, note that here too -->
|
1202
3rdparty/pybind11/.github/workflows/ci.yml
vendored
Normal file
1202
3rdparty/pybind11/.github/workflows/ci.yml
vendored
Normal file
File diff suppressed because it is too large
Load Diff
92
3rdparty/pybind11/.github/workflows/configure.yml
vendored
Normal file
92
3rdparty/pybind11/.github/workflows/configure.yml
vendored
Normal file
@ -0,0 +1,92 @@
|
|||||||
|
name: Config
|
||||||
|
|
||||||
|
on:
|
||||||
|
workflow_dispatch:
|
||||||
|
pull_request:
|
||||||
|
push:
|
||||||
|
branches:
|
||||||
|
- master
|
||||||
|
- stable
|
||||||
|
- v*
|
||||||
|
|
||||||
|
permissions:
|
||||||
|
contents: read
|
||||||
|
|
||||||
|
env:
|
||||||
|
PIP_BREAK_SYSTEM_PACKAGES: 1
|
||||||
|
# For cmake:
|
||||||
|
VERBOSE: 1
|
||||||
|
|
||||||
|
jobs:
|
||||||
|
# This tests various versions of CMake in various combinations, to make sure
|
||||||
|
# the configure step passes.
|
||||||
|
cmake:
|
||||||
|
strategy:
|
||||||
|
fail-fast: false
|
||||||
|
matrix:
|
||||||
|
runs-on: [ubuntu-20.04, macos-latest, windows-latest]
|
||||||
|
arch: [x64]
|
||||||
|
cmake: ["3.26"]
|
||||||
|
|
||||||
|
include:
|
||||||
|
- runs-on: ubuntu-20.04
|
||||||
|
arch: x64
|
||||||
|
cmake: "3.5"
|
||||||
|
|
||||||
|
- runs-on: ubuntu-20.04
|
||||||
|
arch: x64
|
||||||
|
cmake: "3.27"
|
||||||
|
|
||||||
|
- runs-on: macos-latest
|
||||||
|
arch: x64
|
||||||
|
cmake: "3.7"
|
||||||
|
|
||||||
|
- runs-on: windows-2019
|
||||||
|
arch: x64 # x86 compilers seem to be missing on 2019 image
|
||||||
|
cmake: "3.18"
|
||||||
|
|
||||||
|
name: 🐍 3.7 • CMake ${{ matrix.cmake }} • ${{ matrix.runs-on }}
|
||||||
|
runs-on: ${{ matrix.runs-on }}
|
||||||
|
|
||||||
|
steps:
|
||||||
|
- uses: actions/checkout@v4
|
||||||
|
|
||||||
|
- name: Setup Python 3.7
|
||||||
|
uses: actions/setup-python@v5
|
||||||
|
with:
|
||||||
|
python-version: 3.7
|
||||||
|
architecture: ${{ matrix.arch }}
|
||||||
|
|
||||||
|
- name: Prepare env
|
||||||
|
run: python -m pip install -r tests/requirements.txt
|
||||||
|
|
||||||
|
# An action for adding a specific version of CMake:
|
||||||
|
# https://github.com/jwlawson/actions-setup-cmake
|
||||||
|
- name: Setup CMake ${{ matrix.cmake }}
|
||||||
|
uses: jwlawson/actions-setup-cmake@v2.0
|
||||||
|
with:
|
||||||
|
cmake-version: ${{ matrix.cmake }}
|
||||||
|
|
||||||
|
# These steps use a directory with a space in it intentionally
|
||||||
|
- name: Make build directories
|
||||||
|
run: mkdir "build dir"
|
||||||
|
|
||||||
|
- name: Configure
|
||||||
|
working-directory: build dir
|
||||||
|
shell: bash
|
||||||
|
run: >
|
||||||
|
cmake ..
|
||||||
|
-DPYBIND11_WERROR=ON
|
||||||
|
-DDOWNLOAD_CATCH=ON
|
||||||
|
-DPYTHON_EXECUTABLE=$(python -c "import sys; print(sys.executable)")
|
||||||
|
|
||||||
|
# Only build and test if this was manually triggered in the GitHub UI
|
||||||
|
- name: Build
|
||||||
|
working-directory: build dir
|
||||||
|
if: github.event_name == 'workflow_dispatch'
|
||||||
|
run: cmake --build . --config Release
|
||||||
|
|
||||||
|
- name: Test
|
||||||
|
working-directory: build dir
|
||||||
|
if: github.event_name == 'workflow_dispatch'
|
||||||
|
run: cmake --build . --config Release --target check
|
60
3rdparty/pybind11/.github/workflows/format.yml
vendored
Normal file
60
3rdparty/pybind11/.github/workflows/format.yml
vendored
Normal file
@ -0,0 +1,60 @@
|
|||||||
|
# This is a format job. Pre-commit has a first-party GitHub action, so we use
|
||||||
|
# that: https://github.com/pre-commit/action
|
||||||
|
|
||||||
|
name: Format
|
||||||
|
|
||||||
|
on:
|
||||||
|
workflow_dispatch:
|
||||||
|
pull_request:
|
||||||
|
push:
|
||||||
|
branches:
|
||||||
|
- master
|
||||||
|
- stable
|
||||||
|
- "v*"
|
||||||
|
|
||||||
|
permissions:
|
||||||
|
contents: read
|
||||||
|
|
||||||
|
env:
|
||||||
|
FORCE_COLOR: 3
|
||||||
|
# For cmake:
|
||||||
|
VERBOSE: 1
|
||||||
|
|
||||||
|
jobs:
|
||||||
|
pre-commit:
|
||||||
|
name: Format
|
||||||
|
runs-on: ubuntu-latest
|
||||||
|
steps:
|
||||||
|
- uses: actions/checkout@v4
|
||||||
|
- uses: actions/setup-python@v5
|
||||||
|
with:
|
||||||
|
python-version: "3.x"
|
||||||
|
- name: Add matchers
|
||||||
|
run: echo "::add-matcher::$GITHUB_WORKSPACE/.github/matchers/pylint.json"
|
||||||
|
- uses: pre-commit/action@v3.0.1
|
||||||
|
with:
|
||||||
|
# Slow hooks are marked with manual - slow is okay here, run them too
|
||||||
|
extra_args: --hook-stage manual --all-files
|
||||||
|
|
||||||
|
clang-tidy:
|
||||||
|
# When making changes here, please also review the "Clang-Tidy" section
|
||||||
|
# in .github/CONTRIBUTING.md and update as needed.
|
||||||
|
name: Clang-Tidy
|
||||||
|
runs-on: ubuntu-latest
|
||||||
|
container: silkeh/clang:15-bullseye
|
||||||
|
steps:
|
||||||
|
- uses: actions/checkout@v4
|
||||||
|
|
||||||
|
- name: Install requirements
|
||||||
|
run: apt-get update && apt-get install -y git python3-dev python3-pytest
|
||||||
|
|
||||||
|
- name: Configure
|
||||||
|
run: >
|
||||||
|
cmake -S . -B build
|
||||||
|
-DCMAKE_CXX_CLANG_TIDY="$(which clang-tidy);--use-color;--warnings-as-errors=*"
|
||||||
|
-DDOWNLOAD_EIGEN=ON
|
||||||
|
-DDOWNLOAD_CATCH=ON
|
||||||
|
-DCMAKE_CXX_STANDARD=17
|
||||||
|
|
||||||
|
- name: Build
|
||||||
|
run: cmake --build build -j 2 -- --keep-going
|
25
3rdparty/pybind11/.github/workflows/labeler.yml
vendored
Normal file
25
3rdparty/pybind11/.github/workflows/labeler.yml
vendored
Normal file
@ -0,0 +1,25 @@
|
|||||||
|
name: Labeler
|
||||||
|
on:
|
||||||
|
pull_request_target:
|
||||||
|
types: [closed]
|
||||||
|
|
||||||
|
permissions: {}
|
||||||
|
|
||||||
|
jobs:
|
||||||
|
label:
|
||||||
|
name: Labeler
|
||||||
|
runs-on: ubuntu-latest
|
||||||
|
permissions:
|
||||||
|
contents: read
|
||||||
|
pull-requests: write
|
||||||
|
steps:
|
||||||
|
|
||||||
|
- uses: actions/labeler@v4
|
||||||
|
if: >
|
||||||
|
github.event.pull_request.merged == true &&
|
||||||
|
!startsWith(github.event.pull_request.title, 'chore(deps):') &&
|
||||||
|
!startsWith(github.event.pull_request.title, 'ci(fix):') &&
|
||||||
|
!startsWith(github.event.pull_request.title, 'docs(changelog):')
|
||||||
|
with:
|
||||||
|
repo-token: ${{ secrets.GITHUB_TOKEN }}
|
||||||
|
configuration-path: .github/labeler_merged.yml
|
114
3rdparty/pybind11/.github/workflows/pip.yml
vendored
Normal file
114
3rdparty/pybind11/.github/workflows/pip.yml
vendored
Normal file
@ -0,0 +1,114 @@
|
|||||||
|
name: Pip
|
||||||
|
|
||||||
|
on:
|
||||||
|
workflow_dispatch:
|
||||||
|
pull_request:
|
||||||
|
push:
|
||||||
|
branches:
|
||||||
|
- master
|
||||||
|
- stable
|
||||||
|
- v*
|
||||||
|
release:
|
||||||
|
types:
|
||||||
|
- published
|
||||||
|
|
||||||
|
permissions:
|
||||||
|
contents: read
|
||||||
|
|
||||||
|
env:
|
||||||
|
PIP_BREAK_SYSTEM_PACKAGES: 1
|
||||||
|
PIP_ONLY_BINARY: numpy
|
||||||
|
|
||||||
|
jobs:
|
||||||
|
# This builds the sdists and wheels and makes sure the files are exactly as
|
||||||
|
# expected. Using Windows and Python 3.6, since that is often the most
|
||||||
|
# challenging matrix element.
|
||||||
|
test-packaging:
|
||||||
|
name: 🐍 3.6 • 📦 tests • windows-latest
|
||||||
|
runs-on: windows-latest
|
||||||
|
|
||||||
|
steps:
|
||||||
|
- uses: actions/checkout@v4
|
||||||
|
|
||||||
|
- name: Setup 🐍 3.6
|
||||||
|
uses: actions/setup-python@v5
|
||||||
|
with:
|
||||||
|
python-version: 3.6
|
||||||
|
|
||||||
|
- name: Prepare env
|
||||||
|
run: |
|
||||||
|
python -m pip install -r tests/requirements.txt
|
||||||
|
|
||||||
|
- name: Python Packaging tests
|
||||||
|
run: pytest tests/extra_python_package/
|
||||||
|
|
||||||
|
|
||||||
|
# This runs the packaging tests and also builds and saves the packages as
|
||||||
|
# artifacts.
|
||||||
|
packaging:
|
||||||
|
name: 🐍 3.8 • 📦 & 📦 tests • ubuntu-latest
|
||||||
|
runs-on: ubuntu-latest
|
||||||
|
|
||||||
|
steps:
|
||||||
|
- uses: actions/checkout@v4
|
||||||
|
|
||||||
|
- name: Setup 🐍 3.8
|
||||||
|
uses: actions/setup-python@v5
|
||||||
|
with:
|
||||||
|
python-version: 3.8
|
||||||
|
|
||||||
|
- name: Prepare env
|
||||||
|
run: |
|
||||||
|
python -m pip install -r tests/requirements.txt build twine
|
||||||
|
|
||||||
|
- name: Python Packaging tests
|
||||||
|
run: pytest tests/extra_python_package/
|
||||||
|
|
||||||
|
- name: Build SDist and wheels
|
||||||
|
run: |
|
||||||
|
python -m build
|
||||||
|
PYBIND11_GLOBAL_SDIST=1 python -m build
|
||||||
|
|
||||||
|
- name: Check metadata
|
||||||
|
run: twine check dist/*
|
||||||
|
|
||||||
|
- name: Save standard package
|
||||||
|
uses: actions/upload-artifact@v4
|
||||||
|
with:
|
||||||
|
name: standard
|
||||||
|
path: dist/pybind11-*
|
||||||
|
|
||||||
|
- name: Save global package
|
||||||
|
uses: actions/upload-artifact@v4
|
||||||
|
with:
|
||||||
|
name: global
|
||||||
|
path: dist/pybind11_global-*
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
# When a GitHub release is made, upload the artifacts to PyPI
|
||||||
|
upload:
|
||||||
|
name: Upload to PyPI
|
||||||
|
runs-on: ubuntu-latest
|
||||||
|
if: github.event_name == 'release' && github.event.action == 'published'
|
||||||
|
needs: [packaging]
|
||||||
|
|
||||||
|
steps:
|
||||||
|
- uses: actions/setup-python@v5
|
||||||
|
with:
|
||||||
|
python-version: "3.x"
|
||||||
|
|
||||||
|
# Downloads all to directories matching the artifact names
|
||||||
|
- uses: actions/download-artifact@v4
|
||||||
|
|
||||||
|
- name: Publish standard package
|
||||||
|
uses: pypa/gh-action-pypi-publish@release/v1
|
||||||
|
with:
|
||||||
|
password: ${{ secrets.pypi_password }}
|
||||||
|
packages-dir: standard/
|
||||||
|
|
||||||
|
- name: Publish global package
|
||||||
|
uses: pypa/gh-action-pypi-publish@release/v1
|
||||||
|
with:
|
||||||
|
password: ${{ secrets.pypi_password_global }}
|
||||||
|
packages-dir: global/
|
116
3rdparty/pybind11/.github/workflows/upstream.yml
vendored
Normal file
116
3rdparty/pybind11/.github/workflows/upstream.yml
vendored
Normal file
@ -0,0 +1,116 @@
|
|||||||
|
name: Upstream
|
||||||
|
|
||||||
|
on:
|
||||||
|
workflow_dispatch:
|
||||||
|
pull_request:
|
||||||
|
|
||||||
|
permissions:
|
||||||
|
contents: read
|
||||||
|
|
||||||
|
concurrency:
|
||||||
|
group: upstream-${{ github.ref }}
|
||||||
|
cancel-in-progress: true
|
||||||
|
|
||||||
|
env:
|
||||||
|
PIP_BREAK_SYSTEM_PACKAGES: 1
|
||||||
|
# For cmake:
|
||||||
|
VERBOSE: 1
|
||||||
|
|
||||||
|
jobs:
|
||||||
|
standard:
|
||||||
|
name: "🐍 3.13 latest • ubuntu-latest • x64"
|
||||||
|
runs-on: ubuntu-latest
|
||||||
|
# Only runs when the 'python dev' label is selected
|
||||||
|
if: "contains(github.event.pull_request.labels.*.name, 'python dev')"
|
||||||
|
|
||||||
|
steps:
|
||||||
|
- uses: actions/checkout@v4
|
||||||
|
|
||||||
|
- name: Setup Python 3.13
|
||||||
|
uses: actions/setup-python@v5
|
||||||
|
with:
|
||||||
|
python-version: "3.13"
|
||||||
|
allow-prereleases: true
|
||||||
|
|
||||||
|
- name: Setup Boost
|
||||||
|
run: sudo apt-get install libboost-dev
|
||||||
|
|
||||||
|
- name: Update CMake
|
||||||
|
uses: jwlawson/actions-setup-cmake@v2.0
|
||||||
|
|
||||||
|
- name: Run pip installs
|
||||||
|
run: |
|
||||||
|
python -m pip install --upgrade pip
|
||||||
|
python -m pip install -r tests/requirements.txt
|
||||||
|
|
||||||
|
- name: Show platform info
|
||||||
|
run: |
|
||||||
|
python -m platform
|
||||||
|
cmake --version
|
||||||
|
pip list
|
||||||
|
|
||||||
|
# First build - C++11 mode and inplace
|
||||||
|
- name: Configure C++11
|
||||||
|
run: >
|
||||||
|
cmake -S . -B build11
|
||||||
|
-DPYBIND11_WERROR=ON
|
||||||
|
-DDOWNLOAD_CATCH=ON
|
||||||
|
-DDOWNLOAD_EIGEN=ON
|
||||||
|
-DCMAKE_CXX_STANDARD=11
|
||||||
|
-DCMAKE_BUILD_TYPE=Debug
|
||||||
|
|
||||||
|
- name: Build C++11
|
||||||
|
run: cmake --build build11 -j 2
|
||||||
|
|
||||||
|
- name: Python tests C++11
|
||||||
|
run: cmake --build build11 --target pytest -j 2
|
||||||
|
|
||||||
|
- name: C++11 tests
|
||||||
|
run: cmake --build build11 --target cpptest -j 2
|
||||||
|
|
||||||
|
- name: Interface test C++11
|
||||||
|
run: cmake --build build11 --target test_cmake_build
|
||||||
|
|
||||||
|
# Second build - C++17 mode and in a build directory
|
||||||
|
- name: Configure C++17
|
||||||
|
run: >
|
||||||
|
cmake -S . -B build17
|
||||||
|
-DPYBIND11_WERROR=ON
|
||||||
|
-DDOWNLOAD_CATCH=ON
|
||||||
|
-DDOWNLOAD_EIGEN=ON
|
||||||
|
-DCMAKE_CXX_STANDARD=17
|
||||||
|
|
||||||
|
- name: Build C++17
|
||||||
|
run: cmake --build build17 -j 2
|
||||||
|
|
||||||
|
- name: Python tests C++17
|
||||||
|
run: cmake --build build17 --target pytest
|
||||||
|
|
||||||
|
- name: C++17 tests
|
||||||
|
run: cmake --build build17 --target cpptest
|
||||||
|
|
||||||
|
# Third build - C++17 mode with unstable ABI
|
||||||
|
- name: Configure (unstable ABI)
|
||||||
|
run: >
|
||||||
|
cmake -S . -B build17max
|
||||||
|
-DPYBIND11_WERROR=ON
|
||||||
|
-DDOWNLOAD_CATCH=ON
|
||||||
|
-DDOWNLOAD_EIGEN=ON
|
||||||
|
-DCMAKE_CXX_STANDARD=17
|
||||||
|
-DPYBIND11_INTERNALS_VERSION=10000000
|
||||||
|
|
||||||
|
- name: Build (unstable ABI)
|
||||||
|
run: cmake --build build17max -j 2
|
||||||
|
|
||||||
|
- name: Python tests (unstable ABI)
|
||||||
|
run: cmake --build build17max --target pytest
|
||||||
|
|
||||||
|
- name: Interface test (unstable ABI)
|
||||||
|
run: cmake --build build17max --target test_cmake_build
|
||||||
|
|
||||||
|
# This makes sure the setup_helpers module can build packages using
|
||||||
|
# setuptools
|
||||||
|
- name: Setuptools helpers test
|
||||||
|
run: |
|
||||||
|
pip install setuptools
|
||||||
|
pytest tests/extra_setuptools
|
46
3rdparty/pybind11/.gitignore
vendored
Normal file
46
3rdparty/pybind11/.gitignore
vendored
Normal file
@ -0,0 +1,46 @@
|
|||||||
|
CMakeCache.txt
|
||||||
|
CMakeFiles
|
||||||
|
Makefile
|
||||||
|
cmake_install.cmake
|
||||||
|
cmake_uninstall.cmake
|
||||||
|
.DS_Store
|
||||||
|
*.so
|
||||||
|
*.pyd
|
||||||
|
*.dll
|
||||||
|
*.sln
|
||||||
|
*.sdf
|
||||||
|
*.opensdf
|
||||||
|
*.vcxproj
|
||||||
|
*.vcxproj.user
|
||||||
|
*.filters
|
||||||
|
example.dir
|
||||||
|
Win32
|
||||||
|
x64
|
||||||
|
Release
|
||||||
|
Debug
|
||||||
|
.vs
|
||||||
|
CTestTestfile.cmake
|
||||||
|
Testing
|
||||||
|
autogen
|
||||||
|
MANIFEST
|
||||||
|
/.ninja_*
|
||||||
|
/*.ninja
|
||||||
|
/docs/.build
|
||||||
|
*.py[co]
|
||||||
|
*.egg-info
|
||||||
|
*~
|
||||||
|
.*.swp
|
||||||
|
.DS_Store
|
||||||
|
/dist
|
||||||
|
/*build*
|
||||||
|
.cache/
|
||||||
|
sosize-*.txt
|
||||||
|
pybind11Config*.cmake
|
||||||
|
pybind11Targets.cmake
|
||||||
|
/*env*
|
||||||
|
/.vscode
|
||||||
|
/pybind11/include/*
|
||||||
|
/pybind11/share/*
|
||||||
|
/docs/_build/*
|
||||||
|
.ipynb_checkpoints/
|
||||||
|
tests/main.cpp
|
155
3rdparty/pybind11/.pre-commit-config.yaml
vendored
Normal file
155
3rdparty/pybind11/.pre-commit-config.yaml
vendored
Normal file
@ -0,0 +1,155 @@
|
|||||||
|
# To use:
|
||||||
|
#
|
||||||
|
# pre-commit run -a
|
||||||
|
#
|
||||||
|
# Or:
|
||||||
|
#
|
||||||
|
# pre-commit install # (runs every time you commit in git)
|
||||||
|
#
|
||||||
|
# To update this file:
|
||||||
|
#
|
||||||
|
# pre-commit autoupdate
|
||||||
|
#
|
||||||
|
# See https://github.com/pre-commit/pre-commit
|
||||||
|
|
||||||
|
|
||||||
|
ci:
|
||||||
|
autoupdate_commit_msg: "chore(deps): update pre-commit hooks"
|
||||||
|
autofix_commit_msg: "style: pre-commit fixes"
|
||||||
|
autoupdate_schedule: monthly
|
||||||
|
|
||||||
|
# third-party content
|
||||||
|
exclude: ^tools/JoinPaths.cmake$
|
||||||
|
|
||||||
|
repos:
|
||||||
|
|
||||||
|
# Clang format the codebase automatically
|
||||||
|
- repo: https://github.com/pre-commit/mirrors-clang-format
|
||||||
|
rev: "v17.0.6"
|
||||||
|
hooks:
|
||||||
|
- id: clang-format
|
||||||
|
types_or: [c++, c, cuda]
|
||||||
|
|
||||||
|
# Ruff, the Python auto-correcting linter/formatter written in Rust
|
||||||
|
- repo: https://github.com/astral-sh/ruff-pre-commit
|
||||||
|
rev: v0.2.0
|
||||||
|
hooks:
|
||||||
|
- id: ruff
|
||||||
|
args: ["--fix", "--show-fixes"]
|
||||||
|
- id: ruff-format
|
||||||
|
|
||||||
|
# Check static types with mypy
|
||||||
|
- repo: https://github.com/pre-commit/mirrors-mypy
|
||||||
|
rev: "v1.8.0"
|
||||||
|
hooks:
|
||||||
|
- id: mypy
|
||||||
|
args: []
|
||||||
|
exclude: ^(tests|docs)/
|
||||||
|
additional_dependencies:
|
||||||
|
- markdown-it-py<3 # Drop this together with dropping Python 3.7 support.
|
||||||
|
- nox
|
||||||
|
- rich
|
||||||
|
- types-setuptools
|
||||||
|
|
||||||
|
# CMake formatting
|
||||||
|
- repo: https://github.com/cheshirekow/cmake-format-precommit
|
||||||
|
rev: "v0.6.13"
|
||||||
|
hooks:
|
||||||
|
- id: cmake-format
|
||||||
|
additional_dependencies: [pyyaml]
|
||||||
|
types: [file]
|
||||||
|
files: (\.cmake|CMakeLists.txt)(.in)?$
|
||||||
|
|
||||||
|
# Standard hooks
|
||||||
|
- repo: https://github.com/pre-commit/pre-commit-hooks
|
||||||
|
rev: "v4.5.0"
|
||||||
|
hooks:
|
||||||
|
- id: check-added-large-files
|
||||||
|
- id: check-case-conflict
|
||||||
|
- id: check-docstring-first
|
||||||
|
- id: check-merge-conflict
|
||||||
|
- id: check-symlinks
|
||||||
|
- id: check-toml
|
||||||
|
- id: check-yaml
|
||||||
|
- id: debug-statements
|
||||||
|
- id: end-of-file-fixer
|
||||||
|
- id: mixed-line-ending
|
||||||
|
- id: requirements-txt-fixer
|
||||||
|
- id: trailing-whitespace
|
||||||
|
|
||||||
|
# Also code format the docs
|
||||||
|
- repo: https://github.com/asottile/blacken-docs
|
||||||
|
rev: "1.16.0"
|
||||||
|
hooks:
|
||||||
|
- id: blacken-docs
|
||||||
|
additional_dependencies:
|
||||||
|
- black==23.*
|
||||||
|
|
||||||
|
# Changes tabs to spaces
|
||||||
|
- repo: https://github.com/Lucas-C/pre-commit-hooks
|
||||||
|
rev: "v1.5.4"
|
||||||
|
hooks:
|
||||||
|
- id: remove-tabs
|
||||||
|
|
||||||
|
# Avoid directional quotes
|
||||||
|
- repo: https://github.com/sirosen/texthooks
|
||||||
|
rev: "0.6.4"
|
||||||
|
hooks:
|
||||||
|
- id: fix-ligatures
|
||||||
|
- id: fix-smartquotes
|
||||||
|
|
||||||
|
# Checking for common mistakes
|
||||||
|
- repo: https://github.com/pre-commit/pygrep-hooks
|
||||||
|
rev: "v1.10.0"
|
||||||
|
hooks:
|
||||||
|
- id: rst-backticks
|
||||||
|
- id: rst-directive-colons
|
||||||
|
- id: rst-inline-touching-normal
|
||||||
|
|
||||||
|
# Checks the manifest for missing files (native support)
|
||||||
|
- repo: https://github.com/mgedmin/check-manifest
|
||||||
|
rev: "0.49"
|
||||||
|
hooks:
|
||||||
|
- id: check-manifest
|
||||||
|
# This is a slow hook, so only run this if --hook-stage manual is passed
|
||||||
|
stages: [manual]
|
||||||
|
additional_dependencies: [cmake, ninja]
|
||||||
|
|
||||||
|
# Check for spelling
|
||||||
|
# Use tools/codespell_ignore_lines_from_errors.py
|
||||||
|
# to rebuild .codespell-ignore-lines
|
||||||
|
- repo: https://github.com/codespell-project/codespell
|
||||||
|
rev: "v2.2.6"
|
||||||
|
hooks:
|
||||||
|
- id: codespell
|
||||||
|
exclude: ".supp$"
|
||||||
|
args: ["-x.codespell-ignore-lines", "-Lccompiler"]
|
||||||
|
|
||||||
|
# Check for common shell mistakes
|
||||||
|
- repo: https://github.com/shellcheck-py/shellcheck-py
|
||||||
|
rev: "v0.9.0.6"
|
||||||
|
hooks:
|
||||||
|
- id: shellcheck
|
||||||
|
|
||||||
|
# Disallow some common capitalization mistakes
|
||||||
|
- repo: local
|
||||||
|
hooks:
|
||||||
|
- id: disallow-caps
|
||||||
|
name: Disallow improper capitalization
|
||||||
|
language: pygrep
|
||||||
|
entry: PyBind|\bNumpy\b|Cmake|CCache|PyTest
|
||||||
|
exclude: ^\.pre-commit-config.yaml$
|
||||||
|
|
||||||
|
# PyLint has native support - not always usable, but works for us
|
||||||
|
- repo: https://github.com/PyCQA/pylint
|
||||||
|
rev: "v3.0.3"
|
||||||
|
hooks:
|
||||||
|
- id: pylint
|
||||||
|
files: ^pybind11
|
||||||
|
|
||||||
|
- repo: https://github.com/python-jsonschema/check-jsonschema
|
||||||
|
rev: 0.28.0
|
||||||
|
hooks:
|
||||||
|
- id: check-readthedocs
|
||||||
|
- id: check-github-workflows
|
||||||
|
- id: check-dependabot
|
20
3rdparty/pybind11/.readthedocs.yml
vendored
Normal file
20
3rdparty/pybind11/.readthedocs.yml
vendored
Normal file
@ -0,0 +1,20 @@
|
|||||||
|
# https://blog.readthedocs.com/migrate-configuration-v2/
|
||||||
|
|
||||||
|
version: 2
|
||||||
|
|
||||||
|
build:
|
||||||
|
os: ubuntu-22.04
|
||||||
|
apt_packages:
|
||||||
|
- librsvg2-bin
|
||||||
|
tools:
|
||||||
|
python: "3.11"
|
||||||
|
|
||||||
|
sphinx:
|
||||||
|
configuration: docs/conf.py
|
||||||
|
|
||||||
|
python:
|
||||||
|
install:
|
||||||
|
- requirements: docs/requirements.txt
|
||||||
|
|
||||||
|
formats:
|
||||||
|
- pdf
|
374
3rdparty/pybind11/CMakeLists.txt
vendored
Normal file
374
3rdparty/pybind11/CMakeLists.txt
vendored
Normal file
@ -0,0 +1,374 @@
|
|||||||
|
# CMakeLists.txt -- Build system for the pybind11 modules
|
||||||
|
#
|
||||||
|
# Copyright (c) 2015 Wenzel Jakob <wenzel@inf.ethz.ch>
|
||||||
|
#
|
||||||
|
# All rights reserved. Use of this source code is governed by a
|
||||||
|
# BSD-style license that can be found in the LICENSE file.
|
||||||
|
|
||||||
|
# Propagate this policy (FindPythonInterp removal) so it can be detected later
|
||||||
|
if(NOT CMAKE_VERSION VERSION_LESS "3.27")
|
||||||
|
cmake_policy(GET CMP0148 _pybind11_cmp0148)
|
||||||
|
endif()
|
||||||
|
|
||||||
|
cmake_minimum_required(VERSION 3.5)
|
||||||
|
|
||||||
|
# The `cmake_minimum_required(VERSION 3.5...3.27)` syntax does not work with
|
||||||
|
# some versions of VS that have a patched CMake 3.11. This forces us to emulate
|
||||||
|
# the behavior using the following workaround:
|
||||||
|
if(${CMAKE_VERSION} VERSION_LESS 3.27)
|
||||||
|
cmake_policy(VERSION ${CMAKE_MAJOR_VERSION}.${CMAKE_MINOR_VERSION})
|
||||||
|
else()
|
||||||
|
cmake_policy(VERSION 3.27)
|
||||||
|
endif()
|
||||||
|
|
||||||
|
if(_pybind11_cmp0148)
|
||||||
|
cmake_policy(SET CMP0148 ${_pybind11_cmp0148})
|
||||||
|
unset(_pybind11_cmp0148)
|
||||||
|
endif()
|
||||||
|
|
||||||
|
# Avoid infinite recursion if tests include this as a subdirectory
|
||||||
|
if(DEFINED PYBIND11_MASTER_PROJECT)
|
||||||
|
return()
|
||||||
|
endif()
|
||||||
|
|
||||||
|
# Extract project version from source
|
||||||
|
file(STRINGS "${CMAKE_CURRENT_SOURCE_DIR}/include/pybind11/detail/common.h"
|
||||||
|
pybind11_version_defines REGEX "#define PYBIND11_VERSION_(MAJOR|MINOR|PATCH) ")
|
||||||
|
|
||||||
|
foreach(ver ${pybind11_version_defines})
|
||||||
|
if(ver MATCHES [[#define PYBIND11_VERSION_(MAJOR|MINOR|PATCH) +([^ ]+)$]])
|
||||||
|
set(PYBIND11_VERSION_${CMAKE_MATCH_1} "${CMAKE_MATCH_2}")
|
||||||
|
endif()
|
||||||
|
endforeach()
|
||||||
|
|
||||||
|
if(PYBIND11_VERSION_PATCH MATCHES [[\.([a-zA-Z0-9]+)$]])
|
||||||
|
set(pybind11_VERSION_TYPE "${CMAKE_MATCH_1}")
|
||||||
|
endif()
|
||||||
|
string(REGEX MATCH "^[0-9]+" PYBIND11_VERSION_PATCH "${PYBIND11_VERSION_PATCH}")
|
||||||
|
|
||||||
|
project(
|
||||||
|
pybind11
|
||||||
|
LANGUAGES CXX
|
||||||
|
VERSION "${PYBIND11_VERSION_MAJOR}.${PYBIND11_VERSION_MINOR}.${PYBIND11_VERSION_PATCH}")
|
||||||
|
|
||||||
|
# Standard includes
|
||||||
|
include(GNUInstallDirs)
|
||||||
|
include(CMakePackageConfigHelpers)
|
||||||
|
include(CMakeDependentOption)
|
||||||
|
|
||||||
|
if(NOT pybind11_FIND_QUIETLY)
|
||||||
|
message(STATUS "pybind11 v${pybind11_VERSION} ${pybind11_VERSION_TYPE}")
|
||||||
|
endif()
|
||||||
|
|
||||||
|
# Check if pybind11 is being used directly or via add_subdirectory
|
||||||
|
if(CMAKE_SOURCE_DIR STREQUAL PROJECT_SOURCE_DIR)
|
||||||
|
### Warn if not an out-of-source builds
|
||||||
|
if(CMAKE_CURRENT_SOURCE_DIR STREQUAL CMAKE_CURRENT_BINARY_DIR)
|
||||||
|
set(lines
|
||||||
|
"You are building in-place. If that is not what you intended to "
|
||||||
|
"do, you can clean the source directory with:\n"
|
||||||
|
"rm -r CMakeCache.txt CMakeFiles/ cmake_uninstall.cmake pybind11Config.cmake "
|
||||||
|
"pybind11ConfigVersion.cmake tests/CMakeFiles/\n")
|
||||||
|
message(AUTHOR_WARNING ${lines})
|
||||||
|
endif()
|
||||||
|
|
||||||
|
set(PYBIND11_MASTER_PROJECT ON)
|
||||||
|
|
||||||
|
if(OSX AND CMAKE_VERSION VERSION_LESS 3.7)
|
||||||
|
# Bug in macOS CMake < 3.7 is unable to download catch
|
||||||
|
message(WARNING "CMAKE 3.7+ needed on macOS to download catch, and newer HIGHLY recommended")
|
||||||
|
elseif(WINDOWS AND CMAKE_VERSION VERSION_LESS 3.8)
|
||||||
|
# Only tested with 3.8+ in CI.
|
||||||
|
message(WARNING "CMAKE 3.8+ tested on Windows, previous versions untested")
|
||||||
|
endif()
|
||||||
|
|
||||||
|
message(STATUS "CMake ${CMAKE_VERSION}")
|
||||||
|
|
||||||
|
if(CMAKE_CXX_STANDARD)
|
||||||
|
set(CMAKE_CXX_EXTENSIONS OFF)
|
||||||
|
set(CMAKE_CXX_STANDARD_REQUIRED ON)
|
||||||
|
endif()
|
||||||
|
|
||||||
|
set(pybind11_system "")
|
||||||
|
|
||||||
|
set_property(GLOBAL PROPERTY USE_FOLDERS ON)
|
||||||
|
if(CMAKE_VERSION VERSION_LESS "3.18")
|
||||||
|
set(_pybind11_findpython_default OFF)
|
||||||
|
else()
|
||||||
|
set(_pybind11_findpython_default ON)
|
||||||
|
endif()
|
||||||
|
else()
|
||||||
|
set(PYBIND11_MASTER_PROJECT OFF)
|
||||||
|
set(pybind11_system SYSTEM)
|
||||||
|
set(_pybind11_findpython_default OFF)
|
||||||
|
endif()
|
||||||
|
|
||||||
|
# Options
|
||||||
|
option(PYBIND11_INSTALL "Install pybind11 header files?" ${PYBIND11_MASTER_PROJECT})
|
||||||
|
option(PYBIND11_TEST "Build pybind11 test suite?" ${PYBIND11_MASTER_PROJECT})
|
||||||
|
option(PYBIND11_NOPYTHON "Disable search for Python" OFF)
|
||||||
|
option(PYBIND11_DISABLE_HANDLE_TYPE_NAME_DEFAULT_IMPLEMENTATION
|
||||||
|
"To enforce that a handle_type_name<> specialization exists" OFF)
|
||||||
|
option(PYBIND11_SIMPLE_GIL_MANAGEMENT
|
||||||
|
"Use simpler GIL management logic that does not support disassociation" OFF)
|
||||||
|
option(PYBIND11_NUMPY_1_ONLY
|
||||||
|
"Disable NumPy 2 support to avoid changes to previous pybind11 versions." OFF)
|
||||||
|
set(PYBIND11_INTERNALS_VERSION
|
||||||
|
""
|
||||||
|
CACHE STRING "Override the ABI version, may be used to enable the unstable ABI.")
|
||||||
|
|
||||||
|
if(PYBIND11_DISABLE_HANDLE_TYPE_NAME_DEFAULT_IMPLEMENTATION)
|
||||||
|
add_compile_definitions(PYBIND11_DISABLE_HANDLE_TYPE_NAME_DEFAULT_IMPLEMENTATION)
|
||||||
|
endif()
|
||||||
|
if(PYBIND11_SIMPLE_GIL_MANAGEMENT)
|
||||||
|
add_compile_definitions(PYBIND11_SIMPLE_GIL_MANAGEMENT)
|
||||||
|
endif()
|
||||||
|
if(PYBIND11_NUMPY_1_ONLY)
|
||||||
|
add_compile_definitions(PYBIND11_NUMPY_1_ONLY)
|
||||||
|
endif()
|
||||||
|
|
||||||
|
cmake_dependent_option(
|
||||||
|
USE_PYTHON_INCLUDE_DIR
|
||||||
|
"Install pybind11 headers in Python include directory instead of default installation prefix"
|
||||||
|
OFF "PYBIND11_INSTALL" OFF)
|
||||||
|
|
||||||
|
cmake_dependent_option(PYBIND11_FINDPYTHON "Force new FindPython" ${_pybind11_findpython_default}
|
||||||
|
"NOT CMAKE_VERSION VERSION_LESS 3.12" OFF)
|
||||||
|
|
||||||
|
# Allow PYTHON_EXECUTABLE if in FINDPYTHON mode and building pybind11's tests
|
||||||
|
# (makes transition easier while we support both modes).
|
||||||
|
if(PYBIND11_MASTER_PROJECT
|
||||||
|
AND PYBIND11_FINDPYTHON
|
||||||
|
AND DEFINED PYTHON_EXECUTABLE
|
||||||
|
AND NOT DEFINED Python_EXECUTABLE)
|
||||||
|
set(Python_EXECUTABLE "${PYTHON_EXECUTABLE}")
|
||||||
|
endif()
|
||||||
|
|
||||||
|
# NB: when adding a header don't forget to also add it to setup.py
|
||||||
|
set(PYBIND11_HEADERS
|
||||||
|
include/pybind11/detail/class.h
|
||||||
|
include/pybind11/detail/common.h
|
||||||
|
include/pybind11/detail/cpp_conduit.h
|
||||||
|
include/pybind11/detail/descr.h
|
||||||
|
include/pybind11/detail/init.h
|
||||||
|
include/pybind11/detail/internals.h
|
||||||
|
include/pybind11/detail/type_caster_base.h
|
||||||
|
include/pybind11/detail/typeid.h
|
||||||
|
include/pybind11/attr.h
|
||||||
|
include/pybind11/buffer_info.h
|
||||||
|
include/pybind11/cast.h
|
||||||
|
include/pybind11/chrono.h
|
||||||
|
include/pybind11/common.h
|
||||||
|
include/pybind11/complex.h
|
||||||
|
include/pybind11/options.h
|
||||||
|
include/pybind11/eigen.h
|
||||||
|
include/pybind11/eigen/common.h
|
||||||
|
include/pybind11/eigen/matrix.h
|
||||||
|
include/pybind11/eigen/tensor.h
|
||||||
|
include/pybind11/embed.h
|
||||||
|
include/pybind11/eval.h
|
||||||
|
include/pybind11/gil.h
|
||||||
|
include/pybind11/gil_safe_call_once.h
|
||||||
|
include/pybind11/iostream.h
|
||||||
|
include/pybind11/functional.h
|
||||||
|
include/pybind11/numpy.h
|
||||||
|
include/pybind11/operators.h
|
||||||
|
include/pybind11/pybind11.h
|
||||||
|
include/pybind11/pytypes.h
|
||||||
|
include/pybind11/stl.h
|
||||||
|
include/pybind11/stl_bind.h
|
||||||
|
include/pybind11/stl/filesystem.h
|
||||||
|
include/pybind11/type_caster_pyobject_ptr.h
|
||||||
|
include/pybind11/typing.h)
|
||||||
|
|
||||||
|
# Compare with grep and warn if mismatched
|
||||||
|
if(PYBIND11_MASTER_PROJECT AND NOT CMAKE_VERSION VERSION_LESS 3.12)
|
||||||
|
file(
|
||||||
|
GLOB_RECURSE _pybind11_header_check
|
||||||
|
LIST_DIRECTORIES false
|
||||||
|
RELATIVE "${CMAKE_CURRENT_SOURCE_DIR}"
|
||||||
|
CONFIGURE_DEPENDS "include/pybind11/*.h")
|
||||||
|
set(_pybind11_here_only ${PYBIND11_HEADERS})
|
||||||
|
set(_pybind11_disk_only ${_pybind11_header_check})
|
||||||
|
list(REMOVE_ITEM _pybind11_here_only ${_pybind11_header_check})
|
||||||
|
list(REMOVE_ITEM _pybind11_disk_only ${PYBIND11_HEADERS})
|
||||||
|
if(_pybind11_here_only)
|
||||||
|
message(AUTHOR_WARNING "PYBIND11_HEADERS has extra files:" ${_pybind11_here_only})
|
||||||
|
endif()
|
||||||
|
if(_pybind11_disk_only)
|
||||||
|
message(AUTHOR_WARNING "PYBIND11_HEADERS is missing files:" ${_pybind11_disk_only})
|
||||||
|
endif()
|
||||||
|
endif()
|
||||||
|
|
||||||
|
# CMake 3.12 added list(TRANSFORM <list> PREPEND
|
||||||
|
# But we can't use it yet
|
||||||
|
string(REPLACE "include/" "${CMAKE_CURRENT_SOURCE_DIR}/include/" PYBIND11_HEADERS
|
||||||
|
"${PYBIND11_HEADERS}")
|
||||||
|
|
||||||
|
# Cache variable so this can be used in parent projects
|
||||||
|
set(pybind11_INCLUDE_DIR
|
||||||
|
"${CMAKE_CURRENT_LIST_DIR}/include"
|
||||||
|
CACHE INTERNAL "Directory where pybind11 headers are located")
|
||||||
|
|
||||||
|
# Backward compatible variable for add_subdirectory mode
|
||||||
|
if(NOT PYBIND11_MASTER_PROJECT)
|
||||||
|
set(PYBIND11_INCLUDE_DIR
|
||||||
|
"${pybind11_INCLUDE_DIR}"
|
||||||
|
CACHE INTERNAL "")
|
||||||
|
endif()
|
||||||
|
|
||||||
|
# Note: when creating targets, you cannot use if statements at configure time -
|
||||||
|
# you need generator expressions, because those will be placed in the target file.
|
||||||
|
# You can also place ifs *in* the Config.in, but not here.
|
||||||
|
|
||||||
|
# This section builds targets, but does *not* touch Python
|
||||||
|
# Non-IMPORT targets cannot be defined twice
|
||||||
|
if(NOT TARGET pybind11_headers)
|
||||||
|
# Build the headers-only target (no Python included):
|
||||||
|
# (long name used here to keep this from clashing in subdirectory mode)
|
||||||
|
add_library(pybind11_headers INTERFACE)
|
||||||
|
add_library(pybind11::pybind11_headers ALIAS pybind11_headers) # to match exported target
|
||||||
|
add_library(pybind11::headers ALIAS pybind11_headers) # easier to use/remember
|
||||||
|
|
||||||
|
target_include_directories(
|
||||||
|
pybind11_headers ${pybind11_system} INTERFACE $<BUILD_INTERFACE:${pybind11_INCLUDE_DIR}>
|
||||||
|
$<INSTALL_INTERFACE:${CMAKE_INSTALL_INCLUDEDIR}>)
|
||||||
|
|
||||||
|
target_compile_features(pybind11_headers INTERFACE cxx_inheriting_constructors cxx_user_literals
|
||||||
|
cxx_right_angle_brackets)
|
||||||
|
if(NOT "${PYBIND11_INTERNALS_VERSION}" STREQUAL "")
|
||||||
|
target_compile_definitions(
|
||||||
|
pybind11_headers INTERFACE "PYBIND11_INTERNALS_VERSION=${PYBIND11_INTERNALS_VERSION}")
|
||||||
|
endif()
|
||||||
|
else()
|
||||||
|
# It is invalid to install a target twice, too.
|
||||||
|
set(PYBIND11_INSTALL OFF)
|
||||||
|
endif()
|
||||||
|
|
||||||
|
include("${CMAKE_CURRENT_SOURCE_DIR}/tools/pybind11Common.cmake")
|
||||||
|
# https://github.com/jtojnar/cmake-snips/#concatenating-paths-when-building-pkg-config-files
|
||||||
|
# TODO: cmake 3.20 adds the cmake_path() function, which obsoletes this snippet
|
||||||
|
include("${CMAKE_CURRENT_SOURCE_DIR}/tools/JoinPaths.cmake")
|
||||||
|
|
||||||
|
# Relative directory setting
|
||||||
|
if(USE_PYTHON_INCLUDE_DIR AND DEFINED Python_INCLUDE_DIRS)
|
||||||
|
file(RELATIVE_PATH CMAKE_INSTALL_INCLUDEDIR ${CMAKE_INSTALL_PREFIX} ${Python_INCLUDE_DIRS})
|
||||||
|
elseif(USE_PYTHON_INCLUDE_DIR AND DEFINED PYTHON_INCLUDE_DIR)
|
||||||
|
file(RELATIVE_PATH CMAKE_INSTALL_INCLUDEDIR ${CMAKE_INSTALL_PREFIX} ${PYTHON_INCLUDE_DIRS})
|
||||||
|
endif()
|
||||||
|
|
||||||
|
if(PYBIND11_INSTALL)
|
||||||
|
install(DIRECTORY ${pybind11_INCLUDE_DIR}/pybind11 DESTINATION ${CMAKE_INSTALL_INCLUDEDIR})
|
||||||
|
set(PYBIND11_CMAKECONFIG_INSTALL_DIR
|
||||||
|
"${CMAKE_INSTALL_DATAROOTDIR}/cmake/${PROJECT_NAME}"
|
||||||
|
CACHE STRING "install path for pybind11Config.cmake")
|
||||||
|
|
||||||
|
if(IS_ABSOLUTE "${CMAKE_INSTALL_INCLUDEDIR}")
|
||||||
|
set(pybind11_INCLUDEDIR "${CMAKE_INSTALL_FULL_INCLUDEDIR}")
|
||||||
|
else()
|
||||||
|
set(pybind11_INCLUDEDIR "\$\{PACKAGE_PREFIX_DIR\}/${CMAKE_INSTALL_INCLUDEDIR}")
|
||||||
|
endif()
|
||||||
|
|
||||||
|
configure_package_config_file(
|
||||||
|
tools/${PROJECT_NAME}Config.cmake.in "${CMAKE_CURRENT_BINARY_DIR}/${PROJECT_NAME}Config.cmake"
|
||||||
|
INSTALL_DESTINATION ${PYBIND11_CMAKECONFIG_INSTALL_DIR})
|
||||||
|
|
||||||
|
if(CMAKE_VERSION VERSION_LESS 3.14)
|
||||||
|
# Remove CMAKE_SIZEOF_VOID_P from ConfigVersion.cmake since the library does
|
||||||
|
# not depend on architecture specific settings or libraries.
|
||||||
|
set(_PYBIND11_CMAKE_SIZEOF_VOID_P ${CMAKE_SIZEOF_VOID_P})
|
||||||
|
unset(CMAKE_SIZEOF_VOID_P)
|
||||||
|
|
||||||
|
write_basic_package_version_file(
|
||||||
|
${CMAKE_CURRENT_BINARY_DIR}/${PROJECT_NAME}ConfigVersion.cmake
|
||||||
|
VERSION ${PROJECT_VERSION}
|
||||||
|
COMPATIBILITY AnyNewerVersion)
|
||||||
|
|
||||||
|
set(CMAKE_SIZEOF_VOID_P ${_PYBIND11_CMAKE_SIZEOF_VOID_P})
|
||||||
|
else()
|
||||||
|
# CMake 3.14+ natively supports header-only libraries
|
||||||
|
write_basic_package_version_file(
|
||||||
|
${CMAKE_CURRENT_BINARY_DIR}/${PROJECT_NAME}ConfigVersion.cmake
|
||||||
|
VERSION ${PROJECT_VERSION}
|
||||||
|
COMPATIBILITY AnyNewerVersion ARCH_INDEPENDENT)
|
||||||
|
endif()
|
||||||
|
|
||||||
|
install(
|
||||||
|
FILES ${CMAKE_CURRENT_BINARY_DIR}/${PROJECT_NAME}Config.cmake
|
||||||
|
${CMAKE_CURRENT_BINARY_DIR}/${PROJECT_NAME}ConfigVersion.cmake
|
||||||
|
tools/FindPythonLibsNew.cmake
|
||||||
|
tools/pybind11Common.cmake
|
||||||
|
tools/pybind11Tools.cmake
|
||||||
|
tools/pybind11NewTools.cmake
|
||||||
|
DESTINATION ${PYBIND11_CMAKECONFIG_INSTALL_DIR})
|
||||||
|
|
||||||
|
if(NOT PYBIND11_EXPORT_NAME)
|
||||||
|
set(PYBIND11_EXPORT_NAME "${PROJECT_NAME}Targets")
|
||||||
|
endif()
|
||||||
|
|
||||||
|
install(TARGETS pybind11_headers EXPORT "${PYBIND11_EXPORT_NAME}")
|
||||||
|
|
||||||
|
install(
|
||||||
|
EXPORT "${PYBIND11_EXPORT_NAME}"
|
||||||
|
NAMESPACE "pybind11::"
|
||||||
|
DESTINATION ${PYBIND11_CMAKECONFIG_INSTALL_DIR})
|
||||||
|
|
||||||
|
# pkg-config support
|
||||||
|
if(NOT prefix_for_pc_file)
|
||||||
|
if(IS_ABSOLUTE "${CMAKE_INSTALL_DATAROOTDIR}")
|
||||||
|
set(prefix_for_pc_file "${CMAKE_INSTALL_PREFIX}")
|
||||||
|
else()
|
||||||
|
set(pc_datarootdir "${CMAKE_INSTALL_DATAROOTDIR}")
|
||||||
|
if(CMAKE_VERSION VERSION_LESS 3.20)
|
||||||
|
set(prefix_for_pc_file "\${pcfiledir}/..")
|
||||||
|
while(pc_datarootdir)
|
||||||
|
get_filename_component(pc_datarootdir "${pc_datarootdir}" DIRECTORY)
|
||||||
|
string(APPEND prefix_for_pc_file "/..")
|
||||||
|
endwhile()
|
||||||
|
else()
|
||||||
|
cmake_path(RELATIVE_PATH CMAKE_INSTALL_PREFIX BASE_DIRECTORY CMAKE_INSTALL_DATAROOTDIR
|
||||||
|
OUTPUT_VARIABLE prefix_for_pc_file)
|
||||||
|
endif()
|
||||||
|
endif()
|
||||||
|
endif()
|
||||||
|
join_paths(includedir_for_pc_file "\${prefix}" "${CMAKE_INSTALL_INCLUDEDIR}")
|
||||||
|
configure_file("${CMAKE_CURRENT_SOURCE_DIR}/tools/pybind11.pc.in"
|
||||||
|
"${CMAKE_CURRENT_BINARY_DIR}/pybind11.pc" @ONLY)
|
||||||
|
install(FILES "${CMAKE_CURRENT_BINARY_DIR}/pybind11.pc"
|
||||||
|
DESTINATION "${CMAKE_INSTALL_DATAROOTDIR}/pkgconfig/")
|
||||||
|
|
||||||
|
# Uninstall target
|
||||||
|
if(PYBIND11_MASTER_PROJECT)
|
||||||
|
configure_file("${CMAKE_CURRENT_SOURCE_DIR}/tools/cmake_uninstall.cmake.in"
|
||||||
|
"${CMAKE_CURRENT_BINARY_DIR}/cmake_uninstall.cmake" IMMEDIATE @ONLY)
|
||||||
|
|
||||||
|
add_custom_target(uninstall COMMAND ${CMAKE_COMMAND} -P
|
||||||
|
${CMAKE_CURRENT_BINARY_DIR}/cmake_uninstall.cmake)
|
||||||
|
endif()
|
||||||
|
endif()
|
||||||
|
|
||||||
|
# BUILD_TESTING takes priority, but only if this is the master project
|
||||||
|
if(PYBIND11_MASTER_PROJECT AND DEFINED BUILD_TESTING)
|
||||||
|
if(BUILD_TESTING)
|
||||||
|
if(_pybind11_nopython)
|
||||||
|
message(FATAL_ERROR "Cannot activate tests in NOPYTHON mode")
|
||||||
|
else()
|
||||||
|
add_subdirectory(tests)
|
||||||
|
endif()
|
||||||
|
endif()
|
||||||
|
else()
|
||||||
|
if(PYBIND11_TEST)
|
||||||
|
if(_pybind11_nopython)
|
||||||
|
message(FATAL_ERROR "Cannot activate tests in NOPYTHON mode")
|
||||||
|
else()
|
||||||
|
add_subdirectory(tests)
|
||||||
|
endif()
|
||||||
|
endif()
|
||||||
|
endif()
|
||||||
|
|
||||||
|
# Better symmetry with find_package(pybind11 CONFIG) mode.
|
||||||
|
if(NOT PYBIND11_MASTER_PROJECT)
|
||||||
|
set(pybind11_FOUND
|
||||||
|
TRUE
|
||||||
|
CACHE INTERNAL "True if pybind11 and all required components found on the system")
|
||||||
|
endif()
|
29
3rdparty/pybind11/LICENSE
vendored
Normal file
29
3rdparty/pybind11/LICENSE
vendored
Normal file
@ -0,0 +1,29 @@
|
|||||||
|
Copyright (c) 2016 Wenzel Jakob <wenzel.jakob@epfl.ch>, All rights reserved.
|
||||||
|
|
||||||
|
Redistribution and use in source and binary forms, with or without
|
||||||
|
modification, are permitted provided that the following conditions are met:
|
||||||
|
|
||||||
|
1. Redistributions of source code must retain the above copyright notice, this
|
||||||
|
list of conditions and the following disclaimer.
|
||||||
|
|
||||||
|
2. Redistributions in binary form must reproduce the above copyright notice,
|
||||||
|
this list of conditions and the following disclaimer in the documentation
|
||||||
|
and/or other materials provided with the distribution.
|
||||||
|
|
||||||
|
3. Neither the name of the copyright holder nor the names of its contributors
|
||||||
|
may be used to endorse or promote products derived from this software
|
||||||
|
without specific prior written permission.
|
||||||
|
|
||||||
|
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
|
||||||
|
ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
|
||||||
|
WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
|
||||||
|
DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE
|
||||||
|
FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
|
||||||
|
DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
|
||||||
|
SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
|
||||||
|
CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
|
||||||
|
OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
|
||||||
|
OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||||
|
|
||||||
|
Please also refer to the file .github/CONTRIBUTING.md, which clarifies licensing of
|
||||||
|
external contributions to this project including patches, pull requests, etc.
|
6
3rdparty/pybind11/MANIFEST.in
vendored
Normal file
6
3rdparty/pybind11/MANIFEST.in
vendored
Normal file
@ -0,0 +1,6 @@
|
|||||||
|
prune tests
|
||||||
|
recursive-include pybind11/include/pybind11 *.h
|
||||||
|
recursive-include pybind11 *.py
|
||||||
|
recursive-include pybind11 py.typed
|
||||||
|
include pybind11/share/cmake/pybind11/*.cmake
|
||||||
|
include LICENSE README.rst SECURITY.md pyproject.toml setup.py setup.cfg
|
181
3rdparty/pybind11/README.rst
vendored
Normal file
181
3rdparty/pybind11/README.rst
vendored
Normal file
@ -0,0 +1,181 @@
|
|||||||
|
.. figure:: https://github.com/pybind/pybind11/raw/master/docs/pybind11-logo.png
|
||||||
|
:alt: pybind11 logo
|
||||||
|
|
||||||
|
**pybind11 — Seamless operability between C++11 and Python**
|
||||||
|
|
||||||
|
|Latest Documentation Status| |Stable Documentation Status| |Gitter chat| |GitHub Discussions| |CI| |Build status|
|
||||||
|
|
||||||
|
|Repology| |PyPI package| |Conda-forge| |Python Versions|
|
||||||
|
|
||||||
|
`Setuptools example <https://github.com/pybind/python_example>`_
|
||||||
|
• `Scikit-build example <https://github.com/pybind/scikit_build_example>`_
|
||||||
|
• `CMake example <https://github.com/pybind/cmake_example>`_
|
||||||
|
|
||||||
|
.. start
|
||||||
|
|
||||||
|
|
||||||
|
**pybind11** is a lightweight header-only library that exposes C++ types
|
||||||
|
in Python and vice versa, mainly to create Python bindings of existing
|
||||||
|
C++ code. Its goals and syntax are similar to the excellent
|
||||||
|
`Boost.Python <http://www.boost.org/doc/libs/1_58_0/libs/python/doc/>`_
|
||||||
|
library by David Abrahams: to minimize boilerplate code in traditional
|
||||||
|
extension modules by inferring type information using compile-time
|
||||||
|
introspection.
|
||||||
|
|
||||||
|
The main issue with Boost.Python—and the reason for creating such a
|
||||||
|
similar project—is Boost. Boost is an enormously large and complex suite
|
||||||
|
of utility libraries that works with almost every C++ compiler in
|
||||||
|
existence. This compatibility has its cost: arcane template tricks and
|
||||||
|
workarounds are necessary to support the oldest and buggiest of compiler
|
||||||
|
specimens. Now that C++11-compatible compilers are widely available,
|
||||||
|
this heavy machinery has become an excessively large and unnecessary
|
||||||
|
dependency.
|
||||||
|
|
||||||
|
Think of this library as a tiny self-contained version of Boost.Python
|
||||||
|
with everything stripped away that isn't relevant for binding
|
||||||
|
generation. Without comments, the core header files only require ~4K
|
||||||
|
lines of code and depend on Python (3.6+, or PyPy) and the C++
|
||||||
|
standard library. This compact implementation was possible thanks to
|
||||||
|
some C++11 language features (specifically: tuples, lambda functions and
|
||||||
|
variadic templates). Since its creation, this library has grown beyond
|
||||||
|
Boost.Python in many ways, leading to dramatically simpler binding code in many
|
||||||
|
common situations.
|
||||||
|
|
||||||
|
Tutorial and reference documentation is provided at
|
||||||
|
`pybind11.readthedocs.io <https://pybind11.readthedocs.io/en/latest>`_.
|
||||||
|
A PDF version of the manual is available
|
||||||
|
`here <https://pybind11.readthedocs.io/_/downloads/en/latest/pdf/>`_.
|
||||||
|
And the source code is always available at
|
||||||
|
`github.com/pybind/pybind11 <https://github.com/pybind/pybind11>`_.
|
||||||
|
|
||||||
|
|
||||||
|
Core features
|
||||||
|
-------------
|
||||||
|
|
||||||
|
|
||||||
|
pybind11 can map the following core C++ features to Python:
|
||||||
|
|
||||||
|
- Functions accepting and returning custom data structures per value,
|
||||||
|
reference, or pointer
|
||||||
|
- Instance methods and static methods
|
||||||
|
- Overloaded functions
|
||||||
|
- Instance attributes and static attributes
|
||||||
|
- Arbitrary exception types
|
||||||
|
- Enumerations
|
||||||
|
- Callbacks
|
||||||
|
- Iterators and ranges
|
||||||
|
- Custom operators
|
||||||
|
- Single and multiple inheritance
|
||||||
|
- STL data structures
|
||||||
|
- Smart pointers with reference counting like ``std::shared_ptr``
|
||||||
|
- Internal references with correct reference counting
|
||||||
|
- C++ classes with virtual (and pure virtual) methods can be extended
|
||||||
|
in Python
|
||||||
|
- Integrated NumPy support (NumPy 2 requires pybind11 2.12+)
|
||||||
|
|
||||||
|
Goodies
|
||||||
|
-------
|
||||||
|
|
||||||
|
In addition to the core functionality, pybind11 provides some extra
|
||||||
|
goodies:
|
||||||
|
|
||||||
|
- Python 3.6+, and PyPy3 7.3 are supported with an implementation-agnostic
|
||||||
|
interface (pybind11 2.9 was the last version to support Python 2 and 3.5).
|
||||||
|
|
||||||
|
- It is possible to bind C++11 lambda functions with captured
|
||||||
|
variables. The lambda capture data is stored inside the resulting
|
||||||
|
Python function object.
|
||||||
|
|
||||||
|
- pybind11 uses C++11 move constructors and move assignment operators
|
||||||
|
whenever possible to efficiently transfer custom data types.
|
||||||
|
|
||||||
|
- It's easy to expose the internal storage of custom data types through
|
||||||
|
Pythons' buffer protocols. This is handy e.g. for fast conversion
|
||||||
|
between C++ matrix classes like Eigen and NumPy without expensive
|
||||||
|
copy operations.
|
||||||
|
|
||||||
|
- pybind11 can automatically vectorize functions so that they are
|
||||||
|
transparently applied to all entries of one or more NumPy array
|
||||||
|
arguments.
|
||||||
|
|
||||||
|
- Python's slice-based access and assignment operations can be
|
||||||
|
supported with just a few lines of code.
|
||||||
|
|
||||||
|
- Everything is contained in just a few header files; there is no need
|
||||||
|
to link against any additional libraries.
|
||||||
|
|
||||||
|
- Binaries are generally smaller by a factor of at least 2 compared to
|
||||||
|
equivalent bindings generated by Boost.Python. A recent pybind11
|
||||||
|
conversion of PyRosetta, an enormous Boost.Python binding project,
|
||||||
|
`reported <https://graylab.jhu.edu/Sergey/2016.RosettaCon/PyRosetta-4.pdf>`_
|
||||||
|
a binary size reduction of **5.4x** and compile time reduction by
|
||||||
|
**5.8x**.
|
||||||
|
|
||||||
|
- Function signatures are precomputed at compile time (using
|
||||||
|
``constexpr``), leading to smaller binaries.
|
||||||
|
|
||||||
|
- With little extra effort, C++ types can be pickled and unpickled
|
||||||
|
similar to regular Python objects.
|
||||||
|
|
||||||
|
Supported compilers
|
||||||
|
-------------------
|
||||||
|
|
||||||
|
1. Clang/LLVM 3.3 or newer (for Apple Xcode's clang, this is 5.0.0 or
|
||||||
|
newer)
|
||||||
|
2. GCC 4.8 or newer
|
||||||
|
3. Microsoft Visual Studio 2017 or newer
|
||||||
|
4. Intel classic C++ compiler 18 or newer (ICC 20.2 tested in CI)
|
||||||
|
5. Cygwin/GCC (previously tested on 2.5.1)
|
||||||
|
6. NVCC (CUDA 11.0 tested in CI)
|
||||||
|
7. NVIDIA PGI (20.9 tested in CI)
|
||||||
|
|
||||||
|
About
|
||||||
|
-----
|
||||||
|
|
||||||
|
This project was created by `Wenzel
|
||||||
|
Jakob <http://rgl.epfl.ch/people/wjakob>`_. Significant features and/or
|
||||||
|
improvements to the code were contributed by Jonas Adler, Lori A. Burns,
|
||||||
|
Sylvain Corlay, Eric Cousineau, Aaron Gokaslan, Ralf Grosse-Kunstleve, Trent Houliston, Axel
|
||||||
|
Huebl, @hulucc, Yannick Jadoul, Sergey Lyskov, Johan Mabille, Tomasz Miąsko,
|
||||||
|
Dean Moldovan, Ben Pritchard, Jason Rhinelander, Boris Schäling, Pim
|
||||||
|
Schellart, Henry Schreiner, Ivan Smirnov, Boris Staletic, and Patrick Stewart.
|
||||||
|
|
||||||
|
We thank Google for a generous financial contribution to the continuous
|
||||||
|
integration infrastructure used by this project.
|
||||||
|
|
||||||
|
|
||||||
|
Contributing
|
||||||
|
~~~~~~~~~~~~
|
||||||
|
|
||||||
|
See the `contributing
|
||||||
|
guide <https://github.com/pybind/pybind11/blob/master/.github/CONTRIBUTING.md>`_
|
||||||
|
for information on building and contributing to pybind11.
|
||||||
|
|
||||||
|
License
|
||||||
|
~~~~~~~
|
||||||
|
|
||||||
|
pybind11 is provided under a BSD-style license that can be found in the
|
||||||
|
`LICENSE <https://github.com/pybind/pybind11/blob/master/LICENSE>`_
|
||||||
|
file. By using, distributing, or contributing to this project, you agree
|
||||||
|
to the terms and conditions of this license.
|
||||||
|
|
||||||
|
.. |Latest Documentation Status| image:: https://readthedocs.org/projects/pybind11/badge?version=latest
|
||||||
|
:target: http://pybind11.readthedocs.org/en/latest
|
||||||
|
.. |Stable Documentation Status| image:: https://img.shields.io/badge/docs-stable-blue.svg
|
||||||
|
:target: http://pybind11.readthedocs.org/en/stable
|
||||||
|
.. |Gitter chat| image:: https://img.shields.io/gitter/room/gitterHQ/gitter.svg
|
||||||
|
:target: https://gitter.im/pybind/Lobby
|
||||||
|
.. |CI| image:: https://github.com/pybind/pybind11/workflows/CI/badge.svg
|
||||||
|
:target: https://github.com/pybind/pybind11/actions
|
||||||
|
.. |Build status| image:: https://ci.appveyor.com/api/projects/status/riaj54pn4h08xy40?svg=true
|
||||||
|
:target: https://ci.appveyor.com/project/wjakob/pybind11
|
||||||
|
.. |PyPI package| image:: https://img.shields.io/pypi/v/pybind11.svg
|
||||||
|
:target: https://pypi.org/project/pybind11/
|
||||||
|
.. |Conda-forge| image:: https://img.shields.io/conda/vn/conda-forge/pybind11.svg
|
||||||
|
:target: https://github.com/conda-forge/pybind11-feedstock
|
||||||
|
.. |Repology| image:: https://repology.org/badge/latest-versions/python:pybind11.svg
|
||||||
|
:target: https://repology.org/project/python:pybind11/versions
|
||||||
|
.. |Python Versions| image:: https://img.shields.io/pypi/pyversions/pybind11.svg
|
||||||
|
:target: https://pypi.org/project/pybind11/
|
||||||
|
.. |GitHub Discussions| image:: https://img.shields.io/static/v1?label=Discussions&message=Ask&color=blue&logo=github
|
||||||
|
:target: https://github.com/pybind/pybind11/discussions
|
13
3rdparty/pybind11/SECURITY.md
vendored
Normal file
13
3rdparty/pybind11/SECURITY.md
vendored
Normal file
@ -0,0 +1,13 @@
|
|||||||
|
# Security Policy
|
||||||
|
|
||||||
|
## Supported Versions
|
||||||
|
|
||||||
|
Security updates are applied only to the latest release.
|
||||||
|
|
||||||
|
## Reporting a Vulnerability
|
||||||
|
|
||||||
|
If you have discovered a security vulnerability in this project, please report it privately. **Do not disclose it as a public issue.** This gives us time to work with you to fix the issue before public exposure, reducing the chance that the exploit will be used before a patch is released.
|
||||||
|
|
||||||
|
Please disclose it at [security advisory](https://github.com/pybind/pybind11/security/advisories/new).
|
||||||
|
|
||||||
|
This project is maintained by a team of volunteers on a reasonable-effort basis. As such, please give us at least 90 days to work on a fix before public exposure.
|
21
3rdparty/pybind11/docs/Doxyfile
vendored
Normal file
21
3rdparty/pybind11/docs/Doxyfile
vendored
Normal file
@ -0,0 +1,21 @@
|
|||||||
|
PROJECT_NAME = pybind11
|
||||||
|
INPUT = ../include/pybind11/
|
||||||
|
RECURSIVE = YES
|
||||||
|
|
||||||
|
GENERATE_HTML = NO
|
||||||
|
GENERATE_LATEX = NO
|
||||||
|
GENERATE_XML = YES
|
||||||
|
XML_OUTPUT = .build/doxygenxml
|
||||||
|
XML_PROGRAMLISTING = YES
|
||||||
|
|
||||||
|
MACRO_EXPANSION = YES
|
||||||
|
EXPAND_ONLY_PREDEF = YES
|
||||||
|
EXPAND_AS_DEFINED = PYBIND11_RUNTIME_EXCEPTION
|
||||||
|
|
||||||
|
ALIASES = "rst=\verbatim embed:rst"
|
||||||
|
ALIASES += "endrst=\endverbatim"
|
||||||
|
|
||||||
|
QUIET = YES
|
||||||
|
WARNINGS = YES
|
||||||
|
WARN_IF_UNDOCUMENTED = NO
|
||||||
|
PREDEFINED = PYBIND11_NOINLINE
|
3
3rdparty/pybind11/docs/_static/css/custom.css
vendored
Normal file
3
3rdparty/pybind11/docs/_static/css/custom.css
vendored
Normal file
@ -0,0 +1,3 @@
|
|||||||
|
.highlight .go {
|
||||||
|
color: #707070;
|
||||||
|
}
|
81
3rdparty/pybind11/docs/advanced/cast/chrono.rst
vendored
Normal file
81
3rdparty/pybind11/docs/advanced/cast/chrono.rst
vendored
Normal file
@ -0,0 +1,81 @@
|
|||||||
|
Chrono
|
||||||
|
======
|
||||||
|
|
||||||
|
When including the additional header file :file:`pybind11/chrono.h` conversions
|
||||||
|
from C++11 chrono datatypes to python datetime objects are automatically enabled.
|
||||||
|
This header also enables conversions of python floats (often from sources such
|
||||||
|
as ``time.monotonic()``, ``time.perf_counter()`` and ``time.process_time()``)
|
||||||
|
into durations.
|
||||||
|
|
||||||
|
An overview of clocks in C++11
|
||||||
|
------------------------------
|
||||||
|
|
||||||
|
A point of confusion when using these conversions is the differences between
|
||||||
|
clocks provided in C++11. There are three clock types defined by the C++11
|
||||||
|
standard and users can define their own if needed. Each of these clocks have
|
||||||
|
different properties and when converting to and from python will give different
|
||||||
|
results.
|
||||||
|
|
||||||
|
The first clock defined by the standard is ``std::chrono::system_clock``. This
|
||||||
|
clock measures the current date and time. However, this clock changes with to
|
||||||
|
updates to the operating system time. For example, if your time is synchronised
|
||||||
|
with a time server this clock will change. This makes this clock a poor choice
|
||||||
|
for timing purposes but good for measuring the wall time.
|
||||||
|
|
||||||
|
The second clock defined in the standard is ``std::chrono::steady_clock``.
|
||||||
|
This clock ticks at a steady rate and is never adjusted. This makes it excellent
|
||||||
|
for timing purposes, however the value in this clock does not correspond to the
|
||||||
|
current date and time. Often this clock will be the amount of time your system
|
||||||
|
has been on, although it does not have to be. This clock will never be the same
|
||||||
|
clock as the system clock as the system clock can change but steady clocks
|
||||||
|
cannot.
|
||||||
|
|
||||||
|
The third clock defined in the standard is ``std::chrono::high_resolution_clock``.
|
||||||
|
This clock is the clock that has the highest resolution out of the clocks in the
|
||||||
|
system. It is normally a typedef to either the system clock or the steady clock
|
||||||
|
but can be its own independent clock. This is important as when using these
|
||||||
|
conversions as the types you get in python for this clock might be different
|
||||||
|
depending on the system.
|
||||||
|
If it is a typedef of the system clock, python will get datetime objects, but if
|
||||||
|
it is a different clock they will be timedelta objects.
|
||||||
|
|
||||||
|
Provided conversions
|
||||||
|
--------------------
|
||||||
|
|
||||||
|
.. rubric:: C++ to Python
|
||||||
|
|
||||||
|
- ``std::chrono::system_clock::time_point`` → ``datetime.datetime``
|
||||||
|
System clock times are converted to python datetime instances. They are
|
||||||
|
in the local timezone, but do not have any timezone information attached
|
||||||
|
to them (they are naive datetime objects).
|
||||||
|
|
||||||
|
- ``std::chrono::duration`` → ``datetime.timedelta``
|
||||||
|
Durations are converted to timedeltas, any precision in the duration
|
||||||
|
greater than microseconds is lost by rounding towards zero.
|
||||||
|
|
||||||
|
- ``std::chrono::[other_clocks]::time_point`` → ``datetime.timedelta``
|
||||||
|
Any clock time that is not the system clock is converted to a time delta.
|
||||||
|
This timedelta measures the time from the clocks epoch to now.
|
||||||
|
|
||||||
|
.. rubric:: Python to C++
|
||||||
|
|
||||||
|
- ``datetime.datetime`` or ``datetime.date`` or ``datetime.time`` → ``std::chrono::system_clock::time_point``
|
||||||
|
Date/time objects are converted into system clock timepoints. Any
|
||||||
|
timezone information is ignored and the type is treated as a naive
|
||||||
|
object.
|
||||||
|
|
||||||
|
- ``datetime.timedelta`` → ``std::chrono::duration``
|
||||||
|
Time delta are converted into durations with microsecond precision.
|
||||||
|
|
||||||
|
- ``datetime.timedelta`` → ``std::chrono::[other_clocks]::time_point``
|
||||||
|
Time deltas that are converted into clock timepoints are treated as
|
||||||
|
the amount of time from the start of the clocks epoch.
|
||||||
|
|
||||||
|
- ``float`` → ``std::chrono::duration``
|
||||||
|
Floats that are passed to C++ as durations be interpreted as a number of
|
||||||
|
seconds. These will be converted to the duration using ``duration_cast``
|
||||||
|
from the float.
|
||||||
|
|
||||||
|
- ``float`` → ``std::chrono::[other_clocks]::time_point``
|
||||||
|
Floats that are passed to C++ as time points will be interpreted as the
|
||||||
|
number of seconds from the start of the clocks epoch.
|
93
3rdparty/pybind11/docs/advanced/cast/custom.rst
vendored
Normal file
93
3rdparty/pybind11/docs/advanced/cast/custom.rst
vendored
Normal file
@ -0,0 +1,93 @@
|
|||||||
|
Custom type casters
|
||||||
|
===================
|
||||||
|
|
||||||
|
In very rare cases, applications may require custom type casters that cannot be
|
||||||
|
expressed using the abstractions provided by pybind11, thus requiring raw
|
||||||
|
Python C API calls. This is fairly advanced usage and should only be pursued by
|
||||||
|
experts who are familiar with the intricacies of Python reference counting.
|
||||||
|
|
||||||
|
The following snippets demonstrate how this works for a very simple ``inty``
|
||||||
|
type that that should be convertible from Python types that provide a
|
||||||
|
``__int__(self)`` method.
|
||||||
|
|
||||||
|
.. code-block:: cpp
|
||||||
|
|
||||||
|
struct inty { long long_value; };
|
||||||
|
|
||||||
|
void print(inty s) {
|
||||||
|
std::cout << s.long_value << std::endl;
|
||||||
|
}
|
||||||
|
|
||||||
|
The following Python snippet demonstrates the intended usage from the Python side:
|
||||||
|
|
||||||
|
.. code-block:: python
|
||||||
|
|
||||||
|
class A:
|
||||||
|
def __int__(self):
|
||||||
|
return 123
|
||||||
|
|
||||||
|
|
||||||
|
from example import print
|
||||||
|
|
||||||
|
print(A())
|
||||||
|
|
||||||
|
To register the necessary conversion routines, it is necessary to add an
|
||||||
|
instantiation of the ``pybind11::detail::type_caster<T>`` template.
|
||||||
|
Although this is an implementation detail, adding an instantiation of this
|
||||||
|
type is explicitly allowed.
|
||||||
|
|
||||||
|
.. code-block:: cpp
|
||||||
|
|
||||||
|
namespace PYBIND11_NAMESPACE { namespace detail {
|
||||||
|
template <> struct type_caster<inty> {
|
||||||
|
public:
|
||||||
|
/**
|
||||||
|
* This macro establishes the name 'inty' in
|
||||||
|
* function signatures and declares a local variable
|
||||||
|
* 'value' of type inty
|
||||||
|
*/
|
||||||
|
PYBIND11_TYPE_CASTER(inty, const_name("inty"));
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Conversion part 1 (Python->C++): convert a PyObject into a inty
|
||||||
|
* instance or return false upon failure. The second argument
|
||||||
|
* indicates whether implicit conversions should be applied.
|
||||||
|
*/
|
||||||
|
bool load(handle src, bool) {
|
||||||
|
/* Extract PyObject from handle */
|
||||||
|
PyObject *source = src.ptr();
|
||||||
|
/* Try converting into a Python integer value */
|
||||||
|
PyObject *tmp = PyNumber_Long(source);
|
||||||
|
if (!tmp)
|
||||||
|
return false;
|
||||||
|
/* Now try to convert into a C++ int */
|
||||||
|
value.long_value = PyLong_AsLong(tmp);
|
||||||
|
Py_DECREF(tmp);
|
||||||
|
/* Ensure return code was OK (to avoid out-of-range errors etc) */
|
||||||
|
return !(value.long_value == -1 && !PyErr_Occurred());
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Conversion part 2 (C++ -> Python): convert an inty instance into
|
||||||
|
* a Python object. The second and third arguments are used to
|
||||||
|
* indicate the return value policy and parent object (for
|
||||||
|
* ``return_value_policy::reference_internal``) and are generally
|
||||||
|
* ignored by implicit casters.
|
||||||
|
*/
|
||||||
|
static handle cast(inty src, return_value_policy /* policy */, handle /* parent */) {
|
||||||
|
return PyLong_FromLong(src.long_value);
|
||||||
|
}
|
||||||
|
};
|
||||||
|
}} // namespace PYBIND11_NAMESPACE::detail
|
||||||
|
|
||||||
|
.. note::
|
||||||
|
|
||||||
|
A ``type_caster<T>`` defined with ``PYBIND11_TYPE_CASTER(T, ...)`` requires
|
||||||
|
that ``T`` is default-constructible (``value`` is first default constructed
|
||||||
|
and then ``load()`` assigns to it).
|
||||||
|
|
||||||
|
.. warning::
|
||||||
|
|
||||||
|
When using custom type casters, it's important to declare them consistently
|
||||||
|
in every compilation unit of the Python extension module. Otherwise,
|
||||||
|
undefined behavior can ensue.
|
310
3rdparty/pybind11/docs/advanced/cast/eigen.rst
vendored
Normal file
310
3rdparty/pybind11/docs/advanced/cast/eigen.rst
vendored
Normal file
@ -0,0 +1,310 @@
|
|||||||
|
Eigen
|
||||||
|
#####
|
||||||
|
|
||||||
|
`Eigen <http://eigen.tuxfamily.org>`_ is C++ header-based library for dense and
|
||||||
|
sparse linear algebra. Due to its popularity and widespread adoption, pybind11
|
||||||
|
provides transparent conversion and limited mapping support between Eigen and
|
||||||
|
Scientific Python linear algebra data types.
|
||||||
|
|
||||||
|
To enable the built-in Eigen support you must include the optional header file
|
||||||
|
:file:`pybind11/eigen.h`.
|
||||||
|
|
||||||
|
Pass-by-value
|
||||||
|
=============
|
||||||
|
|
||||||
|
When binding a function with ordinary Eigen dense object arguments (for
|
||||||
|
example, ``Eigen::MatrixXd``), pybind11 will accept any input value that is
|
||||||
|
already (or convertible to) a ``numpy.ndarray`` with dimensions compatible with
|
||||||
|
the Eigen type, copy its values into a temporary Eigen variable of the
|
||||||
|
appropriate type, then call the function with this temporary variable.
|
||||||
|
|
||||||
|
Sparse matrices are similarly copied to or from
|
||||||
|
``scipy.sparse.csr_matrix``/``scipy.sparse.csc_matrix`` objects.
|
||||||
|
|
||||||
|
Pass-by-reference
|
||||||
|
=================
|
||||||
|
|
||||||
|
One major limitation of the above is that every data conversion implicitly
|
||||||
|
involves a copy, which can be both expensive (for large matrices) and disallows
|
||||||
|
binding functions that change their (Matrix) arguments. Pybind11 allows you to
|
||||||
|
work around this by using Eigen's ``Eigen::Ref<MatrixType>`` class much as you
|
||||||
|
would when writing a function taking a generic type in Eigen itself (subject to
|
||||||
|
some limitations discussed below).
|
||||||
|
|
||||||
|
When calling a bound function accepting a ``Eigen::Ref<const MatrixType>``
|
||||||
|
type, pybind11 will attempt to avoid copying by using an ``Eigen::Map`` object
|
||||||
|
that maps into the source ``numpy.ndarray`` data: this requires both that the
|
||||||
|
data types are the same (e.g. ``dtype='float64'`` and ``MatrixType::Scalar`` is
|
||||||
|
``double``); and that the storage is layout compatible. The latter limitation
|
||||||
|
is discussed in detail in the section below, and requires careful
|
||||||
|
consideration: by default, numpy matrices and Eigen matrices are *not* storage
|
||||||
|
compatible.
|
||||||
|
|
||||||
|
If the numpy matrix cannot be used as is (either because its types differ, e.g.
|
||||||
|
passing an array of integers to an Eigen parameter requiring doubles, or
|
||||||
|
because the storage is incompatible), pybind11 makes a temporary copy and
|
||||||
|
passes the copy instead.
|
||||||
|
|
||||||
|
When a bound function parameter is instead ``Eigen::Ref<MatrixType>`` (note the
|
||||||
|
lack of ``const``), pybind11 will only allow the function to be called if it
|
||||||
|
can be mapped *and* if the numpy array is writeable (that is
|
||||||
|
``a.flags.writeable`` is true). Any access (including modification) made to
|
||||||
|
the passed variable will be transparently carried out directly on the
|
||||||
|
``numpy.ndarray``.
|
||||||
|
|
||||||
|
This means you can write code such as the following and have it work as
|
||||||
|
expected:
|
||||||
|
|
||||||
|
.. code-block:: cpp
|
||||||
|
|
||||||
|
void scale_by_2(Eigen::Ref<Eigen::VectorXd> v) {
|
||||||
|
v *= 2;
|
||||||
|
}
|
||||||
|
|
||||||
|
Note, however, that you will likely run into limitations due to numpy and
|
||||||
|
Eigen's difference default storage order for data; see the below section on
|
||||||
|
:ref:`storage_orders` for details on how to bind code that won't run into such
|
||||||
|
limitations.
|
||||||
|
|
||||||
|
.. note::
|
||||||
|
|
||||||
|
Passing by reference is not supported for sparse types.
|
||||||
|
|
||||||
|
Returning values to Python
|
||||||
|
==========================
|
||||||
|
|
||||||
|
When returning an ordinary dense Eigen matrix type to numpy (e.g.
|
||||||
|
``Eigen::MatrixXd`` or ``Eigen::RowVectorXf``) pybind11 keeps the matrix and
|
||||||
|
returns a numpy array that directly references the Eigen matrix: no copy of the
|
||||||
|
data is performed. The numpy array will have ``array.flags.owndata`` set to
|
||||||
|
``False`` to indicate that it does not own the data, and the lifetime of the
|
||||||
|
stored Eigen matrix will be tied to the returned ``array``.
|
||||||
|
|
||||||
|
If you bind a function with a non-reference, ``const`` return type (e.g.
|
||||||
|
``const Eigen::MatrixXd``), the same thing happens except that pybind11 also
|
||||||
|
sets the numpy array's ``writeable`` flag to false.
|
||||||
|
|
||||||
|
If you return an lvalue reference or pointer, the usual pybind11 rules apply,
|
||||||
|
as dictated by the binding function's return value policy (see the
|
||||||
|
documentation on :ref:`return_value_policies` for full details). That means,
|
||||||
|
without an explicit return value policy, lvalue references will be copied and
|
||||||
|
pointers will be managed by pybind11. In order to avoid copying, you should
|
||||||
|
explicitly specify an appropriate return value policy, as in the following
|
||||||
|
example:
|
||||||
|
|
||||||
|
.. code-block:: cpp
|
||||||
|
|
||||||
|
class MyClass {
|
||||||
|
Eigen::MatrixXd big_mat = Eigen::MatrixXd::Zero(10000, 10000);
|
||||||
|
public:
|
||||||
|
Eigen::MatrixXd &getMatrix() { return big_mat; }
|
||||||
|
const Eigen::MatrixXd &viewMatrix() { return big_mat; }
|
||||||
|
};
|
||||||
|
|
||||||
|
// Later, in binding code:
|
||||||
|
py::class_<MyClass>(m, "MyClass")
|
||||||
|
.def(py::init<>())
|
||||||
|
.def("copy_matrix", &MyClass::getMatrix) // Makes a copy!
|
||||||
|
.def("get_matrix", &MyClass::getMatrix, py::return_value_policy::reference_internal)
|
||||||
|
.def("view_matrix", &MyClass::viewMatrix, py::return_value_policy::reference_internal)
|
||||||
|
;
|
||||||
|
|
||||||
|
.. code-block:: python
|
||||||
|
|
||||||
|
a = MyClass()
|
||||||
|
m = a.get_matrix() # flags.writeable = True, flags.owndata = False
|
||||||
|
v = a.view_matrix() # flags.writeable = False, flags.owndata = False
|
||||||
|
c = a.copy_matrix() # flags.writeable = True, flags.owndata = True
|
||||||
|
# m[5,6] and v[5,6] refer to the same element, c[5,6] does not.
|
||||||
|
|
||||||
|
Note in this example that ``py::return_value_policy::reference_internal`` is
|
||||||
|
used to tie the life of the MyClass object to the life of the returned arrays.
|
||||||
|
|
||||||
|
You may also return an ``Eigen::Ref``, ``Eigen::Map`` or other map-like Eigen
|
||||||
|
object (for example, the return value of ``matrix.block()`` and related
|
||||||
|
methods) that map into a dense Eigen type. When doing so, the default
|
||||||
|
behaviour of pybind11 is to simply reference the returned data: you must take
|
||||||
|
care to ensure that this data remains valid! You may ask pybind11 to
|
||||||
|
explicitly *copy* such a return value by using the
|
||||||
|
``py::return_value_policy::copy`` policy when binding the function. You may
|
||||||
|
also use ``py::return_value_policy::reference_internal`` or a
|
||||||
|
``py::keep_alive`` to ensure the data stays valid as long as the returned numpy
|
||||||
|
array does.
|
||||||
|
|
||||||
|
When returning such a reference of map, pybind11 additionally respects the
|
||||||
|
readonly-status of the returned value, marking the numpy array as non-writeable
|
||||||
|
if the reference or map was itself read-only.
|
||||||
|
|
||||||
|
.. note::
|
||||||
|
|
||||||
|
Sparse types are always copied when returned.
|
||||||
|
|
||||||
|
.. _storage_orders:
|
||||||
|
|
||||||
|
Storage orders
|
||||||
|
==============
|
||||||
|
|
||||||
|
Passing arguments via ``Eigen::Ref`` has some limitations that you must be
|
||||||
|
aware of in order to effectively pass matrices by reference. First and
|
||||||
|
foremost is that the default ``Eigen::Ref<MatrixType>`` class requires
|
||||||
|
contiguous storage along columns (for column-major types, the default in Eigen)
|
||||||
|
or rows if ``MatrixType`` is specifically an ``Eigen::RowMajor`` storage type.
|
||||||
|
The former, Eigen's default, is incompatible with ``numpy``'s default row-major
|
||||||
|
storage, and so you will not be able to pass numpy arrays to Eigen by reference
|
||||||
|
without making one of two changes.
|
||||||
|
|
||||||
|
(Note that this does not apply to vectors (or column or row matrices): for such
|
||||||
|
types the "row-major" and "column-major" distinction is meaningless).
|
||||||
|
|
||||||
|
The first approach is to change the use of ``Eigen::Ref<MatrixType>`` to the
|
||||||
|
more general ``Eigen::Ref<MatrixType, 0, Eigen::Stride<Eigen::Dynamic,
|
||||||
|
Eigen::Dynamic>>`` (or similar type with a fully dynamic stride type in the
|
||||||
|
third template argument). Since this is a rather cumbersome type, pybind11
|
||||||
|
provides a ``py::EigenDRef<MatrixType>`` type alias for your convenience (along
|
||||||
|
with EigenDMap for the equivalent Map, and EigenDStride for just the stride
|
||||||
|
type).
|
||||||
|
|
||||||
|
This type allows Eigen to map into any arbitrary storage order. This is not
|
||||||
|
the default in Eigen for performance reasons: contiguous storage allows
|
||||||
|
vectorization that cannot be done when storage is not known to be contiguous at
|
||||||
|
compile time. The default ``Eigen::Ref`` stride type allows non-contiguous
|
||||||
|
storage along the outer dimension (that is, the rows of a column-major matrix
|
||||||
|
or columns of a row-major matrix), but not along the inner dimension.
|
||||||
|
|
||||||
|
This type, however, has the added benefit of also being able to map numpy array
|
||||||
|
slices. For example, the following (contrived) example uses Eigen with a numpy
|
||||||
|
slice to multiply by 2 all coefficients that are both on even rows (0, 2, 4,
|
||||||
|
...) and in columns 2, 5, or 8:
|
||||||
|
|
||||||
|
.. code-block:: cpp
|
||||||
|
|
||||||
|
m.def("scale", [](py::EigenDRef<Eigen::MatrixXd> m, double c) { m *= c; });
|
||||||
|
|
||||||
|
.. code-block:: python
|
||||||
|
|
||||||
|
# a = np.array(...)
|
||||||
|
scale_by_2(myarray[0::2, 2:9:3])
|
||||||
|
|
||||||
|
The second approach to avoid copying is more intrusive: rearranging the
|
||||||
|
underlying data types to not run into the non-contiguous storage problem in the
|
||||||
|
first place. In particular, that means using matrices with ``Eigen::RowMajor``
|
||||||
|
storage, where appropriate, such as:
|
||||||
|
|
||||||
|
.. code-block:: cpp
|
||||||
|
|
||||||
|
using RowMatrixXd = Eigen::Matrix<double, Eigen::Dynamic, Eigen::Dynamic, Eigen::RowMajor>;
|
||||||
|
// Use RowMatrixXd instead of MatrixXd
|
||||||
|
|
||||||
|
Now bound functions accepting ``Eigen::Ref<RowMatrixXd>`` arguments will be
|
||||||
|
callable with numpy's (default) arrays without involving a copying.
|
||||||
|
|
||||||
|
You can, alternatively, change the storage order that numpy arrays use by
|
||||||
|
adding the ``order='F'`` option when creating an array:
|
||||||
|
|
||||||
|
.. code-block:: python
|
||||||
|
|
||||||
|
myarray = np.array(source, order="F")
|
||||||
|
|
||||||
|
Such an object will be passable to a bound function accepting an
|
||||||
|
``Eigen::Ref<MatrixXd>`` (or similar column-major Eigen type).
|
||||||
|
|
||||||
|
One major caveat with this approach, however, is that it is not entirely as
|
||||||
|
easy as simply flipping all Eigen or numpy usage from one to the other: some
|
||||||
|
operations may alter the storage order of a numpy array. For example, ``a2 =
|
||||||
|
array.transpose()`` results in ``a2`` being a view of ``array`` that references
|
||||||
|
the same data, but in the opposite storage order!
|
||||||
|
|
||||||
|
While this approach allows fully optimized vectorized calculations in Eigen, it
|
||||||
|
cannot be used with array slices, unlike the first approach.
|
||||||
|
|
||||||
|
When *returning* a matrix to Python (either a regular matrix, a reference via
|
||||||
|
``Eigen::Ref<>``, or a map/block into a matrix), no special storage
|
||||||
|
consideration is required: the created numpy array will have the required
|
||||||
|
stride that allows numpy to properly interpret the array, whatever its storage
|
||||||
|
order.
|
||||||
|
|
||||||
|
Failing rather than copying
|
||||||
|
===========================
|
||||||
|
|
||||||
|
The default behaviour when binding ``Eigen::Ref<const MatrixType>`` Eigen
|
||||||
|
references is to copy matrix values when passed a numpy array that does not
|
||||||
|
conform to the element type of ``MatrixType`` or does not have a compatible
|
||||||
|
stride layout. If you want to explicitly avoid copying in such a case, you
|
||||||
|
should bind arguments using the ``py::arg().noconvert()`` annotation (as
|
||||||
|
described in the :ref:`nonconverting_arguments` documentation).
|
||||||
|
|
||||||
|
The following example shows an example of arguments that don't allow data
|
||||||
|
copying to take place:
|
||||||
|
|
||||||
|
.. code-block:: cpp
|
||||||
|
|
||||||
|
// The method and function to be bound:
|
||||||
|
class MyClass {
|
||||||
|
// ...
|
||||||
|
double some_method(const Eigen::Ref<const MatrixXd> &matrix) { /* ... */ }
|
||||||
|
};
|
||||||
|
float some_function(const Eigen::Ref<const MatrixXf> &big,
|
||||||
|
const Eigen::Ref<const MatrixXf> &small) {
|
||||||
|
// ...
|
||||||
|
}
|
||||||
|
|
||||||
|
// The associated binding code:
|
||||||
|
using namespace pybind11::literals; // for "arg"_a
|
||||||
|
py::class_<MyClass>(m, "MyClass")
|
||||||
|
// ... other class definitions
|
||||||
|
.def("some_method", &MyClass::some_method, py::arg().noconvert());
|
||||||
|
|
||||||
|
m.def("some_function", &some_function,
|
||||||
|
"big"_a.noconvert(), // <- Don't allow copying for this arg
|
||||||
|
"small"_a // <- This one can be copied if needed
|
||||||
|
);
|
||||||
|
|
||||||
|
With the above binding code, attempting to call the the ``some_method(m)``
|
||||||
|
method on a ``MyClass`` object, or attempting to call ``some_function(m, m2)``
|
||||||
|
will raise a ``RuntimeError`` rather than making a temporary copy of the array.
|
||||||
|
It will, however, allow the ``m2`` argument to be copied into a temporary if
|
||||||
|
necessary.
|
||||||
|
|
||||||
|
Note that explicitly specifying ``.noconvert()`` is not required for *mutable*
|
||||||
|
Eigen references (e.g. ``Eigen::Ref<MatrixXd>`` without ``const`` on the
|
||||||
|
``MatrixXd``): mutable references will never be called with a temporary copy.
|
||||||
|
|
||||||
|
Vectors versus column/row matrices
|
||||||
|
==================================
|
||||||
|
|
||||||
|
Eigen and numpy have fundamentally different notions of a vector. In Eigen, a
|
||||||
|
vector is simply a matrix with the number of columns or rows set to 1 at
|
||||||
|
compile time (for a column vector or row vector, respectively). NumPy, in
|
||||||
|
contrast, has comparable 2-dimensional 1xN and Nx1 arrays, but *also* has
|
||||||
|
1-dimensional arrays of size N.
|
||||||
|
|
||||||
|
When passing a 2-dimensional 1xN or Nx1 array to Eigen, the Eigen type must
|
||||||
|
have matching dimensions: That is, you cannot pass a 2-dimensional Nx1 numpy
|
||||||
|
array to an Eigen value expecting a row vector, or a 1xN numpy array as a
|
||||||
|
column vector argument.
|
||||||
|
|
||||||
|
On the other hand, pybind11 allows you to pass 1-dimensional arrays of length N
|
||||||
|
as Eigen parameters. If the Eigen type can hold a column vector of length N it
|
||||||
|
will be passed as such a column vector. If not, but the Eigen type constraints
|
||||||
|
will accept a row vector, it will be passed as a row vector. (The column
|
||||||
|
vector takes precedence when both are supported, for example, when passing a
|
||||||
|
1D numpy array to a MatrixXd argument). Note that the type need not be
|
||||||
|
explicitly a vector: it is permitted to pass a 1D numpy array of size 5 to an
|
||||||
|
Eigen ``Matrix<double, Dynamic, 5>``: you would end up with a 1x5 Eigen matrix.
|
||||||
|
Passing the same to an ``Eigen::MatrixXd`` would result in a 5x1 Eigen matrix.
|
||||||
|
|
||||||
|
When returning an Eigen vector to numpy, the conversion is ambiguous: a row
|
||||||
|
vector of length 4 could be returned as either a 1D array of length 4, or as a
|
||||||
|
2D array of size 1x4. When encountering such a situation, pybind11 compromises
|
||||||
|
by considering the returned Eigen type: if it is a compile-time vector--that
|
||||||
|
is, the type has either the number of rows or columns set to 1 at compile
|
||||||
|
time--pybind11 converts to a 1D numpy array when returning the value. For
|
||||||
|
instances that are a vector only at run-time (e.g. ``MatrixXd``,
|
||||||
|
``Matrix<float, Dynamic, 4>``), pybind11 returns the vector as a 2D array to
|
||||||
|
numpy. If this isn't want you want, you can use ``array.reshape(...)`` to get
|
||||||
|
a view of the same data in the desired dimensions.
|
||||||
|
|
||||||
|
.. seealso::
|
||||||
|
|
||||||
|
The file :file:`tests/test_eigen.cpp` contains a complete example that
|
||||||
|
shows how to pass Eigen sparse and dense data types in more detail.
|
109
3rdparty/pybind11/docs/advanced/cast/functional.rst
vendored
Normal file
109
3rdparty/pybind11/docs/advanced/cast/functional.rst
vendored
Normal file
@ -0,0 +1,109 @@
|
|||||||
|
Functional
|
||||||
|
##########
|
||||||
|
|
||||||
|
The following features must be enabled by including :file:`pybind11/functional.h`.
|
||||||
|
|
||||||
|
|
||||||
|
Callbacks and passing anonymous functions
|
||||||
|
=========================================
|
||||||
|
|
||||||
|
The C++11 standard brought lambda functions and the generic polymorphic
|
||||||
|
function wrapper ``std::function<>`` to the C++ programming language, which
|
||||||
|
enable powerful new ways of working with functions. Lambda functions come in
|
||||||
|
two flavors: stateless lambda function resemble classic function pointers that
|
||||||
|
link to an anonymous piece of code, while stateful lambda functions
|
||||||
|
additionally depend on captured variables that are stored in an anonymous
|
||||||
|
*lambda closure object*.
|
||||||
|
|
||||||
|
Here is a simple example of a C++ function that takes an arbitrary function
|
||||||
|
(stateful or stateless) with signature ``int -> int`` as an argument and runs
|
||||||
|
it with the value 10.
|
||||||
|
|
||||||
|
.. code-block:: cpp
|
||||||
|
|
||||||
|
int func_arg(const std::function<int(int)> &f) {
|
||||||
|
return f(10);
|
||||||
|
}
|
||||||
|
|
||||||
|
The example below is more involved: it takes a function of signature ``int -> int``
|
||||||
|
and returns another function of the same kind. The return value is a stateful
|
||||||
|
lambda function, which stores the value ``f`` in the capture object and adds 1 to
|
||||||
|
its return value upon execution.
|
||||||
|
|
||||||
|
.. code-block:: cpp
|
||||||
|
|
||||||
|
std::function<int(int)> func_ret(const std::function<int(int)> &f) {
|
||||||
|
return [f](int i) {
|
||||||
|
return f(i) + 1;
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
This example demonstrates using python named parameters in C++ callbacks which
|
||||||
|
requires using ``py::cpp_function`` as a wrapper. Usage is similar to defining
|
||||||
|
methods of classes:
|
||||||
|
|
||||||
|
.. code-block:: cpp
|
||||||
|
|
||||||
|
py::cpp_function func_cpp() {
|
||||||
|
return py::cpp_function([](int i) { return i+1; },
|
||||||
|
py::arg("number"));
|
||||||
|
}
|
||||||
|
|
||||||
|
After including the extra header file :file:`pybind11/functional.h`, it is almost
|
||||||
|
trivial to generate binding code for all of these functions.
|
||||||
|
|
||||||
|
.. code-block:: cpp
|
||||||
|
|
||||||
|
#include <pybind11/functional.h>
|
||||||
|
|
||||||
|
PYBIND11_MODULE(example, m) {
|
||||||
|
m.def("func_arg", &func_arg);
|
||||||
|
m.def("func_ret", &func_ret);
|
||||||
|
m.def("func_cpp", &func_cpp);
|
||||||
|
}
|
||||||
|
|
||||||
|
The following interactive session shows how to call them from Python.
|
||||||
|
|
||||||
|
.. code-block:: pycon
|
||||||
|
|
||||||
|
$ python
|
||||||
|
>>> import example
|
||||||
|
>>> def square(i):
|
||||||
|
... return i * i
|
||||||
|
...
|
||||||
|
>>> example.func_arg(square)
|
||||||
|
100L
|
||||||
|
>>> square_plus_1 = example.func_ret(square)
|
||||||
|
>>> square_plus_1(4)
|
||||||
|
17L
|
||||||
|
>>> plus_1 = func_cpp()
|
||||||
|
>>> plus_1(number=43)
|
||||||
|
44L
|
||||||
|
|
||||||
|
.. warning::
|
||||||
|
|
||||||
|
Keep in mind that passing a function from C++ to Python (or vice versa)
|
||||||
|
will instantiate a piece of wrapper code that translates function
|
||||||
|
invocations between the two languages. Naturally, this translation
|
||||||
|
increases the computational cost of each function call somewhat. A
|
||||||
|
problematic situation can arise when a function is copied back and forth
|
||||||
|
between Python and C++ many times in a row, in which case the underlying
|
||||||
|
wrappers will accumulate correspondingly. The resulting long sequence of
|
||||||
|
C++ -> Python -> C++ -> ... roundtrips can significantly decrease
|
||||||
|
performance.
|
||||||
|
|
||||||
|
There is one exception: pybind11 detects case where a stateless function
|
||||||
|
(i.e. a function pointer or a lambda function without captured variables)
|
||||||
|
is passed as an argument to another C++ function exposed in Python. In this
|
||||||
|
case, there is no overhead. Pybind11 will extract the underlying C++
|
||||||
|
function pointer from the wrapped function to sidestep a potential C++ ->
|
||||||
|
Python -> C++ roundtrip. This is demonstrated in :file:`tests/test_callbacks.cpp`.
|
||||||
|
|
||||||
|
.. note::
|
||||||
|
|
||||||
|
This functionality is very useful when generating bindings for callbacks in
|
||||||
|
C++ libraries (e.g. GUI libraries, asynchronous networking libraries, etc.).
|
||||||
|
|
||||||
|
The file :file:`tests/test_callbacks.cpp` contains a complete example
|
||||||
|
that demonstrates how to work with callbacks and anonymous functions in
|
||||||
|
more detail.
|
43
3rdparty/pybind11/docs/advanced/cast/index.rst
vendored
Normal file
43
3rdparty/pybind11/docs/advanced/cast/index.rst
vendored
Normal file
@ -0,0 +1,43 @@
|
|||||||
|
.. _type-conversions:
|
||||||
|
|
||||||
|
Type conversions
|
||||||
|
################
|
||||||
|
|
||||||
|
Apart from enabling cross-language function calls, a fundamental problem
|
||||||
|
that a binding tool like pybind11 must address is to provide access to
|
||||||
|
native Python types in C++ and vice versa. There are three fundamentally
|
||||||
|
different ways to do this—which approach is preferable for a particular type
|
||||||
|
depends on the situation at hand.
|
||||||
|
|
||||||
|
1. Use a native C++ type everywhere. In this case, the type must be wrapped
|
||||||
|
using pybind11-generated bindings so that Python can interact with it.
|
||||||
|
|
||||||
|
2. Use a native Python type everywhere. It will need to be wrapped so that
|
||||||
|
C++ functions can interact with it.
|
||||||
|
|
||||||
|
3. Use a native C++ type on the C++ side and a native Python type on the
|
||||||
|
Python side. pybind11 refers to this as a *type conversion*.
|
||||||
|
|
||||||
|
Type conversions are the most "natural" option in the sense that native
|
||||||
|
(non-wrapped) types are used everywhere. The main downside is that a copy
|
||||||
|
of the data must be made on every Python ↔ C++ transition: this is
|
||||||
|
needed since the C++ and Python versions of the same type generally won't
|
||||||
|
have the same memory layout.
|
||||||
|
|
||||||
|
pybind11 can perform many kinds of conversions automatically. An overview
|
||||||
|
is provided in the table ":ref:`conversion_table`".
|
||||||
|
|
||||||
|
The following subsections discuss the differences between these options in more
|
||||||
|
detail. The main focus in this section is on type conversions, which represent
|
||||||
|
the last case of the above list.
|
||||||
|
|
||||||
|
.. toctree::
|
||||||
|
:maxdepth: 1
|
||||||
|
|
||||||
|
overview
|
||||||
|
strings
|
||||||
|
stl
|
||||||
|
functional
|
||||||
|
chrono
|
||||||
|
eigen
|
||||||
|
custom
|
170
3rdparty/pybind11/docs/advanced/cast/overview.rst
vendored
Normal file
170
3rdparty/pybind11/docs/advanced/cast/overview.rst
vendored
Normal file
@ -0,0 +1,170 @@
|
|||||||
|
Overview
|
||||||
|
########
|
||||||
|
|
||||||
|
.. rubric:: 1. Native type in C++, wrapper in Python
|
||||||
|
|
||||||
|
Exposing a custom C++ type using :class:`py::class_` was covered in detail
|
||||||
|
in the :doc:`/classes` section. There, the underlying data structure is
|
||||||
|
always the original C++ class while the :class:`py::class_` wrapper provides
|
||||||
|
a Python interface. Internally, when an object like this is sent from C++ to
|
||||||
|
Python, pybind11 will just add the outer wrapper layer over the native C++
|
||||||
|
object. Getting it back from Python is just a matter of peeling off the
|
||||||
|
wrapper.
|
||||||
|
|
||||||
|
.. rubric:: 2. Wrapper in C++, native type in Python
|
||||||
|
|
||||||
|
This is the exact opposite situation. Now, we have a type which is native to
|
||||||
|
Python, like a ``tuple`` or a ``list``. One way to get this data into C++ is
|
||||||
|
with the :class:`py::object` family of wrappers. These are explained in more
|
||||||
|
detail in the :doc:`/advanced/pycpp/object` section. We'll just give a quick
|
||||||
|
example here:
|
||||||
|
|
||||||
|
.. code-block:: cpp
|
||||||
|
|
||||||
|
void print_list(py::list my_list) {
|
||||||
|
for (auto item : my_list)
|
||||||
|
std::cout << item << " ";
|
||||||
|
}
|
||||||
|
|
||||||
|
.. code-block:: pycon
|
||||||
|
|
||||||
|
>>> print_list([1, 2, 3])
|
||||||
|
1 2 3
|
||||||
|
|
||||||
|
The Python ``list`` is not converted in any way -- it's just wrapped in a C++
|
||||||
|
:class:`py::list` class. At its core it's still a Python object. Copying a
|
||||||
|
:class:`py::list` will do the usual reference-counting like in Python.
|
||||||
|
Returning the object to Python will just remove the thin wrapper.
|
||||||
|
|
||||||
|
.. rubric:: 3. Converting between native C++ and Python types
|
||||||
|
|
||||||
|
In the previous two cases we had a native type in one language and a wrapper in
|
||||||
|
the other. Now, we have native types on both sides and we convert between them.
|
||||||
|
|
||||||
|
.. code-block:: cpp
|
||||||
|
|
||||||
|
void print_vector(const std::vector<int> &v) {
|
||||||
|
for (auto item : v)
|
||||||
|
std::cout << item << "\n";
|
||||||
|
}
|
||||||
|
|
||||||
|
.. code-block:: pycon
|
||||||
|
|
||||||
|
>>> print_vector([1, 2, 3])
|
||||||
|
1 2 3
|
||||||
|
|
||||||
|
In this case, pybind11 will construct a new ``std::vector<int>`` and copy each
|
||||||
|
element from the Python ``list``. The newly constructed object will be passed
|
||||||
|
to ``print_vector``. The same thing happens in the other direction: a new
|
||||||
|
``list`` is made to match the value returned from C++.
|
||||||
|
|
||||||
|
Lots of these conversions are supported out of the box, as shown in the table
|
||||||
|
below. They are very convenient, but keep in mind that these conversions are
|
||||||
|
fundamentally based on copying data. This is perfectly fine for small immutable
|
||||||
|
types but it may become quite expensive for large data structures. This can be
|
||||||
|
avoided by overriding the automatic conversion with a custom wrapper (i.e. the
|
||||||
|
above-mentioned approach 1). This requires some manual effort and more details
|
||||||
|
are available in the :ref:`opaque` section.
|
||||||
|
|
||||||
|
.. _conversion_table:
|
||||||
|
|
||||||
|
List of all builtin conversions
|
||||||
|
-------------------------------
|
||||||
|
|
||||||
|
The following basic data types are supported out of the box (some may require
|
||||||
|
an additional extension header to be included). To pass other data structures
|
||||||
|
as arguments and return values, refer to the section on binding :ref:`classes`.
|
||||||
|
|
||||||
|
+------------------------------------+---------------------------+-----------------------------------+
|
||||||
|
| Data type | Description | Header file |
|
||||||
|
+====================================+===========================+===================================+
|
||||||
|
| ``int8_t``, ``uint8_t`` | 8-bit integers | :file:`pybind11/pybind11.h` |
|
||||||
|
+------------------------------------+---------------------------+-----------------------------------+
|
||||||
|
| ``int16_t``, ``uint16_t`` | 16-bit integers | :file:`pybind11/pybind11.h` |
|
||||||
|
+------------------------------------+---------------------------+-----------------------------------+
|
||||||
|
| ``int32_t``, ``uint32_t`` | 32-bit integers | :file:`pybind11/pybind11.h` |
|
||||||
|
+------------------------------------+---------------------------+-----------------------------------+
|
||||||
|
| ``int64_t``, ``uint64_t`` | 64-bit integers | :file:`pybind11/pybind11.h` |
|
||||||
|
+------------------------------------+---------------------------+-----------------------------------+
|
||||||
|
| ``ssize_t``, ``size_t`` | Platform-dependent size | :file:`pybind11/pybind11.h` |
|
||||||
|
+------------------------------------+---------------------------+-----------------------------------+
|
||||||
|
| ``float``, ``double`` | Floating point types | :file:`pybind11/pybind11.h` |
|
||||||
|
+------------------------------------+---------------------------+-----------------------------------+
|
||||||
|
| ``bool`` | Two-state Boolean type | :file:`pybind11/pybind11.h` |
|
||||||
|
+------------------------------------+---------------------------+-----------------------------------+
|
||||||
|
| ``char`` | Character literal | :file:`pybind11/pybind11.h` |
|
||||||
|
+------------------------------------+---------------------------+-----------------------------------+
|
||||||
|
| ``char16_t`` | UTF-16 character literal | :file:`pybind11/pybind11.h` |
|
||||||
|
+------------------------------------+---------------------------+-----------------------------------+
|
||||||
|
| ``char32_t`` | UTF-32 character literal | :file:`pybind11/pybind11.h` |
|
||||||
|
+------------------------------------+---------------------------+-----------------------------------+
|
||||||
|
| ``wchar_t`` | Wide character literal | :file:`pybind11/pybind11.h` |
|
||||||
|
+------------------------------------+---------------------------+-----------------------------------+
|
||||||
|
| ``const char *`` | UTF-8 string literal | :file:`pybind11/pybind11.h` |
|
||||||
|
+------------------------------------+---------------------------+-----------------------------------+
|
||||||
|
| ``const char16_t *`` | UTF-16 string literal | :file:`pybind11/pybind11.h` |
|
||||||
|
+------------------------------------+---------------------------+-----------------------------------+
|
||||||
|
| ``const char32_t *`` | UTF-32 string literal | :file:`pybind11/pybind11.h` |
|
||||||
|
+------------------------------------+---------------------------+-----------------------------------+
|
||||||
|
| ``const wchar_t *`` | Wide string literal | :file:`pybind11/pybind11.h` |
|
||||||
|
+------------------------------------+---------------------------+-----------------------------------+
|
||||||
|
| ``std::string`` | STL dynamic UTF-8 string | :file:`pybind11/pybind11.h` |
|
||||||
|
+------------------------------------+---------------------------+-----------------------------------+
|
||||||
|
| ``std::u16string`` | STL dynamic UTF-16 string | :file:`pybind11/pybind11.h` |
|
||||||
|
+------------------------------------+---------------------------+-----------------------------------+
|
||||||
|
| ``std::u32string`` | STL dynamic UTF-32 string | :file:`pybind11/pybind11.h` |
|
||||||
|
+------------------------------------+---------------------------+-----------------------------------+
|
||||||
|
| ``std::wstring`` | STL dynamic wide string | :file:`pybind11/pybind11.h` |
|
||||||
|
+------------------------------------+---------------------------+-----------------------------------+
|
||||||
|
| ``std::string_view``, | STL C++17 string views | :file:`pybind11/pybind11.h` |
|
||||||
|
| ``std::u16string_view``, etc. | | |
|
||||||
|
+------------------------------------+---------------------------+-----------------------------------+
|
||||||
|
| ``std::pair<T1, T2>`` | Pair of two custom types | :file:`pybind11/pybind11.h` |
|
||||||
|
+------------------------------------+---------------------------+-----------------------------------+
|
||||||
|
| ``std::tuple<...>`` | Arbitrary tuple of types | :file:`pybind11/pybind11.h` |
|
||||||
|
+------------------------------------+---------------------------+-----------------------------------+
|
||||||
|
| ``std::reference_wrapper<...>`` | Reference type wrapper | :file:`pybind11/pybind11.h` |
|
||||||
|
+------------------------------------+---------------------------+-----------------------------------+
|
||||||
|
| ``std::complex<T>`` | Complex numbers | :file:`pybind11/complex.h` |
|
||||||
|
+------------------------------------+---------------------------+-----------------------------------+
|
||||||
|
| ``std::array<T, Size>`` | STL static array | :file:`pybind11/stl.h` |
|
||||||
|
+------------------------------------+---------------------------+-----------------------------------+
|
||||||
|
| ``std::vector<T>`` | STL dynamic array | :file:`pybind11/stl.h` |
|
||||||
|
+------------------------------------+---------------------------+-----------------------------------+
|
||||||
|
| ``std::deque<T>`` | STL double-ended queue | :file:`pybind11/stl.h` |
|
||||||
|
+------------------------------------+---------------------------+-----------------------------------+
|
||||||
|
| ``std::valarray<T>`` | STL value array | :file:`pybind11/stl.h` |
|
||||||
|
+------------------------------------+---------------------------+-----------------------------------+
|
||||||
|
| ``std::list<T>`` | STL linked list | :file:`pybind11/stl.h` |
|
||||||
|
+------------------------------------+---------------------------+-----------------------------------+
|
||||||
|
| ``std::map<T1, T2>`` | STL ordered map | :file:`pybind11/stl.h` |
|
||||||
|
+------------------------------------+---------------------------+-----------------------------------+
|
||||||
|
| ``std::unordered_map<T1, T2>`` | STL unordered map | :file:`pybind11/stl.h` |
|
||||||
|
+------------------------------------+---------------------------+-----------------------------------+
|
||||||
|
| ``std::set<T>`` | STL ordered set | :file:`pybind11/stl.h` |
|
||||||
|
+------------------------------------+---------------------------+-----------------------------------+
|
||||||
|
| ``std::unordered_set<T>`` | STL unordered set | :file:`pybind11/stl.h` |
|
||||||
|
+------------------------------------+---------------------------+-----------------------------------+
|
||||||
|
| ``std::optional<T>`` | STL optional type (C++17) | :file:`pybind11/stl.h` |
|
||||||
|
+------------------------------------+---------------------------+-----------------------------------+
|
||||||
|
| ``std::experimental::optional<T>`` | STL optional type (exp.) | :file:`pybind11/stl.h` |
|
||||||
|
+------------------------------------+---------------------------+-----------------------------------+
|
||||||
|
| ``std::variant<...>`` | Type-safe union (C++17) | :file:`pybind11/stl.h` |
|
||||||
|
+------------------------------------+---------------------------+-----------------------------------+
|
||||||
|
| ``std::filesystem::path<T>`` | STL path (C++17) [#]_ | :file:`pybind11/stl/filesystem.h` |
|
||||||
|
+------------------------------------+---------------------------+-----------------------------------+
|
||||||
|
| ``std::function<...>`` | STL polymorphic function | :file:`pybind11/functional.h` |
|
||||||
|
+------------------------------------+---------------------------+-----------------------------------+
|
||||||
|
| ``std::chrono::duration<...>`` | STL time duration | :file:`pybind11/chrono.h` |
|
||||||
|
+------------------------------------+---------------------------+-----------------------------------+
|
||||||
|
| ``std::chrono::time_point<...>`` | STL date/time | :file:`pybind11/chrono.h` |
|
||||||
|
+------------------------------------+---------------------------+-----------------------------------+
|
||||||
|
| ``Eigen::Matrix<...>`` | Eigen: dense matrix | :file:`pybind11/eigen.h` |
|
||||||
|
+------------------------------------+---------------------------+-----------------------------------+
|
||||||
|
| ``Eigen::Map<...>`` | Eigen: mapped memory | :file:`pybind11/eigen.h` |
|
||||||
|
+------------------------------------+---------------------------+-----------------------------------+
|
||||||
|
| ``Eigen::SparseMatrix<...>`` | Eigen: sparse matrix | :file:`pybind11/eigen.h` |
|
||||||
|
+------------------------------------+---------------------------+-----------------------------------+
|
||||||
|
|
||||||
|
.. [#] ``std::filesystem::path`` is converted to ``pathlib.Path`` and
|
||||||
|
``os.PathLike`` is converted to ``std::filesystem::path``.
|
249
3rdparty/pybind11/docs/advanced/cast/stl.rst
vendored
Normal file
249
3rdparty/pybind11/docs/advanced/cast/stl.rst
vendored
Normal file
@ -0,0 +1,249 @@
|
|||||||
|
STL containers
|
||||||
|
##############
|
||||||
|
|
||||||
|
Automatic conversion
|
||||||
|
====================
|
||||||
|
|
||||||
|
When including the additional header file :file:`pybind11/stl.h`, conversions
|
||||||
|
between ``std::vector<>``/``std::deque<>``/``std::list<>``/``std::array<>``/``std::valarray<>``,
|
||||||
|
``std::set<>``/``std::unordered_set<>``, and
|
||||||
|
``std::map<>``/``std::unordered_map<>`` and the Python ``list``, ``set`` and
|
||||||
|
``dict`` data structures are automatically enabled. The types ``std::pair<>``
|
||||||
|
and ``std::tuple<>`` are already supported out of the box with just the core
|
||||||
|
:file:`pybind11/pybind11.h` header.
|
||||||
|
|
||||||
|
The major downside of these implicit conversions is that containers must be
|
||||||
|
converted (i.e. copied) on every Python->C++ and C++->Python transition, which
|
||||||
|
can have implications on the program semantics and performance. Please read the
|
||||||
|
next sections for more details and alternative approaches that avoid this.
|
||||||
|
|
||||||
|
.. note::
|
||||||
|
|
||||||
|
Arbitrary nesting of any of these types is possible.
|
||||||
|
|
||||||
|
.. seealso::
|
||||||
|
|
||||||
|
The file :file:`tests/test_stl.cpp` contains a complete
|
||||||
|
example that demonstrates how to pass STL data types in more detail.
|
||||||
|
|
||||||
|
.. _cpp17_container_casters:
|
||||||
|
|
||||||
|
C++17 library containers
|
||||||
|
========================
|
||||||
|
|
||||||
|
The :file:`pybind11/stl.h` header also includes support for ``std::optional<>``
|
||||||
|
and ``std::variant<>``. These require a C++17 compiler and standard library.
|
||||||
|
In C++14 mode, ``std::experimental::optional<>`` is supported if available.
|
||||||
|
|
||||||
|
Various versions of these containers also exist for C++11 (e.g. in Boost).
|
||||||
|
pybind11 provides an easy way to specialize the ``type_caster`` for such
|
||||||
|
types:
|
||||||
|
|
||||||
|
.. code-block:: cpp
|
||||||
|
|
||||||
|
// `boost::optional` as an example -- can be any `std::optional`-like container
|
||||||
|
namespace PYBIND11_NAMESPACE { namespace detail {
|
||||||
|
template <typename T>
|
||||||
|
struct type_caster<boost::optional<T>> : optional_caster<boost::optional<T>> {};
|
||||||
|
}}
|
||||||
|
|
||||||
|
The above should be placed in a header file and included in all translation units
|
||||||
|
where automatic conversion is needed. Similarly, a specialization can be provided
|
||||||
|
for custom variant types:
|
||||||
|
|
||||||
|
.. code-block:: cpp
|
||||||
|
|
||||||
|
// `boost::variant` as an example -- can be any `std::variant`-like container
|
||||||
|
namespace PYBIND11_NAMESPACE { namespace detail {
|
||||||
|
template <typename... Ts>
|
||||||
|
struct type_caster<boost::variant<Ts...>> : variant_caster<boost::variant<Ts...>> {};
|
||||||
|
|
||||||
|
// Specifies the function used to visit the variant -- `apply_visitor` instead of `visit`
|
||||||
|
template <>
|
||||||
|
struct visit_helper<boost::variant> {
|
||||||
|
template <typename... Args>
|
||||||
|
static auto call(Args &&...args) -> decltype(boost::apply_visitor(args...)) {
|
||||||
|
return boost::apply_visitor(args...);
|
||||||
|
}
|
||||||
|
};
|
||||||
|
}} // namespace PYBIND11_NAMESPACE::detail
|
||||||
|
|
||||||
|
The ``visit_helper`` specialization is not required if your ``name::variant`` provides
|
||||||
|
a ``name::visit()`` function. For any other function name, the specialization must be
|
||||||
|
included to tell pybind11 how to visit the variant.
|
||||||
|
|
||||||
|
.. warning::
|
||||||
|
|
||||||
|
When converting a ``variant`` type, pybind11 follows the same rules as when
|
||||||
|
determining which function overload to call (:ref:`overload_resolution`), and
|
||||||
|
so the same caveats hold. In particular, the order in which the ``variant``'s
|
||||||
|
alternatives are listed is important, since pybind11 will try conversions in
|
||||||
|
this order. This means that, for example, when converting ``variant<int, bool>``,
|
||||||
|
the ``bool`` variant will never be selected, as any Python ``bool`` is already
|
||||||
|
an ``int`` and is convertible to a C++ ``int``. Changing the order of alternatives
|
||||||
|
(and using ``variant<bool, int>``, in this example) provides a solution.
|
||||||
|
|
||||||
|
.. note::
|
||||||
|
|
||||||
|
pybind11 only supports the modern implementation of ``boost::variant``
|
||||||
|
which makes use of variadic templates. This requires Boost 1.56 or newer.
|
||||||
|
|
||||||
|
.. _opaque:
|
||||||
|
|
||||||
|
Making opaque types
|
||||||
|
===================
|
||||||
|
|
||||||
|
pybind11 heavily relies on a template matching mechanism to convert parameters
|
||||||
|
and return values that are constructed from STL data types such as vectors,
|
||||||
|
linked lists, hash tables, etc. This even works in a recursive manner, for
|
||||||
|
instance to deal with lists of hash maps of pairs of elementary and custom
|
||||||
|
types, etc.
|
||||||
|
|
||||||
|
However, a fundamental limitation of this approach is that internal conversions
|
||||||
|
between Python and C++ types involve a copy operation that prevents
|
||||||
|
pass-by-reference semantics. What does this mean?
|
||||||
|
|
||||||
|
Suppose we bind the following function
|
||||||
|
|
||||||
|
.. code-block:: cpp
|
||||||
|
|
||||||
|
void append_1(std::vector<int> &v) {
|
||||||
|
v.push_back(1);
|
||||||
|
}
|
||||||
|
|
||||||
|
and call it from Python, the following happens:
|
||||||
|
|
||||||
|
.. code-block:: pycon
|
||||||
|
|
||||||
|
>>> v = [5, 6]
|
||||||
|
>>> append_1(v)
|
||||||
|
>>> print(v)
|
||||||
|
[5, 6]
|
||||||
|
|
||||||
|
As you can see, when passing STL data structures by reference, modifications
|
||||||
|
are not propagated back the Python side. A similar situation arises when
|
||||||
|
exposing STL data structures using the ``def_readwrite`` or ``def_readonly``
|
||||||
|
functions:
|
||||||
|
|
||||||
|
.. code-block:: cpp
|
||||||
|
|
||||||
|
/* ... definition ... */
|
||||||
|
|
||||||
|
class MyClass {
|
||||||
|
std::vector<int> contents;
|
||||||
|
};
|
||||||
|
|
||||||
|
/* ... binding code ... */
|
||||||
|
|
||||||
|
py::class_<MyClass>(m, "MyClass")
|
||||||
|
.def(py::init<>())
|
||||||
|
.def_readwrite("contents", &MyClass::contents);
|
||||||
|
|
||||||
|
In this case, properties can be read and written in their entirety. However, an
|
||||||
|
``append`` operation involving such a list type has no effect:
|
||||||
|
|
||||||
|
.. code-block:: pycon
|
||||||
|
|
||||||
|
>>> m = MyClass()
|
||||||
|
>>> m.contents = [5, 6]
|
||||||
|
>>> print(m.contents)
|
||||||
|
[5, 6]
|
||||||
|
>>> m.contents.append(7)
|
||||||
|
>>> print(m.contents)
|
||||||
|
[5, 6]
|
||||||
|
|
||||||
|
Finally, the involved copy operations can be costly when dealing with very
|
||||||
|
large lists. To deal with all of the above situations, pybind11 provides a
|
||||||
|
macro named ``PYBIND11_MAKE_OPAQUE(T)`` that disables the template-based
|
||||||
|
conversion machinery of types, thus rendering them *opaque*. The contents of
|
||||||
|
opaque objects are never inspected or extracted, hence they *can* be passed by
|
||||||
|
reference. For instance, to turn ``std::vector<int>`` into an opaque type, add
|
||||||
|
the declaration
|
||||||
|
|
||||||
|
.. code-block:: cpp
|
||||||
|
|
||||||
|
PYBIND11_MAKE_OPAQUE(std::vector<int>);
|
||||||
|
|
||||||
|
before any binding code (e.g. invocations to ``class_::def()``, etc.). This
|
||||||
|
macro must be specified at the top level (and outside of any namespaces), since
|
||||||
|
it adds a template instantiation of ``type_caster``. If your binding code consists of
|
||||||
|
multiple compilation units, it must be present in every file (typically via a
|
||||||
|
common header) preceding any usage of ``std::vector<int>``. Opaque types must
|
||||||
|
also have a corresponding ``class_`` declaration to associate them with a name
|
||||||
|
in Python, and to define a set of available operations, e.g.:
|
||||||
|
|
||||||
|
.. code-block:: cpp
|
||||||
|
|
||||||
|
py::class_<std::vector<int>>(m, "IntVector")
|
||||||
|
.def(py::init<>())
|
||||||
|
.def("clear", &std::vector<int>::clear)
|
||||||
|
.def("pop_back", &std::vector<int>::pop_back)
|
||||||
|
.def("__len__", [](const std::vector<int> &v) { return v.size(); })
|
||||||
|
.def("__iter__", [](std::vector<int> &v) {
|
||||||
|
return py::make_iterator(v.begin(), v.end());
|
||||||
|
}, py::keep_alive<0, 1>()) /* Keep vector alive while iterator is used */
|
||||||
|
// ....
|
||||||
|
|
||||||
|
.. seealso::
|
||||||
|
|
||||||
|
The file :file:`tests/test_opaque_types.cpp` contains a complete
|
||||||
|
example that demonstrates how to create and expose opaque types using
|
||||||
|
pybind11 in more detail.
|
||||||
|
|
||||||
|
.. _stl_bind:
|
||||||
|
|
||||||
|
Binding STL containers
|
||||||
|
======================
|
||||||
|
|
||||||
|
The ability to expose STL containers as native Python objects is a fairly
|
||||||
|
common request, hence pybind11 also provides an optional header file named
|
||||||
|
:file:`pybind11/stl_bind.h` that does exactly this. The mapped containers try
|
||||||
|
to match the behavior of their native Python counterparts as much as possible.
|
||||||
|
|
||||||
|
The following example showcases usage of :file:`pybind11/stl_bind.h`:
|
||||||
|
|
||||||
|
.. code-block:: cpp
|
||||||
|
|
||||||
|
// Don't forget this
|
||||||
|
#include <pybind11/stl_bind.h>
|
||||||
|
|
||||||
|
PYBIND11_MAKE_OPAQUE(std::vector<int>);
|
||||||
|
PYBIND11_MAKE_OPAQUE(std::map<std::string, double>);
|
||||||
|
|
||||||
|
// ...
|
||||||
|
|
||||||
|
// later in binding code:
|
||||||
|
py::bind_vector<std::vector<int>>(m, "VectorInt");
|
||||||
|
py::bind_map<std::map<std::string, double>>(m, "MapStringDouble");
|
||||||
|
|
||||||
|
When binding STL containers pybind11 considers the types of the container's
|
||||||
|
elements to decide whether the container should be confined to the local module
|
||||||
|
(via the :ref:`module_local` feature). If the container element types are
|
||||||
|
anything other than already-bound custom types bound without
|
||||||
|
``py::module_local()`` the container binding will have ``py::module_local()``
|
||||||
|
applied. This includes converting types such as numeric types, strings, Eigen
|
||||||
|
types; and types that have not yet been bound at the time of the stl container
|
||||||
|
binding. This module-local binding is designed to avoid potential conflicts
|
||||||
|
between module bindings (for example, from two separate modules each attempting
|
||||||
|
to bind ``std::vector<int>`` as a python type).
|
||||||
|
|
||||||
|
It is possible to override this behavior to force a definition to be either
|
||||||
|
module-local or global. To do so, you can pass the attributes
|
||||||
|
``py::module_local()`` (to make the binding module-local) or
|
||||||
|
``py::module_local(false)`` (to make the binding global) into the
|
||||||
|
``py::bind_vector`` or ``py::bind_map`` arguments:
|
||||||
|
|
||||||
|
.. code-block:: cpp
|
||||||
|
|
||||||
|
py::bind_vector<std::vector<int>>(m, "VectorInt", py::module_local(false));
|
||||||
|
|
||||||
|
Note, however, that such a global binding would make it impossible to load this
|
||||||
|
module at the same time as any other pybind module that also attempts to bind
|
||||||
|
the same container type (``std::vector<int>`` in the above example).
|
||||||
|
|
||||||
|
See :ref:`module_local` for more details on module-local bindings.
|
||||||
|
|
||||||
|
.. seealso::
|
||||||
|
|
||||||
|
The file :file:`tests/test_stl_binders.cpp` shows how to use the
|
||||||
|
convenience STL container wrappers.
|
296
3rdparty/pybind11/docs/advanced/cast/strings.rst
vendored
Normal file
296
3rdparty/pybind11/docs/advanced/cast/strings.rst
vendored
Normal file
@ -0,0 +1,296 @@
|
|||||||
|
Strings, bytes and Unicode conversions
|
||||||
|
######################################
|
||||||
|
|
||||||
|
Passing Python strings to C++
|
||||||
|
=============================
|
||||||
|
|
||||||
|
When a Python ``str`` is passed from Python to a C++ function that accepts
|
||||||
|
``std::string`` or ``char *`` as arguments, pybind11 will encode the Python
|
||||||
|
string to UTF-8. All Python ``str`` can be encoded in UTF-8, so this operation
|
||||||
|
does not fail.
|
||||||
|
|
||||||
|
The C++ language is encoding agnostic. It is the responsibility of the
|
||||||
|
programmer to track encodings. It's often easiest to simply `use UTF-8
|
||||||
|
everywhere <http://utf8everywhere.org/>`_.
|
||||||
|
|
||||||
|
.. code-block:: c++
|
||||||
|
|
||||||
|
m.def("utf8_test",
|
||||||
|
[](const std::string &s) {
|
||||||
|
cout << "utf-8 is icing on the cake.\n";
|
||||||
|
cout << s;
|
||||||
|
}
|
||||||
|
);
|
||||||
|
m.def("utf8_charptr",
|
||||||
|
[](const char *s) {
|
||||||
|
cout << "My favorite food is\n";
|
||||||
|
cout << s;
|
||||||
|
}
|
||||||
|
);
|
||||||
|
|
||||||
|
.. code-block:: pycon
|
||||||
|
|
||||||
|
>>> utf8_test("🎂")
|
||||||
|
utf-8 is icing on the cake.
|
||||||
|
🎂
|
||||||
|
|
||||||
|
>>> utf8_charptr("🍕")
|
||||||
|
My favorite food is
|
||||||
|
🍕
|
||||||
|
|
||||||
|
.. note::
|
||||||
|
|
||||||
|
Some terminal emulators do not support UTF-8 or emoji fonts and may not
|
||||||
|
display the example above correctly.
|
||||||
|
|
||||||
|
The results are the same whether the C++ function accepts arguments by value or
|
||||||
|
reference, and whether or not ``const`` is used.
|
||||||
|
|
||||||
|
Passing bytes to C++
|
||||||
|
--------------------
|
||||||
|
|
||||||
|
A Python ``bytes`` object will be passed to C++ functions that accept
|
||||||
|
``std::string`` or ``char*`` *without* conversion. In order to make a function
|
||||||
|
*only* accept ``bytes`` (and not ``str``), declare it as taking a ``py::bytes``
|
||||||
|
argument.
|
||||||
|
|
||||||
|
|
||||||
|
Returning C++ strings to Python
|
||||||
|
===============================
|
||||||
|
|
||||||
|
When a C++ function returns a ``std::string`` or ``char*`` to a Python caller,
|
||||||
|
**pybind11 will assume that the string is valid UTF-8** and will decode it to a
|
||||||
|
native Python ``str``, using the same API as Python uses to perform
|
||||||
|
``bytes.decode('utf-8')``. If this implicit conversion fails, pybind11 will
|
||||||
|
raise a ``UnicodeDecodeError``.
|
||||||
|
|
||||||
|
.. code-block:: c++
|
||||||
|
|
||||||
|
m.def("std_string_return",
|
||||||
|
[]() {
|
||||||
|
return std::string("This string needs to be UTF-8 encoded");
|
||||||
|
}
|
||||||
|
);
|
||||||
|
|
||||||
|
.. code-block:: pycon
|
||||||
|
|
||||||
|
>>> isinstance(example.std_string_return(), str)
|
||||||
|
True
|
||||||
|
|
||||||
|
|
||||||
|
Because UTF-8 is inclusive of pure ASCII, there is never any issue with
|
||||||
|
returning a pure ASCII string to Python. If there is any possibility that the
|
||||||
|
string is not pure ASCII, it is necessary to ensure the encoding is valid
|
||||||
|
UTF-8.
|
||||||
|
|
||||||
|
.. warning::
|
||||||
|
|
||||||
|
Implicit conversion assumes that a returned ``char *`` is null-terminated.
|
||||||
|
If there is no null terminator a buffer overrun will occur.
|
||||||
|
|
||||||
|
Explicit conversions
|
||||||
|
--------------------
|
||||||
|
|
||||||
|
If some C++ code constructs a ``std::string`` that is not a UTF-8 string, one
|
||||||
|
can perform a explicit conversion and return a ``py::str`` object. Explicit
|
||||||
|
conversion has the same overhead as implicit conversion.
|
||||||
|
|
||||||
|
.. code-block:: c++
|
||||||
|
|
||||||
|
// This uses the Python C API to convert Latin-1 to Unicode
|
||||||
|
m.def("str_output",
|
||||||
|
[]() {
|
||||||
|
std::string s = "Send your r\xe9sum\xe9 to Alice in HR"; // Latin-1
|
||||||
|
py::handle py_s = PyUnicode_DecodeLatin1(s.data(), s.length(), nullptr);
|
||||||
|
if (!py_s) {
|
||||||
|
throw py::error_already_set();
|
||||||
|
}
|
||||||
|
return py::reinterpret_steal<py::str>(py_s);
|
||||||
|
}
|
||||||
|
);
|
||||||
|
|
||||||
|
.. code-block:: pycon
|
||||||
|
|
||||||
|
>>> str_output()
|
||||||
|
'Send your résumé to Alice in HR'
|
||||||
|
|
||||||
|
The `Python C API
|
||||||
|
<https://docs.python.org/3/c-api/unicode.html#built-in-codecs>`_ provides
|
||||||
|
several built-in codecs. Note that these all return *new* references, so
|
||||||
|
use :cpp:func:`reinterpret_steal` when converting them to a :cpp:class:`str`.
|
||||||
|
|
||||||
|
|
||||||
|
One could also use a third party encoding library such as libiconv to transcode
|
||||||
|
to UTF-8.
|
||||||
|
|
||||||
|
Return C++ strings without conversion
|
||||||
|
-------------------------------------
|
||||||
|
|
||||||
|
If the data in a C++ ``std::string`` does not represent text and should be
|
||||||
|
returned to Python as ``bytes``, then one can return the data as a
|
||||||
|
``py::bytes`` object.
|
||||||
|
|
||||||
|
.. code-block:: c++
|
||||||
|
|
||||||
|
m.def("return_bytes",
|
||||||
|
[]() {
|
||||||
|
std::string s("\xba\xd0\xba\xd0"); // Not valid UTF-8
|
||||||
|
return py::bytes(s); // Return the data without transcoding
|
||||||
|
}
|
||||||
|
);
|
||||||
|
|
||||||
|
.. code-block:: pycon
|
||||||
|
|
||||||
|
>>> example.return_bytes()
|
||||||
|
b'\xba\xd0\xba\xd0'
|
||||||
|
|
||||||
|
|
||||||
|
Note the asymmetry: pybind11 will convert ``bytes`` to ``std::string`` without
|
||||||
|
encoding, but cannot convert ``std::string`` back to ``bytes`` implicitly.
|
||||||
|
|
||||||
|
.. code-block:: c++
|
||||||
|
|
||||||
|
m.def("asymmetry",
|
||||||
|
[](std::string s) { // Accepts str or bytes from Python
|
||||||
|
return s; // Looks harmless, but implicitly converts to str
|
||||||
|
}
|
||||||
|
);
|
||||||
|
|
||||||
|
.. code-block:: pycon
|
||||||
|
|
||||||
|
>>> isinstance(example.asymmetry(b"have some bytes"), str)
|
||||||
|
True
|
||||||
|
|
||||||
|
>>> example.asymmetry(b"\xba\xd0\xba\xd0") # invalid utf-8 as bytes
|
||||||
|
UnicodeDecodeError: 'utf-8' codec can't decode byte 0xba in position 0: invalid start byte
|
||||||
|
|
||||||
|
|
||||||
|
Wide character strings
|
||||||
|
======================
|
||||||
|
|
||||||
|
When a Python ``str`` is passed to a C++ function expecting ``std::wstring``,
|
||||||
|
``wchar_t*``, ``std::u16string`` or ``std::u32string``, the ``str`` will be
|
||||||
|
encoded to UTF-16 or UTF-32 depending on how the C++ compiler implements each
|
||||||
|
type, in the platform's native endianness. When strings of these types are
|
||||||
|
returned, they are assumed to contain valid UTF-16 or UTF-32, and will be
|
||||||
|
decoded to Python ``str``.
|
||||||
|
|
||||||
|
.. code-block:: c++
|
||||||
|
|
||||||
|
#define UNICODE
|
||||||
|
#include <windows.h>
|
||||||
|
|
||||||
|
m.def("set_window_text",
|
||||||
|
[](HWND hwnd, std::wstring s) {
|
||||||
|
// Call SetWindowText with null-terminated UTF-16 string
|
||||||
|
::SetWindowText(hwnd, s.c_str());
|
||||||
|
}
|
||||||
|
);
|
||||||
|
m.def("get_window_text",
|
||||||
|
[](HWND hwnd) {
|
||||||
|
const int buffer_size = ::GetWindowTextLength(hwnd) + 1;
|
||||||
|
auto buffer = std::make_unique< wchar_t[] >(buffer_size);
|
||||||
|
|
||||||
|
::GetWindowText(hwnd, buffer.data(), buffer_size);
|
||||||
|
|
||||||
|
std::wstring text(buffer.get());
|
||||||
|
|
||||||
|
// wstring will be converted to Python str
|
||||||
|
return text;
|
||||||
|
}
|
||||||
|
);
|
||||||
|
|
||||||
|
Strings in multibyte encodings such as Shift-JIS must transcoded to a
|
||||||
|
UTF-8/16/32 before being returned to Python.
|
||||||
|
|
||||||
|
|
||||||
|
Character literals
|
||||||
|
==================
|
||||||
|
|
||||||
|
C++ functions that accept character literals as input will receive the first
|
||||||
|
character of a Python ``str`` as their input. If the string is longer than one
|
||||||
|
Unicode character, trailing characters will be ignored.
|
||||||
|
|
||||||
|
When a character literal is returned from C++ (such as a ``char`` or a
|
||||||
|
``wchar_t``), it will be converted to a ``str`` that represents the single
|
||||||
|
character.
|
||||||
|
|
||||||
|
.. code-block:: c++
|
||||||
|
|
||||||
|
m.def("pass_char", [](char c) { return c; });
|
||||||
|
m.def("pass_wchar", [](wchar_t w) { return w; });
|
||||||
|
|
||||||
|
.. code-block:: pycon
|
||||||
|
|
||||||
|
>>> example.pass_char("A")
|
||||||
|
'A'
|
||||||
|
|
||||||
|
While C++ will cast integers to character types (``char c = 0x65;``), pybind11
|
||||||
|
does not convert Python integers to characters implicitly. The Python function
|
||||||
|
``chr()`` can be used to convert integers to characters.
|
||||||
|
|
||||||
|
.. code-block:: pycon
|
||||||
|
|
||||||
|
>>> example.pass_char(0x65)
|
||||||
|
TypeError
|
||||||
|
|
||||||
|
>>> example.pass_char(chr(0x65))
|
||||||
|
'A'
|
||||||
|
|
||||||
|
If the desire is to work with an 8-bit integer, use ``int8_t`` or ``uint8_t``
|
||||||
|
as the argument type.
|
||||||
|
|
||||||
|
Grapheme clusters
|
||||||
|
-----------------
|
||||||
|
|
||||||
|
A single grapheme may be represented by two or more Unicode characters. For
|
||||||
|
example 'é' is usually represented as U+00E9 but can also be expressed as the
|
||||||
|
combining character sequence U+0065 U+0301 (that is, the letter 'e' followed by
|
||||||
|
a combining acute accent). The combining character will be lost if the
|
||||||
|
two-character sequence is passed as an argument, even though it renders as a
|
||||||
|
single grapheme.
|
||||||
|
|
||||||
|
.. code-block:: pycon
|
||||||
|
|
||||||
|
>>> example.pass_wchar("é")
|
||||||
|
'é'
|
||||||
|
|
||||||
|
>>> combining_e_acute = "e" + "\u0301"
|
||||||
|
|
||||||
|
>>> combining_e_acute
|
||||||
|
'é'
|
||||||
|
|
||||||
|
>>> combining_e_acute == "é"
|
||||||
|
False
|
||||||
|
|
||||||
|
>>> example.pass_wchar(combining_e_acute)
|
||||||
|
'e'
|
||||||
|
|
||||||
|
Normalizing combining characters before passing the character literal to C++
|
||||||
|
may resolve *some* of these issues:
|
||||||
|
|
||||||
|
.. code-block:: pycon
|
||||||
|
|
||||||
|
>>> example.pass_wchar(unicodedata.normalize("NFC", combining_e_acute))
|
||||||
|
'é'
|
||||||
|
|
||||||
|
In some languages (Thai for example), there are `graphemes that cannot be
|
||||||
|
expressed as a single Unicode code point
|
||||||
|
<http://unicode.org/reports/tr29/#Grapheme_Cluster_Boundaries>`_, so there is
|
||||||
|
no way to capture them in a C++ character type.
|
||||||
|
|
||||||
|
|
||||||
|
C++17 string views
|
||||||
|
==================
|
||||||
|
|
||||||
|
C++17 string views are automatically supported when compiling in C++17 mode.
|
||||||
|
They follow the same rules for encoding and decoding as the corresponding STL
|
||||||
|
string type (for example, a ``std::u16string_view`` argument will be passed
|
||||||
|
UTF-16-encoded data, and a returned ``std::string_view`` will be decoded as
|
||||||
|
UTF-8).
|
||||||
|
|
||||||
|
References
|
||||||
|
==========
|
||||||
|
|
||||||
|
* `The Absolute Minimum Every Software Developer Absolutely, Positively Must Know About Unicode and Character Sets (No Excuses!) <https://www.joelonsoftware.com/2003/10/08/the-absolute-minimum-every-software-developer-absolutely-positively-must-know-about-unicode-and-character-sets-no-excuses/>`_
|
||||||
|
* `C++ - Using STL Strings at Win32 API Boundaries <https://msdn.microsoft.com/en-ca/magazine/mt238407.aspx>`_
|
1335
3rdparty/pybind11/docs/advanced/classes.rst
vendored
Normal file
1335
3rdparty/pybind11/docs/advanced/classes.rst
vendored
Normal file
File diff suppressed because it is too large
Load Diff
262
3rdparty/pybind11/docs/advanced/embedding.rst
vendored
Normal file
262
3rdparty/pybind11/docs/advanced/embedding.rst
vendored
Normal file
@ -0,0 +1,262 @@
|
|||||||
|
.. _embedding:
|
||||||
|
|
||||||
|
Embedding the interpreter
|
||||||
|
#########################
|
||||||
|
|
||||||
|
While pybind11 is mainly focused on extending Python using C++, it's also
|
||||||
|
possible to do the reverse: embed the Python interpreter into a C++ program.
|
||||||
|
All of the other documentation pages still apply here, so refer to them for
|
||||||
|
general pybind11 usage. This section will cover a few extra things required
|
||||||
|
for embedding.
|
||||||
|
|
||||||
|
Getting started
|
||||||
|
===============
|
||||||
|
|
||||||
|
A basic executable with an embedded interpreter can be created with just a few
|
||||||
|
lines of CMake and the ``pybind11::embed`` target, as shown below. For more
|
||||||
|
information, see :doc:`/compiling`.
|
||||||
|
|
||||||
|
.. code-block:: cmake
|
||||||
|
|
||||||
|
cmake_minimum_required(VERSION 3.5...3.27)
|
||||||
|
project(example)
|
||||||
|
|
||||||
|
find_package(pybind11 REQUIRED) # or `add_subdirectory(pybind11)`
|
||||||
|
|
||||||
|
add_executable(example main.cpp)
|
||||||
|
target_link_libraries(example PRIVATE pybind11::embed)
|
||||||
|
|
||||||
|
The essential structure of the ``main.cpp`` file looks like this:
|
||||||
|
|
||||||
|
.. code-block:: cpp
|
||||||
|
|
||||||
|
#include <pybind11/embed.h> // everything needed for embedding
|
||||||
|
namespace py = pybind11;
|
||||||
|
|
||||||
|
int main() {
|
||||||
|
py::scoped_interpreter guard{}; // start the interpreter and keep it alive
|
||||||
|
|
||||||
|
py::print("Hello, World!"); // use the Python API
|
||||||
|
}
|
||||||
|
|
||||||
|
The interpreter must be initialized before using any Python API, which includes
|
||||||
|
all the functions and classes in pybind11. The RAII guard class ``scoped_interpreter``
|
||||||
|
takes care of the interpreter lifetime. After the guard is destroyed, the interpreter
|
||||||
|
shuts down and clears its memory. No Python functions can be called after this.
|
||||||
|
|
||||||
|
Executing Python code
|
||||||
|
=====================
|
||||||
|
|
||||||
|
There are a few different ways to run Python code. One option is to use ``eval``,
|
||||||
|
``exec`` or ``eval_file``, as explained in :ref:`eval`. Here is a quick example in
|
||||||
|
the context of an executable with an embedded interpreter:
|
||||||
|
|
||||||
|
.. code-block:: cpp
|
||||||
|
|
||||||
|
#include <pybind11/embed.h>
|
||||||
|
namespace py = pybind11;
|
||||||
|
|
||||||
|
int main() {
|
||||||
|
py::scoped_interpreter guard{};
|
||||||
|
|
||||||
|
py::exec(R"(
|
||||||
|
kwargs = dict(name="World", number=42)
|
||||||
|
message = "Hello, {name}! The answer is {number}".format(**kwargs)
|
||||||
|
print(message)
|
||||||
|
)");
|
||||||
|
}
|
||||||
|
|
||||||
|
Alternatively, similar results can be achieved using pybind11's API (see
|
||||||
|
:doc:`/advanced/pycpp/index` for more details).
|
||||||
|
|
||||||
|
.. code-block:: cpp
|
||||||
|
|
||||||
|
#include <pybind11/embed.h>
|
||||||
|
namespace py = pybind11;
|
||||||
|
using namespace py::literals;
|
||||||
|
|
||||||
|
int main() {
|
||||||
|
py::scoped_interpreter guard{};
|
||||||
|
|
||||||
|
auto kwargs = py::dict("name"_a="World", "number"_a=42);
|
||||||
|
auto message = "Hello, {name}! The answer is {number}"_s.format(**kwargs);
|
||||||
|
py::print(message);
|
||||||
|
}
|
||||||
|
|
||||||
|
The two approaches can also be combined:
|
||||||
|
|
||||||
|
.. code-block:: cpp
|
||||||
|
|
||||||
|
#include <pybind11/embed.h>
|
||||||
|
#include <iostream>
|
||||||
|
|
||||||
|
namespace py = pybind11;
|
||||||
|
using namespace py::literals;
|
||||||
|
|
||||||
|
int main() {
|
||||||
|
py::scoped_interpreter guard{};
|
||||||
|
|
||||||
|
auto locals = py::dict("name"_a="World", "number"_a=42);
|
||||||
|
py::exec(R"(
|
||||||
|
message = "Hello, {name}! The answer is {number}".format(**locals())
|
||||||
|
)", py::globals(), locals);
|
||||||
|
|
||||||
|
auto message = locals["message"].cast<std::string>();
|
||||||
|
std::cout << message;
|
||||||
|
}
|
||||||
|
|
||||||
|
Importing modules
|
||||||
|
=================
|
||||||
|
|
||||||
|
Python modules can be imported using ``module_::import()``:
|
||||||
|
|
||||||
|
.. code-block:: cpp
|
||||||
|
|
||||||
|
py::module_ sys = py::module_::import("sys");
|
||||||
|
py::print(sys.attr("path"));
|
||||||
|
|
||||||
|
For convenience, the current working directory is included in ``sys.path`` when
|
||||||
|
embedding the interpreter. This makes it easy to import local Python files:
|
||||||
|
|
||||||
|
.. code-block:: python
|
||||||
|
|
||||||
|
"""calc.py located in the working directory"""
|
||||||
|
|
||||||
|
|
||||||
|
def add(i, j):
|
||||||
|
return i + j
|
||||||
|
|
||||||
|
|
||||||
|
.. code-block:: cpp
|
||||||
|
|
||||||
|
py::module_ calc = py::module_::import("calc");
|
||||||
|
py::object result = calc.attr("add")(1, 2);
|
||||||
|
int n = result.cast<int>();
|
||||||
|
assert(n == 3);
|
||||||
|
|
||||||
|
Modules can be reloaded using ``module_::reload()`` if the source is modified e.g.
|
||||||
|
by an external process. This can be useful in scenarios where the application
|
||||||
|
imports a user defined data processing script which needs to be updated after
|
||||||
|
changes by the user. Note that this function does not reload modules recursively.
|
||||||
|
|
||||||
|
.. _embedding_modules:
|
||||||
|
|
||||||
|
Adding embedded modules
|
||||||
|
=======================
|
||||||
|
|
||||||
|
Embedded binary modules can be added using the ``PYBIND11_EMBEDDED_MODULE`` macro.
|
||||||
|
Note that the definition must be placed at global scope. They can be imported
|
||||||
|
like any other module.
|
||||||
|
|
||||||
|
.. code-block:: cpp
|
||||||
|
|
||||||
|
#include <pybind11/embed.h>
|
||||||
|
namespace py = pybind11;
|
||||||
|
|
||||||
|
PYBIND11_EMBEDDED_MODULE(fast_calc, m) {
|
||||||
|
// `m` is a `py::module_` which is used to bind functions and classes
|
||||||
|
m.def("add", [](int i, int j) {
|
||||||
|
return i + j;
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
int main() {
|
||||||
|
py::scoped_interpreter guard{};
|
||||||
|
|
||||||
|
auto fast_calc = py::module_::import("fast_calc");
|
||||||
|
auto result = fast_calc.attr("add")(1, 2).cast<int>();
|
||||||
|
assert(result == 3);
|
||||||
|
}
|
||||||
|
|
||||||
|
Unlike extension modules where only a single binary module can be created, on
|
||||||
|
the embedded side an unlimited number of modules can be added using multiple
|
||||||
|
``PYBIND11_EMBEDDED_MODULE`` definitions (as long as they have unique names).
|
||||||
|
|
||||||
|
These modules are added to Python's list of builtins, so they can also be
|
||||||
|
imported in pure Python files loaded by the interpreter. Everything interacts
|
||||||
|
naturally:
|
||||||
|
|
||||||
|
.. code-block:: python
|
||||||
|
|
||||||
|
"""py_module.py located in the working directory"""
|
||||||
|
import cpp_module
|
||||||
|
|
||||||
|
a = cpp_module.a
|
||||||
|
b = a + 1
|
||||||
|
|
||||||
|
|
||||||
|
.. code-block:: cpp
|
||||||
|
|
||||||
|
#include <pybind11/embed.h>
|
||||||
|
namespace py = pybind11;
|
||||||
|
|
||||||
|
PYBIND11_EMBEDDED_MODULE(cpp_module, m) {
|
||||||
|
m.attr("a") = 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
int main() {
|
||||||
|
py::scoped_interpreter guard{};
|
||||||
|
|
||||||
|
auto py_module = py::module_::import("py_module");
|
||||||
|
|
||||||
|
auto locals = py::dict("fmt"_a="{} + {} = {}", **py_module.attr("__dict__"));
|
||||||
|
assert(locals["a"].cast<int>() == 1);
|
||||||
|
assert(locals["b"].cast<int>() == 2);
|
||||||
|
|
||||||
|
py::exec(R"(
|
||||||
|
c = a + b
|
||||||
|
message = fmt.format(a, b, c)
|
||||||
|
)", py::globals(), locals);
|
||||||
|
|
||||||
|
assert(locals["c"].cast<int>() == 3);
|
||||||
|
assert(locals["message"].cast<std::string>() == "1 + 2 = 3");
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
Interpreter lifetime
|
||||||
|
====================
|
||||||
|
|
||||||
|
The Python interpreter shuts down when ``scoped_interpreter`` is destroyed. After
|
||||||
|
this, creating a new instance will restart the interpreter. Alternatively, the
|
||||||
|
``initialize_interpreter`` / ``finalize_interpreter`` pair of functions can be used
|
||||||
|
to directly set the state at any time.
|
||||||
|
|
||||||
|
Modules created with pybind11 can be safely re-initialized after the interpreter
|
||||||
|
has been restarted. However, this may not apply to third-party extension modules.
|
||||||
|
The issue is that Python itself cannot completely unload extension modules and
|
||||||
|
there are several caveats with regard to interpreter restarting. In short, not
|
||||||
|
all memory may be freed, either due to Python reference cycles or user-created
|
||||||
|
global data. All the details can be found in the CPython documentation.
|
||||||
|
|
||||||
|
.. warning::
|
||||||
|
|
||||||
|
Creating two concurrent ``scoped_interpreter`` guards is a fatal error. So is
|
||||||
|
calling ``initialize_interpreter`` for a second time after the interpreter
|
||||||
|
has already been initialized.
|
||||||
|
|
||||||
|
Do not use the raw CPython API functions ``Py_Initialize`` and
|
||||||
|
``Py_Finalize`` as these do not properly handle the lifetime of
|
||||||
|
pybind11's internal data.
|
||||||
|
|
||||||
|
|
||||||
|
Sub-interpreter support
|
||||||
|
=======================
|
||||||
|
|
||||||
|
Creating multiple copies of ``scoped_interpreter`` is not possible because it
|
||||||
|
represents the main Python interpreter. Sub-interpreters are something different
|
||||||
|
and they do permit the existence of multiple interpreters. This is an advanced
|
||||||
|
feature of the CPython API and should be handled with care. pybind11 does not
|
||||||
|
currently offer a C++ interface for sub-interpreters, so refer to the CPython
|
||||||
|
documentation for all the details regarding this feature.
|
||||||
|
|
||||||
|
We'll just mention a couple of caveats the sub-interpreters support in pybind11:
|
||||||
|
|
||||||
|
1. Sub-interpreters will not receive independent copies of embedded modules.
|
||||||
|
Instead, these are shared and modifications in one interpreter may be
|
||||||
|
reflected in another.
|
||||||
|
|
||||||
|
2. Managing multiple threads, multiple interpreters and the GIL can be
|
||||||
|
challenging and there are several caveats here, even within the pure
|
||||||
|
CPython API (please refer to the Python docs for details). As for
|
||||||
|
pybind11, keep in mind that ``gil_scoped_release`` and ``gil_scoped_acquire``
|
||||||
|
do not take sub-interpreters into account.
|
401
3rdparty/pybind11/docs/advanced/exceptions.rst
vendored
Normal file
401
3rdparty/pybind11/docs/advanced/exceptions.rst
vendored
Normal file
@ -0,0 +1,401 @@
|
|||||||
|
Exceptions
|
||||||
|
##########
|
||||||
|
|
||||||
|
Built-in C++ to Python exception translation
|
||||||
|
============================================
|
||||||
|
|
||||||
|
When Python calls C++ code through pybind11, pybind11 provides a C++ exception handler
|
||||||
|
that will trap C++ exceptions, translate them to the corresponding Python exception,
|
||||||
|
and raise them so that Python code can handle them.
|
||||||
|
|
||||||
|
pybind11 defines translations for ``std::exception`` and its standard
|
||||||
|
subclasses, and several special exception classes that translate to specific
|
||||||
|
Python exceptions. Note that these are not actually Python exceptions, so they
|
||||||
|
cannot be examined using the Python C API. Instead, they are pure C++ objects
|
||||||
|
that pybind11 will translate the corresponding Python exception when they arrive
|
||||||
|
at its exception handler.
|
||||||
|
|
||||||
|
.. tabularcolumns:: |p{0.5\textwidth}|p{0.45\textwidth}|
|
||||||
|
|
||||||
|
+--------------------------------------+--------------------------------------+
|
||||||
|
| Exception thrown by C++ | Translated to Python exception type |
|
||||||
|
+======================================+======================================+
|
||||||
|
| :class:`std::exception` | ``RuntimeError`` |
|
||||||
|
+--------------------------------------+--------------------------------------+
|
||||||
|
| :class:`std::bad_alloc` | ``MemoryError`` |
|
||||||
|
+--------------------------------------+--------------------------------------+
|
||||||
|
| :class:`std::domain_error` | ``ValueError`` |
|
||||||
|
+--------------------------------------+--------------------------------------+
|
||||||
|
| :class:`std::invalid_argument` | ``ValueError`` |
|
||||||
|
+--------------------------------------+--------------------------------------+
|
||||||
|
| :class:`std::length_error` | ``ValueError`` |
|
||||||
|
+--------------------------------------+--------------------------------------+
|
||||||
|
| :class:`std::out_of_range` | ``IndexError`` |
|
||||||
|
+--------------------------------------+--------------------------------------+
|
||||||
|
| :class:`std::range_error` | ``ValueError`` |
|
||||||
|
+--------------------------------------+--------------------------------------+
|
||||||
|
| :class:`std::overflow_error` | ``OverflowError`` |
|
||||||
|
+--------------------------------------+--------------------------------------+
|
||||||
|
| :class:`pybind11::stop_iteration` | ``StopIteration`` (used to implement |
|
||||||
|
| | custom iterators) |
|
||||||
|
+--------------------------------------+--------------------------------------+
|
||||||
|
| :class:`pybind11::index_error` | ``IndexError`` (used to indicate out |
|
||||||
|
| | of bounds access in ``__getitem__``, |
|
||||||
|
| | ``__setitem__``, etc.) |
|
||||||
|
+--------------------------------------+--------------------------------------+
|
||||||
|
| :class:`pybind11::key_error` | ``KeyError`` (used to indicate out |
|
||||||
|
| | of bounds access in ``__getitem__``, |
|
||||||
|
| | ``__setitem__`` in dict-like |
|
||||||
|
| | objects, etc.) |
|
||||||
|
+--------------------------------------+--------------------------------------+
|
||||||
|
| :class:`pybind11::value_error` | ``ValueError`` (used to indicate |
|
||||||
|
| | wrong value passed in |
|
||||||
|
| | ``container.remove(...)``) |
|
||||||
|
+--------------------------------------+--------------------------------------+
|
||||||
|
| :class:`pybind11::type_error` | ``TypeError`` |
|
||||||
|
+--------------------------------------+--------------------------------------+
|
||||||
|
| :class:`pybind11::buffer_error` | ``BufferError`` |
|
||||||
|
+--------------------------------------+--------------------------------------+
|
||||||
|
| :class:`pybind11::import_error` | ``ImportError`` |
|
||||||
|
+--------------------------------------+--------------------------------------+
|
||||||
|
| :class:`pybind11::attribute_error` | ``AttributeError`` |
|
||||||
|
+--------------------------------------+--------------------------------------+
|
||||||
|
| Any other exception | ``RuntimeError`` |
|
||||||
|
+--------------------------------------+--------------------------------------+
|
||||||
|
|
||||||
|
Exception translation is not bidirectional. That is, *catching* the C++
|
||||||
|
exceptions defined above will not trap exceptions that originate from
|
||||||
|
Python. For that, catch :class:`pybind11::error_already_set`. See :ref:`below
|
||||||
|
<handling_python_exceptions_cpp>` for further details.
|
||||||
|
|
||||||
|
There is also a special exception :class:`cast_error` that is thrown by
|
||||||
|
:func:`handle::call` when the input arguments cannot be converted to Python
|
||||||
|
objects.
|
||||||
|
|
||||||
|
Registering custom translators
|
||||||
|
==============================
|
||||||
|
|
||||||
|
If the default exception conversion policy described above is insufficient,
|
||||||
|
pybind11 also provides support for registering custom exception translators.
|
||||||
|
Similar to pybind11 classes, exception translators can be local to the module
|
||||||
|
they are defined in or global to the entire python session. To register a simple
|
||||||
|
exception conversion that translates a C++ exception into a new Python exception
|
||||||
|
using the C++ exception's ``what()`` method, a helper function is available:
|
||||||
|
|
||||||
|
.. code-block:: cpp
|
||||||
|
|
||||||
|
py::register_exception<CppExp>(module, "PyExp");
|
||||||
|
|
||||||
|
This call creates a Python exception class with the name ``PyExp`` in the given
|
||||||
|
module and automatically converts any encountered exceptions of type ``CppExp``
|
||||||
|
into Python exceptions of type ``PyExp``.
|
||||||
|
|
||||||
|
A matching function is available for registering a local exception translator:
|
||||||
|
|
||||||
|
.. code-block:: cpp
|
||||||
|
|
||||||
|
py::register_local_exception<CppExp>(module, "PyExp");
|
||||||
|
|
||||||
|
|
||||||
|
It is possible to specify base class for the exception using the third
|
||||||
|
parameter, a ``handle``:
|
||||||
|
|
||||||
|
.. code-block:: cpp
|
||||||
|
|
||||||
|
py::register_exception<CppExp>(module, "PyExp", PyExc_RuntimeError);
|
||||||
|
py::register_local_exception<CppExp>(module, "PyExp", PyExc_RuntimeError);
|
||||||
|
|
||||||
|
Then ``PyExp`` can be caught both as ``PyExp`` and ``RuntimeError``.
|
||||||
|
|
||||||
|
The class objects of the built-in Python exceptions are listed in the Python
|
||||||
|
documentation on `Standard Exceptions <https://docs.python.org/3/c-api/exceptions.html#standard-exceptions>`_.
|
||||||
|
The default base class is ``PyExc_Exception``.
|
||||||
|
|
||||||
|
When more advanced exception translation is needed, the functions
|
||||||
|
``py::register_exception_translator(translator)`` and
|
||||||
|
``py::register_local_exception_translator(translator)`` can be used to register
|
||||||
|
functions that can translate arbitrary exception types (and which may include
|
||||||
|
additional logic to do so). The functions takes a stateless callable (e.g. a
|
||||||
|
function pointer or a lambda function without captured variables) with the call
|
||||||
|
signature ``void(std::exception_ptr)``.
|
||||||
|
|
||||||
|
When a C++ exception is thrown, the registered exception translators are tried
|
||||||
|
in reverse order of registration (i.e. the last registered translator gets the
|
||||||
|
first shot at handling the exception). All local translators will be tried
|
||||||
|
before a global translator is tried.
|
||||||
|
|
||||||
|
Inside the translator, ``std::rethrow_exception`` should be used within
|
||||||
|
a try block to re-throw the exception. One or more catch clauses to catch
|
||||||
|
the appropriate exceptions should then be used with each clause using
|
||||||
|
``py::set_error()`` (see below).
|
||||||
|
|
||||||
|
To declare a custom Python exception type, declare a ``py::exception`` variable
|
||||||
|
and use this in the associated exception translator (note: it is often useful
|
||||||
|
to make this a static declaration when using it inside a lambda expression
|
||||||
|
without requiring capturing).
|
||||||
|
|
||||||
|
The following example demonstrates this for a hypothetical exception classes
|
||||||
|
``MyCustomException`` and ``OtherException``: the first is translated to a
|
||||||
|
custom python exception ``MyCustomError``, while the second is translated to a
|
||||||
|
standard python RuntimeError:
|
||||||
|
|
||||||
|
.. code-block:: cpp
|
||||||
|
|
||||||
|
PYBIND11_CONSTINIT static py::gil_safe_call_once_and_store<py::object> exc_storage;
|
||||||
|
exc_storage.call_once_and_store_result(
|
||||||
|
[&]() { return py::exception<MyCustomException>(m, "MyCustomError"); });
|
||||||
|
py::register_exception_translator([](std::exception_ptr p) {
|
||||||
|
try {
|
||||||
|
if (p) std::rethrow_exception(p);
|
||||||
|
} catch (const MyCustomException &e) {
|
||||||
|
py::set_error(exc_storage.get_stored(), e.what());
|
||||||
|
} catch (const OtherException &e) {
|
||||||
|
py::set_error(PyExc_RuntimeError, e.what());
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
Multiple exceptions can be handled by a single translator, as shown in the
|
||||||
|
example above. If the exception is not caught by the current translator, the
|
||||||
|
previously registered one gets a chance.
|
||||||
|
|
||||||
|
If none of the registered exception translators is able to handle the
|
||||||
|
exception, it is handled by the default converter as described in the previous
|
||||||
|
section.
|
||||||
|
|
||||||
|
.. seealso::
|
||||||
|
|
||||||
|
The file :file:`tests/test_exceptions.cpp` contains examples
|
||||||
|
of various custom exception translators and custom exception types.
|
||||||
|
|
||||||
|
.. note::
|
||||||
|
|
||||||
|
Call ``py::set_error()`` for every exception caught in a custom exception
|
||||||
|
translator. Failure to do so will cause Python to crash with ``SystemError:
|
||||||
|
error return without exception set``.
|
||||||
|
|
||||||
|
Exceptions that you do not plan to handle should simply not be caught, or
|
||||||
|
may be explicitly (re-)thrown to delegate it to the other,
|
||||||
|
previously-declared existing exception translators.
|
||||||
|
|
||||||
|
Note that ``libc++`` and ``libstdc++`` `behave differently under macOS
|
||||||
|
<https://stackoverflow.com/questions/19496643/using-clang-fvisibility-hidden-and-typeinfo-and-type-erasure/28827430>`_
|
||||||
|
with ``-fvisibility=hidden``. Therefore exceptions that are used across ABI
|
||||||
|
boundaries need to be explicitly exported, as exercised in
|
||||||
|
``tests/test_exceptions.h``. See also:
|
||||||
|
"Problems with C++ exceptions" under `GCC Wiki <https://gcc.gnu.org/wiki/Visibility>`_.
|
||||||
|
|
||||||
|
|
||||||
|
Local vs Global Exception Translators
|
||||||
|
=====================================
|
||||||
|
|
||||||
|
When a global exception translator is registered, it will be applied across all
|
||||||
|
modules in the reverse order of registration. This can create behavior where the
|
||||||
|
order of module import influences how exceptions are translated.
|
||||||
|
|
||||||
|
If module1 has the following translator:
|
||||||
|
|
||||||
|
.. code-block:: cpp
|
||||||
|
|
||||||
|
py::register_exception_translator([](std::exception_ptr p) {
|
||||||
|
try {
|
||||||
|
if (p) std::rethrow_exception(p);
|
||||||
|
} catch (const std::invalid_argument &e) {
|
||||||
|
py::set_error(PyExc_ArgumentError, "module1 handled this");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
and module2 has the following similar translator:
|
||||||
|
|
||||||
|
.. code-block:: cpp
|
||||||
|
|
||||||
|
py::register_exception_translator([](std::exception_ptr p) {
|
||||||
|
try {
|
||||||
|
if (p) std::rethrow_exception(p);
|
||||||
|
} catch (const std::invalid_argument &e) {
|
||||||
|
py::set_error(PyExc_ArgumentError, "module2 handled this");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
then which translator handles the invalid_argument will be determined by the
|
||||||
|
order that module1 and module2 are imported. Since exception translators are
|
||||||
|
applied in the reverse order of registration, which ever module was imported
|
||||||
|
last will "win" and that translator will be applied.
|
||||||
|
|
||||||
|
If there are multiple pybind11 modules that share exception types (either
|
||||||
|
standard built-in or custom) loaded into a single python instance and
|
||||||
|
consistent error handling behavior is needed, then local translators should be
|
||||||
|
used.
|
||||||
|
|
||||||
|
Changing the previous example to use ``register_local_exception_translator``
|
||||||
|
would mean that when invalid_argument is thrown in the module2 code, the
|
||||||
|
module2 translator will always handle it, while in module1, the module1
|
||||||
|
translator will do the same.
|
||||||
|
|
||||||
|
.. _handling_python_exceptions_cpp:
|
||||||
|
|
||||||
|
Handling exceptions from Python in C++
|
||||||
|
======================================
|
||||||
|
|
||||||
|
When C++ calls Python functions, such as in a callback function or when
|
||||||
|
manipulating Python objects, and Python raises an ``Exception``, pybind11
|
||||||
|
converts the Python exception into a C++ exception of type
|
||||||
|
:class:`pybind11::error_already_set` whose payload contains a C++ string textual
|
||||||
|
summary and the actual Python exception. ``error_already_set`` is used to
|
||||||
|
propagate Python exception back to Python (or possibly, handle them in C++).
|
||||||
|
|
||||||
|
.. tabularcolumns:: |p{0.5\textwidth}|p{0.45\textwidth}|
|
||||||
|
|
||||||
|
+--------------------------------------+--------------------------------------+
|
||||||
|
| Exception raised in Python | Thrown as C++ exception type |
|
||||||
|
+======================================+======================================+
|
||||||
|
| Any Python ``Exception`` | :class:`pybind11::error_already_set` |
|
||||||
|
+--------------------------------------+--------------------------------------+
|
||||||
|
|
||||||
|
For example:
|
||||||
|
|
||||||
|
.. code-block:: cpp
|
||||||
|
|
||||||
|
try {
|
||||||
|
// open("missing.txt", "r")
|
||||||
|
auto file = py::module_::import("io").attr("open")("missing.txt", "r");
|
||||||
|
auto text = file.attr("read")();
|
||||||
|
file.attr("close")();
|
||||||
|
} catch (py::error_already_set &e) {
|
||||||
|
if (e.matches(PyExc_FileNotFoundError)) {
|
||||||
|
py::print("missing.txt not found");
|
||||||
|
} else if (e.matches(PyExc_PermissionError)) {
|
||||||
|
py::print("missing.txt found but not accessible");
|
||||||
|
} else {
|
||||||
|
throw;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
Note that C++ to Python exception translation does not apply here, since that is
|
||||||
|
a method for translating C++ exceptions to Python, not vice versa. The error raised
|
||||||
|
from Python is always ``error_already_set``.
|
||||||
|
|
||||||
|
This example illustrates this behavior:
|
||||||
|
|
||||||
|
.. code-block:: cpp
|
||||||
|
|
||||||
|
try {
|
||||||
|
py::eval("raise ValueError('The Ring')");
|
||||||
|
} catch (py::value_error &boromir) {
|
||||||
|
// Boromir never gets the ring
|
||||||
|
assert(false);
|
||||||
|
} catch (py::error_already_set &frodo) {
|
||||||
|
// Frodo gets the ring
|
||||||
|
py::print("I will take the ring");
|
||||||
|
}
|
||||||
|
|
||||||
|
try {
|
||||||
|
// py::value_error is a request for pybind11 to raise a Python exception
|
||||||
|
throw py::value_error("The ball");
|
||||||
|
} catch (py::error_already_set &cat) {
|
||||||
|
// cat won't catch the ball since
|
||||||
|
// py::value_error is not a Python exception
|
||||||
|
assert(false);
|
||||||
|
} catch (py::value_error &dog) {
|
||||||
|
// dog will catch the ball
|
||||||
|
py::print("Run Spot run");
|
||||||
|
throw; // Throw it again (pybind11 will raise ValueError)
|
||||||
|
}
|
||||||
|
|
||||||
|
Handling errors from the Python C API
|
||||||
|
=====================================
|
||||||
|
|
||||||
|
Where possible, use :ref:`pybind11 wrappers <wrappers>` instead of calling
|
||||||
|
the Python C API directly. When calling the Python C API directly, in
|
||||||
|
addition to manually managing reference counts, one must follow the pybind11
|
||||||
|
error protocol, which is outlined here.
|
||||||
|
|
||||||
|
After calling the Python C API, if Python returns an error,
|
||||||
|
``throw py::error_already_set();``, which allows pybind11 to deal with the
|
||||||
|
exception and pass it back to the Python interpreter. This includes calls to
|
||||||
|
the error setting functions such as ``py::set_error()``.
|
||||||
|
|
||||||
|
.. code-block:: cpp
|
||||||
|
|
||||||
|
py::set_error(PyExc_TypeError, "C API type error demo");
|
||||||
|
throw py::error_already_set();
|
||||||
|
|
||||||
|
// But it would be easier to simply...
|
||||||
|
throw py::type_error("pybind11 wrapper type error");
|
||||||
|
|
||||||
|
Alternately, to ignore the error, call `PyErr_Clear
|
||||||
|
<https://docs.python.org/3/c-api/exceptions.html#c.PyErr_Clear>`_.
|
||||||
|
|
||||||
|
Any Python error must be thrown or cleared, or Python/pybind11 will be left in
|
||||||
|
an invalid state.
|
||||||
|
|
||||||
|
Chaining exceptions ('raise from')
|
||||||
|
==================================
|
||||||
|
|
||||||
|
Python has a mechanism for indicating that exceptions were caused by other
|
||||||
|
exceptions:
|
||||||
|
|
||||||
|
.. code-block:: py
|
||||||
|
|
||||||
|
try:
|
||||||
|
print(1 / 0)
|
||||||
|
except Exception as exc:
|
||||||
|
raise RuntimeError("could not divide by zero") from exc
|
||||||
|
|
||||||
|
To do a similar thing in pybind11, you can use the ``py::raise_from`` function. It
|
||||||
|
sets the current python error indicator, so to continue propagating the exception
|
||||||
|
you should ``throw py::error_already_set()``.
|
||||||
|
|
||||||
|
.. code-block:: cpp
|
||||||
|
|
||||||
|
try {
|
||||||
|
py::eval("print(1 / 0"));
|
||||||
|
} catch (py::error_already_set &e) {
|
||||||
|
py::raise_from(e, PyExc_RuntimeError, "could not divide by zero");
|
||||||
|
throw py::error_already_set();
|
||||||
|
}
|
||||||
|
|
||||||
|
.. versionadded:: 2.8
|
||||||
|
|
||||||
|
.. _unraisable_exceptions:
|
||||||
|
|
||||||
|
Handling unraisable exceptions
|
||||||
|
==============================
|
||||||
|
|
||||||
|
If a Python function invoked from a C++ destructor or any function marked
|
||||||
|
``noexcept(true)`` (collectively, "noexcept functions") throws an exception, there
|
||||||
|
is no way to propagate the exception, as such functions may not throw.
|
||||||
|
Should they throw or fail to catch any exceptions in their call graph,
|
||||||
|
the C++ runtime calls ``std::terminate()`` to abort immediately.
|
||||||
|
|
||||||
|
Similarly, Python exceptions raised in a class's ``__del__`` method do not
|
||||||
|
propagate, but are logged by Python as an unraisable error. In Python 3.8+, a
|
||||||
|
`system hook is triggered
|
||||||
|
<https://docs.python.org/3/library/sys.html#sys.unraisablehook>`_
|
||||||
|
and an auditing event is logged.
|
||||||
|
|
||||||
|
Any noexcept function should have a try-catch block that traps
|
||||||
|
class:`error_already_set` (or any other exception that can occur). Note that
|
||||||
|
pybind11 wrappers around Python exceptions such as
|
||||||
|
:class:`pybind11::value_error` are *not* Python exceptions; they are C++
|
||||||
|
exceptions that pybind11 catches and converts to Python exceptions. Noexcept
|
||||||
|
functions cannot propagate these exceptions either. A useful approach is to
|
||||||
|
convert them to Python exceptions and then ``discard_as_unraisable`` as shown
|
||||||
|
below.
|
||||||
|
|
||||||
|
.. code-block:: cpp
|
||||||
|
|
||||||
|
void nonthrowing_func() noexcept(true) {
|
||||||
|
try {
|
||||||
|
// ...
|
||||||
|
} catch (py::error_already_set &eas) {
|
||||||
|
// Discard the Python error using Python APIs, using the C++ magic
|
||||||
|
// variable __func__. Python already knows the type and value and of the
|
||||||
|
// exception object.
|
||||||
|
eas.discard_as_unraisable(__func__);
|
||||||
|
} catch (const std::exception &e) {
|
||||||
|
// Log and discard C++ exceptions.
|
||||||
|
third_party::log(e);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
.. versionadded:: 2.6
|
614
3rdparty/pybind11/docs/advanced/functions.rst
vendored
Normal file
614
3rdparty/pybind11/docs/advanced/functions.rst
vendored
Normal file
@ -0,0 +1,614 @@
|
|||||||
|
Functions
|
||||||
|
#########
|
||||||
|
|
||||||
|
Before proceeding with this section, make sure that you are already familiar
|
||||||
|
with the basics of binding functions and classes, as explained in :doc:`/basics`
|
||||||
|
and :doc:`/classes`. The following guide is applicable to both free and member
|
||||||
|
functions, i.e. *methods* in Python.
|
||||||
|
|
||||||
|
.. _return_value_policies:
|
||||||
|
|
||||||
|
Return value policies
|
||||||
|
=====================
|
||||||
|
|
||||||
|
Python and C++ use fundamentally different ways of managing the memory and
|
||||||
|
lifetime of objects managed by them. This can lead to issues when creating
|
||||||
|
bindings for functions that return a non-trivial type. Just by looking at the
|
||||||
|
type information, it is not clear whether Python should take charge of the
|
||||||
|
returned value and eventually free its resources, or if this is handled on the
|
||||||
|
C++ side. For this reason, pybind11 provides several *return value policy*
|
||||||
|
annotations that can be passed to the :func:`module_::def` and
|
||||||
|
:func:`class_::def` functions. The default policy is
|
||||||
|
:enum:`return_value_policy::automatic`.
|
||||||
|
|
||||||
|
Return value policies are tricky, and it's very important to get them right.
|
||||||
|
Just to illustrate what can go wrong, consider the following simple example:
|
||||||
|
|
||||||
|
.. code-block:: cpp
|
||||||
|
|
||||||
|
/* Function declaration */
|
||||||
|
Data *get_data() { return _data; /* (pointer to a static data structure) */ }
|
||||||
|
...
|
||||||
|
|
||||||
|
/* Binding code */
|
||||||
|
m.def("get_data", &get_data); // <-- KABOOM, will cause crash when called from Python
|
||||||
|
|
||||||
|
What's going on here? When ``get_data()`` is called from Python, the return
|
||||||
|
value (a native C++ type) must be wrapped to turn it into a usable Python type.
|
||||||
|
In this case, the default return value policy (:enum:`return_value_policy::automatic`)
|
||||||
|
causes pybind11 to assume ownership of the static ``_data`` instance.
|
||||||
|
|
||||||
|
When Python's garbage collector eventually deletes the Python
|
||||||
|
wrapper, pybind11 will also attempt to delete the C++ instance (via ``operator
|
||||||
|
delete()``) due to the implied ownership. At this point, the entire application
|
||||||
|
will come crashing down, though errors could also be more subtle and involve
|
||||||
|
silent data corruption.
|
||||||
|
|
||||||
|
In the above example, the policy :enum:`return_value_policy::reference` should have
|
||||||
|
been specified so that the global data instance is only *referenced* without any
|
||||||
|
implied transfer of ownership, i.e.:
|
||||||
|
|
||||||
|
.. code-block:: cpp
|
||||||
|
|
||||||
|
m.def("get_data", &get_data, py::return_value_policy::reference);
|
||||||
|
|
||||||
|
On the other hand, this is not the right policy for many other situations,
|
||||||
|
where ignoring ownership could lead to resource leaks.
|
||||||
|
As a developer using pybind11, it's important to be familiar with the different
|
||||||
|
return value policies, including which situation calls for which one of them.
|
||||||
|
The following table provides an overview of available policies:
|
||||||
|
|
||||||
|
.. tabularcolumns:: |p{0.5\textwidth}|p{0.45\textwidth}|
|
||||||
|
|
||||||
|
+--------------------------------------------------+----------------------------------------------------------------------------+
|
||||||
|
| Return value policy | Description |
|
||||||
|
+==================================================+============================================================================+
|
||||||
|
| :enum:`return_value_policy::take_ownership` | Reference an existing object (i.e. do not create a new copy) and take |
|
||||||
|
| | ownership. Python will call the destructor and delete operator when the |
|
||||||
|
| | object's reference count reaches zero. Undefined behavior ensues when the |
|
||||||
|
| | C++ side does the same, or when the data was not dynamically allocated. |
|
||||||
|
+--------------------------------------------------+----------------------------------------------------------------------------+
|
||||||
|
| :enum:`return_value_policy::copy` | Create a new copy of the returned object, which will be owned by Python. |
|
||||||
|
| | This policy is comparably safe because the lifetimes of the two instances |
|
||||||
|
| | are decoupled. |
|
||||||
|
+--------------------------------------------------+----------------------------------------------------------------------------+
|
||||||
|
| :enum:`return_value_policy::move` | Use ``std::move`` to move the return value contents into a new instance |
|
||||||
|
| | that will be owned by Python. This policy is comparably safe because the |
|
||||||
|
| | lifetimes of the two instances (move source and destination) are decoupled.|
|
||||||
|
+--------------------------------------------------+----------------------------------------------------------------------------+
|
||||||
|
| :enum:`return_value_policy::reference` | Reference an existing object, but do not take ownership. The C++ side is |
|
||||||
|
| | responsible for managing the object's lifetime and deallocating it when |
|
||||||
|
| | it is no longer used. Warning: undefined behavior will ensue when the C++ |
|
||||||
|
| | side deletes an object that is still referenced and used by Python. |
|
||||||
|
+--------------------------------------------------+----------------------------------------------------------------------------+
|
||||||
|
| :enum:`return_value_policy::reference_internal` | Indicates that the lifetime of the return value is tied to the lifetime |
|
||||||
|
| | of a parent object, namely the implicit ``this``, or ``self`` argument of |
|
||||||
|
| | the called method or property. Internally, this policy works just like |
|
||||||
|
| | :enum:`return_value_policy::reference` but additionally applies a |
|
||||||
|
| | ``keep_alive<0, 1>`` *call policy* (described in the next section) that |
|
||||||
|
| | prevents the parent object from being garbage collected as long as the |
|
||||||
|
| | return value is referenced by Python. This is the default policy for |
|
||||||
|
| | property getters created via ``def_property``, ``def_readwrite``, etc. |
|
||||||
|
+--------------------------------------------------+----------------------------------------------------------------------------+
|
||||||
|
| :enum:`return_value_policy::automatic` | This policy falls back to the policy |
|
||||||
|
| | :enum:`return_value_policy::take_ownership` when the return value is a |
|
||||||
|
| | pointer. Otherwise, it uses :enum:`return_value_policy::move` or |
|
||||||
|
| | :enum:`return_value_policy::copy` for rvalue and lvalue references, |
|
||||||
|
| | respectively. See above for a description of what all of these different |
|
||||||
|
| | policies do. This is the default policy for ``py::class_``-wrapped types. |
|
||||||
|
+--------------------------------------------------+----------------------------------------------------------------------------+
|
||||||
|
| :enum:`return_value_policy::automatic_reference` | As above, but use policy :enum:`return_value_policy::reference` when the |
|
||||||
|
| | return value is a pointer. This is the default conversion policy for |
|
||||||
|
| | function arguments when calling Python functions manually from C++ code |
|
||||||
|
| | (i.e. via ``handle::operator()``) and the casters in ``pybind11/stl.h``. |
|
||||||
|
| | You probably won't need to use this explicitly. |
|
||||||
|
+--------------------------------------------------+----------------------------------------------------------------------------+
|
||||||
|
|
||||||
|
Return value policies can also be applied to properties:
|
||||||
|
|
||||||
|
.. code-block:: cpp
|
||||||
|
|
||||||
|
class_<MyClass>(m, "MyClass")
|
||||||
|
.def_property("data", &MyClass::getData, &MyClass::setData,
|
||||||
|
py::return_value_policy::copy);
|
||||||
|
|
||||||
|
Technically, the code above applies the policy to both the getter and the
|
||||||
|
setter function, however, the setter doesn't really care about *return*
|
||||||
|
value policies which makes this a convenient terse syntax. Alternatively,
|
||||||
|
targeted arguments can be passed through the :class:`cpp_function` constructor:
|
||||||
|
|
||||||
|
.. code-block:: cpp
|
||||||
|
|
||||||
|
class_<MyClass>(m, "MyClass")
|
||||||
|
.def_property("data",
|
||||||
|
py::cpp_function(&MyClass::getData, py::return_value_policy::copy),
|
||||||
|
py::cpp_function(&MyClass::setData)
|
||||||
|
);
|
||||||
|
|
||||||
|
.. warning::
|
||||||
|
|
||||||
|
Code with invalid return value policies might access uninitialized memory or
|
||||||
|
free data structures multiple times, which can lead to hard-to-debug
|
||||||
|
non-determinism and segmentation faults, hence it is worth spending the
|
||||||
|
time to understand all the different options in the table above.
|
||||||
|
|
||||||
|
.. note::
|
||||||
|
|
||||||
|
One important aspect of the above policies is that they only apply to
|
||||||
|
instances which pybind11 has *not* seen before, in which case the policy
|
||||||
|
clarifies essential questions about the return value's lifetime and
|
||||||
|
ownership. When pybind11 knows the instance already (as identified by its
|
||||||
|
type and address in memory), it will return the existing Python object
|
||||||
|
wrapper rather than creating a new copy.
|
||||||
|
|
||||||
|
.. note::
|
||||||
|
|
||||||
|
The next section on :ref:`call_policies` discusses *call policies* that can be
|
||||||
|
specified *in addition* to a return value policy from the list above. Call
|
||||||
|
policies indicate reference relationships that can involve both return values
|
||||||
|
and parameters of functions.
|
||||||
|
|
||||||
|
.. note::
|
||||||
|
|
||||||
|
As an alternative to elaborate call policies and lifetime management logic,
|
||||||
|
consider using smart pointers (see the section on :ref:`smart_pointers` for
|
||||||
|
details). Smart pointers can tell whether an object is still referenced from
|
||||||
|
C++ or Python, which generally eliminates the kinds of inconsistencies that
|
||||||
|
can lead to crashes or undefined behavior. For functions returning smart
|
||||||
|
pointers, it is not necessary to specify a return value policy.
|
||||||
|
|
||||||
|
.. _call_policies:
|
||||||
|
|
||||||
|
Additional call policies
|
||||||
|
========================
|
||||||
|
|
||||||
|
In addition to the above return value policies, further *call policies* can be
|
||||||
|
specified to indicate dependencies between parameters or ensure a certain state
|
||||||
|
for the function call.
|
||||||
|
|
||||||
|
Keep alive
|
||||||
|
----------
|
||||||
|
|
||||||
|
In general, this policy is required when the C++ object is any kind of container
|
||||||
|
and another object is being added to the container. ``keep_alive<Nurse, Patient>``
|
||||||
|
indicates that the argument with index ``Patient`` should be kept alive at least
|
||||||
|
until the argument with index ``Nurse`` is freed by the garbage collector. Argument
|
||||||
|
indices start at one, while zero refers to the return value. For methods, index
|
||||||
|
``1`` refers to the implicit ``this`` pointer, while regular arguments begin at
|
||||||
|
index ``2``. Arbitrarily many call policies can be specified. When a ``Nurse``
|
||||||
|
with value ``None`` is detected at runtime, the call policy does nothing.
|
||||||
|
|
||||||
|
When the nurse is not a pybind11-registered type, the implementation internally
|
||||||
|
relies on the ability to create a *weak reference* to the nurse object. When
|
||||||
|
the nurse object is not a pybind11-registered type and does not support weak
|
||||||
|
references, an exception will be thrown.
|
||||||
|
|
||||||
|
If you use an incorrect argument index, you will get a ``RuntimeError`` saying
|
||||||
|
``Could not activate keep_alive!``. You should review the indices you're using.
|
||||||
|
|
||||||
|
Consider the following example: here, the binding code for a list append
|
||||||
|
operation ties the lifetime of the newly added element to the underlying
|
||||||
|
container:
|
||||||
|
|
||||||
|
.. code-block:: cpp
|
||||||
|
|
||||||
|
py::class_<List>(m, "List")
|
||||||
|
.def("append", &List::append, py::keep_alive<1, 2>());
|
||||||
|
|
||||||
|
For consistency, the argument indexing is identical for constructors. Index
|
||||||
|
``1`` still refers to the implicit ``this`` pointer, i.e. the object which is
|
||||||
|
being constructed. Index ``0`` refers to the return type which is presumed to
|
||||||
|
be ``void`` when a constructor is viewed like a function. The following example
|
||||||
|
ties the lifetime of the constructor element to the constructed object:
|
||||||
|
|
||||||
|
.. code-block:: cpp
|
||||||
|
|
||||||
|
py::class_<Nurse>(m, "Nurse")
|
||||||
|
.def(py::init<Patient &>(), py::keep_alive<1, 2>());
|
||||||
|
|
||||||
|
.. note::
|
||||||
|
|
||||||
|
``keep_alive`` is analogous to the ``with_custodian_and_ward`` (if Nurse,
|
||||||
|
Patient != 0) and ``with_custodian_and_ward_postcall`` (if Nurse/Patient ==
|
||||||
|
0) policies from Boost.Python.
|
||||||
|
|
||||||
|
Call guard
|
||||||
|
----------
|
||||||
|
|
||||||
|
The ``call_guard<T>`` policy allows any scope guard type ``T`` to be placed
|
||||||
|
around the function call. For example, this definition:
|
||||||
|
|
||||||
|
.. code-block:: cpp
|
||||||
|
|
||||||
|
m.def("foo", foo, py::call_guard<T>());
|
||||||
|
|
||||||
|
is equivalent to the following pseudocode:
|
||||||
|
|
||||||
|
.. code-block:: cpp
|
||||||
|
|
||||||
|
m.def("foo", [](args...) {
|
||||||
|
T scope_guard;
|
||||||
|
return foo(args...); // forwarded arguments
|
||||||
|
});
|
||||||
|
|
||||||
|
The only requirement is that ``T`` is default-constructible, but otherwise any
|
||||||
|
scope guard will work. This is very useful in combination with ``gil_scoped_release``.
|
||||||
|
See :ref:`gil`.
|
||||||
|
|
||||||
|
Multiple guards can also be specified as ``py::call_guard<T1, T2, T3...>``. The
|
||||||
|
constructor order is left to right and destruction happens in reverse.
|
||||||
|
|
||||||
|
.. seealso::
|
||||||
|
|
||||||
|
The file :file:`tests/test_call_policies.cpp` contains a complete example
|
||||||
|
that demonstrates using `keep_alive` and `call_guard` in more detail.
|
||||||
|
|
||||||
|
.. _python_objects_as_args:
|
||||||
|
|
||||||
|
Python objects as arguments
|
||||||
|
===========================
|
||||||
|
|
||||||
|
pybind11 exposes all major Python types using thin C++ wrapper classes. These
|
||||||
|
wrapper classes can also be used as parameters of functions in bindings, which
|
||||||
|
makes it possible to directly work with native Python types on the C++ side.
|
||||||
|
For instance, the following statement iterates over a Python ``dict``:
|
||||||
|
|
||||||
|
.. code-block:: cpp
|
||||||
|
|
||||||
|
void print_dict(const py::dict& dict) {
|
||||||
|
/* Easily interact with Python types */
|
||||||
|
for (auto item : dict)
|
||||||
|
std::cout << "key=" << std::string(py::str(item.first)) << ", "
|
||||||
|
<< "value=" << std::string(py::str(item.second)) << std::endl;
|
||||||
|
}
|
||||||
|
|
||||||
|
It can be exported:
|
||||||
|
|
||||||
|
.. code-block:: cpp
|
||||||
|
|
||||||
|
m.def("print_dict", &print_dict);
|
||||||
|
|
||||||
|
And used in Python as usual:
|
||||||
|
|
||||||
|
.. code-block:: pycon
|
||||||
|
|
||||||
|
>>> print_dict({"foo": 123, "bar": "hello"})
|
||||||
|
key=foo, value=123
|
||||||
|
key=bar, value=hello
|
||||||
|
|
||||||
|
For more information on using Python objects in C++, see :doc:`/advanced/pycpp/index`.
|
||||||
|
|
||||||
|
Accepting \*args and \*\*kwargs
|
||||||
|
===============================
|
||||||
|
|
||||||
|
Python provides a useful mechanism to define functions that accept arbitrary
|
||||||
|
numbers of arguments and keyword arguments:
|
||||||
|
|
||||||
|
.. code-block:: python
|
||||||
|
|
||||||
|
def generic(*args, **kwargs):
|
||||||
|
... # do something with args and kwargs
|
||||||
|
|
||||||
|
Such functions can also be created using pybind11:
|
||||||
|
|
||||||
|
.. code-block:: cpp
|
||||||
|
|
||||||
|
void generic(py::args args, const py::kwargs& kwargs) {
|
||||||
|
/// .. do something with args
|
||||||
|
if (kwargs)
|
||||||
|
/// .. do something with kwargs
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Binding code
|
||||||
|
m.def("generic", &generic);
|
||||||
|
|
||||||
|
The class ``py::args`` derives from ``py::tuple`` and ``py::kwargs`` derives
|
||||||
|
from ``py::dict``.
|
||||||
|
|
||||||
|
You may also use just one or the other, and may combine these with other
|
||||||
|
arguments. Note, however, that ``py::kwargs`` must always be the last argument
|
||||||
|
of the function, and ``py::args`` implies that any further arguments are
|
||||||
|
keyword-only (see :ref:`keyword_only_arguments`).
|
||||||
|
|
||||||
|
Please refer to the other examples for details on how to iterate over these,
|
||||||
|
and on how to cast their entries into C++ objects. A demonstration is also
|
||||||
|
available in ``tests/test_kwargs_and_defaults.cpp``.
|
||||||
|
|
||||||
|
.. note::
|
||||||
|
|
||||||
|
When combining \*args or \*\*kwargs with :ref:`keyword_args` you should
|
||||||
|
*not* include ``py::arg`` tags for the ``py::args`` and ``py::kwargs``
|
||||||
|
arguments.
|
||||||
|
|
||||||
|
Default arguments revisited
|
||||||
|
===========================
|
||||||
|
|
||||||
|
The section on :ref:`default_args` previously discussed basic usage of default
|
||||||
|
arguments using pybind11. One noteworthy aspect of their implementation is that
|
||||||
|
default arguments are converted to Python objects right at declaration time.
|
||||||
|
Consider the following example:
|
||||||
|
|
||||||
|
.. code-block:: cpp
|
||||||
|
|
||||||
|
py::class_<MyClass>("MyClass")
|
||||||
|
.def("myFunction", py::arg("arg") = SomeType(123));
|
||||||
|
|
||||||
|
In this case, pybind11 must already be set up to deal with values of the type
|
||||||
|
``SomeType`` (via a prior instantiation of ``py::class_<SomeType>``), or an
|
||||||
|
exception will be thrown.
|
||||||
|
|
||||||
|
Another aspect worth highlighting is that the "preview" of the default argument
|
||||||
|
in the function signature is generated using the object's ``__repr__`` method.
|
||||||
|
If not available, the signature may not be very helpful, e.g.:
|
||||||
|
|
||||||
|
.. code-block:: pycon
|
||||||
|
|
||||||
|
FUNCTIONS
|
||||||
|
...
|
||||||
|
| myFunction(...)
|
||||||
|
| Signature : (MyClass, arg : SomeType = <SomeType object at 0x101b7b080>) -> NoneType
|
||||||
|
...
|
||||||
|
|
||||||
|
The first way of addressing this is by defining ``SomeType.__repr__``.
|
||||||
|
Alternatively, it is possible to specify the human-readable preview of the
|
||||||
|
default argument manually using the ``arg_v`` notation:
|
||||||
|
|
||||||
|
.. code-block:: cpp
|
||||||
|
|
||||||
|
py::class_<MyClass>("MyClass")
|
||||||
|
.def("myFunction", py::arg_v("arg", SomeType(123), "SomeType(123)"));
|
||||||
|
|
||||||
|
Sometimes it may be necessary to pass a null pointer value as a default
|
||||||
|
argument. In this case, remember to cast it to the underlying type in question,
|
||||||
|
like so:
|
||||||
|
|
||||||
|
.. code-block:: cpp
|
||||||
|
|
||||||
|
py::class_<MyClass>("MyClass")
|
||||||
|
.def("myFunction", py::arg("arg") = static_cast<SomeType *>(nullptr));
|
||||||
|
|
||||||
|
.. _keyword_only_arguments:
|
||||||
|
|
||||||
|
Keyword-only arguments
|
||||||
|
======================
|
||||||
|
|
||||||
|
Python implements keyword-only arguments by specifying an unnamed ``*``
|
||||||
|
argument in a function definition:
|
||||||
|
|
||||||
|
.. code-block:: python
|
||||||
|
|
||||||
|
def f(a, *, b): # a can be positional or via keyword; b must be via keyword
|
||||||
|
pass
|
||||||
|
|
||||||
|
|
||||||
|
f(a=1, b=2) # good
|
||||||
|
f(b=2, a=1) # good
|
||||||
|
f(1, b=2) # good
|
||||||
|
f(1, 2) # TypeError: f() takes 1 positional argument but 2 were given
|
||||||
|
|
||||||
|
Pybind11 provides a ``py::kw_only`` object that allows you to implement
|
||||||
|
the same behaviour by specifying the object between positional and keyword-only
|
||||||
|
argument annotations when registering the function:
|
||||||
|
|
||||||
|
.. code-block:: cpp
|
||||||
|
|
||||||
|
m.def("f", [](int a, int b) { /* ... */ },
|
||||||
|
py::arg("a"), py::kw_only(), py::arg("b"));
|
||||||
|
|
||||||
|
.. versionadded:: 2.6
|
||||||
|
|
||||||
|
A ``py::args`` argument implies that any following arguments are keyword-only,
|
||||||
|
as if ``py::kw_only()`` had been specified in the same relative location of the
|
||||||
|
argument list as the ``py::args`` argument. The ``py::kw_only()`` may be
|
||||||
|
included to be explicit about this, but is not required.
|
||||||
|
|
||||||
|
.. versionchanged:: 2.9
|
||||||
|
This can now be combined with ``py::args``. Before, ``py::args`` could only
|
||||||
|
occur at the end of the argument list, or immediately before a ``py::kwargs``
|
||||||
|
argument at the end.
|
||||||
|
|
||||||
|
|
||||||
|
Positional-only arguments
|
||||||
|
=========================
|
||||||
|
|
||||||
|
Python 3.8 introduced a new positional-only argument syntax, using ``/`` in the
|
||||||
|
function definition (note that this has been a convention for CPython
|
||||||
|
positional arguments, such as in ``pow()``, since Python 2). You can
|
||||||
|
do the same thing in any version of Python using ``py::pos_only()``:
|
||||||
|
|
||||||
|
.. code-block:: cpp
|
||||||
|
|
||||||
|
m.def("f", [](int a, int b) { /* ... */ },
|
||||||
|
py::arg("a"), py::pos_only(), py::arg("b"));
|
||||||
|
|
||||||
|
You now cannot give argument ``a`` by keyword. This can be combined with
|
||||||
|
keyword-only arguments, as well.
|
||||||
|
|
||||||
|
.. versionadded:: 2.6
|
||||||
|
|
||||||
|
.. _nonconverting_arguments:
|
||||||
|
|
||||||
|
Non-converting arguments
|
||||||
|
========================
|
||||||
|
|
||||||
|
Certain argument types may support conversion from one type to another. Some
|
||||||
|
examples of conversions are:
|
||||||
|
|
||||||
|
* :ref:`implicit_conversions` declared using ``py::implicitly_convertible<A,B>()``
|
||||||
|
* Calling a method accepting a double with an integer argument
|
||||||
|
* Calling a ``std::complex<float>`` argument with a non-complex python type
|
||||||
|
(for example, with a float). (Requires the optional ``pybind11/complex.h``
|
||||||
|
header).
|
||||||
|
* Calling a function taking an Eigen matrix reference with a numpy array of the
|
||||||
|
wrong type or of an incompatible data layout. (Requires the optional
|
||||||
|
``pybind11/eigen.h`` header).
|
||||||
|
|
||||||
|
This behaviour is sometimes undesirable: the binding code may prefer to raise
|
||||||
|
an error rather than convert the argument. This behaviour can be obtained
|
||||||
|
through ``py::arg`` by calling the ``.noconvert()`` method of the ``py::arg``
|
||||||
|
object, such as:
|
||||||
|
|
||||||
|
.. code-block:: cpp
|
||||||
|
|
||||||
|
m.def("floats_only", [](double f) { return 0.5 * f; }, py::arg("f").noconvert());
|
||||||
|
m.def("floats_preferred", [](double f) { return 0.5 * f; }, py::arg("f"));
|
||||||
|
|
||||||
|
Attempting the call the second function (the one without ``.noconvert()``) with
|
||||||
|
an integer will succeed, but attempting to call the ``.noconvert()`` version
|
||||||
|
will fail with a ``TypeError``:
|
||||||
|
|
||||||
|
.. code-block:: pycon
|
||||||
|
|
||||||
|
>>> floats_preferred(4)
|
||||||
|
2.0
|
||||||
|
>>> floats_only(4)
|
||||||
|
Traceback (most recent call last):
|
||||||
|
File "<stdin>", line 1, in <module>
|
||||||
|
TypeError: floats_only(): incompatible function arguments. The following argument types are supported:
|
||||||
|
1. (f: float) -> float
|
||||||
|
|
||||||
|
Invoked with: 4
|
||||||
|
|
||||||
|
You may, of course, combine this with the :var:`_a` shorthand notation (see
|
||||||
|
:ref:`keyword_args`) and/or :ref:`default_args`. It is also permitted to omit
|
||||||
|
the argument name by using the ``py::arg()`` constructor without an argument
|
||||||
|
name, i.e. by specifying ``py::arg().noconvert()``.
|
||||||
|
|
||||||
|
.. note::
|
||||||
|
|
||||||
|
When specifying ``py::arg`` options it is necessary to provide the same
|
||||||
|
number of options as the bound function has arguments. Thus if you want to
|
||||||
|
enable no-convert behaviour for just one of several arguments, you will
|
||||||
|
need to specify a ``py::arg()`` annotation for each argument with the
|
||||||
|
no-convert argument modified to ``py::arg().noconvert()``.
|
||||||
|
|
||||||
|
.. _none_arguments:
|
||||||
|
|
||||||
|
Allow/Prohibiting None arguments
|
||||||
|
================================
|
||||||
|
|
||||||
|
When a C++ type registered with :class:`py::class_` is passed as an argument to
|
||||||
|
a function taking the instance as pointer or shared holder (e.g. ``shared_ptr``
|
||||||
|
or a custom, copyable holder as described in :ref:`smart_pointers`), pybind
|
||||||
|
allows ``None`` to be passed from Python which results in calling the C++
|
||||||
|
function with ``nullptr`` (or an empty holder) for the argument.
|
||||||
|
|
||||||
|
To explicitly enable or disable this behaviour, using the
|
||||||
|
``.none`` method of the :class:`py::arg` object:
|
||||||
|
|
||||||
|
.. code-block:: cpp
|
||||||
|
|
||||||
|
py::class_<Dog>(m, "Dog").def(py::init<>());
|
||||||
|
py::class_<Cat>(m, "Cat").def(py::init<>());
|
||||||
|
m.def("bark", [](Dog *dog) -> std::string {
|
||||||
|
if (dog) return "woof!"; /* Called with a Dog instance */
|
||||||
|
else return "(no dog)"; /* Called with None, dog == nullptr */
|
||||||
|
}, py::arg("dog").none(true));
|
||||||
|
m.def("meow", [](Cat *cat) -> std::string {
|
||||||
|
// Can't be called with None argument
|
||||||
|
return "meow";
|
||||||
|
}, py::arg("cat").none(false));
|
||||||
|
|
||||||
|
With the above, the Python call ``bark(None)`` will return the string ``"(no
|
||||||
|
dog)"``, while attempting to call ``meow(None)`` will raise a ``TypeError``:
|
||||||
|
|
||||||
|
.. code-block:: pycon
|
||||||
|
|
||||||
|
>>> from animals import Dog, Cat, bark, meow
|
||||||
|
>>> bark(Dog())
|
||||||
|
'woof!'
|
||||||
|
>>> meow(Cat())
|
||||||
|
'meow'
|
||||||
|
>>> bark(None)
|
||||||
|
'(no dog)'
|
||||||
|
>>> meow(None)
|
||||||
|
Traceback (most recent call last):
|
||||||
|
File "<stdin>", line 1, in <module>
|
||||||
|
TypeError: meow(): incompatible function arguments. The following argument types are supported:
|
||||||
|
1. (cat: animals.Cat) -> str
|
||||||
|
|
||||||
|
Invoked with: None
|
||||||
|
|
||||||
|
The default behaviour when the tag is unspecified is to allow ``None``.
|
||||||
|
|
||||||
|
.. note::
|
||||||
|
|
||||||
|
Even when ``.none(true)`` is specified for an argument, ``None`` will be converted to a
|
||||||
|
``nullptr`` *only* for custom and :ref:`opaque <opaque>` types. Pointers to built-in types
|
||||||
|
(``double *``, ``int *``, ...) and STL types (``std::vector<T> *``, ...; if ``pybind11/stl.h``
|
||||||
|
is included) are copied when converted to C++ (see :doc:`/advanced/cast/overview`) and will
|
||||||
|
not allow ``None`` as argument. To pass optional argument of these copied types consider
|
||||||
|
using ``std::optional<T>``
|
||||||
|
|
||||||
|
.. _overload_resolution:
|
||||||
|
|
||||||
|
Overload resolution order
|
||||||
|
=========================
|
||||||
|
|
||||||
|
When a function or method with multiple overloads is called from Python,
|
||||||
|
pybind11 determines which overload to call in two passes. The first pass
|
||||||
|
attempts to call each overload without allowing argument conversion (as if
|
||||||
|
every argument had been specified as ``py::arg().noconvert()`` as described
|
||||||
|
above).
|
||||||
|
|
||||||
|
If no overload succeeds in the no-conversion first pass, a second pass is
|
||||||
|
attempted in which argument conversion is allowed (except where prohibited via
|
||||||
|
an explicit ``py::arg().noconvert()`` attribute in the function definition).
|
||||||
|
|
||||||
|
If the second pass also fails a ``TypeError`` is raised.
|
||||||
|
|
||||||
|
Within each pass, overloads are tried in the order they were registered with
|
||||||
|
pybind11. If the ``py::prepend()`` tag is added to the definition, a function
|
||||||
|
can be placed at the beginning of the overload sequence instead, allowing user
|
||||||
|
overloads to proceed built in functions.
|
||||||
|
|
||||||
|
What this means in practice is that pybind11 will prefer any overload that does
|
||||||
|
not require conversion of arguments to an overload that does, but otherwise
|
||||||
|
prefers earlier-defined overloads to later-defined ones.
|
||||||
|
|
||||||
|
.. note::
|
||||||
|
|
||||||
|
pybind11 does *not* further prioritize based on the number/pattern of
|
||||||
|
overloaded arguments. That is, pybind11 does not prioritize a function
|
||||||
|
requiring one conversion over one requiring three, but only prioritizes
|
||||||
|
overloads requiring no conversion at all to overloads that require
|
||||||
|
conversion of at least one argument.
|
||||||
|
|
||||||
|
.. versionadded:: 2.6
|
||||||
|
|
||||||
|
The ``py::prepend()`` tag.
|
||||||
|
|
||||||
|
Binding functions with template parameters
|
||||||
|
==========================================
|
||||||
|
|
||||||
|
You can bind functions that have template parameters. Here's a function:
|
||||||
|
|
||||||
|
.. code-block:: cpp
|
||||||
|
|
||||||
|
template <typename T>
|
||||||
|
void set(T t);
|
||||||
|
|
||||||
|
C++ templates cannot be instantiated at runtime, so you cannot bind the
|
||||||
|
non-instantiated function:
|
||||||
|
|
||||||
|
.. code-block:: cpp
|
||||||
|
|
||||||
|
// BROKEN (this will not compile)
|
||||||
|
m.def("set", &set);
|
||||||
|
|
||||||
|
You must bind each instantiated function template separately. You may bind
|
||||||
|
each instantiation with the same name, which will be treated the same as
|
||||||
|
an overloaded function:
|
||||||
|
|
||||||
|
.. code-block:: cpp
|
||||||
|
|
||||||
|
m.def("set", &set<int>);
|
||||||
|
m.def("set", &set<std::string>);
|
||||||
|
|
||||||
|
Sometimes it's more clear to bind them with separate names, which is also
|
||||||
|
an option:
|
||||||
|
|
||||||
|
.. code-block:: cpp
|
||||||
|
|
||||||
|
m.def("setInt", &set<int>);
|
||||||
|
m.def("setString", &set<std::string>);
|
429
3rdparty/pybind11/docs/advanced/misc.rst
vendored
Normal file
429
3rdparty/pybind11/docs/advanced/misc.rst
vendored
Normal file
@ -0,0 +1,429 @@
|
|||||||
|
Miscellaneous
|
||||||
|
#############
|
||||||
|
|
||||||
|
.. _macro_notes:
|
||||||
|
|
||||||
|
General notes regarding convenience macros
|
||||||
|
==========================================
|
||||||
|
|
||||||
|
pybind11 provides a few convenience macros such as
|
||||||
|
:func:`PYBIND11_DECLARE_HOLDER_TYPE` and ``PYBIND11_OVERRIDE_*``. Since these
|
||||||
|
are "just" macros that are evaluated in the preprocessor (which has no concept
|
||||||
|
of types), they *will* get confused by commas in a template argument; for
|
||||||
|
example, consider:
|
||||||
|
|
||||||
|
.. code-block:: cpp
|
||||||
|
|
||||||
|
PYBIND11_OVERRIDE(MyReturnType<T1, T2>, Class<T3, T4>, func)
|
||||||
|
|
||||||
|
The limitation of the C preprocessor interprets this as five arguments (with new
|
||||||
|
arguments beginning after each comma) rather than three. To get around this,
|
||||||
|
there are two alternatives: you can use a type alias, or you can wrap the type
|
||||||
|
using the ``PYBIND11_TYPE`` macro:
|
||||||
|
|
||||||
|
.. code-block:: cpp
|
||||||
|
|
||||||
|
// Version 1: using a type alias
|
||||||
|
using ReturnType = MyReturnType<T1, T2>;
|
||||||
|
using ClassType = Class<T3, T4>;
|
||||||
|
PYBIND11_OVERRIDE(ReturnType, ClassType, func);
|
||||||
|
|
||||||
|
// Version 2: using the PYBIND11_TYPE macro:
|
||||||
|
PYBIND11_OVERRIDE(PYBIND11_TYPE(MyReturnType<T1, T2>),
|
||||||
|
PYBIND11_TYPE(Class<T3, T4>), func)
|
||||||
|
|
||||||
|
The ``PYBIND11_MAKE_OPAQUE`` macro does *not* require the above workarounds.
|
||||||
|
|
||||||
|
.. _gil:
|
||||||
|
|
||||||
|
Global Interpreter Lock (GIL)
|
||||||
|
=============================
|
||||||
|
|
||||||
|
The Python C API dictates that the Global Interpreter Lock (GIL) must always
|
||||||
|
be held by the current thread to safely access Python objects. As a result,
|
||||||
|
when Python calls into C++ via pybind11 the GIL must be held, and pybind11
|
||||||
|
will never implicitly release the GIL.
|
||||||
|
|
||||||
|
.. code-block:: cpp
|
||||||
|
|
||||||
|
void my_function() {
|
||||||
|
/* GIL is held when this function is called from Python */
|
||||||
|
}
|
||||||
|
|
||||||
|
PYBIND11_MODULE(example, m) {
|
||||||
|
m.def("my_function", &my_function);
|
||||||
|
}
|
||||||
|
|
||||||
|
pybind11 will ensure that the GIL is held when it knows that it is calling
|
||||||
|
Python code. For example, if a Python callback is passed to C++ code via
|
||||||
|
``std::function``, when C++ code calls the function the built-in wrapper
|
||||||
|
will acquire the GIL before calling the Python callback. Similarly, the
|
||||||
|
``PYBIND11_OVERRIDE`` family of macros will acquire the GIL before calling
|
||||||
|
back into Python.
|
||||||
|
|
||||||
|
When writing C++ code that is called from other C++ code, if that code accesses
|
||||||
|
Python state, it must explicitly acquire and release the GIL.
|
||||||
|
|
||||||
|
The classes :class:`gil_scoped_release` and :class:`gil_scoped_acquire` can be
|
||||||
|
used to acquire and release the global interpreter lock in the body of a C++
|
||||||
|
function call. In this way, long-running C++ code can be parallelized using
|
||||||
|
multiple Python threads, **but great care must be taken** when any
|
||||||
|
:class:`gil_scoped_release` appear: if there is any way that the C++ code
|
||||||
|
can access Python objects, :class:`gil_scoped_acquire` should be used to
|
||||||
|
reacquire the GIL. Taking :ref:`overriding_virtuals` as an example, this
|
||||||
|
could be realized as follows (important changes highlighted):
|
||||||
|
|
||||||
|
.. code-block:: cpp
|
||||||
|
:emphasize-lines: 8,30,31
|
||||||
|
|
||||||
|
class PyAnimal : public Animal {
|
||||||
|
public:
|
||||||
|
/* Inherit the constructors */
|
||||||
|
using Animal::Animal;
|
||||||
|
|
||||||
|
/* Trampoline (need one for each virtual function) */
|
||||||
|
std::string go(int n_times) {
|
||||||
|
/* PYBIND11_OVERRIDE_PURE will acquire the GIL before accessing Python state */
|
||||||
|
PYBIND11_OVERRIDE_PURE(
|
||||||
|
std::string, /* Return type */
|
||||||
|
Animal, /* Parent class */
|
||||||
|
go, /* Name of function */
|
||||||
|
n_times /* Argument(s) */
|
||||||
|
);
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
PYBIND11_MODULE(example, m) {
|
||||||
|
py::class_<Animal, PyAnimal> animal(m, "Animal");
|
||||||
|
animal
|
||||||
|
.def(py::init<>())
|
||||||
|
.def("go", &Animal::go);
|
||||||
|
|
||||||
|
py::class_<Dog>(m, "Dog", animal)
|
||||||
|
.def(py::init<>());
|
||||||
|
|
||||||
|
m.def("call_go", [](Animal *animal) -> std::string {
|
||||||
|
// GIL is held when called from Python code. Release GIL before
|
||||||
|
// calling into (potentially long-running) C++ code
|
||||||
|
py::gil_scoped_release release;
|
||||||
|
return call_go(animal);
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
The ``call_go`` wrapper can also be simplified using the ``call_guard`` policy
|
||||||
|
(see :ref:`call_policies`) which yields the same result:
|
||||||
|
|
||||||
|
.. code-block:: cpp
|
||||||
|
|
||||||
|
m.def("call_go", &call_go, py::call_guard<py::gil_scoped_release>());
|
||||||
|
|
||||||
|
|
||||||
|
Common Sources Of Global Interpreter Lock Errors
|
||||||
|
==================================================================
|
||||||
|
|
||||||
|
Failing to properly hold the Global Interpreter Lock (GIL) is one of the
|
||||||
|
more common sources of bugs within code that uses pybind11. If you are
|
||||||
|
running into GIL related errors, we highly recommend you consult the
|
||||||
|
following checklist.
|
||||||
|
|
||||||
|
- Do you have any global variables that are pybind11 objects or invoke
|
||||||
|
pybind11 functions in either their constructor or destructor? You are generally
|
||||||
|
not allowed to invoke any Python function in a global static context. We recommend
|
||||||
|
using lazy initialization and then intentionally leaking at the end of the program.
|
||||||
|
|
||||||
|
- Do you have any pybind11 objects that are members of other C++ structures? One
|
||||||
|
commonly overlooked requirement is that pybind11 objects have to increase their reference count
|
||||||
|
whenever their copy constructor is called. Thus, you need to be holding the GIL to invoke
|
||||||
|
the copy constructor of any C++ class that has a pybind11 member. This can sometimes be very
|
||||||
|
tricky to track for complicated programs Think carefully when you make a pybind11 object
|
||||||
|
a member in another struct.
|
||||||
|
|
||||||
|
- C++ destructors that invoke Python functions can be particularly troublesome as
|
||||||
|
destructors can sometimes get invoked in weird and unexpected circumstances as a result
|
||||||
|
of exceptions.
|
||||||
|
|
||||||
|
- You should try running your code in a debug build. That will enable additional assertions
|
||||||
|
within pybind11 that will throw exceptions on certain GIL handling errors
|
||||||
|
(reference counting operations).
|
||||||
|
|
||||||
|
Binding sequence data types, iterators, the slicing protocol, etc.
|
||||||
|
==================================================================
|
||||||
|
|
||||||
|
Please refer to the supplemental example for details.
|
||||||
|
|
||||||
|
.. seealso::
|
||||||
|
|
||||||
|
The file :file:`tests/test_sequences_and_iterators.cpp` contains a
|
||||||
|
complete example that shows how to bind a sequence data type, including
|
||||||
|
length queries (``__len__``), iterators (``__iter__``), the slicing
|
||||||
|
protocol and other kinds of useful operations.
|
||||||
|
|
||||||
|
|
||||||
|
Partitioning code over multiple extension modules
|
||||||
|
=================================================
|
||||||
|
|
||||||
|
It's straightforward to split binding code over multiple extension modules,
|
||||||
|
while referencing types that are declared elsewhere. Everything "just" works
|
||||||
|
without any special precautions. One exception to this rule occurs when
|
||||||
|
extending a type declared in another extension module. Recall the basic example
|
||||||
|
from Section :ref:`inheritance`.
|
||||||
|
|
||||||
|
.. code-block:: cpp
|
||||||
|
|
||||||
|
py::class_<Pet> pet(m, "Pet");
|
||||||
|
pet.def(py::init<const std::string &>())
|
||||||
|
.def_readwrite("name", &Pet::name);
|
||||||
|
|
||||||
|
py::class_<Dog>(m, "Dog", pet /* <- specify parent */)
|
||||||
|
.def(py::init<const std::string &>())
|
||||||
|
.def("bark", &Dog::bark);
|
||||||
|
|
||||||
|
Suppose now that ``Pet`` bindings are defined in a module named ``basic``,
|
||||||
|
whereas the ``Dog`` bindings are defined somewhere else. The challenge is of
|
||||||
|
course that the variable ``pet`` is not available anymore though it is needed
|
||||||
|
to indicate the inheritance relationship to the constructor of ``class_<Dog>``.
|
||||||
|
However, it can be acquired as follows:
|
||||||
|
|
||||||
|
.. code-block:: cpp
|
||||||
|
|
||||||
|
py::object pet = (py::object) py::module_::import("basic").attr("Pet");
|
||||||
|
|
||||||
|
py::class_<Dog>(m, "Dog", pet)
|
||||||
|
.def(py::init<const std::string &>())
|
||||||
|
.def("bark", &Dog::bark);
|
||||||
|
|
||||||
|
Alternatively, you can specify the base class as a template parameter option to
|
||||||
|
``class_``, which performs an automated lookup of the corresponding Python
|
||||||
|
type. Like the above code, however, this also requires invoking the ``import``
|
||||||
|
function once to ensure that the pybind11 binding code of the module ``basic``
|
||||||
|
has been executed:
|
||||||
|
|
||||||
|
.. code-block:: cpp
|
||||||
|
|
||||||
|
py::module_::import("basic");
|
||||||
|
|
||||||
|
py::class_<Dog, Pet>(m, "Dog")
|
||||||
|
.def(py::init<const std::string &>())
|
||||||
|
.def("bark", &Dog::bark);
|
||||||
|
|
||||||
|
Naturally, both methods will fail when there are cyclic dependencies.
|
||||||
|
|
||||||
|
Note that pybind11 code compiled with hidden-by-default symbol visibility (e.g.
|
||||||
|
via the command line flag ``-fvisibility=hidden`` on GCC/Clang), which is
|
||||||
|
required for proper pybind11 functionality, can interfere with the ability to
|
||||||
|
access types defined in another extension module. Working around this requires
|
||||||
|
manually exporting types that are accessed by multiple extension modules;
|
||||||
|
pybind11 provides a macro to do just this:
|
||||||
|
|
||||||
|
.. code-block:: cpp
|
||||||
|
|
||||||
|
class PYBIND11_EXPORT Dog : public Animal {
|
||||||
|
...
|
||||||
|
};
|
||||||
|
|
||||||
|
Note also that it is possible (although would rarely be required) to share arbitrary
|
||||||
|
C++ objects between extension modules at runtime. Internal library data is shared
|
||||||
|
between modules using capsule machinery [#f6]_ which can be also utilized for
|
||||||
|
storing, modifying and accessing user-defined data. Note that an extension module
|
||||||
|
will "see" other extensions' data if and only if they were built with the same
|
||||||
|
pybind11 version. Consider the following example:
|
||||||
|
|
||||||
|
.. code-block:: cpp
|
||||||
|
|
||||||
|
auto data = reinterpret_cast<MyData *>(py::get_shared_data("mydata"));
|
||||||
|
if (!data)
|
||||||
|
data = static_cast<MyData *>(py::set_shared_data("mydata", new MyData(42)));
|
||||||
|
|
||||||
|
If the above snippet was used in several separately compiled extension modules,
|
||||||
|
the first one to be imported would create a ``MyData`` instance and associate
|
||||||
|
a ``"mydata"`` key with a pointer to it. Extensions that are imported later
|
||||||
|
would be then able to access the data behind the same pointer.
|
||||||
|
|
||||||
|
.. [#f6] https://docs.python.org/3/extending/extending.html#using-capsules
|
||||||
|
|
||||||
|
Module Destructors
|
||||||
|
==================
|
||||||
|
|
||||||
|
pybind11 does not provide an explicit mechanism to invoke cleanup code at
|
||||||
|
module destruction time. In rare cases where such functionality is required, it
|
||||||
|
is possible to emulate it using Python capsules or weak references with a
|
||||||
|
destruction callback.
|
||||||
|
|
||||||
|
.. code-block:: cpp
|
||||||
|
|
||||||
|
auto cleanup_callback = []() {
|
||||||
|
// perform cleanup here -- this function is called with the GIL held
|
||||||
|
};
|
||||||
|
|
||||||
|
m.add_object("_cleanup", py::capsule(cleanup_callback));
|
||||||
|
|
||||||
|
This approach has the potential downside that instances of classes exposed
|
||||||
|
within the module may still be alive when the cleanup callback is invoked
|
||||||
|
(whether this is acceptable will generally depend on the application).
|
||||||
|
|
||||||
|
Alternatively, the capsule may also be stashed within a type object, which
|
||||||
|
ensures that it not called before all instances of that type have been
|
||||||
|
collected:
|
||||||
|
|
||||||
|
.. code-block:: cpp
|
||||||
|
|
||||||
|
auto cleanup_callback = []() { /* ... */ };
|
||||||
|
m.attr("BaseClass").attr("_cleanup") = py::capsule(cleanup_callback);
|
||||||
|
|
||||||
|
Both approaches also expose a potentially dangerous ``_cleanup`` attribute in
|
||||||
|
Python, which may be undesirable from an API standpoint (a premature explicit
|
||||||
|
call from Python might lead to undefined behavior). Yet another approach that
|
||||||
|
avoids this issue involves weak reference with a cleanup callback:
|
||||||
|
|
||||||
|
.. code-block:: cpp
|
||||||
|
|
||||||
|
// Register a callback function that is invoked when the BaseClass object is collected
|
||||||
|
py::cpp_function cleanup_callback(
|
||||||
|
[](py::handle weakref) {
|
||||||
|
// perform cleanup here -- this function is called with the GIL held
|
||||||
|
|
||||||
|
weakref.dec_ref(); // release weak reference
|
||||||
|
}
|
||||||
|
);
|
||||||
|
|
||||||
|
// Create a weak reference with a cleanup callback and initially leak it
|
||||||
|
(void) py::weakref(m.attr("BaseClass"), cleanup_callback).release();
|
||||||
|
|
||||||
|
.. note::
|
||||||
|
|
||||||
|
PyPy does not garbage collect objects when the interpreter exits. An alternative
|
||||||
|
approach (which also works on CPython) is to use the :py:mod:`atexit` module [#f7]_,
|
||||||
|
for example:
|
||||||
|
|
||||||
|
.. code-block:: cpp
|
||||||
|
|
||||||
|
auto atexit = py::module_::import("atexit");
|
||||||
|
atexit.attr("register")(py::cpp_function([]() {
|
||||||
|
// perform cleanup here -- this function is called with the GIL held
|
||||||
|
}));
|
||||||
|
|
||||||
|
.. [#f7] https://docs.python.org/3/library/atexit.html
|
||||||
|
|
||||||
|
|
||||||
|
Generating documentation using Sphinx
|
||||||
|
=====================================
|
||||||
|
|
||||||
|
Sphinx [#f4]_ has the ability to inspect the signatures and documentation
|
||||||
|
strings in pybind11-based extension modules to automatically generate beautiful
|
||||||
|
documentation in a variety formats. The python_example repository [#f5]_ contains a
|
||||||
|
simple example repository which uses this approach.
|
||||||
|
|
||||||
|
There are two potential gotchas when using this approach: first, make sure that
|
||||||
|
the resulting strings do not contain any :kbd:`TAB` characters, which break the
|
||||||
|
docstring parsing routines. You may want to use C++11 raw string literals,
|
||||||
|
which are convenient for multi-line comments. Conveniently, any excess
|
||||||
|
indentation will be automatically be removed by Sphinx. However, for this to
|
||||||
|
work, it is important that all lines are indented consistently, i.e.:
|
||||||
|
|
||||||
|
.. code-block:: cpp
|
||||||
|
|
||||||
|
// ok
|
||||||
|
m.def("foo", &foo, R"mydelimiter(
|
||||||
|
The foo function
|
||||||
|
|
||||||
|
Parameters
|
||||||
|
----------
|
||||||
|
)mydelimiter");
|
||||||
|
|
||||||
|
// *not ok*
|
||||||
|
m.def("foo", &foo, R"mydelimiter(The foo function
|
||||||
|
|
||||||
|
Parameters
|
||||||
|
----------
|
||||||
|
)mydelimiter");
|
||||||
|
|
||||||
|
By default, pybind11 automatically generates and prepends a signature to the docstring of a function
|
||||||
|
registered with ``module_::def()`` and ``class_::def()``. Sometimes this
|
||||||
|
behavior is not desirable, because you want to provide your own signature or remove
|
||||||
|
the docstring completely to exclude the function from the Sphinx documentation.
|
||||||
|
The class ``options`` allows you to selectively suppress auto-generated signatures:
|
||||||
|
|
||||||
|
.. code-block:: cpp
|
||||||
|
|
||||||
|
PYBIND11_MODULE(example, m) {
|
||||||
|
py::options options;
|
||||||
|
options.disable_function_signatures();
|
||||||
|
|
||||||
|
m.def("add", [](int a, int b) { return a + b; }, "A function which adds two numbers");
|
||||||
|
}
|
||||||
|
|
||||||
|
pybind11 also appends all members of an enum to the resulting enum docstring.
|
||||||
|
This default behavior can be disabled by using the ``disable_enum_members_docstring()``
|
||||||
|
function of the ``options`` class.
|
||||||
|
|
||||||
|
With ``disable_user_defined_docstrings()`` all user defined docstrings of
|
||||||
|
``module_::def()``, ``class_::def()`` and ``enum_()`` are disabled, but the
|
||||||
|
function signatures and enum members are included in the docstring, unless they
|
||||||
|
are disabled separately.
|
||||||
|
|
||||||
|
Note that changes to the settings affect only function bindings created during the
|
||||||
|
lifetime of the ``options`` instance. When it goes out of scope at the end of the module's init function,
|
||||||
|
the default settings are restored to prevent unwanted side effects.
|
||||||
|
|
||||||
|
.. [#f4] http://www.sphinx-doc.org
|
||||||
|
.. [#f5] http://github.com/pybind/python_example
|
||||||
|
|
||||||
|
.. _avoiding-cpp-types-in-docstrings:
|
||||||
|
|
||||||
|
Avoiding C++ types in docstrings
|
||||||
|
================================
|
||||||
|
|
||||||
|
Docstrings are generated at the time of the declaration, e.g. when ``.def(...)`` is called.
|
||||||
|
At this point parameter and return types should be known to pybind11.
|
||||||
|
If a custom type is not exposed yet through a ``py::class_`` constructor or a custom type caster,
|
||||||
|
its C++ type name will be used instead to generate the signature in the docstring:
|
||||||
|
|
||||||
|
.. code-block:: text
|
||||||
|
|
||||||
|
| __init__(...)
|
||||||
|
| __init__(self: example.Foo, arg0: ns::Bar) -> None
|
||||||
|
^^^^^^^
|
||||||
|
|
||||||
|
|
||||||
|
This limitation can be circumvented by ensuring that C++ classes are registered with pybind11
|
||||||
|
before they are used as a parameter or return type of a function:
|
||||||
|
|
||||||
|
.. code-block:: cpp
|
||||||
|
|
||||||
|
PYBIND11_MODULE(example, m) {
|
||||||
|
|
||||||
|
auto pyFoo = py::class_<ns::Foo>(m, "Foo");
|
||||||
|
auto pyBar = py::class_<ns::Bar>(m, "Bar");
|
||||||
|
|
||||||
|
pyFoo.def(py::init<const ns::Bar&>());
|
||||||
|
pyBar.def(py::init<const ns::Foo&>());
|
||||||
|
}
|
||||||
|
|
||||||
|
Setting inner type hints in docstrings
|
||||||
|
======================================
|
||||||
|
|
||||||
|
When you use pybind11 wrappers for ``list``, ``dict``, and other generic python
|
||||||
|
types, the docstring will just display the generic type. You can convey the
|
||||||
|
inner types in the docstring by using a special 'typed' version of the generic
|
||||||
|
type.
|
||||||
|
|
||||||
|
.. code-block:: cpp
|
||||||
|
|
||||||
|
PYBIND11_MODULE(example, m) {
|
||||||
|
m.def("pass_list_of_str", [](py::typing::List<py::str> arg) {
|
||||||
|
// arg can be used just like py::list
|
||||||
|
));
|
||||||
|
}
|
||||||
|
|
||||||
|
The resulting docstring will be ``pass_list_of_str(arg0: list[str]) -> None``.
|
||||||
|
|
||||||
|
The following special types are available in ``pybind11/typing.h``:
|
||||||
|
|
||||||
|
* ``py::Tuple<Args...>``
|
||||||
|
* ``py::Dict<K, V>``
|
||||||
|
* ``py::List<V>``
|
||||||
|
* ``py::Set<V>``
|
||||||
|
* ``py::Callable<Signature>``
|
||||||
|
|
||||||
|
.. warning:: Just like in python, these are merely hints. They don't actually
|
||||||
|
enforce the types of their contents at runtime or compile time.
|
13
3rdparty/pybind11/docs/advanced/pycpp/index.rst
vendored
Normal file
13
3rdparty/pybind11/docs/advanced/pycpp/index.rst
vendored
Normal file
@ -0,0 +1,13 @@
|
|||||||
|
Python C++ interface
|
||||||
|
####################
|
||||||
|
|
||||||
|
pybind11 exposes Python types and functions using thin C++ wrappers, which
|
||||||
|
makes it possible to conveniently call Python code from C++ without resorting
|
||||||
|
to Python's C API.
|
||||||
|
|
||||||
|
.. toctree::
|
||||||
|
:maxdepth: 2
|
||||||
|
|
||||||
|
object
|
||||||
|
numpy
|
||||||
|
utilities
|
455
3rdparty/pybind11/docs/advanced/pycpp/numpy.rst
vendored
Normal file
455
3rdparty/pybind11/docs/advanced/pycpp/numpy.rst
vendored
Normal file
@ -0,0 +1,455 @@
|
|||||||
|
.. _numpy:
|
||||||
|
|
||||||
|
NumPy
|
||||||
|
#####
|
||||||
|
|
||||||
|
Buffer protocol
|
||||||
|
===============
|
||||||
|
|
||||||
|
Python supports an extremely general and convenient approach for exchanging
|
||||||
|
data between plugin libraries. Types can expose a buffer view [#f2]_, which
|
||||||
|
provides fast direct access to the raw internal data representation. Suppose we
|
||||||
|
want to bind the following simplistic Matrix class:
|
||||||
|
|
||||||
|
.. code-block:: cpp
|
||||||
|
|
||||||
|
class Matrix {
|
||||||
|
public:
|
||||||
|
Matrix(size_t rows, size_t cols) : m_rows(rows), m_cols(cols) {
|
||||||
|
m_data = new float[rows*cols];
|
||||||
|
}
|
||||||
|
float *data() { return m_data; }
|
||||||
|
size_t rows() const { return m_rows; }
|
||||||
|
size_t cols() const { return m_cols; }
|
||||||
|
private:
|
||||||
|
size_t m_rows, m_cols;
|
||||||
|
float *m_data;
|
||||||
|
};
|
||||||
|
|
||||||
|
The following binding code exposes the ``Matrix`` contents as a buffer object,
|
||||||
|
making it possible to cast Matrices into NumPy arrays. It is even possible to
|
||||||
|
completely avoid copy operations with Python expressions like
|
||||||
|
``np.array(matrix_instance, copy = False)``.
|
||||||
|
|
||||||
|
.. code-block:: cpp
|
||||||
|
|
||||||
|
py::class_<Matrix>(m, "Matrix", py::buffer_protocol())
|
||||||
|
.def_buffer([](Matrix &m) -> py::buffer_info {
|
||||||
|
return py::buffer_info(
|
||||||
|
m.data(), /* Pointer to buffer */
|
||||||
|
sizeof(float), /* Size of one scalar */
|
||||||
|
py::format_descriptor<float>::format(), /* Python struct-style format descriptor */
|
||||||
|
2, /* Number of dimensions */
|
||||||
|
{ m.rows(), m.cols() }, /* Buffer dimensions */
|
||||||
|
{ sizeof(float) * m.cols(), /* Strides (in bytes) for each index */
|
||||||
|
sizeof(float) }
|
||||||
|
);
|
||||||
|
});
|
||||||
|
|
||||||
|
Supporting the buffer protocol in a new type involves specifying the special
|
||||||
|
``py::buffer_protocol()`` tag in the ``py::class_`` constructor and calling the
|
||||||
|
``def_buffer()`` method with a lambda function that creates a
|
||||||
|
``py::buffer_info`` description record on demand describing a given matrix
|
||||||
|
instance. The contents of ``py::buffer_info`` mirror the Python buffer protocol
|
||||||
|
specification.
|
||||||
|
|
||||||
|
.. code-block:: cpp
|
||||||
|
|
||||||
|
struct buffer_info {
|
||||||
|
void *ptr;
|
||||||
|
py::ssize_t itemsize;
|
||||||
|
std::string format;
|
||||||
|
py::ssize_t ndim;
|
||||||
|
std::vector<py::ssize_t> shape;
|
||||||
|
std::vector<py::ssize_t> strides;
|
||||||
|
};
|
||||||
|
|
||||||
|
To create a C++ function that can take a Python buffer object as an argument,
|
||||||
|
simply use the type ``py::buffer`` as one of its arguments. Buffers can exist
|
||||||
|
in a great variety of configurations, hence some safety checks are usually
|
||||||
|
necessary in the function body. Below, you can see a basic example on how to
|
||||||
|
define a custom constructor for the Eigen double precision matrix
|
||||||
|
(``Eigen::MatrixXd``) type, which supports initialization from compatible
|
||||||
|
buffer objects (e.g. a NumPy matrix).
|
||||||
|
|
||||||
|
.. code-block:: cpp
|
||||||
|
|
||||||
|
/* Bind MatrixXd (or some other Eigen type) to Python */
|
||||||
|
typedef Eigen::MatrixXd Matrix;
|
||||||
|
|
||||||
|
typedef Matrix::Scalar Scalar;
|
||||||
|
constexpr bool rowMajor = Matrix::Flags & Eigen::RowMajorBit;
|
||||||
|
|
||||||
|
py::class_<Matrix>(m, "Matrix", py::buffer_protocol())
|
||||||
|
.def(py::init([](py::buffer b) {
|
||||||
|
typedef Eigen::Stride<Eigen::Dynamic, Eigen::Dynamic> Strides;
|
||||||
|
|
||||||
|
/* Request a buffer descriptor from Python */
|
||||||
|
py::buffer_info info = b.request();
|
||||||
|
|
||||||
|
/* Some basic validation checks ... */
|
||||||
|
if (info.format != py::format_descriptor<Scalar>::format())
|
||||||
|
throw std::runtime_error("Incompatible format: expected a double array!");
|
||||||
|
|
||||||
|
if (info.ndim != 2)
|
||||||
|
throw std::runtime_error("Incompatible buffer dimension!");
|
||||||
|
|
||||||
|
auto strides = Strides(
|
||||||
|
info.strides[rowMajor ? 0 : 1] / (py::ssize_t)sizeof(Scalar),
|
||||||
|
info.strides[rowMajor ? 1 : 0] / (py::ssize_t)sizeof(Scalar));
|
||||||
|
|
||||||
|
auto map = Eigen::Map<Matrix, 0, Strides>(
|
||||||
|
static_cast<Scalar *>(info.ptr), info.shape[0], info.shape[1], strides);
|
||||||
|
|
||||||
|
return Matrix(map);
|
||||||
|
}));
|
||||||
|
|
||||||
|
For reference, the ``def_buffer()`` call for this Eigen data type should look
|
||||||
|
as follows:
|
||||||
|
|
||||||
|
.. code-block:: cpp
|
||||||
|
|
||||||
|
.def_buffer([](Matrix &m) -> py::buffer_info {
|
||||||
|
return py::buffer_info(
|
||||||
|
m.data(), /* Pointer to buffer */
|
||||||
|
sizeof(Scalar), /* Size of one scalar */
|
||||||
|
py::format_descriptor<Scalar>::format(), /* Python struct-style format descriptor */
|
||||||
|
2, /* Number of dimensions */
|
||||||
|
{ m.rows(), m.cols() }, /* Buffer dimensions */
|
||||||
|
{ sizeof(Scalar) * (rowMajor ? m.cols() : 1),
|
||||||
|
sizeof(Scalar) * (rowMajor ? 1 : m.rows()) }
|
||||||
|
/* Strides (in bytes) for each index */
|
||||||
|
);
|
||||||
|
})
|
||||||
|
|
||||||
|
For a much easier approach of binding Eigen types (although with some
|
||||||
|
limitations), refer to the section on :doc:`/advanced/cast/eigen`.
|
||||||
|
|
||||||
|
.. seealso::
|
||||||
|
|
||||||
|
The file :file:`tests/test_buffers.cpp` contains a complete example
|
||||||
|
that demonstrates using the buffer protocol with pybind11 in more detail.
|
||||||
|
|
||||||
|
.. [#f2] http://docs.python.org/3/c-api/buffer.html
|
||||||
|
|
||||||
|
Arrays
|
||||||
|
======
|
||||||
|
|
||||||
|
By exchanging ``py::buffer`` with ``py::array`` in the above snippet, we can
|
||||||
|
restrict the function so that it only accepts NumPy arrays (rather than any
|
||||||
|
type of Python object satisfying the buffer protocol).
|
||||||
|
|
||||||
|
In many situations, we want to define a function which only accepts a NumPy
|
||||||
|
array of a certain data type. This is possible via the ``py::array_t<T>``
|
||||||
|
template. For instance, the following function requires the argument to be a
|
||||||
|
NumPy array containing double precision values.
|
||||||
|
|
||||||
|
.. code-block:: cpp
|
||||||
|
|
||||||
|
void f(py::array_t<double> array);
|
||||||
|
|
||||||
|
When it is invoked with a different type (e.g. an integer or a list of
|
||||||
|
integers), the binding code will attempt to cast the input into a NumPy array
|
||||||
|
of the requested type. This feature requires the :file:`pybind11/numpy.h`
|
||||||
|
header to be included. Note that :file:`pybind11/numpy.h` does not depend on
|
||||||
|
the NumPy headers, and thus can be used without declaring a build-time
|
||||||
|
dependency on NumPy; NumPy>=1.7.0 is a runtime dependency.
|
||||||
|
|
||||||
|
Data in NumPy arrays is not guaranteed to packed in a dense manner;
|
||||||
|
furthermore, entries can be separated by arbitrary column and row strides.
|
||||||
|
Sometimes, it can be useful to require a function to only accept dense arrays
|
||||||
|
using either the C (row-major) or Fortran (column-major) ordering. This can be
|
||||||
|
accomplished via a second template argument with values ``py::array::c_style``
|
||||||
|
or ``py::array::f_style``.
|
||||||
|
|
||||||
|
.. code-block:: cpp
|
||||||
|
|
||||||
|
void f(py::array_t<double, py::array::c_style | py::array::forcecast> array);
|
||||||
|
|
||||||
|
The ``py::array::forcecast`` argument is the default value of the second
|
||||||
|
template parameter, and it ensures that non-conforming arguments are converted
|
||||||
|
into an array satisfying the specified requirements instead of trying the next
|
||||||
|
function overload.
|
||||||
|
|
||||||
|
There are several methods on arrays; the methods listed below under references
|
||||||
|
work, as well as the following functions based on the NumPy API:
|
||||||
|
|
||||||
|
- ``.dtype()`` returns the type of the contained values.
|
||||||
|
|
||||||
|
- ``.strides()`` returns a pointer to the strides of the array (optionally pass
|
||||||
|
an integer axis to get a number).
|
||||||
|
|
||||||
|
- ``.flags()`` returns the flag settings. ``.writable()`` and ``.owndata()``
|
||||||
|
are directly available.
|
||||||
|
|
||||||
|
- ``.offset_at()`` returns the offset (optionally pass indices).
|
||||||
|
|
||||||
|
- ``.squeeze()`` returns a view with length-1 axes removed.
|
||||||
|
|
||||||
|
- ``.view(dtype)`` returns a view of the array with a different dtype.
|
||||||
|
|
||||||
|
- ``.reshape({i, j, ...})`` returns a view of the array with a different shape.
|
||||||
|
``.resize({...})`` is also available.
|
||||||
|
|
||||||
|
- ``.index_at(i, j, ...)`` gets the count from the beginning to a given index.
|
||||||
|
|
||||||
|
|
||||||
|
There are also several methods for getting references (described below).
|
||||||
|
|
||||||
|
Structured types
|
||||||
|
================
|
||||||
|
|
||||||
|
In order for ``py::array_t`` to work with structured (record) types, we first
|
||||||
|
need to register the memory layout of the type. This can be done via
|
||||||
|
``PYBIND11_NUMPY_DTYPE`` macro, called in the plugin definition code, which
|
||||||
|
expects the type followed by field names:
|
||||||
|
|
||||||
|
.. code-block:: cpp
|
||||||
|
|
||||||
|
struct A {
|
||||||
|
int x;
|
||||||
|
double y;
|
||||||
|
};
|
||||||
|
|
||||||
|
struct B {
|
||||||
|
int z;
|
||||||
|
A a;
|
||||||
|
};
|
||||||
|
|
||||||
|
// ...
|
||||||
|
PYBIND11_MODULE(test, m) {
|
||||||
|
// ...
|
||||||
|
|
||||||
|
PYBIND11_NUMPY_DTYPE(A, x, y);
|
||||||
|
PYBIND11_NUMPY_DTYPE(B, z, a);
|
||||||
|
/* now both A and B can be used as template arguments to py::array_t */
|
||||||
|
}
|
||||||
|
|
||||||
|
The structure should consist of fundamental arithmetic types, ``std::complex``,
|
||||||
|
previously registered substructures, and arrays of any of the above. Both C++
|
||||||
|
arrays and ``std::array`` are supported. While there is a static assertion to
|
||||||
|
prevent many types of unsupported structures, it is still the user's
|
||||||
|
responsibility to use only "plain" structures that can be safely manipulated as
|
||||||
|
raw memory without violating invariants.
|
||||||
|
|
||||||
|
Vectorizing functions
|
||||||
|
=====================
|
||||||
|
|
||||||
|
Suppose we want to bind a function with the following signature to Python so
|
||||||
|
that it can process arbitrary NumPy array arguments (vectors, matrices, general
|
||||||
|
N-D arrays) in addition to its normal arguments:
|
||||||
|
|
||||||
|
.. code-block:: cpp
|
||||||
|
|
||||||
|
double my_func(int x, float y, double z);
|
||||||
|
|
||||||
|
After including the ``pybind11/numpy.h`` header, this is extremely simple:
|
||||||
|
|
||||||
|
.. code-block:: cpp
|
||||||
|
|
||||||
|
m.def("vectorized_func", py::vectorize(my_func));
|
||||||
|
|
||||||
|
Invoking the function like below causes 4 calls to be made to ``my_func`` with
|
||||||
|
each of the array elements. The significant advantage of this compared to
|
||||||
|
solutions like ``numpy.vectorize()`` is that the loop over the elements runs
|
||||||
|
entirely on the C++ side and can be crunched down into a tight, optimized loop
|
||||||
|
by the compiler. The result is returned as a NumPy array of type
|
||||||
|
``numpy.dtype.float64``.
|
||||||
|
|
||||||
|
.. code-block:: pycon
|
||||||
|
|
||||||
|
>>> x = np.array([[1, 3], [5, 7]])
|
||||||
|
>>> y = np.array([[2, 4], [6, 8]])
|
||||||
|
>>> z = 3
|
||||||
|
>>> result = vectorized_func(x, y, z)
|
||||||
|
|
||||||
|
The scalar argument ``z`` is transparently replicated 4 times. The input
|
||||||
|
arrays ``x`` and ``y`` are automatically converted into the right types (they
|
||||||
|
are of type ``numpy.dtype.int64`` but need to be ``numpy.dtype.int32`` and
|
||||||
|
``numpy.dtype.float32``, respectively).
|
||||||
|
|
||||||
|
.. note::
|
||||||
|
|
||||||
|
Only arithmetic, complex, and POD types passed by value or by ``const &``
|
||||||
|
reference are vectorized; all other arguments are passed through as-is.
|
||||||
|
Functions taking rvalue reference arguments cannot be vectorized.
|
||||||
|
|
||||||
|
In cases where the computation is too complicated to be reduced to
|
||||||
|
``vectorize``, it will be necessary to create and access the buffer contents
|
||||||
|
manually. The following snippet contains a complete example that shows how this
|
||||||
|
works (the code is somewhat contrived, since it could have been done more
|
||||||
|
simply using ``vectorize``).
|
||||||
|
|
||||||
|
.. code-block:: cpp
|
||||||
|
|
||||||
|
#include <pybind11/pybind11.h>
|
||||||
|
#include <pybind11/numpy.h>
|
||||||
|
|
||||||
|
namespace py = pybind11;
|
||||||
|
|
||||||
|
py::array_t<double> add_arrays(py::array_t<double> input1, py::array_t<double> input2) {
|
||||||
|
py::buffer_info buf1 = input1.request(), buf2 = input2.request();
|
||||||
|
|
||||||
|
if (buf1.ndim != 1 || buf2.ndim != 1)
|
||||||
|
throw std::runtime_error("Number of dimensions must be one");
|
||||||
|
|
||||||
|
if (buf1.size != buf2.size)
|
||||||
|
throw std::runtime_error("Input shapes must match");
|
||||||
|
|
||||||
|
/* No pointer is passed, so NumPy will allocate the buffer */
|
||||||
|
auto result = py::array_t<double>(buf1.size);
|
||||||
|
|
||||||
|
py::buffer_info buf3 = result.request();
|
||||||
|
|
||||||
|
double *ptr1 = static_cast<double *>(buf1.ptr);
|
||||||
|
double *ptr2 = static_cast<double *>(buf2.ptr);
|
||||||
|
double *ptr3 = static_cast<double *>(buf3.ptr);
|
||||||
|
|
||||||
|
for (size_t idx = 0; idx < buf1.shape[0]; idx++)
|
||||||
|
ptr3[idx] = ptr1[idx] + ptr2[idx];
|
||||||
|
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
|
PYBIND11_MODULE(test, m) {
|
||||||
|
m.def("add_arrays", &add_arrays, "Add two NumPy arrays");
|
||||||
|
}
|
||||||
|
|
||||||
|
.. seealso::
|
||||||
|
|
||||||
|
The file :file:`tests/test_numpy_vectorize.cpp` contains a complete
|
||||||
|
example that demonstrates using :func:`vectorize` in more detail.
|
||||||
|
|
||||||
|
Direct access
|
||||||
|
=============
|
||||||
|
|
||||||
|
For performance reasons, particularly when dealing with very large arrays, it
|
||||||
|
is often desirable to directly access array elements without internal checking
|
||||||
|
of dimensions and bounds on every access when indices are known to be already
|
||||||
|
valid. To avoid such checks, the ``array`` class and ``array_t<T>`` template
|
||||||
|
class offer an unchecked proxy object that can be used for this unchecked
|
||||||
|
access through the ``unchecked<N>`` and ``mutable_unchecked<N>`` methods,
|
||||||
|
where ``N`` gives the required dimensionality of the array:
|
||||||
|
|
||||||
|
.. code-block:: cpp
|
||||||
|
|
||||||
|
m.def("sum_3d", [](py::array_t<double> x) {
|
||||||
|
auto r = x.unchecked<3>(); // x must have ndim = 3; can be non-writeable
|
||||||
|
double sum = 0;
|
||||||
|
for (py::ssize_t i = 0; i < r.shape(0); i++)
|
||||||
|
for (py::ssize_t j = 0; j < r.shape(1); j++)
|
||||||
|
for (py::ssize_t k = 0; k < r.shape(2); k++)
|
||||||
|
sum += r(i, j, k);
|
||||||
|
return sum;
|
||||||
|
});
|
||||||
|
m.def("increment_3d", [](py::array_t<double> x) {
|
||||||
|
auto r = x.mutable_unchecked<3>(); // Will throw if ndim != 3 or flags.writeable is false
|
||||||
|
for (py::ssize_t i = 0; i < r.shape(0); i++)
|
||||||
|
for (py::ssize_t j = 0; j < r.shape(1); j++)
|
||||||
|
for (py::ssize_t k = 0; k < r.shape(2); k++)
|
||||||
|
r(i, j, k) += 1.0;
|
||||||
|
}, py::arg().noconvert());
|
||||||
|
|
||||||
|
To obtain the proxy from an ``array`` object, you must specify both the data
|
||||||
|
type and number of dimensions as template arguments, such as ``auto r =
|
||||||
|
myarray.mutable_unchecked<float, 2>()``.
|
||||||
|
|
||||||
|
If the number of dimensions is not known at compile time, you can omit the
|
||||||
|
dimensions template parameter (i.e. calling ``arr_t.unchecked()`` or
|
||||||
|
``arr.unchecked<T>()``. This will give you a proxy object that works in the
|
||||||
|
same way, but results in less optimizable code and thus a small efficiency
|
||||||
|
loss in tight loops.
|
||||||
|
|
||||||
|
Note that the returned proxy object directly references the array's data, and
|
||||||
|
only reads its shape, strides, and writeable flag when constructed. You must
|
||||||
|
take care to ensure that the referenced array is not destroyed or reshaped for
|
||||||
|
the duration of the returned object, typically by limiting the scope of the
|
||||||
|
returned instance.
|
||||||
|
|
||||||
|
The returned proxy object supports some of the same methods as ``py::array`` so
|
||||||
|
that it can be used as a drop-in replacement for some existing, index-checked
|
||||||
|
uses of ``py::array``:
|
||||||
|
|
||||||
|
- ``.ndim()`` returns the number of dimensions
|
||||||
|
|
||||||
|
- ``.data(1, 2, ...)`` and ``r.mutable_data(1, 2, ...)``` returns a pointer to
|
||||||
|
the ``const T`` or ``T`` data, respectively, at the given indices. The
|
||||||
|
latter is only available to proxies obtained via ``a.mutable_unchecked()``.
|
||||||
|
|
||||||
|
- ``.itemsize()`` returns the size of an item in bytes, i.e. ``sizeof(T)``.
|
||||||
|
|
||||||
|
- ``.ndim()`` returns the number of dimensions.
|
||||||
|
|
||||||
|
- ``.shape(n)`` returns the size of dimension ``n``
|
||||||
|
|
||||||
|
- ``.size()`` returns the total number of elements (i.e. the product of the shapes).
|
||||||
|
|
||||||
|
- ``.nbytes()`` returns the number of bytes used by the referenced elements
|
||||||
|
(i.e. ``itemsize()`` times ``size()``).
|
||||||
|
|
||||||
|
.. seealso::
|
||||||
|
|
||||||
|
The file :file:`tests/test_numpy_array.cpp` contains additional examples
|
||||||
|
demonstrating the use of this feature.
|
||||||
|
|
||||||
|
Ellipsis
|
||||||
|
========
|
||||||
|
|
||||||
|
Python provides a convenient ``...`` ellipsis notation that is often used to
|
||||||
|
slice multidimensional arrays. For instance, the following snippet extracts the
|
||||||
|
middle dimensions of a tensor with the first and last index set to zero.
|
||||||
|
|
||||||
|
.. code-block:: python
|
||||||
|
|
||||||
|
a = ... # a NumPy array
|
||||||
|
b = a[0, ..., 0]
|
||||||
|
|
||||||
|
The function ``py::ellipsis()`` function can be used to perform the same
|
||||||
|
operation on the C++ side:
|
||||||
|
|
||||||
|
.. code-block:: cpp
|
||||||
|
|
||||||
|
py::array a = /* A NumPy array */;
|
||||||
|
py::array b = a[py::make_tuple(0, py::ellipsis(), 0)];
|
||||||
|
|
||||||
|
|
||||||
|
Memory view
|
||||||
|
===========
|
||||||
|
|
||||||
|
For a case when we simply want to provide a direct accessor to C/C++ buffer
|
||||||
|
without a concrete class object, we can return a ``memoryview`` object. Suppose
|
||||||
|
we wish to expose a ``memoryview`` for 2x4 uint8_t array, we can do the
|
||||||
|
following:
|
||||||
|
|
||||||
|
.. code-block:: cpp
|
||||||
|
|
||||||
|
const uint8_t buffer[] = {
|
||||||
|
0, 1, 2, 3,
|
||||||
|
4, 5, 6, 7
|
||||||
|
};
|
||||||
|
m.def("get_memoryview2d", []() {
|
||||||
|
return py::memoryview::from_buffer(
|
||||||
|
buffer, // buffer pointer
|
||||||
|
{ 2, 4 }, // shape (rows, cols)
|
||||||
|
{ sizeof(uint8_t) * 4, sizeof(uint8_t) } // strides in bytes
|
||||||
|
);
|
||||||
|
});
|
||||||
|
|
||||||
|
This approach is meant for providing a ``memoryview`` for a C/C++ buffer not
|
||||||
|
managed by Python. The user is responsible for managing the lifetime of the
|
||||||
|
buffer. Using a ``memoryview`` created in this way after deleting the buffer in
|
||||||
|
C++ side results in undefined behavior.
|
||||||
|
|
||||||
|
We can also use ``memoryview::from_memory`` for a simple 1D contiguous buffer:
|
||||||
|
|
||||||
|
.. code-block:: cpp
|
||||||
|
|
||||||
|
m.def("get_memoryview1d", []() {
|
||||||
|
return py::memoryview::from_memory(
|
||||||
|
buffer, // buffer pointer
|
||||||
|
sizeof(uint8_t) * 8 // buffer size
|
||||||
|
);
|
||||||
|
});
|
||||||
|
|
||||||
|
.. versionchanged:: 2.6
|
||||||
|
``memoryview::from_memory`` added.
|
286
3rdparty/pybind11/docs/advanced/pycpp/object.rst
vendored
Normal file
286
3rdparty/pybind11/docs/advanced/pycpp/object.rst
vendored
Normal file
@ -0,0 +1,286 @@
|
|||||||
|
Python types
|
||||||
|
############
|
||||||
|
|
||||||
|
.. _wrappers:
|
||||||
|
|
||||||
|
Available wrappers
|
||||||
|
==================
|
||||||
|
|
||||||
|
All major Python types are available as thin C++ wrapper classes. These
|
||||||
|
can also be used as function parameters -- see :ref:`python_objects_as_args`.
|
||||||
|
|
||||||
|
Available types include :class:`handle`, :class:`object`, :class:`bool_`,
|
||||||
|
:class:`int_`, :class:`float_`, :class:`str`, :class:`bytes`, :class:`tuple`,
|
||||||
|
:class:`list`, :class:`dict`, :class:`slice`, :class:`none`, :class:`capsule`,
|
||||||
|
:class:`iterable`, :class:`iterator`, :class:`function`, :class:`buffer`,
|
||||||
|
:class:`array`, and :class:`array_t`.
|
||||||
|
|
||||||
|
.. warning::
|
||||||
|
|
||||||
|
Be sure to review the :ref:`pytypes_gotchas` before using this heavily in
|
||||||
|
your C++ API.
|
||||||
|
|
||||||
|
.. _instantiating_compound_types:
|
||||||
|
|
||||||
|
Instantiating compound Python types from C++
|
||||||
|
============================================
|
||||||
|
|
||||||
|
Dictionaries can be initialized in the :class:`dict` constructor:
|
||||||
|
|
||||||
|
.. code-block:: cpp
|
||||||
|
|
||||||
|
using namespace pybind11::literals; // to bring in the `_a` literal
|
||||||
|
py::dict d("spam"_a=py::none(), "eggs"_a=42);
|
||||||
|
|
||||||
|
A tuple of python objects can be instantiated using :func:`py::make_tuple`:
|
||||||
|
|
||||||
|
.. code-block:: cpp
|
||||||
|
|
||||||
|
py::tuple tup = py::make_tuple(42, py::none(), "spam");
|
||||||
|
|
||||||
|
Each element is converted to a supported Python type.
|
||||||
|
|
||||||
|
A `simple namespace`_ can be instantiated using
|
||||||
|
|
||||||
|
.. code-block:: cpp
|
||||||
|
|
||||||
|
using namespace pybind11::literals; // to bring in the `_a` literal
|
||||||
|
py::object SimpleNamespace = py::module_::import("types").attr("SimpleNamespace");
|
||||||
|
py::object ns = SimpleNamespace("spam"_a=py::none(), "eggs"_a=42);
|
||||||
|
|
||||||
|
Attributes on a namespace can be modified with the :func:`py::delattr`,
|
||||||
|
:func:`py::getattr`, and :func:`py::setattr` functions. Simple namespaces can
|
||||||
|
be useful as lightweight stand-ins for class instances.
|
||||||
|
|
||||||
|
.. _simple namespace: https://docs.python.org/3/library/types.html#types.SimpleNamespace
|
||||||
|
|
||||||
|
.. _casting_back_and_forth:
|
||||||
|
|
||||||
|
Casting back and forth
|
||||||
|
======================
|
||||||
|
|
||||||
|
In this kind of mixed code, it is often necessary to convert arbitrary C++
|
||||||
|
types to Python, which can be done using :func:`py::cast`:
|
||||||
|
|
||||||
|
.. code-block:: cpp
|
||||||
|
|
||||||
|
MyClass *cls = ...;
|
||||||
|
py::object obj = py::cast(cls);
|
||||||
|
|
||||||
|
The reverse direction uses the following syntax:
|
||||||
|
|
||||||
|
.. code-block:: cpp
|
||||||
|
|
||||||
|
py::object obj = ...;
|
||||||
|
MyClass *cls = obj.cast<MyClass *>();
|
||||||
|
|
||||||
|
When conversion fails, both directions throw the exception :class:`cast_error`.
|
||||||
|
|
||||||
|
.. _python_libs:
|
||||||
|
|
||||||
|
Accessing Python libraries from C++
|
||||||
|
===================================
|
||||||
|
|
||||||
|
It is also possible to import objects defined in the Python standard
|
||||||
|
library or available in the current Python environment (``sys.path``) and work
|
||||||
|
with these in C++.
|
||||||
|
|
||||||
|
This example obtains a reference to the Python ``Decimal`` class.
|
||||||
|
|
||||||
|
.. code-block:: cpp
|
||||||
|
|
||||||
|
// Equivalent to "from decimal import Decimal"
|
||||||
|
py::object Decimal = py::module_::import("decimal").attr("Decimal");
|
||||||
|
|
||||||
|
.. code-block:: cpp
|
||||||
|
|
||||||
|
// Try to import scipy
|
||||||
|
py::object scipy = py::module_::import("scipy");
|
||||||
|
return scipy.attr("__version__");
|
||||||
|
|
||||||
|
|
||||||
|
.. _calling_python_functions:
|
||||||
|
|
||||||
|
Calling Python functions
|
||||||
|
========================
|
||||||
|
|
||||||
|
It is also possible to call Python classes, functions and methods
|
||||||
|
via ``operator()``.
|
||||||
|
|
||||||
|
.. code-block:: cpp
|
||||||
|
|
||||||
|
// Construct a Python object of class Decimal
|
||||||
|
py::object pi = Decimal("3.14159");
|
||||||
|
|
||||||
|
.. code-block:: cpp
|
||||||
|
|
||||||
|
// Use Python to make our directories
|
||||||
|
py::object os = py::module_::import("os");
|
||||||
|
py::object makedirs = os.attr("makedirs");
|
||||||
|
makedirs("/tmp/path/to/somewhere");
|
||||||
|
|
||||||
|
One can convert the result obtained from Python to a pure C++ version
|
||||||
|
if a ``py::class_`` or type conversion is defined.
|
||||||
|
|
||||||
|
.. code-block:: cpp
|
||||||
|
|
||||||
|
py::function f = <...>;
|
||||||
|
py::object result_py = f(1234, "hello", some_instance);
|
||||||
|
MyClass &result = result_py.cast<MyClass>();
|
||||||
|
|
||||||
|
.. _calling_python_methods:
|
||||||
|
|
||||||
|
Calling Python methods
|
||||||
|
========================
|
||||||
|
|
||||||
|
To call an object's method, one can again use ``.attr`` to obtain access to the
|
||||||
|
Python method.
|
||||||
|
|
||||||
|
.. code-block:: cpp
|
||||||
|
|
||||||
|
// Calculate e^π in decimal
|
||||||
|
py::object exp_pi = pi.attr("exp")();
|
||||||
|
py::print(py::str(exp_pi));
|
||||||
|
|
||||||
|
In the example above ``pi.attr("exp")`` is a *bound method*: it will always call
|
||||||
|
the method for that same instance of the class. Alternately one can create an
|
||||||
|
*unbound method* via the Python class (instead of instance) and pass the ``self``
|
||||||
|
object explicitly, followed by other arguments.
|
||||||
|
|
||||||
|
.. code-block:: cpp
|
||||||
|
|
||||||
|
py::object decimal_exp = Decimal.attr("exp");
|
||||||
|
|
||||||
|
// Compute the e^n for n=0..4
|
||||||
|
for (int n = 0; n < 5; n++) {
|
||||||
|
py::print(decimal_exp(Decimal(n));
|
||||||
|
}
|
||||||
|
|
||||||
|
Keyword arguments
|
||||||
|
=================
|
||||||
|
|
||||||
|
Keyword arguments are also supported. In Python, there is the usual call syntax:
|
||||||
|
|
||||||
|
.. code-block:: python
|
||||||
|
|
||||||
|
def f(number, say, to):
|
||||||
|
... # function code
|
||||||
|
|
||||||
|
|
||||||
|
f(1234, say="hello", to=some_instance) # keyword call in Python
|
||||||
|
|
||||||
|
In C++, the same call can be made using:
|
||||||
|
|
||||||
|
.. code-block:: cpp
|
||||||
|
|
||||||
|
using namespace pybind11::literals; // to bring in the `_a` literal
|
||||||
|
f(1234, "say"_a="hello", "to"_a=some_instance); // keyword call in C++
|
||||||
|
|
||||||
|
Unpacking arguments
|
||||||
|
===================
|
||||||
|
|
||||||
|
Unpacking of ``*args`` and ``**kwargs`` is also possible and can be mixed with
|
||||||
|
other arguments:
|
||||||
|
|
||||||
|
.. code-block:: cpp
|
||||||
|
|
||||||
|
// * unpacking
|
||||||
|
py::tuple args = py::make_tuple(1234, "hello", some_instance);
|
||||||
|
f(*args);
|
||||||
|
|
||||||
|
// ** unpacking
|
||||||
|
py::dict kwargs = py::dict("number"_a=1234, "say"_a="hello", "to"_a=some_instance);
|
||||||
|
f(**kwargs);
|
||||||
|
|
||||||
|
// mixed keywords, * and ** unpacking
|
||||||
|
py::tuple args = py::make_tuple(1234);
|
||||||
|
py::dict kwargs = py::dict("to"_a=some_instance);
|
||||||
|
f(*args, "say"_a="hello", **kwargs);
|
||||||
|
|
||||||
|
Generalized unpacking according to PEP448_ is also supported:
|
||||||
|
|
||||||
|
.. code-block:: cpp
|
||||||
|
|
||||||
|
py::dict kwargs1 = py::dict("number"_a=1234);
|
||||||
|
py::dict kwargs2 = py::dict("to"_a=some_instance);
|
||||||
|
f(**kwargs1, "say"_a="hello", **kwargs2);
|
||||||
|
|
||||||
|
.. seealso::
|
||||||
|
|
||||||
|
The file :file:`tests/test_pytypes.cpp` contains a complete
|
||||||
|
example that demonstrates passing native Python types in more detail. The
|
||||||
|
file :file:`tests/test_callbacks.cpp` presents a few examples of calling
|
||||||
|
Python functions from C++, including keywords arguments and unpacking.
|
||||||
|
|
||||||
|
.. _PEP448: https://www.python.org/dev/peps/pep-0448/
|
||||||
|
|
||||||
|
.. _implicit_casting:
|
||||||
|
|
||||||
|
Implicit casting
|
||||||
|
================
|
||||||
|
|
||||||
|
When using the C++ interface for Python types, or calling Python functions,
|
||||||
|
objects of type :class:`object` are returned. It is possible to invoke implicit
|
||||||
|
conversions to subclasses like :class:`dict`. The same holds for the proxy objects
|
||||||
|
returned by ``operator[]`` or ``obj.attr()``.
|
||||||
|
Casting to subtypes improves code readability and allows values to be passed to
|
||||||
|
C++ functions that require a specific subtype rather than a generic :class:`object`.
|
||||||
|
|
||||||
|
.. code-block:: cpp
|
||||||
|
|
||||||
|
#include <pybind11/numpy.h>
|
||||||
|
using namespace pybind11::literals;
|
||||||
|
|
||||||
|
py::module_ os = py::module_::import("os");
|
||||||
|
py::module_ path = py::module_::import("os.path"); // like 'import os.path as path'
|
||||||
|
py::module_ np = py::module_::import("numpy"); // like 'import numpy as np'
|
||||||
|
|
||||||
|
py::str curdir_abs = path.attr("abspath")(path.attr("curdir"));
|
||||||
|
py::print(py::str("Current directory: ") + curdir_abs);
|
||||||
|
py::dict environ = os.attr("environ");
|
||||||
|
py::print(environ["HOME"]);
|
||||||
|
py::array_t<float> arr = np.attr("ones")(3, "dtype"_a="float32");
|
||||||
|
py::print(py::repr(arr + py::int_(1)));
|
||||||
|
|
||||||
|
These implicit conversions are available for subclasses of :class:`object`; there
|
||||||
|
is no need to call ``obj.cast()`` explicitly as for custom classes, see
|
||||||
|
:ref:`casting_back_and_forth`.
|
||||||
|
|
||||||
|
.. note::
|
||||||
|
If a trivial conversion via move constructor is not possible, both implicit and
|
||||||
|
explicit casting (calling ``obj.cast()``) will attempt a "rich" conversion.
|
||||||
|
For instance, ``py::list env = os.attr("environ");`` will succeed and is
|
||||||
|
equivalent to the Python code ``env = list(os.environ)`` that produces a
|
||||||
|
list of the dict keys.
|
||||||
|
|
||||||
|
.. TODO: Adapt text once PR #2349 has landed
|
||||||
|
|
||||||
|
Handling exceptions
|
||||||
|
===================
|
||||||
|
|
||||||
|
Python exceptions from wrapper classes will be thrown as a ``py::error_already_set``.
|
||||||
|
See :ref:`Handling exceptions from Python in C++
|
||||||
|
<handling_python_exceptions_cpp>` for more information on handling exceptions
|
||||||
|
raised when calling C++ wrapper classes.
|
||||||
|
|
||||||
|
.. _pytypes_gotchas:
|
||||||
|
|
||||||
|
Gotchas
|
||||||
|
=======
|
||||||
|
|
||||||
|
Default-Constructed Wrappers
|
||||||
|
----------------------------
|
||||||
|
|
||||||
|
When a wrapper type is default-constructed, it is **not** a valid Python object (i.e. it is not ``py::none()``). It is simply the same as
|
||||||
|
``PyObject*`` null pointer. To check for this, use
|
||||||
|
``static_cast<bool>(my_wrapper)``.
|
||||||
|
|
||||||
|
Assigning py::none() to wrappers
|
||||||
|
--------------------------------
|
||||||
|
|
||||||
|
You may be tempted to use types like ``py::str`` and ``py::dict`` in C++
|
||||||
|
signatures (either pure C++, or in bound signatures), and assign them default
|
||||||
|
values of ``py::none()``. However, in a best case scenario, it will fail fast
|
||||||
|
because ``None`` is not convertible to that type (e.g. ``py::dict``), or in a
|
||||||
|
worse case scenario, it will silently work but corrupt the types you want to
|
||||||
|
work with (e.g. ``py::str(py::none())`` will yield ``"None"`` in Python).
|
155
3rdparty/pybind11/docs/advanced/pycpp/utilities.rst
vendored
Normal file
155
3rdparty/pybind11/docs/advanced/pycpp/utilities.rst
vendored
Normal file
@ -0,0 +1,155 @@
|
|||||||
|
Utilities
|
||||||
|
#########
|
||||||
|
|
||||||
|
Using Python's print function in C++
|
||||||
|
====================================
|
||||||
|
|
||||||
|
The usual way to write output in C++ is using ``std::cout`` while in Python one
|
||||||
|
would use ``print``. Since these methods use different buffers, mixing them can
|
||||||
|
lead to output order issues. To resolve this, pybind11 modules can use the
|
||||||
|
:func:`py::print` function which writes to Python's ``sys.stdout`` for consistency.
|
||||||
|
|
||||||
|
Python's ``print`` function is replicated in the C++ API including optional
|
||||||
|
keyword arguments ``sep``, ``end``, ``file``, ``flush``. Everything works as
|
||||||
|
expected in Python:
|
||||||
|
|
||||||
|
.. code-block:: cpp
|
||||||
|
|
||||||
|
py::print(1, 2.0, "three"); // 1 2.0 three
|
||||||
|
py::print(1, 2.0, "three", "sep"_a="-"); // 1-2.0-three
|
||||||
|
|
||||||
|
auto args = py::make_tuple("unpacked", true);
|
||||||
|
py::print("->", *args, "end"_a="<-"); // -> unpacked True <-
|
||||||
|
|
||||||
|
.. _ostream_redirect:
|
||||||
|
|
||||||
|
Capturing standard output from ostream
|
||||||
|
======================================
|
||||||
|
|
||||||
|
Often, a library will use the streams ``std::cout`` and ``std::cerr`` to print,
|
||||||
|
but this does not play well with Python's standard ``sys.stdout`` and ``sys.stderr``
|
||||||
|
redirection. Replacing a library's printing with ``py::print <print>`` may not
|
||||||
|
be feasible. This can be fixed using a guard around the library function that
|
||||||
|
redirects output to the corresponding Python streams:
|
||||||
|
|
||||||
|
.. code-block:: cpp
|
||||||
|
|
||||||
|
#include <pybind11/iostream.h>
|
||||||
|
|
||||||
|
...
|
||||||
|
|
||||||
|
// Add a scoped redirect for your noisy code
|
||||||
|
m.def("noisy_func", []() {
|
||||||
|
py::scoped_ostream_redirect stream(
|
||||||
|
std::cout, // std::ostream&
|
||||||
|
py::module_::import("sys").attr("stdout") // Python output
|
||||||
|
);
|
||||||
|
call_noisy_func();
|
||||||
|
});
|
||||||
|
|
||||||
|
.. warning::
|
||||||
|
|
||||||
|
The implementation in ``pybind11/iostream.h`` is NOT thread safe. Multiple
|
||||||
|
threads writing to a redirected ostream concurrently cause data races
|
||||||
|
and potentially buffer overflows. Therefore it is currently a requirement
|
||||||
|
that all (possibly) concurrent redirected ostream writes are protected by
|
||||||
|
a mutex. #HelpAppreciated: Work on iostream.h thread safety. For more
|
||||||
|
background see the discussions under
|
||||||
|
`PR #2982 <https://github.com/pybind/pybind11/pull/2982>`_ and
|
||||||
|
`PR #2995 <https://github.com/pybind/pybind11/pull/2995>`_.
|
||||||
|
|
||||||
|
This method respects flushes on the output streams and will flush if needed
|
||||||
|
when the scoped guard is destroyed. This allows the output to be redirected in
|
||||||
|
real time, such as to a Jupyter notebook. The two arguments, the C++ stream and
|
||||||
|
the Python output, are optional, and default to standard output if not given. An
|
||||||
|
extra type, ``py::scoped_estream_redirect <scoped_estream_redirect>``, is identical
|
||||||
|
except for defaulting to ``std::cerr`` and ``sys.stderr``; this can be useful with
|
||||||
|
``py::call_guard``, which allows multiple items, but uses the default constructor:
|
||||||
|
|
||||||
|
.. code-block:: cpp
|
||||||
|
|
||||||
|
// Alternative: Call single function using call guard
|
||||||
|
m.def("noisy_func", &call_noisy_function,
|
||||||
|
py::call_guard<py::scoped_ostream_redirect,
|
||||||
|
py::scoped_estream_redirect>());
|
||||||
|
|
||||||
|
The redirection can also be done in Python with the addition of a context
|
||||||
|
manager, using the ``py::add_ostream_redirect() <add_ostream_redirect>`` function:
|
||||||
|
|
||||||
|
.. code-block:: cpp
|
||||||
|
|
||||||
|
py::add_ostream_redirect(m, "ostream_redirect");
|
||||||
|
|
||||||
|
The name in Python defaults to ``ostream_redirect`` if no name is passed. This
|
||||||
|
creates the following context manager in Python:
|
||||||
|
|
||||||
|
.. code-block:: python
|
||||||
|
|
||||||
|
with ostream_redirect(stdout=True, stderr=True):
|
||||||
|
noisy_function()
|
||||||
|
|
||||||
|
It defaults to redirecting both streams, though you can use the keyword
|
||||||
|
arguments to disable one of the streams if needed.
|
||||||
|
|
||||||
|
.. note::
|
||||||
|
|
||||||
|
The above methods will not redirect C-level output to file descriptors, such
|
||||||
|
as ``fprintf``. For those cases, you'll need to redirect the file
|
||||||
|
descriptors either directly in C or with Python's ``os.dup2`` function
|
||||||
|
in an operating-system dependent way.
|
||||||
|
|
||||||
|
.. _eval:
|
||||||
|
|
||||||
|
Evaluating Python expressions from strings and files
|
||||||
|
====================================================
|
||||||
|
|
||||||
|
pybind11 provides the ``eval``, ``exec`` and ``eval_file`` functions to evaluate
|
||||||
|
Python expressions and statements. The following example illustrates how they
|
||||||
|
can be used.
|
||||||
|
|
||||||
|
.. code-block:: cpp
|
||||||
|
|
||||||
|
// At beginning of file
|
||||||
|
#include <pybind11/eval.h>
|
||||||
|
|
||||||
|
...
|
||||||
|
|
||||||
|
// Evaluate in scope of main module
|
||||||
|
py::object scope = py::module_::import("__main__").attr("__dict__");
|
||||||
|
|
||||||
|
// Evaluate an isolated expression
|
||||||
|
int result = py::eval("my_variable + 10", scope).cast<int>();
|
||||||
|
|
||||||
|
// Evaluate a sequence of statements
|
||||||
|
py::exec(
|
||||||
|
"print('Hello')\n"
|
||||||
|
"print('world!');",
|
||||||
|
scope);
|
||||||
|
|
||||||
|
// Evaluate the statements in an separate Python file on disk
|
||||||
|
py::eval_file("script.py", scope);
|
||||||
|
|
||||||
|
C++11 raw string literals are also supported and quite handy for this purpose.
|
||||||
|
The only requirement is that the first statement must be on a new line following
|
||||||
|
the raw string delimiter ``R"(``, ensuring all lines have common leading indent:
|
||||||
|
|
||||||
|
.. code-block:: cpp
|
||||||
|
|
||||||
|
py::exec(R"(
|
||||||
|
x = get_answer()
|
||||||
|
if x == 42:
|
||||||
|
print('Hello World!')
|
||||||
|
else:
|
||||||
|
print('Bye!')
|
||||||
|
)", scope
|
||||||
|
);
|
||||||
|
|
||||||
|
.. note::
|
||||||
|
|
||||||
|
`eval` and `eval_file` accept a template parameter that describes how the
|
||||||
|
string/file should be interpreted. Possible choices include ``eval_expr``
|
||||||
|
(isolated expression), ``eval_single_statement`` (a single statement, return
|
||||||
|
value is always ``none``), and ``eval_statements`` (sequence of statements,
|
||||||
|
return value is always ``none``). `eval` defaults to ``eval_expr``,
|
||||||
|
`eval_file` defaults to ``eval_statements`` and `exec` is just a shortcut
|
||||||
|
for ``eval<eval_statements>``.
|
174
3rdparty/pybind11/docs/advanced/smart_ptrs.rst
vendored
Normal file
174
3rdparty/pybind11/docs/advanced/smart_ptrs.rst
vendored
Normal file
@ -0,0 +1,174 @@
|
|||||||
|
Smart pointers
|
||||||
|
##############
|
||||||
|
|
||||||
|
std::unique_ptr
|
||||||
|
===============
|
||||||
|
|
||||||
|
Given a class ``Example`` with Python bindings, it's possible to return
|
||||||
|
instances wrapped in C++11 unique pointers, like so
|
||||||
|
|
||||||
|
.. code-block:: cpp
|
||||||
|
|
||||||
|
std::unique_ptr<Example> create_example() { return std::unique_ptr<Example>(new Example()); }
|
||||||
|
|
||||||
|
.. code-block:: cpp
|
||||||
|
|
||||||
|
m.def("create_example", &create_example);
|
||||||
|
|
||||||
|
In other words, there is nothing special that needs to be done. While returning
|
||||||
|
unique pointers in this way is allowed, it is *illegal* to use them as function
|
||||||
|
arguments. For instance, the following function signature cannot be processed
|
||||||
|
by pybind11.
|
||||||
|
|
||||||
|
.. code-block:: cpp
|
||||||
|
|
||||||
|
void do_something_with_example(std::unique_ptr<Example> ex) { ... }
|
||||||
|
|
||||||
|
The above signature would imply that Python needs to give up ownership of an
|
||||||
|
object that is passed to this function, which is generally not possible (for
|
||||||
|
instance, the object might be referenced elsewhere).
|
||||||
|
|
||||||
|
std::shared_ptr
|
||||||
|
===============
|
||||||
|
|
||||||
|
The binding generator for classes, :class:`class_`, can be passed a template
|
||||||
|
type that denotes a special *holder* type that is used to manage references to
|
||||||
|
the object. If no such holder type template argument is given, the default for
|
||||||
|
a type named ``Type`` is ``std::unique_ptr<Type>``, which means that the object
|
||||||
|
is deallocated when Python's reference count goes to zero.
|
||||||
|
|
||||||
|
It is possible to switch to other types of reference counting wrappers or smart
|
||||||
|
pointers, which is useful in codebases that rely on them. For instance, the
|
||||||
|
following snippet causes ``std::shared_ptr`` to be used instead.
|
||||||
|
|
||||||
|
.. code-block:: cpp
|
||||||
|
|
||||||
|
py::class_<Example, std::shared_ptr<Example> /* <- holder type */> obj(m, "Example");
|
||||||
|
|
||||||
|
Note that any particular class can only be associated with a single holder type.
|
||||||
|
|
||||||
|
One potential stumbling block when using holder types is that they need to be
|
||||||
|
applied consistently. Can you guess what's broken about the following binding
|
||||||
|
code?
|
||||||
|
|
||||||
|
.. code-block:: cpp
|
||||||
|
|
||||||
|
class Child { };
|
||||||
|
|
||||||
|
class Parent {
|
||||||
|
public:
|
||||||
|
Parent() : child(std::make_shared<Child>()) { }
|
||||||
|
Child *get_child() { return child.get(); } /* Hint: ** DON'T DO THIS ** */
|
||||||
|
private:
|
||||||
|
std::shared_ptr<Child> child;
|
||||||
|
};
|
||||||
|
|
||||||
|
PYBIND11_MODULE(example, m) {
|
||||||
|
py::class_<Child, std::shared_ptr<Child>>(m, "Child");
|
||||||
|
|
||||||
|
py::class_<Parent, std::shared_ptr<Parent>>(m, "Parent")
|
||||||
|
.def(py::init<>())
|
||||||
|
.def("get_child", &Parent::get_child);
|
||||||
|
}
|
||||||
|
|
||||||
|
The following Python code will cause undefined behavior (and likely a
|
||||||
|
segmentation fault).
|
||||||
|
|
||||||
|
.. code-block:: python
|
||||||
|
|
||||||
|
from example import Parent
|
||||||
|
|
||||||
|
print(Parent().get_child())
|
||||||
|
|
||||||
|
The problem is that ``Parent::get_child()`` returns a pointer to an instance of
|
||||||
|
``Child``, but the fact that this instance is already managed by
|
||||||
|
``std::shared_ptr<...>`` is lost when passing raw pointers. In this case,
|
||||||
|
pybind11 will create a second independent ``std::shared_ptr<...>`` that also
|
||||||
|
claims ownership of the pointer. In the end, the object will be freed **twice**
|
||||||
|
since these shared pointers have no way of knowing about each other.
|
||||||
|
|
||||||
|
There are two ways to resolve this issue:
|
||||||
|
|
||||||
|
1. For types that are managed by a smart pointer class, never use raw pointers
|
||||||
|
in function arguments or return values. In other words: always consistently
|
||||||
|
wrap pointers into their designated holder types (such as
|
||||||
|
``std::shared_ptr<...>``). In this case, the signature of ``get_child()``
|
||||||
|
should be modified as follows:
|
||||||
|
|
||||||
|
.. code-block:: cpp
|
||||||
|
|
||||||
|
std::shared_ptr<Child> get_child() { return child; }
|
||||||
|
|
||||||
|
2. Adjust the definition of ``Child`` by specifying
|
||||||
|
``std::enable_shared_from_this<T>`` (see cppreference_ for details) as a
|
||||||
|
base class. This adds a small bit of information to ``Child`` that allows
|
||||||
|
pybind11 to realize that there is already an existing
|
||||||
|
``std::shared_ptr<...>`` and communicate with it. In this case, the
|
||||||
|
declaration of ``Child`` should look as follows:
|
||||||
|
|
||||||
|
.. _cppreference: http://en.cppreference.com/w/cpp/memory/enable_shared_from_this
|
||||||
|
|
||||||
|
.. code-block:: cpp
|
||||||
|
|
||||||
|
class Child : public std::enable_shared_from_this<Child> { };
|
||||||
|
|
||||||
|
.. _smart_pointers:
|
||||||
|
|
||||||
|
Custom smart pointers
|
||||||
|
=====================
|
||||||
|
|
||||||
|
pybind11 supports ``std::unique_ptr`` and ``std::shared_ptr`` right out of the
|
||||||
|
box. For any other custom smart pointer, transparent conversions can be enabled
|
||||||
|
using a macro invocation similar to the following. It must be declared at the
|
||||||
|
top namespace level before any binding code:
|
||||||
|
|
||||||
|
.. code-block:: cpp
|
||||||
|
|
||||||
|
PYBIND11_DECLARE_HOLDER_TYPE(T, SmartPtr<T>);
|
||||||
|
|
||||||
|
The first argument of :func:`PYBIND11_DECLARE_HOLDER_TYPE` should be a
|
||||||
|
placeholder name that is used as a template parameter of the second argument.
|
||||||
|
Thus, feel free to use any identifier, but use it consistently on both sides;
|
||||||
|
also, don't use the name of a type that already exists in your codebase.
|
||||||
|
|
||||||
|
The macro also accepts a third optional boolean parameter that is set to false
|
||||||
|
by default. Specify
|
||||||
|
|
||||||
|
.. code-block:: cpp
|
||||||
|
|
||||||
|
PYBIND11_DECLARE_HOLDER_TYPE(T, SmartPtr<T>, true);
|
||||||
|
|
||||||
|
if ``SmartPtr<T>`` can always be initialized from a ``T*`` pointer without the
|
||||||
|
risk of inconsistencies (such as multiple independent ``SmartPtr`` instances
|
||||||
|
believing that they are the sole owner of the ``T*`` pointer). A common
|
||||||
|
situation where ``true`` should be passed is when the ``T`` instances use
|
||||||
|
*intrusive* reference counting.
|
||||||
|
|
||||||
|
Please take a look at the :ref:`macro_notes` before using this feature.
|
||||||
|
|
||||||
|
By default, pybind11 assumes that your custom smart pointer has a standard
|
||||||
|
interface, i.e. provides a ``.get()`` member function to access the underlying
|
||||||
|
raw pointer. If this is not the case, pybind11's ``holder_helper`` must be
|
||||||
|
specialized:
|
||||||
|
|
||||||
|
.. code-block:: cpp
|
||||||
|
|
||||||
|
// Always needed for custom holder types
|
||||||
|
PYBIND11_DECLARE_HOLDER_TYPE(T, SmartPtr<T>);
|
||||||
|
|
||||||
|
// Only needed if the type's `.get()` goes by another name
|
||||||
|
namespace PYBIND11_NAMESPACE { namespace detail {
|
||||||
|
template <typename T>
|
||||||
|
struct holder_helper<SmartPtr<T>> { // <-- specialization
|
||||||
|
static const T *get(const SmartPtr<T> &p) { return p.getPointer(); }
|
||||||
|
};
|
||||||
|
}}
|
||||||
|
|
||||||
|
The above specialization informs pybind11 that the custom ``SmartPtr`` class
|
||||||
|
provides ``.get()`` functionality via ``.getPointer()``.
|
||||||
|
|
||||||
|
.. seealso::
|
||||||
|
|
||||||
|
The file :file:`tests/test_smart_ptr.cpp` contains a complete example
|
||||||
|
that demonstrates how to work with custom reference-counting holder types
|
||||||
|
in more detail.
|
307
3rdparty/pybind11/docs/basics.rst
vendored
Normal file
307
3rdparty/pybind11/docs/basics.rst
vendored
Normal file
@ -0,0 +1,307 @@
|
|||||||
|
.. _basics:
|
||||||
|
|
||||||
|
First steps
|
||||||
|
###########
|
||||||
|
|
||||||
|
This sections demonstrates the basic features of pybind11. Before getting
|
||||||
|
started, make sure that development environment is set up to compile the
|
||||||
|
included set of test cases.
|
||||||
|
|
||||||
|
|
||||||
|
Compiling the test cases
|
||||||
|
========================
|
||||||
|
|
||||||
|
Linux/macOS
|
||||||
|
-----------
|
||||||
|
|
||||||
|
On Linux you'll need to install the **python-dev** or **python3-dev** packages as
|
||||||
|
well as **cmake**. On macOS, the included python version works out of the box,
|
||||||
|
but **cmake** must still be installed.
|
||||||
|
|
||||||
|
After installing the prerequisites, run
|
||||||
|
|
||||||
|
.. code-block:: bash
|
||||||
|
|
||||||
|
mkdir build
|
||||||
|
cd build
|
||||||
|
cmake ..
|
||||||
|
make check -j 4
|
||||||
|
|
||||||
|
The last line will both compile and run the tests.
|
||||||
|
|
||||||
|
Windows
|
||||||
|
-------
|
||||||
|
|
||||||
|
On Windows, only **Visual Studio 2017** and newer are supported.
|
||||||
|
|
||||||
|
.. Note::
|
||||||
|
|
||||||
|
To use the C++17 in Visual Studio 2017 (MSVC 14.1), pybind11 requires the flag
|
||||||
|
``/permissive-`` to be passed to the compiler `to enforce standard conformance`_. When
|
||||||
|
building with Visual Studio 2019, this is not strictly necessary, but still advised.
|
||||||
|
|
||||||
|
.. _`to enforce standard conformance`: https://docs.microsoft.com/en-us/cpp/build/reference/permissive-standards-conformance?view=vs-2017
|
||||||
|
|
||||||
|
To compile and run the tests:
|
||||||
|
|
||||||
|
.. code-block:: batch
|
||||||
|
|
||||||
|
mkdir build
|
||||||
|
cd build
|
||||||
|
cmake ..
|
||||||
|
cmake --build . --config Release --target check
|
||||||
|
|
||||||
|
This will create a Visual Studio project, compile and run the target, all from the
|
||||||
|
command line.
|
||||||
|
|
||||||
|
.. Note::
|
||||||
|
|
||||||
|
If all tests fail, make sure that the Python binary and the testcases are compiled
|
||||||
|
for the same processor type and bitness (i.e. either **i386** or **x86_64**). You
|
||||||
|
can specify **x86_64** as the target architecture for the generated Visual Studio
|
||||||
|
project using ``cmake -A x64 ..``.
|
||||||
|
|
||||||
|
.. seealso::
|
||||||
|
|
||||||
|
Advanced users who are already familiar with Boost.Python may want to skip
|
||||||
|
the tutorial and look at the test cases in the :file:`tests` directory,
|
||||||
|
which exercise all features of pybind11.
|
||||||
|
|
||||||
|
Header and namespace conventions
|
||||||
|
================================
|
||||||
|
|
||||||
|
For brevity, all code examples assume that the following two lines are present:
|
||||||
|
|
||||||
|
.. code-block:: cpp
|
||||||
|
|
||||||
|
#include <pybind11/pybind11.h>
|
||||||
|
|
||||||
|
namespace py = pybind11;
|
||||||
|
|
||||||
|
Some features may require additional headers, but those will be specified as needed.
|
||||||
|
|
||||||
|
.. _simple_example:
|
||||||
|
|
||||||
|
Creating bindings for a simple function
|
||||||
|
=======================================
|
||||||
|
|
||||||
|
Let's start by creating Python bindings for an extremely simple function, which
|
||||||
|
adds two numbers and returns their result:
|
||||||
|
|
||||||
|
.. code-block:: cpp
|
||||||
|
|
||||||
|
int add(int i, int j) {
|
||||||
|
return i + j;
|
||||||
|
}
|
||||||
|
|
||||||
|
For simplicity [#f1]_, we'll put both this function and the binding code into
|
||||||
|
a file named :file:`example.cpp` with the following contents:
|
||||||
|
|
||||||
|
.. code-block:: cpp
|
||||||
|
|
||||||
|
#include <pybind11/pybind11.h>
|
||||||
|
|
||||||
|
int add(int i, int j) {
|
||||||
|
return i + j;
|
||||||
|
}
|
||||||
|
|
||||||
|
PYBIND11_MODULE(example, m) {
|
||||||
|
m.doc() = "pybind11 example plugin"; // optional module docstring
|
||||||
|
|
||||||
|
m.def("add", &add, "A function that adds two numbers");
|
||||||
|
}
|
||||||
|
|
||||||
|
.. [#f1] In practice, implementation and binding code will generally be located
|
||||||
|
in separate files.
|
||||||
|
|
||||||
|
The :func:`PYBIND11_MODULE` macro creates a function that will be called when an
|
||||||
|
``import`` statement is issued from within Python. The module name (``example``)
|
||||||
|
is given as the first macro argument (it should not be in quotes). The second
|
||||||
|
argument (``m``) defines a variable of type :class:`py::module_ <module>` which
|
||||||
|
is the main interface for creating bindings. The method :func:`module_::def`
|
||||||
|
generates binding code that exposes the ``add()`` function to Python.
|
||||||
|
|
||||||
|
.. note::
|
||||||
|
|
||||||
|
Notice how little code was needed to expose our function to Python: all
|
||||||
|
details regarding the function's parameters and return value were
|
||||||
|
automatically inferred using template metaprogramming. This overall
|
||||||
|
approach and the used syntax are borrowed from Boost.Python, though the
|
||||||
|
underlying implementation is very different.
|
||||||
|
|
||||||
|
pybind11 is a header-only library, hence it is not necessary to link against
|
||||||
|
any special libraries and there are no intermediate (magic) translation steps.
|
||||||
|
On Linux, the above example can be compiled using the following command:
|
||||||
|
|
||||||
|
.. code-block:: bash
|
||||||
|
|
||||||
|
$ c++ -O3 -Wall -shared -std=c++11 -fPIC $(python3 -m pybind11 --includes) example.cpp -o example$(python3-config --extension-suffix)
|
||||||
|
|
||||||
|
.. note::
|
||||||
|
|
||||||
|
If you used :ref:`include_as_a_submodule` to get the pybind11 source, then
|
||||||
|
use ``$(python3-config --includes) -Iextern/pybind11/include`` instead of
|
||||||
|
``$(python3 -m pybind11 --includes)`` in the above compilation, as
|
||||||
|
explained in :ref:`building_manually`.
|
||||||
|
|
||||||
|
For more details on the required compiler flags on Linux and macOS, see
|
||||||
|
:ref:`building_manually`. For complete cross-platform compilation instructions,
|
||||||
|
refer to the :ref:`compiling` page.
|
||||||
|
|
||||||
|
The `python_example`_ and `cmake_example`_ repositories are also a good place
|
||||||
|
to start. They are both complete project examples with cross-platform build
|
||||||
|
systems. The only difference between the two is that `python_example`_ uses
|
||||||
|
Python's ``setuptools`` to build the module, while `cmake_example`_ uses CMake
|
||||||
|
(which may be preferable for existing C++ projects).
|
||||||
|
|
||||||
|
.. _python_example: https://github.com/pybind/python_example
|
||||||
|
.. _cmake_example: https://github.com/pybind/cmake_example
|
||||||
|
|
||||||
|
Building the above C++ code will produce a binary module file that can be
|
||||||
|
imported to Python. Assuming that the compiled module is located in the
|
||||||
|
current directory, the following interactive Python session shows how to
|
||||||
|
load and execute the example:
|
||||||
|
|
||||||
|
.. code-block:: pycon
|
||||||
|
|
||||||
|
$ python
|
||||||
|
Python 3.9.10 (main, Jan 15 2022, 11:48:04)
|
||||||
|
[Clang 13.0.0 (clang-1300.0.29.3)] on darwin
|
||||||
|
Type "help", "copyright", "credits" or "license" for more information.
|
||||||
|
>>> import example
|
||||||
|
>>> example.add(1, 2)
|
||||||
|
3
|
||||||
|
>>>
|
||||||
|
|
||||||
|
.. _keyword_args:
|
||||||
|
|
||||||
|
Keyword arguments
|
||||||
|
=================
|
||||||
|
|
||||||
|
With a simple code modification, it is possible to inform Python about the
|
||||||
|
names of the arguments ("i" and "j" in this case).
|
||||||
|
|
||||||
|
.. code-block:: cpp
|
||||||
|
|
||||||
|
m.def("add", &add, "A function which adds two numbers",
|
||||||
|
py::arg("i"), py::arg("j"));
|
||||||
|
|
||||||
|
:class:`arg` is one of several special tag classes which can be used to pass
|
||||||
|
metadata into :func:`module_::def`. With this modified binding code, we can now
|
||||||
|
call the function using keyword arguments, which is a more readable alternative
|
||||||
|
particularly for functions taking many parameters:
|
||||||
|
|
||||||
|
.. code-block:: pycon
|
||||||
|
|
||||||
|
>>> import example
|
||||||
|
>>> example.add(i=1, j=2)
|
||||||
|
3L
|
||||||
|
|
||||||
|
The keyword names also appear in the function signatures within the documentation.
|
||||||
|
|
||||||
|
.. code-block:: pycon
|
||||||
|
|
||||||
|
>>> help(example)
|
||||||
|
|
||||||
|
....
|
||||||
|
|
||||||
|
FUNCTIONS
|
||||||
|
add(...)
|
||||||
|
Signature : (i: int, j: int) -> int
|
||||||
|
|
||||||
|
A function which adds two numbers
|
||||||
|
|
||||||
|
A shorter notation for named arguments is also available:
|
||||||
|
|
||||||
|
.. code-block:: cpp
|
||||||
|
|
||||||
|
// regular notation
|
||||||
|
m.def("add1", &add, py::arg("i"), py::arg("j"));
|
||||||
|
// shorthand
|
||||||
|
using namespace pybind11::literals;
|
||||||
|
m.def("add2", &add, "i"_a, "j"_a);
|
||||||
|
|
||||||
|
The :var:`_a` suffix forms a C++11 literal which is equivalent to :class:`arg`.
|
||||||
|
Note that the literal operator must first be made visible with the directive
|
||||||
|
``using namespace pybind11::literals``. This does not bring in anything else
|
||||||
|
from the ``pybind11`` namespace except for literals.
|
||||||
|
|
||||||
|
.. _default_args:
|
||||||
|
|
||||||
|
Default arguments
|
||||||
|
=================
|
||||||
|
|
||||||
|
Suppose now that the function to be bound has default arguments, e.g.:
|
||||||
|
|
||||||
|
.. code-block:: cpp
|
||||||
|
|
||||||
|
int add(int i = 1, int j = 2) {
|
||||||
|
return i + j;
|
||||||
|
}
|
||||||
|
|
||||||
|
Unfortunately, pybind11 cannot automatically extract these parameters, since they
|
||||||
|
are not part of the function's type information. However, they are simple to specify
|
||||||
|
using an extension of :class:`arg`:
|
||||||
|
|
||||||
|
.. code-block:: cpp
|
||||||
|
|
||||||
|
m.def("add", &add, "A function which adds two numbers",
|
||||||
|
py::arg("i") = 1, py::arg("j") = 2);
|
||||||
|
|
||||||
|
The default values also appear within the documentation.
|
||||||
|
|
||||||
|
.. code-block:: pycon
|
||||||
|
|
||||||
|
>>> help(example)
|
||||||
|
|
||||||
|
....
|
||||||
|
|
||||||
|
FUNCTIONS
|
||||||
|
add(...)
|
||||||
|
Signature : (i: int = 1, j: int = 2) -> int
|
||||||
|
|
||||||
|
A function which adds two numbers
|
||||||
|
|
||||||
|
The shorthand notation is also available for default arguments:
|
||||||
|
|
||||||
|
.. code-block:: cpp
|
||||||
|
|
||||||
|
// regular notation
|
||||||
|
m.def("add1", &add, py::arg("i") = 1, py::arg("j") = 2);
|
||||||
|
// shorthand
|
||||||
|
m.def("add2", &add, "i"_a=1, "j"_a=2);
|
||||||
|
|
||||||
|
Exporting variables
|
||||||
|
===================
|
||||||
|
|
||||||
|
To expose a value from C++, use the ``attr`` function to register it in a
|
||||||
|
module as shown below. Built-in types and general objects (more on that later)
|
||||||
|
are automatically converted when assigned as attributes, and can be explicitly
|
||||||
|
converted using the function ``py::cast``.
|
||||||
|
|
||||||
|
.. code-block:: cpp
|
||||||
|
|
||||||
|
PYBIND11_MODULE(example, m) {
|
||||||
|
m.attr("the_answer") = 42;
|
||||||
|
py::object world = py::cast("World");
|
||||||
|
m.attr("what") = world;
|
||||||
|
}
|
||||||
|
|
||||||
|
These are then accessible from Python:
|
||||||
|
|
||||||
|
.. code-block:: pycon
|
||||||
|
|
||||||
|
>>> import example
|
||||||
|
>>> example.the_answer
|
||||||
|
42
|
||||||
|
>>> example.what
|
||||||
|
'World'
|
||||||
|
|
||||||
|
.. _supported_types:
|
||||||
|
|
||||||
|
Supported data types
|
||||||
|
====================
|
||||||
|
|
||||||
|
A large number of data types are supported out of the box and can be used
|
||||||
|
seamlessly as functions arguments, return values or with ``py::cast`` in general.
|
||||||
|
For a full overview, see the :doc:`advanced/cast/index` section.
|
87
3rdparty/pybind11/docs/benchmark.py
vendored
Normal file
87
3rdparty/pybind11/docs/benchmark.py
vendored
Normal file
@ -0,0 +1,87 @@
|
|||||||
|
import datetime as dt
|
||||||
|
import os
|
||||||
|
import random
|
||||||
|
|
||||||
|
nfns = 4 # Functions per class
|
||||||
|
nargs = 4 # Arguments per function
|
||||||
|
|
||||||
|
|
||||||
|
def generate_dummy_code_pybind11(nclasses=10):
|
||||||
|
decl = ""
|
||||||
|
bindings = ""
|
||||||
|
|
||||||
|
for cl in range(nclasses):
|
||||||
|
decl += f"class cl{cl:03};\n"
|
||||||
|
decl += "\n"
|
||||||
|
|
||||||
|
for cl in range(nclasses):
|
||||||
|
decl += f"class {cl:03} {{\n"
|
||||||
|
decl += "public:\n"
|
||||||
|
bindings += f' py::class_<cl{cl:03}>(m, "cl{cl:03}")\n'
|
||||||
|
for fn in range(nfns):
|
||||||
|
ret = random.randint(0, nclasses - 1)
|
||||||
|
params = [random.randint(0, nclasses - 1) for i in range(nargs)]
|
||||||
|
decl += f" cl{ret:03} *fn_{fn:03}("
|
||||||
|
decl += ", ".join(f"cl{p:03} *" for p in params)
|
||||||
|
decl += ");\n"
|
||||||
|
bindings += f' .def("fn_{fn:03}", &cl{cl:03}::fn_{fn:03})\n'
|
||||||
|
decl += "};\n\n"
|
||||||
|
bindings += " ;\n"
|
||||||
|
|
||||||
|
result = "#include <pybind11/pybind11.h>\n\n"
|
||||||
|
result += "namespace py = pybind11;\n\n"
|
||||||
|
result += decl + "\n"
|
||||||
|
result += "PYBIND11_MODULE(example, m) {\n"
|
||||||
|
result += bindings
|
||||||
|
result += "}"
|
||||||
|
return result
|
||||||
|
|
||||||
|
|
||||||
|
def generate_dummy_code_boost(nclasses=10):
|
||||||
|
decl = ""
|
||||||
|
bindings = ""
|
||||||
|
|
||||||
|
for cl in range(nclasses):
|
||||||
|
decl += f"class cl{cl:03};\n"
|
||||||
|
decl += "\n"
|
||||||
|
|
||||||
|
for cl in range(nclasses):
|
||||||
|
decl += "class cl%03i {\n" % cl
|
||||||
|
decl += "public:\n"
|
||||||
|
bindings += f' py::class_<cl{cl:03}>("cl{cl:03}")\n'
|
||||||
|
for fn in range(nfns):
|
||||||
|
ret = random.randint(0, nclasses - 1)
|
||||||
|
params = [random.randint(0, nclasses - 1) for i in range(nargs)]
|
||||||
|
decl += f" cl{ret:03} *fn_{fn:03}("
|
||||||
|
decl += ", ".join(f"cl{p:03} *" for p in params)
|
||||||
|
decl += ");\n"
|
||||||
|
bindings += f' .def("fn_{fn:03}", &cl{cl:03}::fn_{fn:03}, py::return_value_policy<py::manage_new_object>())\n'
|
||||||
|
decl += "};\n\n"
|
||||||
|
bindings += " ;\n"
|
||||||
|
|
||||||
|
result = "#include <boost/python.hpp>\n\n"
|
||||||
|
result += "namespace py = boost::python;\n\n"
|
||||||
|
result += decl + "\n"
|
||||||
|
result += "BOOST_PYTHON_MODULE(example) {\n"
|
||||||
|
result += bindings
|
||||||
|
result += "}"
|
||||||
|
return result
|
||||||
|
|
||||||
|
|
||||||
|
for codegen in [generate_dummy_code_pybind11, generate_dummy_code_boost]:
|
||||||
|
print("{")
|
||||||
|
for i in range(10):
|
||||||
|
nclasses = 2**i
|
||||||
|
with open("test.cpp", "w") as f:
|
||||||
|
f.write(codegen(nclasses))
|
||||||
|
n1 = dt.datetime.now()
|
||||||
|
os.system(
|
||||||
|
"g++ -Os -shared -rdynamic -undefined dynamic_lookup "
|
||||||
|
"-fvisibility=hidden -std=c++14 test.cpp -I include "
|
||||||
|
"-I /System/Library/Frameworks/Python.framework/Headers -o test.so"
|
||||||
|
)
|
||||||
|
n2 = dt.datetime.now()
|
||||||
|
elapsed = (n2 - n1).total_seconds()
|
||||||
|
size = os.stat("test.so").st_size
|
||||||
|
print(" {%i, %f, %i}," % (nclasses * nfns, elapsed, size))
|
||||||
|
print("}")
|
95
3rdparty/pybind11/docs/benchmark.rst
vendored
Normal file
95
3rdparty/pybind11/docs/benchmark.rst
vendored
Normal file
@ -0,0 +1,95 @@
|
|||||||
|
Benchmark
|
||||||
|
=========
|
||||||
|
|
||||||
|
The following is the result of a synthetic benchmark comparing both compilation
|
||||||
|
time and module size of pybind11 against Boost.Python. A detailed report about a
|
||||||
|
Boost.Python to pybind11 conversion of a real project is available here: [#f1]_.
|
||||||
|
|
||||||
|
.. [#f1] http://graylab.jhu.edu/RosettaCon2016/PyRosetta-4.pdf
|
||||||
|
|
||||||
|
Setup
|
||||||
|
-----
|
||||||
|
|
||||||
|
A python script (see the ``docs/benchmark.py`` file) was used to generate a set
|
||||||
|
of files with dummy classes whose count increases for each successive benchmark
|
||||||
|
(between 1 and 2048 classes in powers of two). Each class has four methods with
|
||||||
|
a randomly generated signature with a return value and four arguments. (There
|
||||||
|
was no particular reason for this setup other than the desire to generate many
|
||||||
|
unique function signatures whose count could be controlled in a simple way.)
|
||||||
|
|
||||||
|
Here is an example of the binding code for one class:
|
||||||
|
|
||||||
|
.. code-block:: cpp
|
||||||
|
|
||||||
|
...
|
||||||
|
class cl034 {
|
||||||
|
public:
|
||||||
|
cl279 *fn_000(cl084 *, cl057 *, cl065 *, cl042 *);
|
||||||
|
cl025 *fn_001(cl098 *, cl262 *, cl414 *, cl121 *);
|
||||||
|
cl085 *fn_002(cl445 *, cl297 *, cl145 *, cl421 *);
|
||||||
|
cl470 *fn_003(cl200 *, cl323 *, cl332 *, cl492 *);
|
||||||
|
};
|
||||||
|
...
|
||||||
|
|
||||||
|
PYBIND11_MODULE(example, m) {
|
||||||
|
...
|
||||||
|
py::class_<cl034>(m, "cl034")
|
||||||
|
.def("fn_000", &cl034::fn_000)
|
||||||
|
.def("fn_001", &cl034::fn_001)
|
||||||
|
.def("fn_002", &cl034::fn_002)
|
||||||
|
.def("fn_003", &cl034::fn_003)
|
||||||
|
...
|
||||||
|
}
|
||||||
|
|
||||||
|
The Boost.Python version looks almost identical except that a return value
|
||||||
|
policy had to be specified as an argument to ``def()``. For both libraries,
|
||||||
|
compilation was done with
|
||||||
|
|
||||||
|
.. code-block:: bash
|
||||||
|
|
||||||
|
Apple LLVM version 7.0.2 (clang-700.1.81)
|
||||||
|
|
||||||
|
and the following compilation flags
|
||||||
|
|
||||||
|
.. code-block:: bash
|
||||||
|
|
||||||
|
g++ -Os -shared -rdynamic -undefined dynamic_lookup -fvisibility=hidden -std=c++14
|
||||||
|
|
||||||
|
Compilation time
|
||||||
|
----------------
|
||||||
|
|
||||||
|
The following log-log plot shows how the compilation time grows for an
|
||||||
|
increasing number of class and function declarations. pybind11 includes many
|
||||||
|
fewer headers, which initially leads to shorter compilation times, but the
|
||||||
|
performance is ultimately fairly similar (pybind11 is 19.8 seconds faster for
|
||||||
|
the largest largest file with 2048 classes and a total of 8192 methods -- a
|
||||||
|
modest **1.2x** speedup relative to Boost.Python, which required 116.35
|
||||||
|
seconds).
|
||||||
|
|
||||||
|
.. only:: not latex
|
||||||
|
|
||||||
|
.. image:: pybind11_vs_boost_python1.svg
|
||||||
|
|
||||||
|
.. only:: latex
|
||||||
|
|
||||||
|
.. image:: pybind11_vs_boost_python1.png
|
||||||
|
|
||||||
|
Module size
|
||||||
|
-----------
|
||||||
|
|
||||||
|
Differences between the two libraries become much more pronounced when
|
||||||
|
considering the file size of the generated Python plugin: for the largest file,
|
||||||
|
the binary generated by Boost.Python required 16.8 MiB, which was **2.17
|
||||||
|
times** / **9.1 megabytes** larger than the output generated by pybind11. For
|
||||||
|
very small inputs, Boost.Python has an edge in the plot below -- however, note
|
||||||
|
that it stores many definitions in an external library, whose size was not
|
||||||
|
included here, hence the comparison is slightly shifted in Boost.Python's
|
||||||
|
favor.
|
||||||
|
|
||||||
|
.. only:: not latex
|
||||||
|
|
||||||
|
.. image:: pybind11_vs_boost_python2.svg
|
||||||
|
|
||||||
|
.. only:: latex
|
||||||
|
|
||||||
|
.. image:: pybind11_vs_boost_python2.png
|
3019
3rdparty/pybind11/docs/changelog.rst
vendored
Normal file
3019
3rdparty/pybind11/docs/changelog.rst
vendored
Normal file
File diff suppressed because it is too large
Load Diff
555
3rdparty/pybind11/docs/classes.rst
vendored
Normal file
555
3rdparty/pybind11/docs/classes.rst
vendored
Normal file
@ -0,0 +1,555 @@
|
|||||||
|
.. _classes:
|
||||||
|
|
||||||
|
Object-oriented code
|
||||||
|
####################
|
||||||
|
|
||||||
|
Creating bindings for a custom type
|
||||||
|
===================================
|
||||||
|
|
||||||
|
Let's now look at a more complex example where we'll create bindings for a
|
||||||
|
custom C++ data structure named ``Pet``. Its definition is given below:
|
||||||
|
|
||||||
|
.. code-block:: cpp
|
||||||
|
|
||||||
|
struct Pet {
|
||||||
|
Pet(const std::string &name) : name(name) { }
|
||||||
|
void setName(const std::string &name_) { name = name_; }
|
||||||
|
const std::string &getName() const { return name; }
|
||||||
|
|
||||||
|
std::string name;
|
||||||
|
};
|
||||||
|
|
||||||
|
The binding code for ``Pet`` looks as follows:
|
||||||
|
|
||||||
|
.. code-block:: cpp
|
||||||
|
|
||||||
|
#include <pybind11/pybind11.h>
|
||||||
|
|
||||||
|
namespace py = pybind11;
|
||||||
|
|
||||||
|
PYBIND11_MODULE(example, m) {
|
||||||
|
py::class_<Pet>(m, "Pet")
|
||||||
|
.def(py::init<const std::string &>())
|
||||||
|
.def("setName", &Pet::setName)
|
||||||
|
.def("getName", &Pet::getName);
|
||||||
|
}
|
||||||
|
|
||||||
|
:class:`class_` creates bindings for a C++ *class* or *struct*-style data
|
||||||
|
structure. :func:`init` is a convenience function that takes the types of a
|
||||||
|
constructor's parameters as template arguments and wraps the corresponding
|
||||||
|
constructor (see the :ref:`custom_constructors` section for details). An
|
||||||
|
interactive Python session demonstrating this example is shown below:
|
||||||
|
|
||||||
|
.. code-block:: pycon
|
||||||
|
|
||||||
|
% python
|
||||||
|
>>> import example
|
||||||
|
>>> p = example.Pet("Molly")
|
||||||
|
>>> print(p)
|
||||||
|
<example.Pet object at 0x10cd98060>
|
||||||
|
>>> p.getName()
|
||||||
|
'Molly'
|
||||||
|
>>> p.setName("Charly")
|
||||||
|
>>> p.getName()
|
||||||
|
'Charly'
|
||||||
|
|
||||||
|
.. seealso::
|
||||||
|
|
||||||
|
Static member functions can be bound in the same way using
|
||||||
|
:func:`class_::def_static`.
|
||||||
|
|
||||||
|
.. note::
|
||||||
|
|
||||||
|
Binding C++ types in unnamed namespaces (also known as anonymous namespaces)
|
||||||
|
works reliably on many platforms, but not all. The `XFAIL_CONDITION` in
|
||||||
|
tests/test_unnamed_namespace_a.py encodes the currently known conditions.
|
||||||
|
For background see `#4319 <https://github.com/pybind/pybind11/pull/4319>`_.
|
||||||
|
If portability is a concern, it is therefore not recommended to bind C++
|
||||||
|
types in unnamed namespaces. It will be safest to manually pick unique
|
||||||
|
namespace names.
|
||||||
|
|
||||||
|
Keyword and default arguments
|
||||||
|
=============================
|
||||||
|
It is possible to specify keyword and default arguments using the syntax
|
||||||
|
discussed in the previous chapter. Refer to the sections :ref:`keyword_args`
|
||||||
|
and :ref:`default_args` for details.
|
||||||
|
|
||||||
|
Binding lambda functions
|
||||||
|
========================
|
||||||
|
|
||||||
|
Note how ``print(p)`` produced a rather useless summary of our data structure in the example above:
|
||||||
|
|
||||||
|
.. code-block:: pycon
|
||||||
|
|
||||||
|
>>> print(p)
|
||||||
|
<example.Pet object at 0x10cd98060>
|
||||||
|
|
||||||
|
To address this, we could bind a utility function that returns a human-readable
|
||||||
|
summary to the special method slot named ``__repr__``. Unfortunately, there is no
|
||||||
|
suitable functionality in the ``Pet`` data structure, and it would be nice if
|
||||||
|
we did not have to change it. This can easily be accomplished by binding a
|
||||||
|
Lambda function instead:
|
||||||
|
|
||||||
|
.. code-block:: cpp
|
||||||
|
|
||||||
|
py::class_<Pet>(m, "Pet")
|
||||||
|
.def(py::init<const std::string &>())
|
||||||
|
.def("setName", &Pet::setName)
|
||||||
|
.def("getName", &Pet::getName)
|
||||||
|
.def("__repr__",
|
||||||
|
[](const Pet &a) {
|
||||||
|
return "<example.Pet named '" + a.name + "'>";
|
||||||
|
}
|
||||||
|
);
|
||||||
|
|
||||||
|
Both stateless [#f1]_ and stateful lambda closures are supported by pybind11.
|
||||||
|
With the above change, the same Python code now produces the following output:
|
||||||
|
|
||||||
|
.. code-block:: pycon
|
||||||
|
|
||||||
|
>>> print(p)
|
||||||
|
<example.Pet named 'Molly'>
|
||||||
|
|
||||||
|
.. [#f1] Stateless closures are those with an empty pair of brackets ``[]`` as the capture object.
|
||||||
|
|
||||||
|
.. _properties:
|
||||||
|
|
||||||
|
Instance and static fields
|
||||||
|
==========================
|
||||||
|
|
||||||
|
We can also directly expose the ``name`` field using the
|
||||||
|
:func:`class_::def_readwrite` method. A similar :func:`class_::def_readonly`
|
||||||
|
method also exists for ``const`` fields.
|
||||||
|
|
||||||
|
.. code-block:: cpp
|
||||||
|
|
||||||
|
py::class_<Pet>(m, "Pet")
|
||||||
|
.def(py::init<const std::string &>())
|
||||||
|
.def_readwrite("name", &Pet::name)
|
||||||
|
// ... remainder ...
|
||||||
|
|
||||||
|
This makes it possible to write
|
||||||
|
|
||||||
|
.. code-block:: pycon
|
||||||
|
|
||||||
|
>>> p = example.Pet("Molly")
|
||||||
|
>>> p.name
|
||||||
|
'Molly'
|
||||||
|
>>> p.name = "Charly"
|
||||||
|
>>> p.name
|
||||||
|
'Charly'
|
||||||
|
|
||||||
|
Now suppose that ``Pet::name`` was a private internal variable
|
||||||
|
that can only be accessed via setters and getters.
|
||||||
|
|
||||||
|
.. code-block:: cpp
|
||||||
|
|
||||||
|
class Pet {
|
||||||
|
public:
|
||||||
|
Pet(const std::string &name) : name(name) { }
|
||||||
|
void setName(const std::string &name_) { name = name_; }
|
||||||
|
const std::string &getName() const { return name; }
|
||||||
|
private:
|
||||||
|
std::string name;
|
||||||
|
};
|
||||||
|
|
||||||
|
In this case, the method :func:`class_::def_property`
|
||||||
|
(:func:`class_::def_property_readonly` for read-only data) can be used to
|
||||||
|
provide a field-like interface within Python that will transparently call
|
||||||
|
the setter and getter functions:
|
||||||
|
|
||||||
|
.. code-block:: cpp
|
||||||
|
|
||||||
|
py::class_<Pet>(m, "Pet")
|
||||||
|
.def(py::init<const std::string &>())
|
||||||
|
.def_property("name", &Pet::getName, &Pet::setName)
|
||||||
|
// ... remainder ...
|
||||||
|
|
||||||
|
Write only properties can be defined by passing ``nullptr`` as the
|
||||||
|
input for the read function.
|
||||||
|
|
||||||
|
.. seealso::
|
||||||
|
|
||||||
|
Similar functions :func:`class_::def_readwrite_static`,
|
||||||
|
:func:`class_::def_readonly_static` :func:`class_::def_property_static`,
|
||||||
|
and :func:`class_::def_property_readonly_static` are provided for binding
|
||||||
|
static variables and properties. Please also see the section on
|
||||||
|
:ref:`static_properties` in the advanced part of the documentation.
|
||||||
|
|
||||||
|
Dynamic attributes
|
||||||
|
==================
|
||||||
|
|
||||||
|
Native Python classes can pick up new attributes dynamically:
|
||||||
|
|
||||||
|
.. code-block:: pycon
|
||||||
|
|
||||||
|
>>> class Pet:
|
||||||
|
... name = "Molly"
|
||||||
|
...
|
||||||
|
>>> p = Pet()
|
||||||
|
>>> p.name = "Charly" # overwrite existing
|
||||||
|
>>> p.age = 2 # dynamically add a new attribute
|
||||||
|
|
||||||
|
By default, classes exported from C++ do not support this and the only writable
|
||||||
|
attributes are the ones explicitly defined using :func:`class_::def_readwrite`
|
||||||
|
or :func:`class_::def_property`.
|
||||||
|
|
||||||
|
.. code-block:: cpp
|
||||||
|
|
||||||
|
py::class_<Pet>(m, "Pet")
|
||||||
|
.def(py::init<>())
|
||||||
|
.def_readwrite("name", &Pet::name);
|
||||||
|
|
||||||
|
Trying to set any other attribute results in an error:
|
||||||
|
|
||||||
|
.. code-block:: pycon
|
||||||
|
|
||||||
|
>>> p = example.Pet()
|
||||||
|
>>> p.name = "Charly" # OK, attribute defined in C++
|
||||||
|
>>> p.age = 2 # fail
|
||||||
|
AttributeError: 'Pet' object has no attribute 'age'
|
||||||
|
|
||||||
|
To enable dynamic attributes for C++ classes, the :class:`py::dynamic_attr` tag
|
||||||
|
must be added to the :class:`py::class_` constructor:
|
||||||
|
|
||||||
|
.. code-block:: cpp
|
||||||
|
|
||||||
|
py::class_<Pet>(m, "Pet", py::dynamic_attr())
|
||||||
|
.def(py::init<>())
|
||||||
|
.def_readwrite("name", &Pet::name);
|
||||||
|
|
||||||
|
Now everything works as expected:
|
||||||
|
|
||||||
|
.. code-block:: pycon
|
||||||
|
|
||||||
|
>>> p = example.Pet()
|
||||||
|
>>> p.name = "Charly" # OK, overwrite value in C++
|
||||||
|
>>> p.age = 2 # OK, dynamically add a new attribute
|
||||||
|
>>> p.__dict__ # just like a native Python class
|
||||||
|
{'age': 2}
|
||||||
|
|
||||||
|
Note that there is a small runtime cost for a class with dynamic attributes.
|
||||||
|
Not only because of the addition of a ``__dict__``, but also because of more
|
||||||
|
expensive garbage collection tracking which must be activated to resolve
|
||||||
|
possible circular references. Native Python classes incur this same cost by
|
||||||
|
default, so this is not anything to worry about. By default, pybind11 classes
|
||||||
|
are more efficient than native Python classes. Enabling dynamic attributes
|
||||||
|
just brings them on par.
|
||||||
|
|
||||||
|
.. _inheritance:
|
||||||
|
|
||||||
|
Inheritance and automatic downcasting
|
||||||
|
=====================================
|
||||||
|
|
||||||
|
Suppose now that the example consists of two data structures with an
|
||||||
|
inheritance relationship:
|
||||||
|
|
||||||
|
.. code-block:: cpp
|
||||||
|
|
||||||
|
struct Pet {
|
||||||
|
Pet(const std::string &name) : name(name) { }
|
||||||
|
std::string name;
|
||||||
|
};
|
||||||
|
|
||||||
|
struct Dog : Pet {
|
||||||
|
Dog(const std::string &name) : Pet(name) { }
|
||||||
|
std::string bark() const { return "woof!"; }
|
||||||
|
};
|
||||||
|
|
||||||
|
There are two different ways of indicating a hierarchical relationship to
|
||||||
|
pybind11: the first specifies the C++ base class as an extra template
|
||||||
|
parameter of the :class:`class_`:
|
||||||
|
|
||||||
|
.. code-block:: cpp
|
||||||
|
|
||||||
|
py::class_<Pet>(m, "Pet")
|
||||||
|
.def(py::init<const std::string &>())
|
||||||
|
.def_readwrite("name", &Pet::name);
|
||||||
|
|
||||||
|
// Method 1: template parameter:
|
||||||
|
py::class_<Dog, Pet /* <- specify C++ parent type */>(m, "Dog")
|
||||||
|
.def(py::init<const std::string &>())
|
||||||
|
.def("bark", &Dog::bark);
|
||||||
|
|
||||||
|
Alternatively, we can also assign a name to the previously bound ``Pet``
|
||||||
|
:class:`class_` object and reference it when binding the ``Dog`` class:
|
||||||
|
|
||||||
|
.. code-block:: cpp
|
||||||
|
|
||||||
|
py::class_<Pet> pet(m, "Pet");
|
||||||
|
pet.def(py::init<const std::string &>())
|
||||||
|
.def_readwrite("name", &Pet::name);
|
||||||
|
|
||||||
|
// Method 2: pass parent class_ object:
|
||||||
|
py::class_<Dog>(m, "Dog", pet /* <- specify Python parent type */)
|
||||||
|
.def(py::init<const std::string &>())
|
||||||
|
.def("bark", &Dog::bark);
|
||||||
|
|
||||||
|
Functionality-wise, both approaches are equivalent. Afterwards, instances will
|
||||||
|
expose fields and methods of both types:
|
||||||
|
|
||||||
|
.. code-block:: pycon
|
||||||
|
|
||||||
|
>>> p = example.Dog("Molly")
|
||||||
|
>>> p.name
|
||||||
|
'Molly'
|
||||||
|
>>> p.bark()
|
||||||
|
'woof!'
|
||||||
|
|
||||||
|
The C++ classes defined above are regular non-polymorphic types with an
|
||||||
|
inheritance relationship. This is reflected in Python:
|
||||||
|
|
||||||
|
.. code-block:: cpp
|
||||||
|
|
||||||
|
// Return a base pointer to a derived instance
|
||||||
|
m.def("pet_store", []() { return std::unique_ptr<Pet>(new Dog("Molly")); });
|
||||||
|
|
||||||
|
.. code-block:: pycon
|
||||||
|
|
||||||
|
>>> p = example.pet_store()
|
||||||
|
>>> type(p) # `Dog` instance behind `Pet` pointer
|
||||||
|
Pet # no pointer downcasting for regular non-polymorphic types
|
||||||
|
>>> p.bark()
|
||||||
|
AttributeError: 'Pet' object has no attribute 'bark'
|
||||||
|
|
||||||
|
The function returned a ``Dog`` instance, but because it's a non-polymorphic
|
||||||
|
type behind a base pointer, Python only sees a ``Pet``. In C++, a type is only
|
||||||
|
considered polymorphic if it has at least one virtual function and pybind11
|
||||||
|
will automatically recognize this:
|
||||||
|
|
||||||
|
.. code-block:: cpp
|
||||||
|
|
||||||
|
struct PolymorphicPet {
|
||||||
|
virtual ~PolymorphicPet() = default;
|
||||||
|
};
|
||||||
|
|
||||||
|
struct PolymorphicDog : PolymorphicPet {
|
||||||
|
std::string bark() const { return "woof!"; }
|
||||||
|
};
|
||||||
|
|
||||||
|
// Same binding code
|
||||||
|
py::class_<PolymorphicPet>(m, "PolymorphicPet");
|
||||||
|
py::class_<PolymorphicDog, PolymorphicPet>(m, "PolymorphicDog")
|
||||||
|
.def(py::init<>())
|
||||||
|
.def("bark", &PolymorphicDog::bark);
|
||||||
|
|
||||||
|
// Again, return a base pointer to a derived instance
|
||||||
|
m.def("pet_store2", []() { return std::unique_ptr<PolymorphicPet>(new PolymorphicDog); });
|
||||||
|
|
||||||
|
.. code-block:: pycon
|
||||||
|
|
||||||
|
>>> p = example.pet_store2()
|
||||||
|
>>> type(p)
|
||||||
|
PolymorphicDog # automatically downcast
|
||||||
|
>>> p.bark()
|
||||||
|
'woof!'
|
||||||
|
|
||||||
|
Given a pointer to a polymorphic base, pybind11 performs automatic downcasting
|
||||||
|
to the actual derived type. Note that this goes beyond the usual situation in
|
||||||
|
C++: we don't just get access to the virtual functions of the base, we get the
|
||||||
|
concrete derived type including functions and attributes that the base type may
|
||||||
|
not even be aware of.
|
||||||
|
|
||||||
|
.. seealso::
|
||||||
|
|
||||||
|
For more information about polymorphic behavior see :ref:`overriding_virtuals`.
|
||||||
|
|
||||||
|
|
||||||
|
Overloaded methods
|
||||||
|
==================
|
||||||
|
|
||||||
|
Sometimes there are several overloaded C++ methods with the same name taking
|
||||||
|
different kinds of input arguments:
|
||||||
|
|
||||||
|
.. code-block:: cpp
|
||||||
|
|
||||||
|
struct Pet {
|
||||||
|
Pet(const std::string &name, int age) : name(name), age(age) { }
|
||||||
|
|
||||||
|
void set(int age_) { age = age_; }
|
||||||
|
void set(const std::string &name_) { name = name_; }
|
||||||
|
|
||||||
|
std::string name;
|
||||||
|
int age;
|
||||||
|
};
|
||||||
|
|
||||||
|
Attempting to bind ``Pet::set`` will cause an error since the compiler does not
|
||||||
|
know which method the user intended to select. We can disambiguate by casting
|
||||||
|
them to function pointers. Binding multiple functions to the same Python name
|
||||||
|
automatically creates a chain of function overloads that will be tried in
|
||||||
|
sequence.
|
||||||
|
|
||||||
|
.. code-block:: cpp
|
||||||
|
|
||||||
|
py::class_<Pet>(m, "Pet")
|
||||||
|
.def(py::init<const std::string &, int>())
|
||||||
|
.def("set", static_cast<void (Pet::*)(int)>(&Pet::set), "Set the pet's age")
|
||||||
|
.def("set", static_cast<void (Pet::*)(const std::string &)>(&Pet::set), "Set the pet's name");
|
||||||
|
|
||||||
|
The overload signatures are also visible in the method's docstring:
|
||||||
|
|
||||||
|
.. code-block:: pycon
|
||||||
|
|
||||||
|
>>> help(example.Pet)
|
||||||
|
|
||||||
|
class Pet(__builtin__.object)
|
||||||
|
| Methods defined here:
|
||||||
|
|
|
||||||
|
| __init__(...)
|
||||||
|
| Signature : (Pet, str, int) -> NoneType
|
||||||
|
|
|
||||||
|
| set(...)
|
||||||
|
| 1. Signature : (Pet, int) -> NoneType
|
||||||
|
|
|
||||||
|
| Set the pet's age
|
||||||
|
|
|
||||||
|
| 2. Signature : (Pet, str) -> NoneType
|
||||||
|
|
|
||||||
|
| Set the pet's name
|
||||||
|
|
||||||
|
If you have a C++14 compatible compiler [#cpp14]_, you can use an alternative
|
||||||
|
syntax to cast the overloaded function:
|
||||||
|
|
||||||
|
.. code-block:: cpp
|
||||||
|
|
||||||
|
py::class_<Pet>(m, "Pet")
|
||||||
|
.def("set", py::overload_cast<int>(&Pet::set), "Set the pet's age")
|
||||||
|
.def("set", py::overload_cast<const std::string &>(&Pet::set), "Set the pet's name");
|
||||||
|
|
||||||
|
Here, ``py::overload_cast`` only requires the parameter types to be specified.
|
||||||
|
The return type and class are deduced. This avoids the additional noise of
|
||||||
|
``void (Pet::*)()`` as seen in the raw cast. If a function is overloaded based
|
||||||
|
on constness, the ``py::const_`` tag should be used:
|
||||||
|
|
||||||
|
.. code-block:: cpp
|
||||||
|
|
||||||
|
struct Widget {
|
||||||
|
int foo(int x, float y);
|
||||||
|
int foo(int x, float y) const;
|
||||||
|
};
|
||||||
|
|
||||||
|
py::class_<Widget>(m, "Widget")
|
||||||
|
.def("foo_mutable", py::overload_cast<int, float>(&Widget::foo))
|
||||||
|
.def("foo_const", py::overload_cast<int, float>(&Widget::foo, py::const_));
|
||||||
|
|
||||||
|
If you prefer the ``py::overload_cast`` syntax but have a C++11 compatible compiler only,
|
||||||
|
you can use ``py::detail::overload_cast_impl`` with an additional set of parentheses:
|
||||||
|
|
||||||
|
.. code-block:: cpp
|
||||||
|
|
||||||
|
template <typename... Args>
|
||||||
|
using overload_cast_ = pybind11::detail::overload_cast_impl<Args...>;
|
||||||
|
|
||||||
|
py::class_<Pet>(m, "Pet")
|
||||||
|
.def("set", overload_cast_<int>()(&Pet::set), "Set the pet's age")
|
||||||
|
.def("set", overload_cast_<const std::string &>()(&Pet::set), "Set the pet's name");
|
||||||
|
|
||||||
|
.. [#cpp14] A compiler which supports the ``-std=c++14`` flag.
|
||||||
|
|
||||||
|
.. note::
|
||||||
|
|
||||||
|
To define multiple overloaded constructors, simply declare one after the
|
||||||
|
other using the ``.def(py::init<...>())`` syntax. The existing machinery
|
||||||
|
for specifying keyword and default arguments also works.
|
||||||
|
|
||||||
|
Enumerations and internal types
|
||||||
|
===============================
|
||||||
|
|
||||||
|
Let's now suppose that the example class contains internal types like enumerations, e.g.:
|
||||||
|
|
||||||
|
.. code-block:: cpp
|
||||||
|
|
||||||
|
struct Pet {
|
||||||
|
enum Kind {
|
||||||
|
Dog = 0,
|
||||||
|
Cat
|
||||||
|
};
|
||||||
|
|
||||||
|
struct Attributes {
|
||||||
|
float age = 0;
|
||||||
|
};
|
||||||
|
|
||||||
|
Pet(const std::string &name, Kind type) : name(name), type(type) { }
|
||||||
|
|
||||||
|
std::string name;
|
||||||
|
Kind type;
|
||||||
|
Attributes attr;
|
||||||
|
};
|
||||||
|
|
||||||
|
The binding code for this example looks as follows:
|
||||||
|
|
||||||
|
.. code-block:: cpp
|
||||||
|
|
||||||
|
py::class_<Pet> pet(m, "Pet");
|
||||||
|
|
||||||
|
pet.def(py::init<const std::string &, Pet::Kind>())
|
||||||
|
.def_readwrite("name", &Pet::name)
|
||||||
|
.def_readwrite("type", &Pet::type)
|
||||||
|
.def_readwrite("attr", &Pet::attr);
|
||||||
|
|
||||||
|
py::enum_<Pet::Kind>(pet, "Kind")
|
||||||
|
.value("Dog", Pet::Kind::Dog)
|
||||||
|
.value("Cat", Pet::Kind::Cat)
|
||||||
|
.export_values();
|
||||||
|
|
||||||
|
py::class_<Pet::Attributes>(pet, "Attributes")
|
||||||
|
.def(py::init<>())
|
||||||
|
.def_readwrite("age", &Pet::Attributes::age);
|
||||||
|
|
||||||
|
|
||||||
|
To ensure that the nested types ``Kind`` and ``Attributes`` are created within the scope of ``Pet``, the
|
||||||
|
``pet`` :class:`class_` instance must be supplied to the :class:`enum_` and :class:`class_`
|
||||||
|
constructor. The :func:`enum_::export_values` function exports the enum entries
|
||||||
|
into the parent scope, which should be skipped for newer C++11-style strongly
|
||||||
|
typed enums.
|
||||||
|
|
||||||
|
.. code-block:: pycon
|
||||||
|
|
||||||
|
>>> p = Pet("Lucy", Pet.Cat)
|
||||||
|
>>> p.type
|
||||||
|
Kind.Cat
|
||||||
|
>>> int(p.type)
|
||||||
|
1L
|
||||||
|
|
||||||
|
The entries defined by the enumeration type are exposed in the ``__members__`` property:
|
||||||
|
|
||||||
|
.. code-block:: pycon
|
||||||
|
|
||||||
|
>>> Pet.Kind.__members__
|
||||||
|
{'Dog': Kind.Dog, 'Cat': Kind.Cat}
|
||||||
|
|
||||||
|
The ``name`` property returns the name of the enum value as a unicode string.
|
||||||
|
|
||||||
|
.. note::
|
||||||
|
|
||||||
|
It is also possible to use ``str(enum)``, however these accomplish different
|
||||||
|
goals. The following shows how these two approaches differ.
|
||||||
|
|
||||||
|
.. code-block:: pycon
|
||||||
|
|
||||||
|
>>> p = Pet("Lucy", Pet.Cat)
|
||||||
|
>>> pet_type = p.type
|
||||||
|
>>> pet_type
|
||||||
|
Pet.Cat
|
||||||
|
>>> str(pet_type)
|
||||||
|
'Pet.Cat'
|
||||||
|
>>> pet_type.name
|
||||||
|
'Cat'
|
||||||
|
|
||||||
|
.. note::
|
||||||
|
|
||||||
|
When the special tag ``py::arithmetic()`` is specified to the ``enum_``
|
||||||
|
constructor, pybind11 creates an enumeration that also supports rudimentary
|
||||||
|
arithmetic and bit-level operations like comparisons, and, or, xor, negation,
|
||||||
|
etc.
|
||||||
|
|
||||||
|
.. code-block:: cpp
|
||||||
|
|
||||||
|
py::enum_<Pet::Kind>(pet, "Kind", py::arithmetic())
|
||||||
|
...
|
||||||
|
|
||||||
|
By default, these are omitted to conserve space.
|
||||||
|
|
||||||
|
.. warning::
|
||||||
|
|
||||||
|
Contrary to Python customs, enum values from the wrappers should not be compared using ``is``, but with ``==`` (see `#1177 <https://github.com/pybind/pybind11/issues/1177>`_ for background).
|
8
3rdparty/pybind11/docs/cmake/index.rst
vendored
Normal file
8
3rdparty/pybind11/docs/cmake/index.rst
vendored
Normal file
@ -0,0 +1,8 @@
|
|||||||
|
CMake helpers
|
||||||
|
-------------
|
||||||
|
|
||||||
|
Pybind11 can be used with ``add_subdirectory(extern/pybind11)``, or from an
|
||||||
|
install with ``find_package(pybind11 CONFIG)``. The interface provided in
|
||||||
|
either case is functionally identical.
|
||||||
|
|
||||||
|
.. cmake-module:: ../../tools/pybind11Config.cmake.in
|
649
3rdparty/pybind11/docs/compiling.rst
vendored
Normal file
649
3rdparty/pybind11/docs/compiling.rst
vendored
Normal file
@ -0,0 +1,649 @@
|
|||||||
|
.. _compiling:
|
||||||
|
|
||||||
|
Build systems
|
||||||
|
#############
|
||||||
|
|
||||||
|
.. _build-setuptools:
|
||||||
|
|
||||||
|
Building with setuptools
|
||||||
|
========================
|
||||||
|
|
||||||
|
For projects on PyPI, building with setuptools is the way to go. Sylvain Corlay
|
||||||
|
has kindly provided an example project which shows how to set up everything,
|
||||||
|
including automatic generation of documentation using Sphinx. Please refer to
|
||||||
|
the [python_example]_ repository.
|
||||||
|
|
||||||
|
.. [python_example] https://github.com/pybind/python_example
|
||||||
|
|
||||||
|
A helper file is provided with pybind11 that can simplify usage with setuptools.
|
||||||
|
|
||||||
|
To use pybind11 inside your ``setup.py``, you have to have some system to
|
||||||
|
ensure that ``pybind11`` is installed when you build your package. There are
|
||||||
|
four possible ways to do this, and pybind11 supports all four: You can ask all
|
||||||
|
users to install pybind11 beforehand (bad), you can use
|
||||||
|
:ref:`setup_helpers-pep518` (good, but very new and requires Pip 10),
|
||||||
|
:ref:`setup_helpers-setup_requires` (discouraged by Python packagers now that
|
||||||
|
PEP 518 is available, but it still works everywhere), or you can
|
||||||
|
:ref:`setup_helpers-copy-manually` (always works but you have to manually sync
|
||||||
|
your copy to get updates).
|
||||||
|
|
||||||
|
An example of a ``setup.py`` using pybind11's helpers:
|
||||||
|
|
||||||
|
.. code-block:: python
|
||||||
|
|
||||||
|
from glob import glob
|
||||||
|
from setuptools import setup
|
||||||
|
from pybind11.setup_helpers import Pybind11Extension
|
||||||
|
|
||||||
|
ext_modules = [
|
||||||
|
Pybind11Extension(
|
||||||
|
"python_example",
|
||||||
|
sorted(glob("src/*.cpp")), # Sort source files for reproducibility
|
||||||
|
),
|
||||||
|
]
|
||||||
|
|
||||||
|
setup(..., ext_modules=ext_modules)
|
||||||
|
|
||||||
|
If you want to do an automatic search for the highest supported C++ standard,
|
||||||
|
that is supported via a ``build_ext`` command override; it will only affect
|
||||||
|
``Pybind11Extensions``:
|
||||||
|
|
||||||
|
.. code-block:: python
|
||||||
|
|
||||||
|
from glob import glob
|
||||||
|
from setuptools import setup
|
||||||
|
from pybind11.setup_helpers import Pybind11Extension, build_ext
|
||||||
|
|
||||||
|
ext_modules = [
|
||||||
|
Pybind11Extension(
|
||||||
|
"python_example",
|
||||||
|
sorted(glob("src/*.cpp")),
|
||||||
|
),
|
||||||
|
]
|
||||||
|
|
||||||
|
setup(..., cmdclass={"build_ext": build_ext}, ext_modules=ext_modules)
|
||||||
|
|
||||||
|
If you have single-file extension modules that are directly stored in the
|
||||||
|
Python source tree (``foo.cpp`` in the same directory as where a ``foo.py``
|
||||||
|
would be located), you can also generate ``Pybind11Extensions`` using
|
||||||
|
``setup_helpers.intree_extensions``: ``intree_extensions(["path/to/foo.cpp",
|
||||||
|
...])`` returns a list of ``Pybind11Extensions`` which can be passed to
|
||||||
|
``ext_modules``, possibly after further customizing their attributes
|
||||||
|
(``libraries``, ``include_dirs``, etc.). By doing so, a ``foo.*.so`` extension
|
||||||
|
module will be generated and made available upon installation.
|
||||||
|
|
||||||
|
``intree_extension`` will automatically detect if you are using a ``src``-style
|
||||||
|
layout (as long as no namespace packages are involved), but you can also
|
||||||
|
explicitly pass ``package_dir`` to it (as in ``setuptools.setup``).
|
||||||
|
|
||||||
|
Since pybind11 does not require NumPy when building, a light-weight replacement
|
||||||
|
for NumPy's parallel compilation distutils tool is included. Use it like this:
|
||||||
|
|
||||||
|
.. code-block:: python
|
||||||
|
|
||||||
|
from pybind11.setup_helpers import ParallelCompile
|
||||||
|
|
||||||
|
# Optional multithreaded build
|
||||||
|
ParallelCompile("NPY_NUM_BUILD_JOBS").install()
|
||||||
|
|
||||||
|
setup(...)
|
||||||
|
|
||||||
|
The argument is the name of an environment variable to control the number of
|
||||||
|
threads, such as ``NPY_NUM_BUILD_JOBS`` (as used by NumPy), though you can set
|
||||||
|
something different if you want; ``CMAKE_BUILD_PARALLEL_LEVEL`` is another choice
|
||||||
|
a user might expect. You can also pass ``default=N`` to set the default number
|
||||||
|
of threads (0 will take the number of threads available) and ``max=N``, the
|
||||||
|
maximum number of threads; if you have a large extension you may want set this
|
||||||
|
to a memory dependent number.
|
||||||
|
|
||||||
|
If you are developing rapidly and have a lot of C++ files, you may want to
|
||||||
|
avoid rebuilding files that have not changed. For simple cases were you are
|
||||||
|
using ``pip install -e .`` and do not have local headers, you can skip the
|
||||||
|
rebuild if an object file is newer than its source (headers are not checked!)
|
||||||
|
with the following:
|
||||||
|
|
||||||
|
.. code-block:: python
|
||||||
|
|
||||||
|
from pybind11.setup_helpers import ParallelCompile, naive_recompile
|
||||||
|
|
||||||
|
ParallelCompile("NPY_NUM_BUILD_JOBS", needs_recompile=naive_recompile).install()
|
||||||
|
|
||||||
|
|
||||||
|
If you have a more complex build, you can implement a smarter function and pass
|
||||||
|
it to ``needs_recompile``, or you can use [Ccache]_ instead. ``CXX="cache g++"
|
||||||
|
pip install -e .`` would be the way to use it with GCC, for example. Unlike the
|
||||||
|
simple solution, this even works even when not compiling in editable mode, but
|
||||||
|
it does require Ccache to be installed.
|
||||||
|
|
||||||
|
Keep in mind that Pip will not even attempt to rebuild if it thinks it has
|
||||||
|
already built a copy of your code, which it deduces from the version number.
|
||||||
|
One way to avoid this is to use [setuptools_scm]_, which will generate a
|
||||||
|
version number that includes the number of commits since your last tag and a
|
||||||
|
hash for a dirty directory. Another way to force a rebuild is purge your cache
|
||||||
|
or use Pip's ``--no-cache-dir`` option.
|
||||||
|
|
||||||
|
.. [Ccache] https://ccache.dev
|
||||||
|
|
||||||
|
.. [setuptools_scm] https://github.com/pypa/setuptools_scm
|
||||||
|
|
||||||
|
.. _setup_helpers-pep518:
|
||||||
|
|
||||||
|
PEP 518 requirements (Pip 10+ required)
|
||||||
|
---------------------------------------
|
||||||
|
|
||||||
|
If you use `PEP 518's <https://www.python.org/dev/peps/pep-0518/>`_
|
||||||
|
``pyproject.toml`` file, you can ensure that ``pybind11`` is available during
|
||||||
|
the compilation of your project. When this file exists, Pip will make a new
|
||||||
|
virtual environment, download just the packages listed here in ``requires=``,
|
||||||
|
and build a wheel (binary Python package). It will then throw away the
|
||||||
|
environment, and install your wheel.
|
||||||
|
|
||||||
|
Your ``pyproject.toml`` file will likely look something like this:
|
||||||
|
|
||||||
|
.. code-block:: toml
|
||||||
|
|
||||||
|
[build-system]
|
||||||
|
requires = ["setuptools>=42", "pybind11>=2.6.1"]
|
||||||
|
build-backend = "setuptools.build_meta"
|
||||||
|
|
||||||
|
.. note::
|
||||||
|
|
||||||
|
The main drawback to this method is that a `PEP 517`_ compliant build tool,
|
||||||
|
such as Pip 10+, is required for this approach to work; older versions of
|
||||||
|
Pip completely ignore this file. If you distribute binaries (called wheels
|
||||||
|
in Python) using something like `cibuildwheel`_, remember that ``setup.py``
|
||||||
|
and ``pyproject.toml`` are not even contained in the wheel, so this high
|
||||||
|
Pip requirement is only for source builds, and will not affect users of
|
||||||
|
your binary wheels. If you are building SDists and wheels, then
|
||||||
|
`pypa-build`_ is the recommended official tool.
|
||||||
|
|
||||||
|
.. _PEP 517: https://www.python.org/dev/peps/pep-0517/
|
||||||
|
.. _cibuildwheel: https://cibuildwheel.readthedocs.io
|
||||||
|
.. _pypa-build: https://pypa-build.readthedocs.io/en/latest/
|
||||||
|
|
||||||
|
.. _setup_helpers-setup_requires:
|
||||||
|
|
||||||
|
Classic ``setup_requires``
|
||||||
|
--------------------------
|
||||||
|
|
||||||
|
If you want to support old versions of Pip with the classic
|
||||||
|
``setup_requires=["pybind11"]`` keyword argument to setup, which triggers a
|
||||||
|
two-phase ``setup.py`` run, then you will need to use something like this to
|
||||||
|
ensure the first pass works (which has not yet installed the ``setup_requires``
|
||||||
|
packages, since it can't install something it does not know about):
|
||||||
|
|
||||||
|
.. code-block:: python
|
||||||
|
|
||||||
|
try:
|
||||||
|
from pybind11.setup_helpers import Pybind11Extension
|
||||||
|
except ImportError:
|
||||||
|
from setuptools import Extension as Pybind11Extension
|
||||||
|
|
||||||
|
|
||||||
|
It doesn't matter that the Extension class is not the enhanced subclass for the
|
||||||
|
first pass run; and the second pass will have the ``setup_requires``
|
||||||
|
requirements.
|
||||||
|
|
||||||
|
This is obviously more of a hack than the PEP 518 method, but it supports
|
||||||
|
ancient versions of Pip.
|
||||||
|
|
||||||
|
.. _setup_helpers-copy-manually:
|
||||||
|
|
||||||
|
Copy manually
|
||||||
|
-------------
|
||||||
|
|
||||||
|
You can also copy ``setup_helpers.py`` directly to your project; it was
|
||||||
|
designed to be usable standalone, like the old example ``setup.py``. You can
|
||||||
|
set ``include_pybind11=False`` to skip including the pybind11 package headers,
|
||||||
|
so you can use it with git submodules and a specific git version. If you use
|
||||||
|
this, you will need to import from a local file in ``setup.py`` and ensure the
|
||||||
|
helper file is part of your MANIFEST.
|
||||||
|
|
||||||
|
|
||||||
|
Closely related, if you include pybind11 as a subproject, you can run the
|
||||||
|
``setup_helpers.py`` inplace. If loaded correctly, this should even pick up
|
||||||
|
the correct include for pybind11, though you can turn it off as shown above if
|
||||||
|
you want to input it manually.
|
||||||
|
|
||||||
|
Suggested usage if you have pybind11 as a submodule in ``extern/pybind11``:
|
||||||
|
|
||||||
|
.. code-block:: python
|
||||||
|
|
||||||
|
DIR = os.path.abspath(os.path.dirname(__file__))
|
||||||
|
|
||||||
|
sys.path.append(os.path.join(DIR, "extern", "pybind11"))
|
||||||
|
from pybind11.setup_helpers import Pybind11Extension # noqa: E402
|
||||||
|
|
||||||
|
del sys.path[-1]
|
||||||
|
|
||||||
|
|
||||||
|
.. versionchanged:: 2.6
|
||||||
|
|
||||||
|
Added ``setup_helpers`` file.
|
||||||
|
|
||||||
|
Building with cppimport
|
||||||
|
========================
|
||||||
|
|
||||||
|
[cppimport]_ is a small Python import hook that determines whether there is a C++
|
||||||
|
source file whose name matches the requested module. If there is, the file is
|
||||||
|
compiled as a Python extension using pybind11 and placed in the same folder as
|
||||||
|
the C++ source file. Python is then able to find the module and load it.
|
||||||
|
|
||||||
|
.. [cppimport] https://github.com/tbenthompson/cppimport
|
||||||
|
|
||||||
|
.. _cmake:
|
||||||
|
|
||||||
|
Building with CMake
|
||||||
|
===================
|
||||||
|
|
||||||
|
For C++ codebases that have an existing CMake-based build system, a Python
|
||||||
|
extension module can be created with just a few lines of code:
|
||||||
|
|
||||||
|
.. code-block:: cmake
|
||||||
|
|
||||||
|
cmake_minimum_required(VERSION 3.5...3.27)
|
||||||
|
project(example LANGUAGES CXX)
|
||||||
|
|
||||||
|
add_subdirectory(pybind11)
|
||||||
|
pybind11_add_module(example example.cpp)
|
||||||
|
|
||||||
|
This assumes that the pybind11 repository is located in a subdirectory named
|
||||||
|
:file:`pybind11` and that the code is located in a file named :file:`example.cpp`.
|
||||||
|
The CMake command ``add_subdirectory`` will import the pybind11 project which
|
||||||
|
provides the ``pybind11_add_module`` function. It will take care of all the
|
||||||
|
details needed to build a Python extension module on any platform.
|
||||||
|
|
||||||
|
A working sample project, including a way to invoke CMake from :file:`setup.py` for
|
||||||
|
PyPI integration, can be found in the [cmake_example]_ repository.
|
||||||
|
|
||||||
|
.. [cmake_example] https://github.com/pybind/cmake_example
|
||||||
|
|
||||||
|
.. versionchanged:: 2.6
|
||||||
|
CMake 3.4+ is required.
|
||||||
|
|
||||||
|
.. versionchanged:: 2.11
|
||||||
|
CMake 3.5+ is required.
|
||||||
|
|
||||||
|
Further information can be found at :doc:`cmake/index`.
|
||||||
|
|
||||||
|
pybind11_add_module
|
||||||
|
-------------------
|
||||||
|
|
||||||
|
To ease the creation of Python extension modules, pybind11 provides a CMake
|
||||||
|
function with the following signature:
|
||||||
|
|
||||||
|
.. code-block:: cmake
|
||||||
|
|
||||||
|
pybind11_add_module(<name> [MODULE | SHARED] [EXCLUDE_FROM_ALL]
|
||||||
|
[NO_EXTRAS] [THIN_LTO] [OPT_SIZE] source1 [source2 ...])
|
||||||
|
|
||||||
|
This function behaves very much like CMake's builtin ``add_library`` (in fact,
|
||||||
|
it's a wrapper function around that command). It will add a library target
|
||||||
|
called ``<name>`` to be built from the listed source files. In addition, it
|
||||||
|
will take care of all the Python-specific compiler and linker flags as well
|
||||||
|
as the OS- and Python-version-specific file extension. The produced target
|
||||||
|
``<name>`` can be further manipulated with regular CMake commands.
|
||||||
|
|
||||||
|
``MODULE`` or ``SHARED`` may be given to specify the type of library. If no
|
||||||
|
type is given, ``MODULE`` is used by default which ensures the creation of a
|
||||||
|
Python-exclusive module. Specifying ``SHARED`` will create a more traditional
|
||||||
|
dynamic library which can also be linked from elsewhere. ``EXCLUDE_FROM_ALL``
|
||||||
|
removes this target from the default build (see CMake docs for details).
|
||||||
|
|
||||||
|
Since pybind11 is a template library, ``pybind11_add_module`` adds compiler
|
||||||
|
flags to ensure high quality code generation without bloat arising from long
|
||||||
|
symbol names and duplication of code in different translation units. It
|
||||||
|
sets default visibility to *hidden*, which is required for some pybind11
|
||||||
|
features and functionality when attempting to load multiple pybind11 modules
|
||||||
|
compiled under different pybind11 versions. It also adds additional flags
|
||||||
|
enabling LTO (Link Time Optimization) and strip unneeded symbols. See the
|
||||||
|
:ref:`FAQ entry <faq:symhidden>` for a more detailed explanation. These
|
||||||
|
latter optimizations are never applied in ``Debug`` mode. If ``NO_EXTRAS`` is
|
||||||
|
given, they will always be disabled, even in ``Release`` mode. However, this
|
||||||
|
will result in code bloat and is generally not recommended.
|
||||||
|
|
||||||
|
As stated above, LTO is enabled by default. Some newer compilers also support
|
||||||
|
different flavors of LTO such as `ThinLTO`_. Setting ``THIN_LTO`` will cause
|
||||||
|
the function to prefer this flavor if available. The function falls back to
|
||||||
|
regular LTO if ``-flto=thin`` is not available. If
|
||||||
|
``CMAKE_INTERPROCEDURAL_OPTIMIZATION`` is set (either ``ON`` or ``OFF``), then
|
||||||
|
that will be respected instead of the built-in flag search.
|
||||||
|
|
||||||
|
.. note::
|
||||||
|
|
||||||
|
If you want to set the property form on targets or the
|
||||||
|
``CMAKE_INTERPROCEDURAL_OPTIMIZATION_<CONFIG>`` versions of this, you should
|
||||||
|
still use ``set(CMAKE_INTERPROCEDURAL_OPTIMIZATION OFF)`` (otherwise a
|
||||||
|
no-op) to disable pybind11's ipo flags.
|
||||||
|
|
||||||
|
The ``OPT_SIZE`` flag enables size-based optimization equivalent to the
|
||||||
|
standard ``/Os`` or ``-Os`` compiler flags and the ``MinSizeRel`` build type,
|
||||||
|
which avoid optimizations that that can substantially increase the size of the
|
||||||
|
resulting binary. This flag is particularly useful in projects that are split
|
||||||
|
into performance-critical parts and associated bindings. In this case, we can
|
||||||
|
compile the project in release mode (and hence, optimize performance globally),
|
||||||
|
and specify ``OPT_SIZE`` for the binding target, where size might be the main
|
||||||
|
concern as performance is often less critical here. A ~25% size reduction has
|
||||||
|
been observed in practice. This flag only changes the optimization behavior at
|
||||||
|
a per-target level and takes precedence over the global CMake build type
|
||||||
|
(``Release``, ``RelWithDebInfo``) except for ``Debug`` builds, where
|
||||||
|
optimizations remain disabled.
|
||||||
|
|
||||||
|
.. _ThinLTO: http://clang.llvm.org/docs/ThinLTO.html
|
||||||
|
|
||||||
|
Configuration variables
|
||||||
|
-----------------------
|
||||||
|
|
||||||
|
By default, pybind11 will compile modules with the compiler default or the
|
||||||
|
minimum standard required by pybind11, whichever is higher. You can set the
|
||||||
|
standard explicitly with
|
||||||
|
`CMAKE_CXX_STANDARD <https://cmake.org/cmake/help/latest/variable/CMAKE_CXX_STANDARD.html>`_:
|
||||||
|
|
||||||
|
.. code-block:: cmake
|
||||||
|
|
||||||
|
set(CMAKE_CXX_STANDARD 14 CACHE STRING "C++ version selection") # or 11, 14, 17, 20
|
||||||
|
set(CMAKE_CXX_STANDARD_REQUIRED ON) # optional, ensure standard is supported
|
||||||
|
set(CMAKE_CXX_EXTENSIONS OFF) # optional, keep compiler extensions off
|
||||||
|
|
||||||
|
The variables can also be set when calling CMake from the command line using
|
||||||
|
the ``-D<variable>=<value>`` flag. You can also manually set ``CXX_STANDARD``
|
||||||
|
on a target or use ``target_compile_features`` on your targets - anything that
|
||||||
|
CMake supports.
|
||||||
|
|
||||||
|
Classic Python support: The target Python version can be selected by setting
|
||||||
|
``PYBIND11_PYTHON_VERSION`` or an exact Python installation can be specified
|
||||||
|
with ``PYTHON_EXECUTABLE``. For example:
|
||||||
|
|
||||||
|
.. code-block:: bash
|
||||||
|
|
||||||
|
cmake -DPYBIND11_PYTHON_VERSION=3.6 ..
|
||||||
|
|
||||||
|
# Another method:
|
||||||
|
cmake -DPYTHON_EXECUTABLE=/path/to/python ..
|
||||||
|
|
||||||
|
# This often is a good way to get the current Python, works in environments:
|
||||||
|
cmake -DPYTHON_EXECUTABLE=$(python3 -c "import sys; print(sys.executable)") ..
|
||||||
|
|
||||||
|
|
||||||
|
find_package vs. add_subdirectory
|
||||||
|
---------------------------------
|
||||||
|
|
||||||
|
For CMake-based projects that don't include the pybind11 repository internally,
|
||||||
|
an external installation can be detected through ``find_package(pybind11)``.
|
||||||
|
See the `Config file`_ docstring for details of relevant CMake variables.
|
||||||
|
|
||||||
|
.. code-block:: cmake
|
||||||
|
|
||||||
|
cmake_minimum_required(VERSION 3.4...3.18)
|
||||||
|
project(example LANGUAGES CXX)
|
||||||
|
|
||||||
|
find_package(pybind11 REQUIRED)
|
||||||
|
pybind11_add_module(example example.cpp)
|
||||||
|
|
||||||
|
Note that ``find_package(pybind11)`` will only work correctly if pybind11
|
||||||
|
has been correctly installed on the system, e. g. after downloading or cloning
|
||||||
|
the pybind11 repository :
|
||||||
|
|
||||||
|
.. code-block:: bash
|
||||||
|
|
||||||
|
# Classic CMake
|
||||||
|
cd pybind11
|
||||||
|
mkdir build
|
||||||
|
cd build
|
||||||
|
cmake ..
|
||||||
|
make install
|
||||||
|
|
||||||
|
# CMake 3.15+
|
||||||
|
cd pybind11
|
||||||
|
cmake -S . -B build
|
||||||
|
cmake --build build -j 2 # Build on 2 cores
|
||||||
|
cmake --install build
|
||||||
|
|
||||||
|
Once detected, the aforementioned ``pybind11_add_module`` can be employed as
|
||||||
|
before. The function usage and configuration variables are identical no matter
|
||||||
|
if pybind11 is added as a subdirectory or found as an installed package. You
|
||||||
|
can refer to the same [cmake_example]_ repository for a full sample project
|
||||||
|
-- just swap out ``add_subdirectory`` for ``find_package``.
|
||||||
|
|
||||||
|
.. _Config file: https://github.com/pybind/pybind11/blob/master/tools/pybind11Config.cmake.in
|
||||||
|
|
||||||
|
|
||||||
|
.. _find-python-mode:
|
||||||
|
|
||||||
|
FindPython mode
|
||||||
|
---------------
|
||||||
|
|
||||||
|
CMake 3.12+ (3.15+ recommended, 3.18.2+ ideal) added a new module called
|
||||||
|
FindPython that had a highly improved search algorithm and modern targets
|
||||||
|
and tools. If you use FindPython, pybind11 will detect this and use the
|
||||||
|
existing targets instead:
|
||||||
|
|
||||||
|
.. code-block:: cmake
|
||||||
|
|
||||||
|
cmake_minimum_required(VERSION 3.15...3.22)
|
||||||
|
project(example LANGUAGES CXX)
|
||||||
|
|
||||||
|
find_package(Python 3.6 COMPONENTS Interpreter Development REQUIRED)
|
||||||
|
find_package(pybind11 CONFIG REQUIRED)
|
||||||
|
# or add_subdirectory(pybind11)
|
||||||
|
|
||||||
|
pybind11_add_module(example example.cpp)
|
||||||
|
|
||||||
|
You can also use the targets (as listed below) with FindPython. If you define
|
||||||
|
``PYBIND11_FINDPYTHON``, pybind11 will perform the FindPython step for you
|
||||||
|
(mostly useful when building pybind11's own tests, or as a way to change search
|
||||||
|
algorithms from the CMake invocation, with ``-DPYBIND11_FINDPYTHON=ON``.
|
||||||
|
|
||||||
|
.. warning::
|
||||||
|
|
||||||
|
If you use FindPython to multi-target Python versions, use the individual
|
||||||
|
targets listed below, and avoid targets that directly include Python parts.
|
||||||
|
|
||||||
|
There are `many ways to hint or force a discovery of a specific Python
|
||||||
|
installation <https://cmake.org/cmake/help/latest/module/FindPython.html>`_),
|
||||||
|
setting ``Python_ROOT_DIR`` may be the most common one (though with
|
||||||
|
virtualenv/venv support, and Conda support, this tends to find the correct
|
||||||
|
Python version more often than the old system did).
|
||||||
|
|
||||||
|
.. warning::
|
||||||
|
|
||||||
|
When the Python libraries (i.e. ``libpythonXX.a`` and ``libpythonXX.so``
|
||||||
|
on Unix) are not available, as is the case on a manylinux image, the
|
||||||
|
``Development`` component will not be resolved by ``FindPython``. When not
|
||||||
|
using the embedding functionality, CMake 3.18+ allows you to specify
|
||||||
|
``Development.Module`` instead of ``Development`` to resolve this issue.
|
||||||
|
|
||||||
|
.. versionadded:: 2.6
|
||||||
|
|
||||||
|
Advanced: interface library targets
|
||||||
|
-----------------------------------
|
||||||
|
|
||||||
|
Pybind11 supports modern CMake usage patterns with a set of interface targets,
|
||||||
|
available in all modes. The targets provided are:
|
||||||
|
|
||||||
|
``pybind11::headers``
|
||||||
|
Just the pybind11 headers and minimum compile requirements
|
||||||
|
|
||||||
|
``pybind11::pybind11``
|
||||||
|
Python headers + ``pybind11::headers``
|
||||||
|
|
||||||
|
``pybind11::python_link_helper``
|
||||||
|
Just the "linking" part of pybind11:module
|
||||||
|
|
||||||
|
``pybind11::module``
|
||||||
|
Everything for extension modules - ``pybind11::pybind11`` + ``Python::Module`` (FindPython CMake 3.15+) or ``pybind11::python_link_helper``
|
||||||
|
|
||||||
|
``pybind11::embed``
|
||||||
|
Everything for embedding the Python interpreter - ``pybind11::pybind11`` + ``Python::Python`` (FindPython) or Python libs
|
||||||
|
|
||||||
|
``pybind11::lto`` / ``pybind11::thin_lto``
|
||||||
|
An alternative to `INTERPROCEDURAL_OPTIMIZATION` for adding link-time optimization.
|
||||||
|
|
||||||
|
``pybind11::windows_extras``
|
||||||
|
``/bigobj`` and ``/mp`` for MSVC.
|
||||||
|
|
||||||
|
``pybind11::opt_size``
|
||||||
|
``/Os`` for MSVC, ``-Os`` for other compilers. Does nothing for debug builds.
|
||||||
|
|
||||||
|
Two helper functions are also provided:
|
||||||
|
|
||||||
|
``pybind11_strip(target)``
|
||||||
|
Strips a target (uses ``CMAKE_STRIP`` after the target is built)
|
||||||
|
|
||||||
|
``pybind11_extension(target)``
|
||||||
|
Sets the correct extension (with SOABI) for a target.
|
||||||
|
|
||||||
|
You can use these targets to build complex applications. For example, the
|
||||||
|
``add_python_module`` function is identical to:
|
||||||
|
|
||||||
|
.. code-block:: cmake
|
||||||
|
|
||||||
|
cmake_minimum_required(VERSION 3.5...3.27)
|
||||||
|
project(example LANGUAGES CXX)
|
||||||
|
|
||||||
|
find_package(pybind11 REQUIRED) # or add_subdirectory(pybind11)
|
||||||
|
|
||||||
|
add_library(example MODULE main.cpp)
|
||||||
|
|
||||||
|
target_link_libraries(example PRIVATE pybind11::module pybind11::lto pybind11::windows_extras)
|
||||||
|
|
||||||
|
pybind11_extension(example)
|
||||||
|
if(NOT MSVC AND NOT ${CMAKE_BUILD_TYPE} MATCHES Debug|RelWithDebInfo)
|
||||||
|
# Strip unnecessary sections of the binary on Linux/macOS
|
||||||
|
pybind11_strip(example)
|
||||||
|
endif()
|
||||||
|
|
||||||
|
set_target_properties(example PROPERTIES CXX_VISIBILITY_PRESET "hidden"
|
||||||
|
CUDA_VISIBILITY_PRESET "hidden")
|
||||||
|
|
||||||
|
Instead of setting properties, you can set ``CMAKE_*`` variables to initialize these correctly.
|
||||||
|
|
||||||
|
.. warning::
|
||||||
|
|
||||||
|
Since pybind11 is a metatemplate library, it is crucial that certain
|
||||||
|
compiler flags are provided to ensure high quality code generation. In
|
||||||
|
contrast to the ``pybind11_add_module()`` command, the CMake interface
|
||||||
|
provides a *composable* set of targets to ensure that you retain flexibility.
|
||||||
|
It can be especially important to provide or set these properties; the
|
||||||
|
:ref:`FAQ <faq:symhidden>` contains an explanation on why these are needed.
|
||||||
|
|
||||||
|
.. versionadded:: 2.6
|
||||||
|
|
||||||
|
.. _nopython-mode:
|
||||||
|
|
||||||
|
Advanced: NOPYTHON mode
|
||||||
|
-----------------------
|
||||||
|
|
||||||
|
If you want complete control, you can set ``PYBIND11_NOPYTHON`` to completely
|
||||||
|
disable Python integration (this also happens if you run ``FindPython2`` and
|
||||||
|
``FindPython3`` without running ``FindPython``). This gives you complete
|
||||||
|
freedom to integrate into an existing system (like `Scikit-Build's
|
||||||
|
<https://scikit-build.readthedocs.io>`_ ``PythonExtensions``).
|
||||||
|
``pybind11_add_module`` and ``pybind11_extension`` will be unavailable, and the
|
||||||
|
targets will be missing any Python specific behavior.
|
||||||
|
|
||||||
|
.. versionadded:: 2.6
|
||||||
|
|
||||||
|
Embedding the Python interpreter
|
||||||
|
--------------------------------
|
||||||
|
|
||||||
|
In addition to extension modules, pybind11 also supports embedding Python into
|
||||||
|
a C++ executable or library. In CMake, simply link with the ``pybind11::embed``
|
||||||
|
target. It provides everything needed to get the interpreter running. The Python
|
||||||
|
headers and libraries are attached to the target. Unlike ``pybind11::module``,
|
||||||
|
there is no need to manually set any additional properties here. For more
|
||||||
|
information about usage in C++, see :doc:`/advanced/embedding`.
|
||||||
|
|
||||||
|
.. code-block:: cmake
|
||||||
|
|
||||||
|
cmake_minimum_required(VERSION 3.5...3.27)
|
||||||
|
project(example LANGUAGES CXX)
|
||||||
|
|
||||||
|
find_package(pybind11 REQUIRED) # or add_subdirectory(pybind11)
|
||||||
|
|
||||||
|
add_executable(example main.cpp)
|
||||||
|
target_link_libraries(example PRIVATE pybind11::embed)
|
||||||
|
|
||||||
|
.. _building_manually:
|
||||||
|
|
||||||
|
Building manually
|
||||||
|
=================
|
||||||
|
|
||||||
|
pybind11 is a header-only library, hence it is not necessary to link against
|
||||||
|
any special libraries and there are no intermediate (magic) translation steps.
|
||||||
|
|
||||||
|
On Linux, you can compile an example such as the one given in
|
||||||
|
:ref:`simple_example` using the following command:
|
||||||
|
|
||||||
|
.. code-block:: bash
|
||||||
|
|
||||||
|
$ c++ -O3 -Wall -shared -std=c++11 -fPIC $(python3 -m pybind11 --includes) example.cpp -o example$(python3-config --extension-suffix)
|
||||||
|
|
||||||
|
The ``python3 -m pybind11 --includes`` command fetches the include paths for
|
||||||
|
both pybind11 and Python headers. This assumes that pybind11 has been installed
|
||||||
|
using ``pip`` or ``conda``. If it hasn't, you can also manually specify
|
||||||
|
``-I <path-to-pybind11>/include`` together with the Python includes path
|
||||||
|
``python3-config --includes``.
|
||||||
|
|
||||||
|
On macOS: the build command is almost the same but it also requires passing
|
||||||
|
the ``-undefined dynamic_lookup`` flag so as to ignore missing symbols when
|
||||||
|
building the module:
|
||||||
|
|
||||||
|
.. code-block:: bash
|
||||||
|
|
||||||
|
$ c++ -O3 -Wall -shared -std=c++11 -undefined dynamic_lookup $(python3 -m pybind11 --includes) example.cpp -o example$(python3-config --extension-suffix)
|
||||||
|
|
||||||
|
In general, it is advisable to include several additional build parameters
|
||||||
|
that can considerably reduce the size of the created binary. Refer to section
|
||||||
|
:ref:`cmake` for a detailed example of a suitable cross-platform CMake-based
|
||||||
|
build system that works on all platforms including Windows.
|
||||||
|
|
||||||
|
.. note::
|
||||||
|
|
||||||
|
On Linux and macOS, it's better to (intentionally) not link against
|
||||||
|
``libpython``. The symbols will be resolved when the extension library
|
||||||
|
is loaded into a Python binary. This is preferable because you might
|
||||||
|
have several different installations of a given Python version (e.g. the
|
||||||
|
system-provided Python, and one that ships with a piece of commercial
|
||||||
|
software). In this way, the plugin will work with both versions, instead
|
||||||
|
of possibly importing a second Python library into a process that already
|
||||||
|
contains one (which will lead to a segfault).
|
||||||
|
|
||||||
|
|
||||||
|
Building with Bazel
|
||||||
|
===================
|
||||||
|
|
||||||
|
You can build with the Bazel build system using the `pybind11_bazel
|
||||||
|
<https://github.com/pybind/pybind11_bazel>`_ repository.
|
||||||
|
|
||||||
|
Generating binding code automatically
|
||||||
|
=====================================
|
||||||
|
|
||||||
|
The ``Binder`` project is a tool for automatic generation of pybind11 binding
|
||||||
|
code by introspecting existing C++ codebases using LLVM/Clang. See the
|
||||||
|
[binder]_ documentation for details.
|
||||||
|
|
||||||
|
.. [binder] http://cppbinder.readthedocs.io/en/latest/about.html
|
||||||
|
|
||||||
|
[AutoWIG]_ is a Python library that wraps automatically compiled libraries into
|
||||||
|
high-level languages. It parses C++ code using LLVM/Clang technologies and
|
||||||
|
generates the wrappers using the Mako templating engine. The approach is automatic,
|
||||||
|
extensible, and applies to very complex C++ libraries, composed of thousands of
|
||||||
|
classes or incorporating modern meta-programming constructs.
|
||||||
|
|
||||||
|
.. [AutoWIG] https://github.com/StatisKit/AutoWIG
|
||||||
|
|
||||||
|
[robotpy-build]_ is a is a pure python, cross platform build tool that aims to
|
||||||
|
simplify creation of python wheels for pybind11 projects, and provide
|
||||||
|
cross-project dependency management. Additionally, it is able to autogenerate
|
||||||
|
customizable pybind11-based wrappers by parsing C++ header files.
|
||||||
|
|
||||||
|
.. [robotpy-build] https://robotpy-build.readthedocs.io
|
||||||
|
|
||||||
|
[litgen]_ is an automatic python bindings generator with a focus on generating
|
||||||
|
documented and discoverable bindings: bindings will nicely reproduce the documentation
|
||||||
|
found in headers. It is is based on srcML (srcml.org), a highly scalable, multi-language
|
||||||
|
parsing tool with a developer centric approach. The API that you want to expose to python
|
||||||
|
must be C++14 compatible (but your implementation can use more modern constructs).
|
||||||
|
|
||||||
|
.. [litgen] https://pthom.github.io/litgen
|
368
3rdparty/pybind11/docs/conf.py
vendored
Normal file
368
3rdparty/pybind11/docs/conf.py
vendored
Normal file
@ -0,0 +1,368 @@
|
|||||||
|
#!/usr/bin/env python3
|
||||||
|
#
|
||||||
|
# pybind11 documentation build configuration file, created by
|
||||||
|
# sphinx-quickstart on Sun Oct 11 19:23:48 2015.
|
||||||
|
#
|
||||||
|
# This file is execfile()d with the current directory set to its
|
||||||
|
# containing dir.
|
||||||
|
#
|
||||||
|
# Note that not all possible configuration values are present in this
|
||||||
|
# autogenerated file.
|
||||||
|
#
|
||||||
|
# All configuration values have a default; values that are commented out
|
||||||
|
# serve to show the default.
|
||||||
|
|
||||||
|
import os
|
||||||
|
import re
|
||||||
|
import subprocess
|
||||||
|
import sys
|
||||||
|
from pathlib import Path
|
||||||
|
|
||||||
|
DIR = Path(__file__).parent.resolve()
|
||||||
|
|
||||||
|
# If extensions (or modules to document with autodoc) are in another directory,
|
||||||
|
# add these directories to sys.path here. If the directory is relative to the
|
||||||
|
# documentation root, use os.path.abspath to make it absolute, like shown here.
|
||||||
|
# sys.path.insert(0, os.path.abspath('.'))
|
||||||
|
|
||||||
|
# -- General configuration ------------------------------------------------
|
||||||
|
|
||||||
|
# If your documentation needs a minimal Sphinx version, state it here.
|
||||||
|
# needs_sphinx = '1.0'
|
||||||
|
|
||||||
|
# Add any Sphinx extension module names here, as strings. They can be
|
||||||
|
# extensions coming with Sphinx (named 'sphinx.ext.*') or your custom
|
||||||
|
# ones.
|
||||||
|
extensions = [
|
||||||
|
"breathe",
|
||||||
|
"sphinx_copybutton",
|
||||||
|
"sphinxcontrib.rsvgconverter",
|
||||||
|
"sphinxcontrib.moderncmakedomain",
|
||||||
|
]
|
||||||
|
|
||||||
|
breathe_projects = {"pybind11": ".build/doxygenxml/"}
|
||||||
|
breathe_default_project = "pybind11"
|
||||||
|
breathe_domain_by_extension = {"h": "cpp"}
|
||||||
|
|
||||||
|
# Add any paths that contain templates here, relative to this directory.
|
||||||
|
templates_path = [".templates"]
|
||||||
|
|
||||||
|
# The suffix(es) of source filenames.
|
||||||
|
# You can specify multiple suffix as a list of string:
|
||||||
|
# source_suffix = ['.rst', '.md']
|
||||||
|
source_suffix = ".rst"
|
||||||
|
|
||||||
|
# The encoding of source files.
|
||||||
|
# source_encoding = 'utf-8-sig'
|
||||||
|
|
||||||
|
# The master toctree document.
|
||||||
|
master_doc = "index"
|
||||||
|
|
||||||
|
# General information about the project.
|
||||||
|
project = "pybind11"
|
||||||
|
copyright = "2017, Wenzel Jakob"
|
||||||
|
author = "Wenzel Jakob"
|
||||||
|
|
||||||
|
# The version info for the project you're documenting, acts as replacement for
|
||||||
|
# |version| and |release|, also used in various other places throughout the
|
||||||
|
# built documents.
|
||||||
|
|
||||||
|
# Read the listed version
|
||||||
|
with open("../pybind11/_version.py") as f:
|
||||||
|
code = compile(f.read(), "../pybind11/_version.py", "exec")
|
||||||
|
loc = {}
|
||||||
|
exec(code, loc)
|
||||||
|
|
||||||
|
# The full version, including alpha/beta/rc tags.
|
||||||
|
version = loc["__version__"]
|
||||||
|
|
||||||
|
# The language for content autogenerated by Sphinx. Refer to documentation
|
||||||
|
# for a list of supported languages.
|
||||||
|
#
|
||||||
|
# This is also used if you do content translation via gettext catalogs.
|
||||||
|
# Usually you set "language" from the command line for these cases.
|
||||||
|
language = None
|
||||||
|
|
||||||
|
# There are two options for replacing |today|: either, you set today to some
|
||||||
|
# non-false value, then it is used:
|
||||||
|
# today = ''
|
||||||
|
# Else, today_fmt is used as the format for a strftime call.
|
||||||
|
# today_fmt = '%B %d, %Y'
|
||||||
|
|
||||||
|
# List of patterns, relative to source directory, that match files and
|
||||||
|
# directories to ignore when looking for source files.
|
||||||
|
exclude_patterns = [".build", "release.rst"]
|
||||||
|
|
||||||
|
# The reST default role (used for this markup: `text`) to use for all
|
||||||
|
# documents.
|
||||||
|
default_role = "any"
|
||||||
|
|
||||||
|
# If true, '()' will be appended to :func: etc. cross-reference text.
|
||||||
|
# add_function_parentheses = True
|
||||||
|
|
||||||
|
# If true, the current module name will be prepended to all description
|
||||||
|
# unit titles (such as .. function::).
|
||||||
|
# add_module_names = True
|
||||||
|
|
||||||
|
# If true, sectionauthor and moduleauthor directives will be shown in the
|
||||||
|
# output. They are ignored by default.
|
||||||
|
# show_authors = False
|
||||||
|
|
||||||
|
# The name of the Pygments (syntax highlighting) style to use.
|
||||||
|
# pygments_style = 'monokai'
|
||||||
|
|
||||||
|
# A list of ignored prefixes for module index sorting.
|
||||||
|
# modindex_common_prefix = []
|
||||||
|
|
||||||
|
# If true, keep warnings as "system message" paragraphs in the built documents.
|
||||||
|
# keep_warnings = False
|
||||||
|
|
||||||
|
# If true, `todo` and `todoList` produce output, else they produce nothing.
|
||||||
|
todo_include_todos = False
|
||||||
|
|
||||||
|
|
||||||
|
# -- Options for HTML output ----------------------------------------------
|
||||||
|
|
||||||
|
# The theme to use for HTML and HTML Help pages. See the documentation for
|
||||||
|
# a list of builtin themes.
|
||||||
|
|
||||||
|
html_theme = "furo"
|
||||||
|
|
||||||
|
# Theme options are theme-specific and customize the look and feel of a theme
|
||||||
|
# further. For a list of options available for each theme, see the
|
||||||
|
# documentation.
|
||||||
|
# html_theme_options = {}
|
||||||
|
|
||||||
|
# Add any paths that contain custom themes here, relative to this directory.
|
||||||
|
# html_theme_path = []
|
||||||
|
|
||||||
|
# The name for this set of Sphinx documents. If None, it defaults to
|
||||||
|
# "<project> v<version> documentation".
|
||||||
|
# html_title = None
|
||||||
|
|
||||||
|
# A shorter title for the navigation bar. Default is the same as html_title.
|
||||||
|
# html_short_title = None
|
||||||
|
|
||||||
|
# The name of an image file (relative to this directory) to place at the top
|
||||||
|
# of the sidebar.
|
||||||
|
# html_logo = None
|
||||||
|
|
||||||
|
# The name of an image file (within the static path) to use as favicon of the
|
||||||
|
# docs. This file should be a Windows icon file (.ico) being 16x16 or 32x32
|
||||||
|
# pixels large.
|
||||||
|
# html_favicon = None
|
||||||
|
|
||||||
|
# Add any paths that contain custom static files (such as style sheets) here,
|
||||||
|
# relative to this directory. They are copied after the builtin static files,
|
||||||
|
# so a file named "default.css" will overwrite the builtin "default.css".
|
||||||
|
html_static_path = ["_static"]
|
||||||
|
|
||||||
|
html_css_files = [
|
||||||
|
"css/custom.css",
|
||||||
|
]
|
||||||
|
|
||||||
|
# Add any extra paths that contain custom files (such as robots.txt or
|
||||||
|
# .htaccess) here, relative to this directory. These files are copied
|
||||||
|
# directly to the root of the documentation.
|
||||||
|
# html_extra_path = []
|
||||||
|
|
||||||
|
# If not '', a 'Last updated on:' timestamp is inserted at every page bottom,
|
||||||
|
# using the given strftime format.
|
||||||
|
# html_last_updated_fmt = '%b %d, %Y'
|
||||||
|
|
||||||
|
# If true, SmartyPants will be used to convert quotes and dashes to
|
||||||
|
# typographically correct entities.
|
||||||
|
# html_use_smartypants = True
|
||||||
|
|
||||||
|
# Custom sidebar templates, maps document names to template names.
|
||||||
|
# html_sidebars = {}
|
||||||
|
|
||||||
|
# Additional templates that should be rendered to pages, maps page names to
|
||||||
|
# template names.
|
||||||
|
# html_additional_pages = {}
|
||||||
|
|
||||||
|
# If false, no module index is generated.
|
||||||
|
# html_domain_indices = True
|
||||||
|
|
||||||
|
# If false, no index is generated.
|
||||||
|
# html_use_index = True
|
||||||
|
|
||||||
|
# If true, the index is split into individual pages for each letter.
|
||||||
|
# html_split_index = False
|
||||||
|
|
||||||
|
# If true, links to the reST sources are added to the pages.
|
||||||
|
# html_show_sourcelink = True
|
||||||
|
|
||||||
|
# If true, "Created using Sphinx" is shown in the HTML footer. Default is True.
|
||||||
|
# html_show_sphinx = True
|
||||||
|
|
||||||
|
# If true, "(C) Copyright ..." is shown in the HTML footer. Default is True.
|
||||||
|
# html_show_copyright = True
|
||||||
|
|
||||||
|
# If true, an OpenSearch description file will be output, and all pages will
|
||||||
|
# contain a <link> tag referring to it. The value of this option must be the
|
||||||
|
# base URL from which the finished HTML is served.
|
||||||
|
# html_use_opensearch = ''
|
||||||
|
|
||||||
|
# This is the file name suffix for HTML files (e.g. ".xhtml").
|
||||||
|
# html_file_suffix = None
|
||||||
|
|
||||||
|
# Language to be used for generating the HTML full-text search index.
|
||||||
|
# Sphinx supports the following languages:
|
||||||
|
# 'da', 'de', 'en', 'es', 'fi', 'fr', 'h', 'it', 'ja'
|
||||||
|
# 'nl', 'no', 'pt', 'ro', 'r', 'sv', 'tr'
|
||||||
|
# html_search_language = 'en'
|
||||||
|
|
||||||
|
# A dictionary with options for the search language support, empty by default.
|
||||||
|
# Now only 'ja' uses this config value
|
||||||
|
# html_search_options = {'type': 'default'}
|
||||||
|
|
||||||
|
# The name of a javascript file (relative to the configuration directory) that
|
||||||
|
# implements a search results scorer. If empty, the default will be used.
|
||||||
|
# html_search_scorer = 'scorer.js'
|
||||||
|
|
||||||
|
# Output file base name for HTML help builder.
|
||||||
|
htmlhelp_basename = "pybind11doc"
|
||||||
|
|
||||||
|
# -- Options for LaTeX output ---------------------------------------------
|
||||||
|
|
||||||
|
latex_engine = "pdflatex"
|
||||||
|
|
||||||
|
latex_elements = {
|
||||||
|
# The paper size ('letterpaper' or 'a4paper').
|
||||||
|
# 'papersize': 'letterpaper',
|
||||||
|
#
|
||||||
|
# The font size ('10pt', '11pt' or '12pt').
|
||||||
|
# 'pointsize': '10pt',
|
||||||
|
#
|
||||||
|
# Additional stuff for the LaTeX preamble.
|
||||||
|
# remove blank pages (between the title page and the TOC, etc.)
|
||||||
|
"classoptions": ",openany,oneside",
|
||||||
|
"preamble": r"""
|
||||||
|
\usepackage{fontawesome}
|
||||||
|
\usepackage{textgreek}
|
||||||
|
\DeclareUnicodeCharacter{00A0}{}
|
||||||
|
\DeclareUnicodeCharacter{2194}{\faArrowsH}
|
||||||
|
\DeclareUnicodeCharacter{1F382}{\faBirthdayCake}
|
||||||
|
\DeclareUnicodeCharacter{1F355}{\faAdjust}
|
||||||
|
\DeclareUnicodeCharacter{0301}{'}
|
||||||
|
\DeclareUnicodeCharacter{03C0}{\textpi}
|
||||||
|
|
||||||
|
""",
|
||||||
|
# Latex figure (float) alignment
|
||||||
|
# 'figure_align': 'htbp',
|
||||||
|
}
|
||||||
|
|
||||||
|
# Grouping the document tree into LaTeX files. List of tuples
|
||||||
|
# (source start file, target name, title,
|
||||||
|
# author, documentclass [howto, manual, or own class]).
|
||||||
|
latex_documents = [
|
||||||
|
(master_doc, "pybind11.tex", "pybind11 Documentation", "Wenzel Jakob", "manual"),
|
||||||
|
]
|
||||||
|
|
||||||
|
# The name of an image file (relative to this directory) to place at the top of
|
||||||
|
# the title page.
|
||||||
|
# latex_logo = 'pybind11-logo.png'
|
||||||
|
|
||||||
|
# For "manual" documents, if this is true, then toplevel headings are parts,
|
||||||
|
# not chapters.
|
||||||
|
# latex_use_parts = False
|
||||||
|
|
||||||
|
# If true, show page references after internal links.
|
||||||
|
# latex_show_pagerefs = False
|
||||||
|
|
||||||
|
# If true, show URL addresses after external links.
|
||||||
|
# latex_show_urls = False
|
||||||
|
|
||||||
|
# Documents to append as an appendix to all manuals.
|
||||||
|
# latex_appendices = []
|
||||||
|
|
||||||
|
# If false, no module index is generated.
|
||||||
|
# latex_domain_indices = True
|
||||||
|
|
||||||
|
|
||||||
|
# -- Options for manual page output ---------------------------------------
|
||||||
|
|
||||||
|
# One entry per manual page. List of tuples
|
||||||
|
# (source start file, name, description, authors, manual section).
|
||||||
|
man_pages = [(master_doc, "pybind11", "pybind11 Documentation", [author], 1)]
|
||||||
|
|
||||||
|
# If true, show URL addresses after external links.
|
||||||
|
# man_show_urls = False
|
||||||
|
|
||||||
|
|
||||||
|
# -- Options for Texinfo output -------------------------------------------
|
||||||
|
|
||||||
|
# Grouping the document tree into Texinfo files. List of tuples
|
||||||
|
# (source start file, target name, title, author,
|
||||||
|
# dir menu entry, description, category)
|
||||||
|
texinfo_documents = [
|
||||||
|
(
|
||||||
|
master_doc,
|
||||||
|
"pybind11",
|
||||||
|
"pybind11 Documentation",
|
||||||
|
author,
|
||||||
|
"pybind11",
|
||||||
|
"One line description of project.",
|
||||||
|
"Miscellaneous",
|
||||||
|
),
|
||||||
|
]
|
||||||
|
|
||||||
|
# Documents to append as an appendix to all manuals.
|
||||||
|
# texinfo_appendices = []
|
||||||
|
|
||||||
|
# If false, no module index is generated.
|
||||||
|
# texinfo_domain_indices = True
|
||||||
|
|
||||||
|
# How to display URL addresses: 'footnote', 'no', or 'inline'.
|
||||||
|
# texinfo_show_urls = 'footnote'
|
||||||
|
|
||||||
|
# If true, do not generate a @detailmenu in the "Top" node's menu.
|
||||||
|
# texinfo_no_detailmenu = False
|
||||||
|
|
||||||
|
primary_domain = "cpp"
|
||||||
|
highlight_language = "cpp"
|
||||||
|
|
||||||
|
|
||||||
|
def generate_doxygen_xml(app):
|
||||||
|
build_dir = os.path.join(app.confdir, ".build")
|
||||||
|
if not os.path.exists(build_dir):
|
||||||
|
os.mkdir(build_dir)
|
||||||
|
|
||||||
|
try:
|
||||||
|
subprocess.call(["doxygen", "--version"])
|
||||||
|
retcode = subprocess.call(["doxygen"], cwd=app.confdir)
|
||||||
|
if retcode < 0:
|
||||||
|
sys.stderr.write(f"doxygen error code: {-retcode}\n")
|
||||||
|
except OSError as e:
|
||||||
|
sys.stderr.write(f"doxygen execution failed: {e}\n")
|
||||||
|
|
||||||
|
|
||||||
|
def prepare(app):
|
||||||
|
with open(DIR.parent / "README.rst") as f:
|
||||||
|
contents = f.read()
|
||||||
|
|
||||||
|
if app.builder.name == "latex":
|
||||||
|
# Remove badges and stuff from start
|
||||||
|
contents = contents[contents.find(r".. start") :]
|
||||||
|
|
||||||
|
# Filter out section titles for index.rst for LaTeX
|
||||||
|
contents = re.sub(r"^(.*)\n[-~]{3,}$", r"**\1**", contents, flags=re.MULTILINE)
|
||||||
|
|
||||||
|
with open(DIR / "readme.rst", "w") as f:
|
||||||
|
f.write(contents)
|
||||||
|
|
||||||
|
|
||||||
|
def clean_up(app, exception): # noqa: ARG001
|
||||||
|
(DIR / "readme.rst").unlink()
|
||||||
|
|
||||||
|
|
||||||
|
def setup(app):
|
||||||
|
# Add hook for building doxygen xml when needed
|
||||||
|
app.connect("builder-inited", generate_doxygen_xml)
|
||||||
|
|
||||||
|
# Copy the readme in
|
||||||
|
app.connect("builder-inited", prepare)
|
||||||
|
|
||||||
|
# Clean up the generated readme
|
||||||
|
app.connect("build-finished", clean_up)
|
308
3rdparty/pybind11/docs/faq.rst
vendored
Normal file
308
3rdparty/pybind11/docs/faq.rst
vendored
Normal file
@ -0,0 +1,308 @@
|
|||||||
|
Frequently asked questions
|
||||||
|
##########################
|
||||||
|
|
||||||
|
"ImportError: dynamic module does not define init function"
|
||||||
|
===========================================================
|
||||||
|
|
||||||
|
1. Make sure that the name specified in PYBIND11_MODULE is identical to the
|
||||||
|
filename of the extension library (without suffixes such as ``.so``).
|
||||||
|
|
||||||
|
2. If the above did not fix the issue, you are likely using an incompatible
|
||||||
|
version of Python that does not match what you compiled with.
|
||||||
|
|
||||||
|
"Symbol not found: ``__Py_ZeroStruct`` / ``_PyInstanceMethod_Type``"
|
||||||
|
========================================================================
|
||||||
|
|
||||||
|
See the first answer.
|
||||||
|
|
||||||
|
"SystemError: dynamic module not initialized properly"
|
||||||
|
======================================================
|
||||||
|
|
||||||
|
See the first answer.
|
||||||
|
|
||||||
|
The Python interpreter immediately crashes when importing my module
|
||||||
|
===================================================================
|
||||||
|
|
||||||
|
See the first answer.
|
||||||
|
|
||||||
|
.. _faq_reference_arguments:
|
||||||
|
|
||||||
|
Limitations involving reference arguments
|
||||||
|
=========================================
|
||||||
|
|
||||||
|
In C++, it's fairly common to pass arguments using mutable references or
|
||||||
|
mutable pointers, which allows both read and write access to the value
|
||||||
|
supplied by the caller. This is sometimes done for efficiency reasons, or to
|
||||||
|
realize functions that have multiple return values. Here are two very basic
|
||||||
|
examples:
|
||||||
|
|
||||||
|
.. code-block:: cpp
|
||||||
|
|
||||||
|
void increment(int &i) { i++; }
|
||||||
|
void increment_ptr(int *i) { (*i)++; }
|
||||||
|
|
||||||
|
In Python, all arguments are passed by reference, so there is no general
|
||||||
|
issue in binding such code from Python.
|
||||||
|
|
||||||
|
However, certain basic Python types (like ``str``, ``int``, ``bool``,
|
||||||
|
``float``, etc.) are **immutable**. This means that the following attempt
|
||||||
|
to port the function to Python doesn't have the same effect on the value
|
||||||
|
provided by the caller -- in fact, it does nothing at all.
|
||||||
|
|
||||||
|
.. code-block:: python
|
||||||
|
|
||||||
|
def increment(i):
|
||||||
|
i += 1 # nope..
|
||||||
|
|
||||||
|
pybind11 is also affected by such language-level conventions, which means that
|
||||||
|
binding ``increment`` or ``increment_ptr`` will also create Python functions
|
||||||
|
that don't modify their arguments.
|
||||||
|
|
||||||
|
Although inconvenient, one workaround is to encapsulate the immutable types in
|
||||||
|
a custom type that does allow modifications.
|
||||||
|
|
||||||
|
An other alternative involves binding a small wrapper lambda function that
|
||||||
|
returns a tuple with all output arguments (see the remainder of the
|
||||||
|
documentation for examples on binding lambda functions). An example:
|
||||||
|
|
||||||
|
.. code-block:: cpp
|
||||||
|
|
||||||
|
int foo(int &i) { i++; return 123; }
|
||||||
|
|
||||||
|
and the binding code
|
||||||
|
|
||||||
|
.. code-block:: cpp
|
||||||
|
|
||||||
|
m.def("foo", [](int i) { int rv = foo(i); return std::make_tuple(rv, i); });
|
||||||
|
|
||||||
|
|
||||||
|
How can I reduce the build time?
|
||||||
|
================================
|
||||||
|
|
||||||
|
It's good practice to split binding code over multiple files, as in the
|
||||||
|
following example:
|
||||||
|
|
||||||
|
:file:`example.cpp`:
|
||||||
|
|
||||||
|
.. code-block:: cpp
|
||||||
|
|
||||||
|
void init_ex1(py::module_ &);
|
||||||
|
void init_ex2(py::module_ &);
|
||||||
|
/* ... */
|
||||||
|
|
||||||
|
PYBIND11_MODULE(example, m) {
|
||||||
|
init_ex1(m);
|
||||||
|
init_ex2(m);
|
||||||
|
/* ... */
|
||||||
|
}
|
||||||
|
|
||||||
|
:file:`ex1.cpp`:
|
||||||
|
|
||||||
|
.. code-block:: cpp
|
||||||
|
|
||||||
|
void init_ex1(py::module_ &m) {
|
||||||
|
m.def("add", [](int a, int b) { return a + b; });
|
||||||
|
}
|
||||||
|
|
||||||
|
:file:`ex2.cpp`:
|
||||||
|
|
||||||
|
.. code-block:: cpp
|
||||||
|
|
||||||
|
void init_ex2(py::module_ &m) {
|
||||||
|
m.def("sub", [](int a, int b) { return a - b; });
|
||||||
|
}
|
||||||
|
|
||||||
|
:command:`python`:
|
||||||
|
|
||||||
|
.. code-block:: pycon
|
||||||
|
|
||||||
|
>>> import example
|
||||||
|
>>> example.add(1, 2)
|
||||||
|
3
|
||||||
|
>>> example.sub(1, 1)
|
||||||
|
0
|
||||||
|
|
||||||
|
As shown above, the various ``init_ex`` functions should be contained in
|
||||||
|
separate files that can be compiled independently from one another, and then
|
||||||
|
linked together into the same final shared object. Following this approach
|
||||||
|
will:
|
||||||
|
|
||||||
|
1. reduce memory requirements per compilation unit.
|
||||||
|
|
||||||
|
2. enable parallel builds (if desired).
|
||||||
|
|
||||||
|
3. allow for faster incremental builds. For instance, when a single class
|
||||||
|
definition is changed, only a subset of the binding code will generally need
|
||||||
|
to be recompiled.
|
||||||
|
|
||||||
|
"recursive template instantiation exceeded maximum depth of 256"
|
||||||
|
================================================================
|
||||||
|
|
||||||
|
If you receive an error about excessive recursive template evaluation, try
|
||||||
|
specifying a larger value, e.g. ``-ftemplate-depth=1024`` on GCC/Clang. The
|
||||||
|
culprit is generally the generation of function signatures at compile time
|
||||||
|
using C++14 template metaprogramming.
|
||||||
|
|
||||||
|
.. _`faq:hidden_visibility`:
|
||||||
|
|
||||||
|
"'SomeClass' declared with greater visibility than the type of its field 'SomeClass::member' [-Wattributes]"
|
||||||
|
============================================================================================================
|
||||||
|
|
||||||
|
This error typically indicates that you are compiling without the required
|
||||||
|
``-fvisibility`` flag. pybind11 code internally forces hidden visibility on
|
||||||
|
all internal code, but if non-hidden (and thus *exported*) code attempts to
|
||||||
|
include a pybind type (for example, ``py::object`` or ``py::list``) you can run
|
||||||
|
into this warning.
|
||||||
|
|
||||||
|
To avoid it, make sure you are specifying ``-fvisibility=hidden`` when
|
||||||
|
compiling pybind code.
|
||||||
|
|
||||||
|
As to why ``-fvisibility=hidden`` is necessary, because pybind modules could
|
||||||
|
have been compiled under different versions of pybind itself, it is also
|
||||||
|
important that the symbols defined in one module do not clash with the
|
||||||
|
potentially-incompatible symbols defined in another. While Python extension
|
||||||
|
modules are usually loaded with localized symbols (under POSIX systems
|
||||||
|
typically using ``dlopen`` with the ``RTLD_LOCAL`` flag), this Python default
|
||||||
|
can be changed, but even if it isn't it is not always enough to guarantee
|
||||||
|
complete independence of the symbols involved when not using
|
||||||
|
``-fvisibility=hidden``.
|
||||||
|
|
||||||
|
Additionally, ``-fvisibility=hidden`` can deliver considerably binary size
|
||||||
|
savings. (See the following section for more details.)
|
||||||
|
|
||||||
|
|
||||||
|
.. _`faq:symhidden`:
|
||||||
|
|
||||||
|
How can I create smaller binaries?
|
||||||
|
==================================
|
||||||
|
|
||||||
|
To do its job, pybind11 extensively relies on a programming technique known as
|
||||||
|
*template metaprogramming*, which is a way of performing computation at compile
|
||||||
|
time using type information. Template metaprogramming usually instantiates code
|
||||||
|
involving significant numbers of deeply nested types that are either completely
|
||||||
|
removed or reduced to just a few instructions during the compiler's optimization
|
||||||
|
phase. However, due to the nested nature of these types, the resulting symbol
|
||||||
|
names in the compiled extension library can be extremely long. For instance,
|
||||||
|
the included test suite contains the following symbol:
|
||||||
|
|
||||||
|
.. only:: html
|
||||||
|
|
||||||
|
.. code-block:: none
|
||||||
|
|
||||||
|
__ZN8pybind1112cpp_functionC1Iv8Example2JRNSt3__16vectorINS3_12basic_stringIwNS3_11char_traitsIwEENS3_9allocatorIwEEEENS8_ISA_EEEEEJNS_4nameENS_7siblingENS_9is_methodEA28_cEEEMT0_FT_DpT1_EDpRKT2_
|
||||||
|
|
||||||
|
.. only:: not html
|
||||||
|
|
||||||
|
.. code-block:: cpp
|
||||||
|
|
||||||
|
__ZN8pybind1112cpp_functionC1Iv8Example2JRNSt3__16vectorINS3_12basic_stringIwNS3_11char_traitsIwEENS3_9allocatorIwEEEENS8_ISA_EEEEEJNS_4nameENS_7siblingENS_9is_methodEA28_cEEEMT0_FT_DpT1_EDpRKT2_
|
||||||
|
|
||||||
|
which is the mangled form of the following function type:
|
||||||
|
|
||||||
|
.. code-block:: cpp
|
||||||
|
|
||||||
|
pybind11::cpp_function::cpp_function<void, Example2, std::__1::vector<std::__1::basic_string<wchar_t, std::__1::char_traits<wchar_t>, std::__1::allocator<wchar_t> >, std::__1::allocator<std::__1::basic_string<wchar_t, std::__1::char_traits<wchar_t>, std::__1::allocator<wchar_t> > > >&, pybind11::name, pybind11::sibling, pybind11::is_method, char [28]>(void (Example2::*)(std::__1::vector<std::__1::basic_string<wchar_t, std::__1::char_traits<wchar_t>, std::__1::allocator<wchar_t> >, std::__1::allocator<std::__1::basic_string<wchar_t, std::__1::char_traits<wchar_t>, std::__1::allocator<wchar_t> > > >&), pybind11::name const&, pybind11::sibling const&, pybind11::is_method const&, char const (&) [28])
|
||||||
|
|
||||||
|
The memory needed to store just the mangled name of this function (196 bytes)
|
||||||
|
is larger than the actual piece of code (111 bytes) it represents! On the other
|
||||||
|
hand, it's silly to even give this function a name -- after all, it's just a
|
||||||
|
tiny cog in a bigger piece of machinery that is not exposed to the outside
|
||||||
|
world. So we'll generally only want to export symbols for those functions which
|
||||||
|
are actually called from the outside.
|
||||||
|
|
||||||
|
This can be achieved by specifying the parameter ``-fvisibility=hidden`` to GCC
|
||||||
|
and Clang, which sets the default symbol visibility to *hidden*, which has a
|
||||||
|
tremendous impact on the final binary size of the resulting extension library.
|
||||||
|
(On Visual Studio, symbols are already hidden by default, so nothing needs to
|
||||||
|
be done there.)
|
||||||
|
|
||||||
|
In addition to decreasing binary size, ``-fvisibility=hidden`` also avoids
|
||||||
|
potential serious issues when loading multiple modules and is required for
|
||||||
|
proper pybind operation. See the previous FAQ entry for more details.
|
||||||
|
|
||||||
|
How can I properly handle Ctrl-C in long-running functions?
|
||||||
|
===========================================================
|
||||||
|
|
||||||
|
Ctrl-C is received by the Python interpreter, and holds it until the GIL
|
||||||
|
is released, so a long-running function won't be interrupted.
|
||||||
|
|
||||||
|
To interrupt from inside your function, you can use the ``PyErr_CheckSignals()``
|
||||||
|
function, that will tell if a signal has been raised on the Python side. This
|
||||||
|
function merely checks a flag, so its impact is negligible. When a signal has
|
||||||
|
been received, you must either explicitly interrupt execution by throwing
|
||||||
|
``py::error_already_set`` (which will propagate the existing
|
||||||
|
``KeyboardInterrupt``), or clear the error (which you usually will not want):
|
||||||
|
|
||||||
|
.. code-block:: cpp
|
||||||
|
|
||||||
|
PYBIND11_MODULE(example, m)
|
||||||
|
{
|
||||||
|
m.def("long running_func", []()
|
||||||
|
{
|
||||||
|
for (;;) {
|
||||||
|
if (PyErr_CheckSignals() != 0)
|
||||||
|
throw py::error_already_set();
|
||||||
|
// Long running iteration
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
CMake doesn't detect the right Python version
|
||||||
|
=============================================
|
||||||
|
|
||||||
|
The CMake-based build system will try to automatically detect the installed
|
||||||
|
version of Python and link against that. When this fails, or when there are
|
||||||
|
multiple versions of Python and it finds the wrong one, delete
|
||||||
|
``CMakeCache.txt`` and then add ``-DPYTHON_EXECUTABLE=$(which python)`` to your
|
||||||
|
CMake configure line. (Replace ``$(which python)`` with a path to python if
|
||||||
|
your prefer.)
|
||||||
|
|
||||||
|
You can alternatively try ``-DPYBIND11_FINDPYTHON=ON``, which will activate the
|
||||||
|
new CMake FindPython support instead of pybind11's custom search. Requires
|
||||||
|
CMake 3.12+, and 3.15+ or 3.18.2+ are even better. You can set this in your
|
||||||
|
``CMakeLists.txt`` before adding or finding pybind11, as well.
|
||||||
|
|
||||||
|
Inconsistent detection of Python version in CMake and pybind11
|
||||||
|
==============================================================
|
||||||
|
|
||||||
|
The functions ``find_package(PythonInterp)`` and ``find_package(PythonLibs)``
|
||||||
|
provided by CMake for Python version detection are modified by pybind11 due to
|
||||||
|
unreliability and limitations that make them unsuitable for pybind11's needs.
|
||||||
|
Instead pybind11 provides its own, more reliable Python detection CMake code.
|
||||||
|
Conflicts can arise, however, when using pybind11 in a project that *also* uses
|
||||||
|
the CMake Python detection in a system with several Python versions installed.
|
||||||
|
|
||||||
|
This difference may cause inconsistencies and errors if *both* mechanisms are
|
||||||
|
used in the same project.
|
||||||
|
|
||||||
|
There are three possible solutions:
|
||||||
|
|
||||||
|
1. Avoid using ``find_package(PythonInterp)`` and ``find_package(PythonLibs)``
|
||||||
|
from CMake and rely on pybind11 in detecting Python version. If this is not
|
||||||
|
possible, the CMake machinery should be called *before* including pybind11.
|
||||||
|
2. Set ``PYBIND11_FINDPYTHON`` to ``True`` or use ``find_package(Python
|
||||||
|
COMPONENTS Interpreter Development)`` on modern CMake (3.12+, 3.15+ better,
|
||||||
|
3.18.2+ best). Pybind11 in these cases uses the new CMake FindPython instead
|
||||||
|
of the old, deprecated search tools, and these modules are much better at
|
||||||
|
finding the correct Python. If FindPythonLibs/Interp are not available
|
||||||
|
(CMake 3.27+), then this will be ignored and FindPython will be used.
|
||||||
|
3. Set ``PYBIND11_NOPYTHON`` to ``TRUE``. Pybind11 will not search for Python.
|
||||||
|
However, you will have to use the target-based system, and do more setup
|
||||||
|
yourself, because it does not know about or include things that depend on
|
||||||
|
Python, like ``pybind11_add_module``. This might be ideal for integrating
|
||||||
|
into an existing system, like scikit-build's Python helpers.
|
||||||
|
|
||||||
|
How to cite this project?
|
||||||
|
=========================
|
||||||
|
|
||||||
|
We suggest the following BibTeX template to cite pybind11 in scientific
|
||||||
|
discourse:
|
||||||
|
|
||||||
|
.. code-block:: bash
|
||||||
|
|
||||||
|
@misc{pybind11,
|
||||||
|
author = {Wenzel Jakob and Jason Rhinelander and Dean Moldovan},
|
||||||
|
year = {2017},
|
||||||
|
note = {https://github.com/pybind/pybind11},
|
||||||
|
title = {pybind11 -- Seamless operability between C++11 and Python}
|
||||||
|
}
|
48
3rdparty/pybind11/docs/index.rst
vendored
Normal file
48
3rdparty/pybind11/docs/index.rst
vendored
Normal file
@ -0,0 +1,48 @@
|
|||||||
|
.. only:: latex
|
||||||
|
|
||||||
|
Intro
|
||||||
|
=====
|
||||||
|
|
||||||
|
.. include:: readme.rst
|
||||||
|
|
||||||
|
.. only:: not latex
|
||||||
|
|
||||||
|
Contents:
|
||||||
|
|
||||||
|
.. toctree::
|
||||||
|
:maxdepth: 1
|
||||||
|
|
||||||
|
changelog
|
||||||
|
upgrade
|
||||||
|
|
||||||
|
.. toctree::
|
||||||
|
:caption: The Basics
|
||||||
|
:maxdepth: 2
|
||||||
|
|
||||||
|
installing
|
||||||
|
basics
|
||||||
|
classes
|
||||||
|
compiling
|
||||||
|
|
||||||
|
.. toctree::
|
||||||
|
:caption: Advanced Topics
|
||||||
|
:maxdepth: 2
|
||||||
|
|
||||||
|
advanced/functions
|
||||||
|
advanced/classes
|
||||||
|
advanced/exceptions
|
||||||
|
advanced/smart_ptrs
|
||||||
|
advanced/cast/index
|
||||||
|
advanced/pycpp/index
|
||||||
|
advanced/embedding
|
||||||
|
advanced/misc
|
||||||
|
|
||||||
|
.. toctree::
|
||||||
|
:caption: Extra Information
|
||||||
|
:maxdepth: 1
|
||||||
|
|
||||||
|
faq
|
||||||
|
benchmark
|
||||||
|
limitations
|
||||||
|
reference
|
||||||
|
cmake/index
|
105
3rdparty/pybind11/docs/installing.rst
vendored
Normal file
105
3rdparty/pybind11/docs/installing.rst
vendored
Normal file
@ -0,0 +1,105 @@
|
|||||||
|
.. _installing:
|
||||||
|
|
||||||
|
Installing the library
|
||||||
|
######################
|
||||||
|
|
||||||
|
There are several ways to get the pybind11 source, which lives at
|
||||||
|
`pybind/pybind11 on GitHub <https://github.com/pybind/pybind11>`_. The pybind11
|
||||||
|
developers recommend one of the first three ways listed here, submodule, PyPI,
|
||||||
|
or conda-forge, for obtaining pybind11.
|
||||||
|
|
||||||
|
.. _include_as_a_submodule:
|
||||||
|
|
||||||
|
Include as a submodule
|
||||||
|
======================
|
||||||
|
|
||||||
|
When you are working on a project in Git, you can use the pybind11 repository
|
||||||
|
as a submodule. From your git repository, use:
|
||||||
|
|
||||||
|
.. code-block:: bash
|
||||||
|
|
||||||
|
git submodule add -b stable ../../pybind/pybind11 extern/pybind11
|
||||||
|
git submodule update --init
|
||||||
|
|
||||||
|
This assumes you are placing your dependencies in ``extern/``, and that you are
|
||||||
|
using GitHub; if you are not using GitHub, use the full https or ssh URL
|
||||||
|
instead of the relative URL ``../../pybind/pybind11`` above. Some other servers
|
||||||
|
also require the ``.git`` extension (GitHub does not).
|
||||||
|
|
||||||
|
From here, you can now include ``extern/pybind11/include``, or you can use
|
||||||
|
the various integration tools (see :ref:`compiling`) pybind11 provides directly
|
||||||
|
from the local folder.
|
||||||
|
|
||||||
|
Include with PyPI
|
||||||
|
=================
|
||||||
|
|
||||||
|
You can download the sources and CMake files as a Python package from PyPI
|
||||||
|
using Pip. Just use:
|
||||||
|
|
||||||
|
.. code-block:: bash
|
||||||
|
|
||||||
|
pip install pybind11
|
||||||
|
|
||||||
|
This will provide pybind11 in a standard Python package format. If you want
|
||||||
|
pybind11 available directly in your environment root, you can use:
|
||||||
|
|
||||||
|
.. code-block:: bash
|
||||||
|
|
||||||
|
pip install "pybind11[global]"
|
||||||
|
|
||||||
|
This is not recommended if you are installing with your system Python, as it
|
||||||
|
will add files to ``/usr/local/include/pybind11`` and
|
||||||
|
``/usr/local/share/cmake/pybind11``, so unless that is what you want, it is
|
||||||
|
recommended only for use in virtual environments or your ``pyproject.toml``
|
||||||
|
file (see :ref:`compiling`).
|
||||||
|
|
||||||
|
Include with conda-forge
|
||||||
|
========================
|
||||||
|
|
||||||
|
You can use pybind11 with conda packaging via `conda-forge
|
||||||
|
<https://github.com/conda-forge/pybind11-feedstock>`_:
|
||||||
|
|
||||||
|
.. code-block:: bash
|
||||||
|
|
||||||
|
conda install -c conda-forge pybind11
|
||||||
|
|
||||||
|
|
||||||
|
Include with vcpkg
|
||||||
|
==================
|
||||||
|
You can download and install pybind11 using the Microsoft `vcpkg
|
||||||
|
<https://github.com/Microsoft/vcpkg/>`_ dependency manager:
|
||||||
|
|
||||||
|
.. code-block:: bash
|
||||||
|
|
||||||
|
git clone https://github.com/Microsoft/vcpkg.git
|
||||||
|
cd vcpkg
|
||||||
|
./bootstrap-vcpkg.sh
|
||||||
|
./vcpkg integrate install
|
||||||
|
vcpkg install pybind11
|
||||||
|
|
||||||
|
The pybind11 port in vcpkg is kept up to date by Microsoft team members and
|
||||||
|
community contributors. If the version is out of date, please `create an issue
|
||||||
|
or pull request <https://github.com/Microsoft/vcpkg/>`_ on the vcpkg
|
||||||
|
repository.
|
||||||
|
|
||||||
|
Global install with brew
|
||||||
|
========================
|
||||||
|
|
||||||
|
The brew package manager (Homebrew on macOS, or Linuxbrew on Linux) has a
|
||||||
|
`pybind11 package
|
||||||
|
<https://github.com/Homebrew/homebrew-core/blob/master/Formula/pybind11.rb>`_.
|
||||||
|
To install:
|
||||||
|
|
||||||
|
.. code-block:: bash
|
||||||
|
|
||||||
|
brew install pybind11
|
||||||
|
|
||||||
|
.. We should list Conan, and possibly a few other C++ package managers (hunter,
|
||||||
|
.. perhaps). Conan has a very clean CMake integration that would be good to show.
|
||||||
|
|
||||||
|
Other options
|
||||||
|
=============
|
||||||
|
|
||||||
|
Other locations you can find pybind11 are `listed here
|
||||||
|
<https://repology.org/project/python:pybind11/versions>`_; these are maintained
|
||||||
|
by various packagers and the community.
|
72
3rdparty/pybind11/docs/limitations.rst
vendored
Normal file
72
3rdparty/pybind11/docs/limitations.rst
vendored
Normal file
@ -0,0 +1,72 @@
|
|||||||
|
Limitations
|
||||||
|
###########
|
||||||
|
|
||||||
|
Design choices
|
||||||
|
^^^^^^^^^^^^^^
|
||||||
|
|
||||||
|
pybind11 strives to be a general solution to binding generation, but it also has
|
||||||
|
certain limitations:
|
||||||
|
|
||||||
|
- pybind11 casts away ``const``-ness in function arguments and return values.
|
||||||
|
This is in line with the Python language, which has no concept of ``const``
|
||||||
|
values. This means that some additional care is needed to avoid bugs that
|
||||||
|
would be caught by the type checker in a traditional C++ program.
|
||||||
|
|
||||||
|
- The NumPy interface ``pybind11::array`` greatly simplifies accessing
|
||||||
|
numerical data from C++ (and vice versa), but it's not a full-blown array
|
||||||
|
class like ``Eigen::Array`` or ``boost.multi_array``. ``Eigen`` objects are
|
||||||
|
directly supported, however, with ``pybind11/eigen.h``.
|
||||||
|
|
||||||
|
Large but useful features could be implemented in pybind11 but would lead to a
|
||||||
|
significant increase in complexity. Pybind11 strives to be simple and compact.
|
||||||
|
Users who require large new features are encouraged to write an extension to
|
||||||
|
pybind11; see `pybind11_json <https://github.com/pybind/pybind11_json>`_ for an
|
||||||
|
example.
|
||||||
|
|
||||||
|
|
||||||
|
Known bugs
|
||||||
|
^^^^^^^^^^
|
||||||
|
|
||||||
|
These are issues that hopefully will one day be fixed, but currently are
|
||||||
|
unsolved. If you know how to help with one of these issues, contributions
|
||||||
|
are welcome!
|
||||||
|
|
||||||
|
- Intel 20.2 is currently having an issue with the test suite.
|
||||||
|
`#2573 <https://github.com/pybind/pybind11/pull/2573>`_
|
||||||
|
|
||||||
|
- Debug mode Python does not support 1-5 tests in the test suite currently.
|
||||||
|
`#2422 <https://github.com/pybind/pybind11/pull/2422>`_
|
||||||
|
|
||||||
|
- PyPy3 7.3.1 and 7.3.2 have issues with several tests on 32-bit Windows.
|
||||||
|
|
||||||
|
Known limitations
|
||||||
|
^^^^^^^^^^^^^^^^^
|
||||||
|
|
||||||
|
These are issues that are probably solvable, but have not been fixed yet. A
|
||||||
|
clean, well written patch would likely be accepted to solve them.
|
||||||
|
|
||||||
|
- Type casters are not kept alive recursively.
|
||||||
|
`#2527 <https://github.com/pybind/pybind11/issues/2527>`_
|
||||||
|
One consequence is that containers of ``char *`` are currently not supported.
|
||||||
|
`#2245 <https://github.com/pybind/pybind11/issues/2245>`_
|
||||||
|
|
||||||
|
- The ``cpptest`` does not run on Windows with Python 3.8 or newer, due to DLL
|
||||||
|
loader changes. User code that is correctly installed should not be affected.
|
||||||
|
`#2560 <https://github.com/pybind/pybind11/issue/2560>`_
|
||||||
|
|
||||||
|
Python 3.9.0 warning
|
||||||
|
^^^^^^^^^^^^^^^^^^^^
|
||||||
|
|
||||||
|
Combining older versions of pybind11 (< 2.6.0) with Python on exactly 3.9.0
|
||||||
|
will trigger undefined behavior that typically manifests as crashes during
|
||||||
|
interpreter shutdown (but could also destroy your data. **You have been
|
||||||
|
warned**).
|
||||||
|
|
||||||
|
This issue was `fixed in Python <https://github.com/python/cpython/pull/22670>`_.
|
||||||
|
As a mitigation for this bug, pybind11 2.6.0 or newer includes a workaround
|
||||||
|
specifically when Python 3.9.0 is detected at runtime, leaking about 50 bytes
|
||||||
|
of memory when a callback function is garbage collected. For reference, the
|
||||||
|
pybind11 test suite has about 2,000 such callbacks, but only 49 are garbage
|
||||||
|
collected before the end-of-process. Wheels (even if built with Python 3.9.0)
|
||||||
|
will correctly avoid the leak when run in Python 3.9.1, and this does not
|
||||||
|
affect other 3.X versions.
|
BIN
3rdparty/pybind11/docs/pybind11-logo.png
vendored
Normal file
BIN
3rdparty/pybind11/docs/pybind11-logo.png
vendored
Normal file
Binary file not shown.
After Width: | Height: | Size: 60 KiB |
BIN
3rdparty/pybind11/docs/pybind11_vs_boost_python1.png
vendored
Normal file
BIN
3rdparty/pybind11/docs/pybind11_vs_boost_python1.png
vendored
Normal file
Binary file not shown.
After Width: | Height: | Size: 44 KiB |
BIN
3rdparty/pybind11/docs/pybind11_vs_boost_python1.svg
vendored
Normal file
BIN
3rdparty/pybind11/docs/pybind11_vs_boost_python1.svg
vendored
Normal file
Binary file not shown.
After Width: | Height: | Size: 86 KiB |
Some files were not shown because too many files have changed in this diff Show More
Loading…
Reference in New Issue
Block a user