Codebase list pypy3 / 272b936
New upstream version 7.0.0+dfsg Stefano Rivera 5 years ago
741 changed file(s) with 37106 addition(s) and 29416 deletion(s). Raw diff Collapse all Expand all
2929 DEALINGS IN THE SOFTWARE.
3030
3131
32 PyPy Copyright holders 2003-2018
32 PyPy Copyright holders 2003-2019
3333 --------------------------------
3434
3535 Except when otherwise stated (look for LICENSE files or information at
3939 Armin Rigo
4040 Maciej Fijalkowski
4141 Carl Friedrich Bolz-Tereick
42 Antonio Cuni
4243 Amaury Forgeot d'Arc
43 Antonio Cuni
4444 Matti Picus
4545 Samuele Pedroni
4646 Ronan Lamy
4747 Alex Gaynor
4848 Philip Jenvey
49 Richard Plangger
4950 Brian Kearns
50 Richard Plangger
51 Michael Hudson
51 Michael Hudson-Doyle
5252 Manuel Jacob
5353 David Schneider
5454 Holger Krekel
5858 Anders Chrigstrom
5959 Wim Lavrijsen
6060 Eric van Riet Paap
61 Remi Meier
6162 Richard Emslie
62 Remi Meier
6363 Alexander Schremmer
6464 Dan Villiom Podlaski Christiansen
6565 Lukas Diekmann
6969 Niklaus Haldimann
7070 Camillo Bruni
7171 Laura Creighton
72 Romain Guillebert
7372 Toon Verwaest
7473 Leonardo Santagada
7574 Seo Sanghyeon
75 Romain Guillebert
7676 Ronny Pfannschmidt
7777 Justin Peel
7878 Raffael Tfirst
113113 Squeaky
114114 Edd Barrett
115115 Timo Paulssen
116 Laurence Tratt
116117 Marius Gedminas
117118 Nicolas Truessel
118119 Alexandre Fayolle
119120 Simon Burton
120121 Martin Matusiak
121 Laurence Tratt
122122 Wenzhu Man
123123 Konstantin Lopuhin
124124 John Witulski
133133 Jean-Philippe St. Pierre
134134 Guido van Rossum
135135 Pavel Vinogradov
136 Stefan Beyer
137 William Leslie
136138 Paweł Piotr Przeradowski
137 William Leslie
138139 marky1991
139140 Ilya Osadchiy
140141 Tobias Oberstein
143144 Taavi Burns
144145 Adrian Kuhn
145146 tav
147 Stian Andreassen
146148 Georg Brandl
147149 Joannah Nanjekye
148150 Bert Freudenberg
149 Stian Andreassen
150151 Wanja Saatkamp
151152 Mike Blume
152153 Gerald Klix
162163 Vasily Kuznetsov
163164 Preston Timmons
164165 David Ripton
166 Pieter Zieschang
165167 Dusty Phillips
166168 Lukas Renggli
167169 Guenter Jantzen
175177 Andrew Durdin
176178 Ben Young
177179 Michael Schneider
180 Yusuke Tsutsumi
178181 Nicholas Riley
179182 Jason Chu
180183 Igor Trindade Oliveira
186189 Mariano Anaya
187190 anatoly techtonik
188191 Karl Bartel
189 Stefan Beyer
190192 Gabriel Lavoie
191193 Jared Grubb
192194 Alecsandru Patrascu
197199 Victor Stinner
198200 Andrews Medina
199201 Aaron Iles
200 p_zieschang@yahoo.de
201202 Toby Watson
202203 Daniel Patrick
203204 Stuart Williams
209210 Mikael Schönenberg
210211 Stanislaw Halik
211212 Mihnea Saracin
213 Matt Jackson
212214 Berkin Ilbeyi
213215 Gasper Zejn
214216 Faye Zhao
216218 Anders Qvist
217219 Corbin Simpson
218220 Chirag Jadwani
221 Pauli Virtanen
219222 Jonathan David Riehl
220223 Beatrice During
221224 Alex Perry
222225 Robert Zaremba
223226 Alan McIntyre
224227 Alexander Sedov
228 David C Ellis
225229 Vaibhav Sood
226230 Reuben Cummings
227231 Attila Gobi
241245 Arjun Naik
242246 Aaron Gallagher
243247 Alexis Daboville
244 Pieter Zieschang
245248 Karl Ramm
246249 Lukas Vacek
247250 Omer Katz
269272 Catalin Gabriel Manciu
270273 Jacob Oscarson
271274 Ryan Gonzalez
275 Antoine Dupre
272276 Kristjan Valur Jonsson
273277 Lucio Torre
274278 Richard Lancaster
275279 Dan Buch
276280 Lene Wagner
277281 Tomo Cocoa
282 Miro Hrončok
283 Anthony Sottile
278284 David Lievens
279285 Neil Blakey-Milner
280286 Henrik Vendelbo
289295 Bobby Impollonia
290296 Roberto De Ioris
291297 Jeong YunWon
298 andrewjlawrence
292299 Christopher Armstrong
293300 Aaron Tubbs
294301 Vasantha Ganesh K
295302 Jason Michalski
303 Radu Ciorba
296304 Markus Holtermann
297305 Andrew Thompson
298306 Yusei Tahara
300308 Fabio Niephaus
301309 Akira Li
302310 Gustavo Niemeyer
303 Rafał Gałczyński
311 Nate Bragg
304312 Lucas Stadler
305313 roberto@goyle
314 Carl Bordum Hansen
306315 Matt Bogosian
307316 Yury V. Zaytsev
308317 florinpapa
309318 Anders Sigfridsson
310 Matt Jackson
311319 Nikolay Zinov
312320 rafalgalczynski@gmail.com
313321 Joshua Gilbert
314322 Anna Katrina Dominguez
315323 Kim Jin Su
316324 Amber Brown
317 Miro Hrončok
318 Anthony Sottile
319 Nate Bragg
325 Andrew Stepanov
326 Rafał Gałczyński
320327 Ben Darnell
321328 Juan Francisco Cantero Hurtado
322329 Godefroid Chappelle
323330 Julian Berman
324 Michael Hudson-Doyle
325331 Stephan Busemann
326332 Dan Colish
327333 timo
331337 halgari
332338 Jim Baker
333339 Chris Lambacher
340 John Aldis
334341 coolbutuseless@gmail.com
335342 Mike Bayer
336343 Rodrigo Araújo
339346 OlivierBlanvillain
340347 Jonas Pfannschmidt
341348 Zearin
349 Johan Forsberg
342350 Andrey Churin
343351 Dan Crosta
344352 reubano@gmail.com
348356 Steve Papanik
349357 Eli Stevens
350358 Boglarka Vezer
351 gabrielg
359 gabrielg@ec2-54-146-239-158.compute-1.amazonaws.com
352360 PavloKapyshin
361 Hervé Beraud
353362 Tomer Chachamu
354363 Christopher Groskopf
355364 Asmo Soinio
363372 Michael Chermside
364373 Anna Ravencroft
365374 remarkablerocket
366 Pauli Virtanen
367375 Petre Vijiac
368376 Berker Peksag
369377 Christian Muirhead
383391 Zooko Wilcox-O Hearn
384392 James Lan
385393 jiaaro
394 Evgenii Gorinov
386395 Markus Unterwaditzer
387396 Kristoffer Kleine
388397 Graham Markall
389398 Dan Loewenherz
390399 werat
391 Andrew Stepanov
400 Filip Salomonsson
392401 Niclas Olofsson
393402 Chris Pressey
394403 Tobias Diaz
33
44 Welcome to PyPy!
55
6 PyPy is an interperter that implements the Python programming language, based
6 PyPy is an interpreter that implements the Python programming language, based
77 on the RPython compiler framework for dynamic language implementations.
88
99 The home page for the interpreter is:
1414
1515 http://doc.pypy.org/
1616
17 More documentation about the RPython framework can be found here
17 More documentation about the RPython framework can be found here:
1818
19 http://rpython.readthedocs.io
19 http://rpython.readthedocs.io/
2020
21 The source for the documentation is in the pypy/doc directory
21 The source for the documentation is in the pypy/doc directory.
22
2223
2324 Using PyPy instead of CPython
24 =============================
25 -----------------------------
2526
26 Please read the information at http://pypy.org to find the correct way to
27 Please read the information at http://pypy.org/ to find the correct way to
2728 download and use PyPy as an alternative to CPython.
2829
30
2931 Building
30 ========
32 --------
3133
3234 Building PyPy is not the recommended way to obtain the PyPy alternative python
3335 interpreter. It is time-consuming and requires significant computing resources.
34 More information can be found here
36 More information can be found here:
3537
3638 http://doc.pypy.org/en/latest/build.html
3739
3840 Enjoy and send us feedback!
3941
4042 the pypy-dev team <pypy-dev@python.org>
41
42
0
1 Copyright (c) 2005-2008, The Android Open Source Project
2
3 Licensed under the Apache License, Version 2.0 (the "License");
4 you may not use this file except in compliance with the License.
5
6 Unless required by applicable law or agreed to in writing, software
7 distributed under the License is distributed on an "AS IS" BASIS,
8 WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
9 See the License for the specific language governing permissions and
10 limitations under the License.
11
12
13 Apache License
14 Version 2.0, January 2004
15 http://www.apache.org/licenses/
16
17 TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION
18
19 1. Definitions.
20
21 "License" shall mean the terms and conditions for use, reproduction,
22 and distribution as defined by Sections 1 through 9 of this document.
23
24 "Licensor" shall mean the copyright owner or entity authorized by
25 the copyright owner that is granting the License.
26
27 "Legal Entity" shall mean the union of the acting entity and all
28 other entities that control, are controlled by, or are under common
29 control with that entity. For the purposes of this definition,
30 "control" means (i) the power, direct or indirect, to cause the
31 direction or management of such entity, whether by contract or
32 otherwise, or (ii) ownership of fifty percent (50%) or more of the
33 outstanding shares, or (iii) beneficial ownership of such entity.
34
35 "You" (or "Your") shall mean an individual or Legal Entity
36 exercising permissions granted by this License.
37
38 "Source" form shall mean the preferred form for making modifications,
39 including but not limited to software source code, documentation
40 source, and configuration files.
41
42 "Object" form shall mean any form resulting from mechanical
43 transformation or translation of a Source form, including but
44 not limited to compiled object code, generated documentation,
45 and conversions to other media types.
46
47 "Work" shall mean the work of authorship, whether in Source or
48 Object form, made available under the License, as indicated by a
49 copyright notice that is included in or attached to the work
50 (an example is provided in the Appendix below).
51
52 "Derivative Works" shall mean any work, whether in Source or Object
53 form, that is based on (or derived from) the Work and for which the
54 editorial revisions, annotations, elaborations, or other modifications
55 represent, as a whole, an original work of authorship. For the purposes
56 of this License, Derivative Works shall not include works that remain
57 separable from, or merely link (or bind by name) to the interfaces of,
58 the Work and Derivative Works thereof.
59
60 "Contribution" shall mean any work of authorship, including
61 the original version of the Work and any modifications or additions
62 to that Work or Derivative Works thereof, that is intentionally
63 submitted to Licensor for inclusion in the Work by the copyright owner
64 or by an individual or Legal Entity authorized to submit on behalf of
65 the copyright owner. For the purposes of this definition, "submitted"
66 means any form of electronic, verbal, or written communication sent
67 to the Licensor or its representatives, including but not limited to
68 communication on electronic mailing lists, source code control systems,
69 and issue tracking systems that are managed by, or on behalf of, the
70 Licensor for the purpose of discussing and improving the Work, but
71 excluding communication that is conspicuously marked or otherwise
72 designated in writing by the copyright owner as "Not a Contribution."
73
74 "Contributor" shall mean Licensor and any individual or Legal Entity
75 on behalf of whom a Contribution has been received by Licensor and
76 subsequently incorporated within the Work.
77
78 2. Grant of Copyright License. Subject to the terms and conditions of
79 this License, each Contributor hereby grants to You a perpetual,
80 worldwide, non-exclusive, no-charge, royalty-free, irrevocable
81 copyright license to reproduce, prepare Derivative Works of,
82 publicly display, publicly perform, sublicense, and distribute the
83 Work and such Derivative Works in Source or Object form.
84
85 3. Grant of Patent License. Subject to the terms and conditions of
86 this License, each Contributor hereby grants to You a perpetual,
87 worldwide, non-exclusive, no-charge, royalty-free, irrevocable
88 (except as stated in this section) patent license to make, have made,
89 use, offer to sell, sell, import, and otherwise transfer the Work,
90 where such license applies only to those patent claims licensable
91 by such Contributor that are necessarily infringed by their
92 Contribution(s) alone or by combination of their Contribution(s)
93 with the Work to which such Contribution(s) was submitted. If You
94 institute patent litigation against any entity (including a
95 cross-claim or counterclaim in a lawsuit) alleging that the Work
96 or a Contribution incorporated within the Work constitutes direct
97 or contributory patent infringement, then any patent licenses
98 granted to You under this License for that Work shall terminate
99 as of the date such litigation is filed.
100
101 4. Redistribution. You may reproduce and distribute copies of the
102 Work or Derivative Works thereof in any medium, with or without
103 modifications, and in Source or Object form, provided that You
104 meet the following conditions:
105
106 (a) You must give any other recipients of the Work or
107 Derivative Works a copy of this License; and
108
109 (b) You must cause any modified files to carry prominent notices
110 stating that You changed the files; and
111
112 (c) You must retain, in the Source form of any Derivative Works
113 that You distribute, all copyright, patent, trademark, and
114 attribution notices from the Source form of the Work,
115 excluding those notices that do not pertain to any part of
116 the Derivative Works; and
117
118 (d) If the Work includes a "NOTICE" text file as part of its
119 distribution, then any Derivative Works that You distribute must
120 include a readable copy of the attribution notices contained
121 within such NOTICE file, excluding those notices that do not
122 pertain to any part of the Derivative Works, in at least one
123 of the following places: within a NOTICE text file distributed
124 as part of the Derivative Works; within the Source form or
125 documentation, if provided along with the Derivative Works; or,
126 within a display generated by the Derivative Works, if and
127 wherever such third-party notices normally appear. The contents
128 of the NOTICE file are for informational purposes only and
129 do not modify the License. You may add Your own attribution
130 notices within Derivative Works that You distribute, alongside
131 or as an addendum to the NOTICE text from the Work, provided
132 that such additional attribution notices cannot be construed
133 as modifying the License.
134
135 You may add Your own copyright statement to Your modifications and
136 may provide additional or different license terms and conditions
137 for use, reproduction, or distribution of Your modifications, or
138 for any such Derivative Works as a whole, provided Your use,
139 reproduction, and distribution of the Work otherwise complies with
140 the conditions stated in this License.
141
142 5. Submission of Contributions. Unless You explicitly state otherwise,
143 any Contribution intentionally submitted for inclusion in the Work
144 by You to the Licensor shall be under the terms and conditions of
145 this License, without any additional terms or conditions.
146 Notwithstanding the above, nothing herein shall supersede or modify
147 the terms of any separate license agreement you may have executed
148 with Licensor regarding such Contributions.
149
150 6. Trademarks. This License does not grant permission to use the trade
151 names, trademarks, service marks, or product names of the Licensor,
152 except as required for reasonable and customary use in describing the
153 origin of the Work and reproducing the content of the NOTICE file.
154
155 7. Disclaimer of Warranty. Unless required by applicable law or
156 agreed to in writing, Licensor provides the Work (and each
157 Contributor provides its Contributions) on an "AS IS" BASIS,
158 WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
159 implied, including, without limitation, any warranties or conditions
160 of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A
161 PARTICULAR PURPOSE. You are solely responsible for determining the
162 appropriateness of using or redistributing the Work and assume any
163 risks associated with Your exercise of permissions under this License.
164
165 8. Limitation of Liability. In no event and under no legal theory,
166 whether in tort (including negligence), contract, or otherwise,
167 unless required by applicable law (such as deliberate and grossly
168 negligent acts) or agreed to in writing, shall any Contributor be
169 liable to You for damages, including any direct, indirect, special,
170 incidental, or consequential damages of any character arising as a
171 result of this License or out of the use or inability to use the
172 Work (including but not limited to damages for loss of goodwill,
173 work stoppage, computer failure or malfunction, or any and all
174 other commercial damages or losses), even if such Contributor
175 has been advised of the possibility of such damages.
176
177 9. Accepting Warranty or Additional Liability. While redistributing
178 the Work or Derivative Works thereof, You may choose to offer,
179 and charge a fee for, acceptance of support, warranty, indemnity,
180 or other liability obligations and/or rights consistent with this
181 License. However, in accepting such obligations, You may act only
182 on Your own behalf and on Your sole responsibility, not on behalf
183 of any other Contributor, and only if You agree to indemnify,
184 defend, and hold each Contributor harmless for any liability
185 incurred by, or claims asserted against, such Contributor by reason
186 of your accepting any such warranty or additional liability.
187
188 END OF TERMS AND CONDITIONS
189
+0
-190
dotviewer/font/NOTICE less more
0
1 Copyright (c) 2005-2008, The Android Open Source Project
2
3 Licensed under the Apache License, Version 2.0 (the "License");
4 you may not use this file except in compliance with the License.
5
6 Unless required by applicable law or agreed to in writing, software
7 distributed under the License is distributed on an "AS IS" BASIS,
8 WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
9 See the License for the specific language governing permissions and
10 limitations under the License.
11
12
13 Apache License
14 Version 2.0, January 2004
15 http://www.apache.org/licenses/
16
17 TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION
18
19 1. Definitions.
20
21 "License" shall mean the terms and conditions for use, reproduction,
22 and distribution as defined by Sections 1 through 9 of this document.
23
24 "Licensor" shall mean the copyright owner or entity authorized by
25 the copyright owner that is granting the License.
26
27 "Legal Entity" shall mean the union of the acting entity and all
28 other entities that control, are controlled by, or are under common
29 control with that entity. For the purposes of this definition,
30 "control" means (i) the power, direct or indirect, to cause the
31 direction or management of such entity, whether by contract or
32 otherwise, or (ii) ownership of fifty percent (50%) or more of the
33 outstanding shares, or (iii) beneficial ownership of such entity.
34
35 "You" (or "Your") shall mean an individual or Legal Entity
36 exercising permissions granted by this License.
37
38 "Source" form shall mean the preferred form for making modifications,
39 including but not limited to software source code, documentation
40 source, and configuration files.
41
42 "Object" form shall mean any form resulting from mechanical
43 transformation or translation of a Source form, including but
44 not limited to compiled object code, generated documentation,
45 and conversions to other media types.
46
47 "Work" shall mean the work of authorship, whether in Source or
48 Object form, made available under the License, as indicated by a
49 copyright notice that is included in or attached to the work
50 (an example is provided in the Appendix below).
51
52 "Derivative Works" shall mean any work, whether in Source or Object
53 form, that is based on (or derived from) the Work and for which the
54 editorial revisions, annotations, elaborations, or other modifications
55 represent, as a whole, an original work of authorship. For the purposes
56 of this License, Derivative Works shall not include works that remain
57 separable from, or merely link (or bind by name) to the interfaces of,
58 the Work and Derivative Works thereof.
59
60 "Contribution" shall mean any work of authorship, including
61 the original version of the Work and any modifications or additions
62 to that Work or Derivative Works thereof, that is intentionally
63 submitted to Licensor for inclusion in the Work by the copyright owner
64 or by an individual or Legal Entity authorized to submit on behalf of
65 the copyright owner. For the purposes of this definition, "submitted"
66 means any form of electronic, verbal, or written communication sent
67 to the Licensor or its representatives, including but not limited to
68 communication on electronic mailing lists, source code control systems,
69 and issue tracking systems that are managed by, or on behalf of, the
70 Licensor for the purpose of discussing and improving the Work, but
71 excluding communication that is conspicuously marked or otherwise
72 designated in writing by the copyright owner as "Not a Contribution."
73
74 "Contributor" shall mean Licensor and any individual or Legal Entity
75 on behalf of whom a Contribution has been received by Licensor and
76 subsequently incorporated within the Work.
77
78 2. Grant of Copyright License. Subject to the terms and conditions of
79 this License, each Contributor hereby grants to You a perpetual,
80 worldwide, non-exclusive, no-charge, royalty-free, irrevocable
81 copyright license to reproduce, prepare Derivative Works of,
82 publicly display, publicly perform, sublicense, and distribute the
83 Work and such Derivative Works in Source or Object form.
84
85 3. Grant of Patent License. Subject to the terms and conditions of
86 this License, each Contributor hereby grants to You a perpetual,
87 worldwide, non-exclusive, no-charge, royalty-free, irrevocable
88 (except as stated in this section) patent license to make, have made,
89 use, offer to sell, sell, import, and otherwise transfer the Work,
90 where such license applies only to those patent claims licensable
91 by such Contributor that are necessarily infringed by their
92 Contribution(s) alone or by combination of their Contribution(s)
93 with the Work to which such Contribution(s) was submitted. If You
94 institute patent litigation against any entity (including a
95 cross-claim or counterclaim in a lawsuit) alleging that the Work
96 or a Contribution incorporated within the Work constitutes direct
97 or contributory patent infringement, then any patent licenses
98 granted to You under this License for that Work shall terminate
99 as of the date such litigation is filed.
100
101 4. Redistribution. You may reproduce and distribute copies of the
102 Work or Derivative Works thereof in any medium, with or without
103 modifications, and in Source or Object form, provided that You
104 meet the following conditions:
105
106 (a) You must give any other recipients of the Work or
107 Derivative Works a copy of this License; and
108
109 (b) You must cause any modified files to carry prominent notices
110 stating that You changed the files; and
111
112 (c) You must retain, in the Source form of any Derivative Works
113 that You distribute, all copyright, patent, trademark, and
114 attribution notices from the Source form of the Work,
115 excluding those notices that do not pertain to any part of
116 the Derivative Works; and
117
118 (d) If the Work includes a "NOTICE" text file as part of its
119 distribution, then any Derivative Works that You distribute must
120 include a readable copy of the attribution notices contained
121 within such NOTICE file, excluding those notices that do not
122 pertain to any part of the Derivative Works, in at least one
123 of the following places: within a NOTICE text file distributed
124 as part of the Derivative Works; within the Source form or
125 documentation, if provided along with the Derivative Works; or,
126 within a display generated by the Derivative Works, if and
127 wherever such third-party notices normally appear. The contents
128 of the NOTICE file are for informational purposes only and
129 do not modify the License. You may add Your own attribution
130 notices within Derivative Works that You distribute, alongside
131 or as an addendum to the NOTICE text from the Work, provided
132 that such additional attribution notices cannot be construed
133 as modifying the License.
134
135 You may add Your own copyright statement to Your modifications and
136 may provide additional or different license terms and conditions
137 for use, reproduction, or distribution of Your modifications, or
138 for any such Derivative Works as a whole, provided Your use,
139 reproduction, and distribution of the Work otherwise complies with
140 the conditions stated in this License.
141
142 5. Submission of Contributions. Unless You explicitly state otherwise,
143 any Contribution intentionally submitted for inclusion in the Work
144 by You to the Licensor shall be under the terms and conditions of
145 this License, without any additional terms or conditions.
146 Notwithstanding the above, nothing herein shall supersede or modify
147 the terms of any separate license agreement you may have executed
148 with Licensor regarding such Contributions.
149
150 6. Trademarks. This License does not grant permission to use the trade
151 names, trademarks, service marks, or product names of the Licensor,
152 except as required for reasonable and customary use in describing the
153 origin of the Work and reproducing the content of the NOTICE file.
154
155 7. Disclaimer of Warranty. Unless required by applicable law or
156 agreed to in writing, Licensor provides the Work (and each
157 Contributor provides its Contributions) on an "AS IS" BASIS,
158 WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
159 implied, including, without limitation, any warranties or conditions
160 of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A
161 PARTICULAR PURPOSE. You are solely responsible for determining the
162 appropriateness of using or redistributing the Work and assume any
163 risks associated with Your exercise of permissions under this License.
164
165 8. Limitation of Liability. In no event and under no legal theory,
166 whether in tort (including negligence), contract, or otherwise,
167 unless required by applicable law (such as deliberate and grossly
168 negligent acts) or agreed to in writing, shall any Contributor be
169 liable to You for damages, including any direct, indirect, special,
170 incidental, or consequential damages of any character arising as a
171 result of this License or out of the use or inability to use the
172 Work (including but not limited to damages for loss of goodwill,
173 work stoppage, computer failure or malfunction, or any and all
174 other commercial damages or losses), even if such Contributor
175 has been advised of the possibility of such damages.
176
177 9. Accepting Warranty or Additional Liability. While redistributing
178 the Work or Derivative Works thereof, You may choose to offer,
179 and charge a fee for, acceptance of support, warranty, indemnity,
180 or other liability obligations and/or rights consistent with this
181 License. However, in accepting such obligations, You may act only
182 on Your own behalf and on Your sole responsibility, not on behalf
183 of any other Contributor, and only if You agree to indemnify,
184 defend, and hold each Contributor harmless for any liability
185 incurred by, or claims asserted against, such Contributor by reason
186 of your accepting any such warranty or additional liability.
187
188 END OF TERMS AND CONDITIONS
189
(New empty file)
0 # Generated by pypy/tool/import_cffi.py
0 # Generated by pypy/tool/import_cffi.py
0 # Generated by pypy/tool/import_cffi.py
1 import py
2 import platform
3 import sys, ctypes
4 from cffi import FFI, CDefError, FFIError, VerificationMissing
5 from extra_tests.cffi_tests.support import *
6
7 SIZE_OF_INT = ctypes.sizeof(ctypes.c_int)
8 SIZE_OF_LONG = ctypes.sizeof(ctypes.c_long)
9 SIZE_OF_SHORT = ctypes.sizeof(ctypes.c_short)
10 SIZE_OF_PTR = ctypes.sizeof(ctypes.c_void_p)
11 SIZE_OF_WCHAR = ctypes.sizeof(ctypes.c_wchar)
12
13 def needs_dlopen_none():
14 if sys.platform == 'win32' and sys.version_info >= (3,):
15 py.test.skip("dlopen(None) cannot work on Windows for Python 3")
16
17
18 class BackendTests:
19
20 def test_integer_ranges(self):
21 ffi = FFI(backend=self.Backend())
22 for (c_type, size) in [('char', 1),
23 ('short', 2),
24 ('short int', 2),
25 ('', 4),
26 ('int', 4),
27 ('long', SIZE_OF_LONG),
28 ('long int', SIZE_OF_LONG),
29 ('long long', 8),
30 ('long long int', 8),
31 ]:
32 for unsigned in [None, False, True]:
33 c_decl = {None: '',
34 False: 'signed ',
35 True: 'unsigned '}[unsigned] + c_type
36 if c_decl == 'char' or c_decl == '':
37 continue
38 self._test_int_type(ffi, c_decl, size, unsigned)
39
40 def test_fixedsize_int(self):
41 ffi = FFI(backend=self.Backend())
42 for size in [1, 2, 4, 8]:
43 self._test_int_type(ffi, 'int%d_t' % (8*size), size, False)
44 self._test_int_type(ffi, 'uint%d_t' % (8*size), size, True)
45 self._test_int_type(ffi, 'intptr_t', SIZE_OF_PTR, False)
46 self._test_int_type(ffi, 'uintptr_t', SIZE_OF_PTR, True)
47 self._test_int_type(ffi, 'ptrdiff_t', SIZE_OF_PTR, False)
48 self._test_int_type(ffi, 'size_t', SIZE_OF_PTR, True)
49 self._test_int_type(ffi, 'ssize_t', SIZE_OF_PTR, False)
50
51 def _test_int_type(self, ffi, c_decl, size, unsigned):
52 if unsigned:
53 min = 0
54 max = (1 << (8*size)) - 1
55 else:
56 min = -(1 << (8*size-1))
57 max = (1 << (8*size-1)) - 1
58 min = int(min)
59 max = int(max)
60 p = ffi.cast(c_decl, min)
61 assert p == min
62 assert hash(p) == hash(min)
63 assert bool(p) is bool(min)
64 assert int(p) == min
65 p = ffi.cast(c_decl, max)
66 assert int(p) == max
67 p = ffi.cast(c_decl, long(max))
68 assert int(p) == max
69 q = ffi.cast(c_decl, min - 1)
70 assert ffi.typeof(q) is ffi.typeof(p) and int(q) == max
71 q = ffi.cast(c_decl, long(min - 1))
72 assert ffi.typeof(q) is ffi.typeof(p) and int(q) == max
73 assert q == p
74 assert int(q) == int(p)
75 assert hash(q) == hash(p)
76 c_decl_ptr = '%s *' % c_decl
77 py.test.raises(OverflowError, ffi.new, c_decl_ptr, min - 1)
78 py.test.raises(OverflowError, ffi.new, c_decl_ptr, max + 1)
79 py.test.raises(OverflowError, ffi.new, c_decl_ptr, long(min - 1))
80 py.test.raises(OverflowError, ffi.new, c_decl_ptr, long(max + 1))
81 assert ffi.new(c_decl_ptr, min)[0] == min
82 assert ffi.new(c_decl_ptr, max)[0] == max
83 assert ffi.new(c_decl_ptr, long(min))[0] == min
84 assert ffi.new(c_decl_ptr, long(max))[0] == max
85
86 def test_new_unsupported_type(self):
87 ffi = FFI(backend=self.Backend())
88 e = py.test.raises(TypeError, ffi.new, "int")
89 assert str(e.value) == "expected a pointer or array ctype, got 'int'"
90
91 def test_new_single_integer(self):
92 ffi = FFI(backend=self.Backend())
93 p = ffi.new("int *") # similar to ffi.new("int[1]")
94 assert p[0] == 0
95 p[0] = -123
96 assert p[0] == -123
97 p = ffi.new("int *", -42)
98 assert p[0] == -42
99 assert repr(p) == "<cdata 'int *' owning %d bytes>" % SIZE_OF_INT
100
101 def test_new_array_no_arg(self):
102 ffi = FFI(backend=self.Backend())
103 p = ffi.new("int[10]")
104 # the object was zero-initialized:
105 for i in range(10):
106 assert p[i] == 0
107
108 def test_array_indexing(self):
109 ffi = FFI(backend=self.Backend())
110 p = ffi.new("int[10]")
111 p[0] = 42
112 p[9] = 43
113 assert p[0] == 42
114 assert p[9] == 43
115 py.test.raises(IndexError, "p[10]")
116 py.test.raises(IndexError, "p[10] = 44")
117 py.test.raises(IndexError, "p[-1]")
118 py.test.raises(IndexError, "p[-1] = 44")
119
120 def test_new_array_args(self):
121 ffi = FFI(backend=self.Backend())
122 # this tries to be closer to C: where we say "int x[5] = {10, 20, ..}"
123 # then here we must enclose the items in a list
124 p = ffi.new("int[5]", [10, 20, 30, 40, 50])
125 assert p[0] == 10
126 assert p[1] == 20
127 assert p[2] == 30
128 assert p[3] == 40
129 assert p[4] == 50
130 p = ffi.new("int[4]", [25])
131 assert p[0] == 25
132 assert p[1] == 0 # follow C convention rather than LuaJIT's
133 assert p[2] == 0
134 assert p[3] == 0
135 p = ffi.new("int[4]", [ffi.cast("int", -5)])
136 assert p[0] == -5
137 assert repr(p) == "<cdata 'int[4]' owning %d bytes>" % (4*SIZE_OF_INT)
138
139 def test_new_array_varsize(self):
140 ffi = FFI(backend=self.Backend())
141 p = ffi.new("int[]", 10) # a single integer is the length
142 assert p[9] == 0
143 py.test.raises(IndexError, "p[10]")
144 #
145 py.test.raises(TypeError, ffi.new, "int[]")
146 #
147 p = ffi.new("int[]", [-6, -7]) # a list is all the items, like C
148 assert p[0] == -6
149 assert p[1] == -7
150 py.test.raises(IndexError, "p[2]")
151 assert repr(p) == "<cdata 'int[]' owning %d bytes>" % (2*SIZE_OF_INT)
152 #
153 p = ffi.new("int[]", 0)
154 py.test.raises(IndexError, "p[0]")
155 py.test.raises(ValueError, ffi.new, "int[]", -1)
156 assert repr(p) == "<cdata 'int[]' owning 0 bytes>"
157
158 def test_pointer_init(self):
159 ffi = FFI(backend=self.Backend())
160 n = ffi.new("int *", 24)
161 a = ffi.new("int *[10]", [ffi.NULL, ffi.NULL, n, n, ffi.NULL])
162 for i in range(10):
163 if i not in (2, 3):
164 assert a[i] == ffi.NULL
165 assert a[2] == a[3] == n
166
167 def test_cannot_cast(self):
168 ffi = FFI(backend=self.Backend())
169 a = ffi.new("short int[10]")
170 e = py.test.raises(TypeError, ffi.new, "long int **", a)
171 msg = str(e.value)
172 assert "'short[10]'" in msg and "'long *'" in msg
173
174 def test_new_pointer_to_array(self):
175 ffi = FFI(backend=self.Backend())
176 a = ffi.new("int[4]", [100, 102, 104, 106])
177 p = ffi.new("int **", a)
178 assert p[0] == ffi.cast("int *", a)
179 assert p[0][2] == 104
180 p = ffi.cast("int *", a)
181 assert p[0] == 100
182 assert p[1] == 102
183 assert p[2] == 104
184 assert p[3] == 106
185 # keepalive: a
186
187 def test_pointer_direct(self):
188 ffi = FFI(backend=self.Backend())
189 p = ffi.cast("int*", 0)
190 assert p is not None
191 assert bool(p) is False
192 assert p == ffi.cast("int*", 0)
193 assert p != None
194 assert repr(p) == "<cdata 'int *' NULL>"
195 a = ffi.new("int[]", [123, 456])
196 p = ffi.cast("int*", a)
197 assert bool(p) is True
198 assert p == ffi.cast("int*", a)
199 assert p != ffi.cast("int*", 0)
200 assert p[0] == 123
201 assert p[1] == 456
202
203 def test_repr(self):
204 typerepr = self.TypeRepr
205 ffi = FFI(backend=self.Backend())
206 ffi.cdef("struct foo { short a, b, c; };")
207 p = ffi.cast("short unsigned int", 0)
208 assert repr(p) == "<cdata 'unsigned short' 0>"
209 assert repr(ffi.typeof(p)) == typerepr % "unsigned short"
210 p = ffi.cast("unsigned short int", 0)
211 assert repr(p) == "<cdata 'unsigned short' 0>"
212 assert repr(ffi.typeof(p)) == typerepr % "unsigned short"
213 p = ffi.cast("int*", 0)
214 assert repr(p) == "<cdata 'int *' NULL>"
215 assert repr(ffi.typeof(p)) == typerepr % "int *"
216 #
217 p = ffi.new("int*")
218 assert repr(p) == "<cdata 'int *' owning %d bytes>" % SIZE_OF_INT
219 assert repr(ffi.typeof(p)) == typerepr % "int *"
220 p = ffi.new("int**")
221 assert repr(p) == "<cdata 'int * *' owning %d bytes>" % SIZE_OF_PTR
222 assert repr(ffi.typeof(p)) == typerepr % "int * *"
223 p = ffi.new("int [2]")
224 assert repr(p) == "<cdata 'int[2]' owning %d bytes>" % (2*SIZE_OF_INT)
225 assert repr(ffi.typeof(p)) == typerepr % "int[2]"
226 p = ffi.new("int*[2][3]")
227 assert repr(p) == "<cdata 'int *[2][3]' owning %d bytes>" % (
228 6*SIZE_OF_PTR)
229 assert repr(ffi.typeof(p)) == typerepr % "int *[2][3]"
230 p = ffi.new("struct foo *")
231 assert repr(p) == "<cdata 'struct foo *' owning %d bytes>" % (
232 3*SIZE_OF_SHORT)
233 assert repr(ffi.typeof(p)) == typerepr % "struct foo *"
234 #
235 q = ffi.cast("short", -123)
236 assert repr(q) == "<cdata 'short' -123>"
237 assert repr(ffi.typeof(q)) == typerepr % "short"
238 p = ffi.new("int*")
239 q = ffi.cast("short*", p)
240 assert repr(q).startswith("<cdata 'short *' 0x")
241 assert repr(ffi.typeof(q)) == typerepr % "short *"
242 p = ffi.new("int [2]")
243 q = ffi.cast("int*", p)
244 assert repr(q).startswith("<cdata 'int *' 0x")
245 assert repr(ffi.typeof(q)) == typerepr % "int *"
246 p = ffi.new("struct foo*")
247 q = ffi.cast("struct foo *", p)
248 assert repr(q).startswith("<cdata 'struct foo *' 0x")
249 assert repr(ffi.typeof(q)) == typerepr % "struct foo *"
250 prevrepr = repr(q)
251 q = q[0]
252 assert repr(q) == prevrepr.replace(' *', ' &')
253 assert repr(ffi.typeof(q)) == typerepr % "struct foo"
254
255 def test_new_array_of_array(self):
256 ffi = FFI(backend=self.Backend())
257 p = ffi.new("int[3][4]")
258 p[0][0] = 10
259 p[2][3] = 33
260 assert p[0][0] == 10
261 assert p[2][3] == 33
262 py.test.raises(IndexError, "p[1][-1]")
263
264 def test_constructor_array_of_array(self):
265 ffi = FFI(backend=self.Backend())
266 p = ffi.new("int[3][2]", [[10, 11], [12, 13], [14, 15]])
267 assert p[2][1] == 15
268
269 def test_new_array_of_pointer_1(self):
270 ffi = FFI(backend=self.Backend())
271 n = ffi.new("int*", 99)
272 p = ffi.new("int*[4]")
273 p[3] = n
274 a = p[3]
275 assert repr(a).startswith("<cdata 'int *' 0x")
276 assert a[0] == 99
277
278 def test_new_array_of_pointer_2(self):
279 ffi = FFI(backend=self.Backend())
280 n = ffi.new("int[1]", [99])
281 p = ffi.new("int*[4]")
282 p[3] = n
283 a = p[3]
284 assert repr(a).startswith("<cdata 'int *' 0x")
285 assert a[0] == 99
286
287 def test_char(self):
288 ffi = FFI(backend=self.Backend())
289 assert ffi.new("char*", b"\xff")[0] == b'\xff'
290 assert ffi.new("char*")[0] == b'\x00'
291 assert int(ffi.cast("char", 300)) == 300 - 256
292 assert not bool(ffi.cast("char", 0))
293 assert bool(ffi.cast("char", 1))
294 assert bool(ffi.cast("char", 255))
295 py.test.raises(TypeError, ffi.new, "char*", 32)
296 py.test.raises(TypeError, ffi.new, "char*", u+"x")
297 py.test.raises(TypeError, ffi.new, "char*", b"foo")
298 #
299 p = ffi.new("char[]", [b'a', b'b', b'\x9c'])
300 assert len(p) == 3
301 assert p[0] == b'a'
302 assert p[1] == b'b'
303 assert p[2] == b'\x9c'
304 p[0] = b'\xff'
305 assert p[0] == b'\xff'
306 p = ffi.new("char[]", b"abcd")
307 assert len(p) == 5
308 assert p[4] == b'\x00' # like in C, with: char[] p = "abcd";
309 #
310 p = ffi.new("char[4]", b"ab")
311 assert len(p) == 4
312 assert [p[i] for i in range(4)] == [b'a', b'b', b'\x00', b'\x00']
313 p = ffi.new("char[2]", b"ab")
314 assert len(p) == 2
315 assert [p[i] for i in range(2)] == [b'a', b'b']
316 py.test.raises(IndexError, ffi.new, "char[2]", b"abc")
317
318 def check_wchar_t(self, ffi):
319 try:
320 ffi.cast("wchar_t", 0)
321 except NotImplementedError:
322 py.test.skip("NotImplementedError: wchar_t")
323
324 def test_wchar_t(self):
325 ffi = FFI(backend=self.Backend())
326 self.check_wchar_t(ffi)
327 assert ffi.new("wchar_t*", u+'x')[0] == u+'x'
328 assert ffi.new("wchar_t*", u+'\u1234')[0] == u+'\u1234'
329 if SIZE_OF_WCHAR > 2:
330 assert ffi.new("wchar_t*", u+'\U00012345')[0] == u+'\U00012345'
331 else:
332 py.test.raises(TypeError, ffi.new, "wchar_t*", u+'\U00012345')
333 assert ffi.new("wchar_t*")[0] == u+'\x00'
334 assert int(ffi.cast("wchar_t", 300)) == 300
335 assert not bool(ffi.cast("wchar_t", 0))
336 assert bool(ffi.cast("wchar_t", 1))
337 assert bool(ffi.cast("wchar_t", 65535))
338 if SIZE_OF_WCHAR > 2:
339 assert bool(ffi.cast("wchar_t", 65536))
340 py.test.raises(TypeError, ffi.new, "wchar_t*", 32)
341 py.test.raises(TypeError, ffi.new, "wchar_t*", "foo")
342 #
343 p = ffi.new("wchar_t[]", [u+'a', u+'b', u+'\u1234'])
344 assert len(p) == 3
345 assert p[0] == u+'a'
346 assert p[1] == u+'b' and type(p[1]) is unicode
347 assert p[2] == u+'\u1234'
348 p[0] = u+'x'
349 assert p[0] == u+'x' and type(p[0]) is unicode
350 p[1] = u+'\u1357'
351 assert p[1] == u+'\u1357'
352 p = ffi.new("wchar_t[]", u+"abcd")
353 assert len(p) == 5
354 assert p[4] == u+'\x00'
355 p = ffi.new("wchar_t[]", u+"a\u1234b")
356 assert len(p) == 4
357 assert p[1] == u+'\u1234'
358 #
359 p = ffi.new("wchar_t[]", u+'\U00023456')
360 if SIZE_OF_WCHAR == 2:
361 assert len(p) == 3
362 assert p[0] == u+'\ud84d'
363 assert p[1] == u+'\udc56'
364 assert p[2] == u+'\x00'
365 else:
366 assert len(p) == 2
367 assert p[0] == u+'\U00023456'
368 assert p[1] == u+'\x00'
369 #
370 p = ffi.new("wchar_t[4]", u+"ab")
371 assert len(p) == 4
372 assert [p[i] for i in range(4)] == [u+'a', u+'b', u+'\x00', u+'\x00']
373 p = ffi.new("wchar_t[2]", u+"ab")
374 assert len(p) == 2
375 assert [p[i] for i in range(2)] == [u+'a', u+'b']
376 py.test.raises(IndexError, ffi.new, "wchar_t[2]", u+"abc")
377
378 def test_none_as_null_doesnt_work(self):
379 ffi = FFI(backend=self.Backend())
380 p = ffi.new("int*[1]")
381 assert p[0] is not None
382 assert p[0] != None
383 assert p[0] == ffi.NULL
384 assert repr(p[0]) == "<cdata 'int *' NULL>"
385 #
386 n = ffi.new("int*", 99)
387 p = ffi.new("int*[]", [n])
388 assert p[0][0] == 99
389 py.test.raises(TypeError, "p[0] = None")
390 p[0] = ffi.NULL
391 assert p[0] == ffi.NULL
392
393 def test_float(self):
394 ffi = FFI(backend=self.Backend())
395 p = ffi.new("float[]", [-2, -2.5])
396 assert p[0] == -2.0
397 assert p[1] == -2.5
398 p[1] += 17.75
399 assert p[1] == 15.25
400 #
401 p = ffi.new("float*", 15.75)
402 assert p[0] == 15.75
403 py.test.raises(TypeError, int, p)
404 py.test.raises(TypeError, float, p)
405 p[0] = 0.0
406 assert bool(p) is True
407 #
408 p = ffi.new("float*", 1.1)
409 f = p[0]
410 assert f != 1.1 # because of rounding effect
411 assert abs(f - 1.1) < 1E-7
412 #
413 INF = 1E200 * 1E200
414 assert 1E200 != INF
415 p[0] = 1E200
416 assert p[0] == INF # infinite, not enough precision
417
418 def test_struct_simple(self):
419 ffi = FFI(backend=self.Backend())
420 ffi.cdef("struct foo { int a; short b, c; };")
421 s = ffi.new("struct foo*")
422 assert s.a == s.b == s.c == 0
423 s.b = -23
424 assert s.b == -23
425 py.test.raises(OverflowError, "s.b = 32768")
426 #
427 s = ffi.new("struct foo*", [-2, -3])
428 assert s.a == -2
429 assert s.b == -3
430 assert s.c == 0
431 py.test.raises((AttributeError, TypeError), "del s.a")
432 assert repr(s) == "<cdata 'struct foo *' owning %d bytes>" % (
433 SIZE_OF_INT + 2 * SIZE_OF_SHORT)
434 #
435 py.test.raises(ValueError, ffi.new, "struct foo*", [1, 2, 3, 4])
436
437 def test_constructor_struct_from_dict(self):
438 ffi = FFI(backend=self.Backend())
439 ffi.cdef("struct foo { int a; short b, c; };")
440 s = ffi.new("struct foo*", {'b': 123, 'c': 456})
441 assert s.a == 0
442 assert s.b == 123
443 assert s.c == 456
444 py.test.raises(KeyError, ffi.new, "struct foo*", {'d': 456})
445
446 def test_struct_pointer(self):
447 ffi = FFI(backend=self.Backend())
448 ffi.cdef("struct foo { int a; short b, c; };")
449 s = ffi.new("struct foo*")
450 assert s[0].a == s[0].b == s[0].c == 0
451 s[0].b = -23
452 assert s[0].b == s.b == -23
453 py.test.raises(OverflowError, "s[0].b = -32769")
454 py.test.raises(IndexError, "s[1]")
455
456 def test_struct_opaque(self):
457 ffi = FFI(backend=self.Backend())
458 py.test.raises(TypeError, ffi.new, "struct baz*")
459 p = ffi.new("struct baz **") # this works
460 assert p[0] == ffi.NULL
461
462 def test_pointer_to_struct(self):
463 ffi = FFI(backend=self.Backend())
464 ffi.cdef("struct foo { int a; short b, c; };")
465 s = ffi.new("struct foo *")
466 s.a = -42
467 assert s[0].a == -42
468 p = ffi.new("struct foo **", s)
469 assert p[0].a == -42
470 assert p[0][0].a == -42
471 p[0].a = -43
472 assert s.a == -43
473 assert s[0].a == -43
474 p[0][0].a = -44
475 assert s.a == -44
476 assert s[0].a == -44
477 s.a = -45
478 assert p[0].a == -45
479 assert p[0][0].a == -45
480 s[0].a = -46
481 assert p[0].a == -46
482 assert p[0][0].a == -46
483
484 def test_constructor_struct_of_array(self):
485 ffi = FFI(backend=self.Backend())
486 ffi.cdef("struct foo { int a[2]; char b[3]; };")
487 s = ffi.new("struct foo *", [[10, 11], [b'a', b'b', b'c']])
488 assert s.a[1] == 11
489 assert s.b[2] == b'c'
490 s.b[1] = b'X'
491 assert s.b[0] == b'a'
492 assert s.b[1] == b'X'
493 assert s.b[2] == b'c'
494
495 def test_recursive_struct(self):
496 ffi = FFI(backend=self.Backend())
497 ffi.cdef("struct foo { int value; struct foo *next; };")
498 s = ffi.new("struct foo*")
499 t = ffi.new("struct foo*")
500 s.value = 123
501 s.next = t
502 t.value = 456
503 assert s.value == 123
504 assert s.next.value == 456
505
506 def test_union_simple(self):
507 ffi = FFI(backend=self.Backend())
508 ffi.cdef("union foo { int a; short b, c; };")
509 u = ffi.new("union foo*")
510 assert u.a == u.b == u.c == 0
511 u.b = -23
512 assert u.b == -23
513 assert u.a != 0
514 py.test.raises(OverflowError, "u.b = 32768")
515 #
516 u = ffi.new("union foo*", [-2])
517 assert u.a == -2
518 py.test.raises((AttributeError, TypeError), "del u.a")
519 assert repr(u) == "<cdata 'union foo *' owning %d bytes>" % SIZE_OF_INT
520
521 def test_union_opaque(self):
522 ffi = FFI(backend=self.Backend())
523 py.test.raises(TypeError, ffi.new, "union baz *")
524 u = ffi.new("union baz **") # this works
525 assert u[0] == ffi.NULL
526
527 def test_union_initializer(self):
528 ffi = FFI(backend=self.Backend())
529 ffi.cdef("union foo { char a; int b; };")
530 py.test.raises(TypeError, ffi.new, "union foo*", b'A')
531 py.test.raises(TypeError, ffi.new, "union foo*", 5)
532 py.test.raises(ValueError, ffi.new, "union foo*", [b'A', 5])
533 u = ffi.new("union foo*", [b'A'])
534 assert u.a == b'A'
535 py.test.raises(TypeError, ffi.new, "union foo*", [1005])
536 u = ffi.new("union foo*", {'b': 12345})
537 assert u.b == 12345
538 u = ffi.new("union foo*", [])
539 assert u.a == b'\x00'
540 assert u.b == 0
541
542 def test_sizeof_type(self):
543 ffi = FFI(backend=self.Backend())
544 ffi.cdef("""
545 struct foo { int a; short b, c, d; };
546 union foo { int a; short b, c, d; };
547 """)
548 for c_type, expected_size in [
549 ('char', 1),
550 ('unsigned int', 4),
551 ('char *', SIZE_OF_PTR),
552 ('int[5]', 20),
553 ('struct foo', 12),
554 ('union foo', 4),
555 ]:
556 size = ffi.sizeof(c_type)
557 assert size == expected_size, (size, expected_size, ctype)
558
559 def test_sizeof_cdata(self):
560 ffi = FFI(backend=self.Backend())
561 assert ffi.sizeof(ffi.new("short*")) == SIZE_OF_PTR
562 assert ffi.sizeof(ffi.cast("short", 123)) == SIZE_OF_SHORT
563 #
564 a = ffi.new("int[]", [10, 11, 12, 13, 14])
565 assert len(a) == 5
566 assert ffi.sizeof(a) == 5 * SIZE_OF_INT
567
568 def test_string_from_char_pointer(self):
569 ffi = FFI(backend=self.Backend())
570 x = ffi.new("char*", b"x")
571 assert str(x) == repr(x)
572 assert ffi.string(x) == b"x"
573 assert ffi.string(ffi.new("char*", b"\x00")) == b""
574 py.test.raises(TypeError, ffi.new, "char*", unicode("foo"))
575
576 def test_unicode_from_wchar_pointer(self):
577 ffi = FFI(backend=self.Backend())
578 self.check_wchar_t(ffi)
579 x = ffi.new("wchar_t*", u+"x")
580 assert unicode(x) == unicode(repr(x))
581 assert ffi.string(x) == u+"x"
582 assert ffi.string(ffi.new("wchar_t*", u+"\x00")) == u+""
583
584 def test_string_from_char_array(self):
585 ffi = FFI(backend=self.Backend())
586 p = ffi.new("char[]", b"hello.")
587 p[5] = b'!'
588 assert ffi.string(p) == b"hello!"
589 p[6] = b'?'
590 assert ffi.string(p) == b"hello!?"
591 p[3] = b'\x00'
592 assert ffi.string(p) == b"hel"
593 assert ffi.string(p, 2) == b"he"
594 py.test.raises(IndexError, "p[7] = b'X'")
595 #
596 a = ffi.new("char[]", b"hello\x00world")
597 assert len(a) == 12
598 p = ffi.cast("char *", a)
599 assert ffi.string(p) == b'hello'
600
601 def test_string_from_wchar_array(self):
602 ffi = FFI(backend=self.Backend())
603 self.check_wchar_t(ffi)
604 assert ffi.string(ffi.cast("wchar_t", "x")) == u+"x"
605 assert ffi.string(ffi.cast("wchar_t", u+"x")) == u+"x"
606 x = ffi.cast("wchar_t", "x")
607 assert str(x) == repr(x)
608 assert ffi.string(x) == u+"x"
609 #
610 p = ffi.new("wchar_t[]", u+"hello.")
611 p[5] = u+'!'
612 assert ffi.string(p) == u+"hello!"
613 p[6] = u+'\u04d2'
614 assert ffi.string(p) == u+"hello!\u04d2"
615 p[3] = u+'\x00'
616 assert ffi.string(p) == u+"hel"
617 assert ffi.string(p, 123) == u+"hel"
618 py.test.raises(IndexError, "p[7] = u+'X'")
619 #
620 a = ffi.new("wchar_t[]", u+"hello\x00world")
621 assert len(a) == 12
622 p = ffi.cast("wchar_t *", a)
623 assert ffi.string(p) == u+'hello'
624 assert ffi.string(p, 123) == u+'hello'
625 assert ffi.string(p, 5) == u+'hello'
626 assert ffi.string(p, 2) == u+'he'
627
628 def test_fetch_const_char_p_field(self):
629 # 'const' is ignored so far
630 ffi = FFI(backend=self.Backend())
631 ffi.cdef("struct foo { const char *name; };")
632 t = ffi.new("const char[]", b"testing")
633 s = ffi.new("struct foo*", [t])
634 assert type(s.name) not in (bytes, str, unicode)
635 assert ffi.string(s.name) == b"testing"
636 py.test.raises(TypeError, "s.name = None")
637 s.name = ffi.NULL
638 assert s.name == ffi.NULL
639
640 def test_fetch_const_wchar_p_field(self):
641 # 'const' is ignored so far
642 ffi = FFI(backend=self.Backend())
643 self.check_wchar_t(ffi)
644 ffi.cdef("struct foo { const wchar_t *name; };")
645 t = ffi.new("const wchar_t[]", u+"testing")
646 s = ffi.new("struct foo*", [t])
647 assert type(s.name) not in (bytes, str, unicode)
648 assert ffi.string(s.name) == u+"testing"
649 s.name = ffi.NULL
650 assert s.name == ffi.NULL
651
652 def test_voidp(self):
653 ffi = FFI(backend=self.Backend())
654 py.test.raises(TypeError, ffi.new, "void*")
655 p = ffi.new("void **")
656 assert p[0] == ffi.NULL
657 a = ffi.new("int[]", [10, 11, 12])
658 p = ffi.new("void **", a)
659 vp = p[0]
660 py.test.raises(TypeError, "vp[0]")
661 py.test.raises(TypeError, ffi.new, "short **", a)
662 #
663 ffi.cdef("struct foo { void *p; int *q; short *r; };")
664 s = ffi.new("struct foo *")
665 s.p = a # works
666 s.q = a # works
667 py.test.raises(TypeError, "s.r = a") # fails
668 b = ffi.cast("int *", a)
669 s.p = b # works
670 s.q = b # works
671 py.test.raises(TypeError, "s.r = b") # fails
672
673 def test_functionptr_simple(self):
674 ffi = FFI(backend=self.Backend())
675 py.test.raises(TypeError, ffi.callback, "int(*)(int)", 0)
676 def cb(n):
677 return n + 1
678 cb.__qualname__ = 'cb'
679 p = ffi.callback("int(*)(int)", cb)
680 res = p(41) # calling an 'int(*)(int)', i.e. a function pointer
681 assert res == 42 and type(res) is int
682 res = p(ffi.cast("int", -41))
683 assert res == -40 and type(res) is int
684 assert repr(p).startswith(
685 "<cdata 'int(*)(int)' calling <function cb at 0x")
686 assert ffi.typeof(p) is ffi.typeof("int(*)(int)")
687 q = ffi.new("int(**)(int)", p)
688 assert repr(q) == "<cdata 'int(* *)(int)' owning %d bytes>" % (
689 SIZE_OF_PTR)
690 py.test.raises(TypeError, "q(43)")
691 res = q[0](43)
692 assert res == 44
693 q = ffi.cast("int(*)(int)", p)
694 assert repr(q).startswith("<cdata 'int(*)(int)' 0x")
695 res = q(45)
696 assert res == 46
697
698 def test_functionptr_advanced(self):
699 ffi = FFI(backend=self.Backend())
700 t = ffi.typeof("int(*(*)(int))(int)")
701 assert repr(t) == self.TypeRepr % "int(*(*)(int))(int)"
702
703 def test_functionptr_voidptr_return(self):
704 ffi = FFI(backend=self.Backend())
705 def cb():
706 return ffi.NULL
707 p = ffi.callback("void*(*)()", cb)
708 res = p()
709 assert res is not None
710 assert res == ffi.NULL
711 int_ptr = ffi.new('int*')
712 void_ptr = ffi.cast('void*', int_ptr)
713 def cb():
714 return void_ptr
715 p = ffi.callback("void*(*)()", cb)
716 res = p()
717 assert res == void_ptr
718
719 def test_functionptr_intptr_return(self):
720 ffi = FFI(backend=self.Backend())
721 def cb():
722 return ffi.NULL
723 p = ffi.callback("int*(*)()", cb)
724 res = p()
725 assert res == ffi.NULL
726 int_ptr = ffi.new('int*')
727 def cb():
728 return int_ptr
729 p = ffi.callback("int*(*)()", cb)
730 res = p()
731 assert repr(res).startswith("<cdata 'int *' 0x")
732 assert res == int_ptr
733 int_array_ptr = ffi.new('int[1]')
734 def cb():
735 return int_array_ptr
736 p = ffi.callback("int*(*)()", cb)
737 res = p()
738 assert repr(res).startswith("<cdata 'int *' 0x")
739 assert res == int_array_ptr
740
741 def test_functionptr_void_return(self):
742 ffi = FFI(backend=self.Backend())
743 def foo():
744 pass
745 foo_cb = ffi.callback("void foo()", foo)
746 result = foo_cb()
747 assert result is None
748
749 def test_char_cast(self):
750 ffi = FFI(backend=self.Backend())
751 p = ffi.cast("int", b'\x01')
752 assert ffi.typeof(p) is ffi.typeof("int")
753 assert int(p) == 1
754 p = ffi.cast("int", ffi.cast("char", b"a"))
755 assert int(p) == ord("a")
756 p = ffi.cast("int", ffi.cast("char", b"\x80"))
757 assert int(p) == 0x80 # "char" is considered unsigned in this case
758 p = ffi.cast("int", b"\x81")
759 assert int(p) == 0x81
760
761 def test_wchar_cast(self):
762 ffi = FFI(backend=self.Backend())
763 self.check_wchar_t(ffi)
764 p = ffi.cast("int", ffi.cast("wchar_t", u+'\u1234'))
765 assert int(p) == 0x1234
766 p = ffi.cast("long long", ffi.cast("wchar_t", -1))
767 if SIZE_OF_WCHAR == 2: # 2 bytes, unsigned
768 assert int(p) == 0xffff
769 elif (sys.platform.startswith('linux') and
770 platform.machine().startswith('x86')): # known to be signed
771 assert int(p) == -1
772 else: # in general, it can be either signed or not
773 assert int(p) in [-1, 0xffffffff] # e.g. on arm, both cases occur
774 p = ffi.cast("int", u+'\u1234')
775 assert int(p) == 0x1234
776
777 def test_cast_array_to_charp(self):
778 ffi = FFI(backend=self.Backend())
779 a = ffi.new("short int[]", [0x1234, 0x5678])
780 p = ffi.cast("char*", a)
781 data = b''.join([p[i] for i in range(4)])
782 if sys.byteorder == 'little':
783 assert data == b'\x34\x12\x78\x56'
784 else:
785 assert data == b'\x12\x34\x56\x78'
786
787 def test_cast_between_pointers(self):
788 ffi = FFI(backend=self.Backend())
789 a = ffi.new("short int[]", [0x1234, 0x5678])
790 p = ffi.cast("short*", a)
791 p2 = ffi.cast("int*", p)
792 q = ffi.cast("char*", p2)
793 data = b''.join([q[i] for i in range(4)])
794 if sys.byteorder == 'little':
795 assert data == b'\x34\x12\x78\x56'
796 else:
797 assert data == b'\x12\x34\x56\x78'
798
799 def test_cast_pointer_and_int(self):
800 ffi = FFI(backend=self.Backend())
801 a = ffi.new("short int[]", [0x1234, 0x5678])
802 l1 = ffi.cast("intptr_t", a)
803 p = ffi.cast("short*", a)
804 l2 = ffi.cast("intptr_t", p)
805 assert int(l1) == int(l2) != 0
806 q = ffi.cast("short*", l1)
807 assert q == ffi.cast("short*", int(l1))
808 assert q[0] == 0x1234
809 assert int(ffi.cast("intptr_t", ffi.NULL)) == 0
810
811 def test_cast_functionptr_and_int(self):
812 ffi = FFI(backend=self.Backend())
813 def cb(n):
814 return n + 1
815 a = ffi.callback("int(*)(int)", cb)
816 p = ffi.cast("void *", a)
817 assert p
818 b = ffi.cast("int(*)(int)", p)
819 assert b(41) == 42
820 assert a == b
821 assert hash(a) == hash(b)
822
823 def test_callback_crash(self):
824 ffi = FFI(backend=self.Backend())
825 def cb(n):
826 raise Exception
827 a = ffi.callback("int(*)(int)", cb, error=42)
828 res = a(1) # and the error reported to stderr
829 assert res == 42
830
831 def test_structptr_argument(self):
832 ffi = FFI(backend=self.Backend())
833 ffi.cdef("struct foo_s { int a, b; };")
834 def cb(p):
835 return p[0].a * 1000 + p[0].b * 100 + p[1].a * 10 + p[1].b
836 a = ffi.callback("int(*)(struct foo_s[])", cb)
837 res = a([[5, 6], {'a': 7, 'b': 8}])
838 assert res == 5678
839 res = a([[5], {'b': 8}])
840 assert res == 5008
841
842 def test_array_argument_as_list(self):
843 ffi = FFI(backend=self.Backend())
844 ffi.cdef("struct foo_s { int a, b; };")
845 seen = []
846 def cb(argv):
847 seen.append(ffi.string(argv[0]))
848 seen.append(ffi.string(argv[1]))
849 a = ffi.callback("void(*)(char *[])", cb)
850 a([ffi.new("char[]", b"foobar"), ffi.new("char[]", b"baz")])
851 assert seen == [b"foobar", b"baz"]
852
853 def test_cast_float(self):
854 ffi = FFI(backend=self.Backend())
855 a = ffi.cast("float", 12)
856 assert float(a) == 12.0
857 a = ffi.cast("float", 12.5)
858 assert float(a) == 12.5
859 a = ffi.cast("float", b"A")
860 assert float(a) == ord("A")
861 a = ffi.cast("int", 12.9)
862 assert int(a) == 12
863 a = ffi.cast("char", 66.9 + 256)
864 assert ffi.string(a) == b"B"
865 #
866 a = ffi.cast("float", ffi.cast("int", 12))
867 assert float(a) == 12.0
868 a = ffi.cast("float", ffi.cast("double", 12.5))
869 assert float(a) == 12.5
870 a = ffi.cast("float", ffi.cast("char", b"A"))
871 assert float(a) == ord("A")
872 a = ffi.cast("int", ffi.cast("double", 12.9))
873 assert int(a) == 12
874 a = ffi.cast("char", ffi.cast("double", 66.9 + 256))
875 assert ffi.string(a) == b"B"
876
877 def test_enum(self):
878 ffi = FFI(backend=self.Backend())
879 ffi.cdef("enum foo { A0, B0, CC0, D0 };")
880 assert ffi.string(ffi.cast("enum foo", 0)) == "A0"
881 assert ffi.string(ffi.cast("enum foo", 2)) == "CC0"
882 assert ffi.string(ffi.cast("enum foo", 3)) == "D0"
883 assert ffi.string(ffi.cast("enum foo", 4)) == "4"
884 ffi.cdef("enum bar { A1, B1=-2, CC1, D1, E1 };")
885 assert ffi.string(ffi.cast("enum bar", 0)) == "A1"
886 assert ffi.string(ffi.cast("enum bar", -2)) == "B1"
887 assert ffi.string(ffi.cast("enum bar", -1)) == "CC1"
888 assert ffi.string(ffi.cast("enum bar", 1)) == "E1"
889 assert ffi.cast("enum bar", -2) == ffi.cast("enum bar", -2)
890 assert ffi.cast("enum foo", 0) == ffi.cast("enum bar", 0)
891 assert ffi.cast("enum bar", 0) == ffi.cast("int", 0)
892 assert repr(ffi.cast("enum bar", -1)) == "<cdata 'enum bar' -1: CC1>"
893 assert repr(ffi.cast("enum foo", -1)) == ( # enums are unsigned, if
894 "<cdata 'enum foo' 4294967295>") # they contain no neg value
895 ffi.cdef("enum baz { A2=0x1000, B2=0x2000 };")
896 assert ffi.string(ffi.cast("enum baz", 0x1000)) == "A2"
897 assert ffi.string(ffi.cast("enum baz", 0x2000)) == "B2"
898
899 def test_enum_in_struct(self):
900 ffi = FFI(backend=self.Backend())
901 ffi.cdef("enum foo { A, B, C, D }; struct bar { enum foo e; };")
902 s = ffi.new("struct bar *")
903 s.e = 0
904 assert s.e == 0
905 s.e = 3
906 assert s.e == 3
907 assert s[0].e == 3
908 s[0].e = 2
909 assert s.e == 2
910 assert s[0].e == 2
911 s.e = ffi.cast("enum foo", -1)
912 assert s.e == 4294967295
913 assert s[0].e == 4294967295
914 s.e = s.e
915 py.test.raises(TypeError, "s.e = 'B'")
916 py.test.raises(TypeError, "s.e = '2'")
917 py.test.raises(TypeError, "s.e = '#2'")
918 py.test.raises(TypeError, "s.e = '#7'")
919
920 def test_enum_non_contiguous(self):
921 ffi = FFI(backend=self.Backend())
922 ffi.cdef("enum foo { A, B=42, C };")
923 assert ffi.string(ffi.cast("enum foo", 0)) == "A"
924 assert ffi.string(ffi.cast("enum foo", 42)) == "B"
925 assert ffi.string(ffi.cast("enum foo", 43)) == "C"
926 invalid_value = ffi.cast("enum foo", 2)
927 assert int(invalid_value) == 2
928 assert ffi.string(invalid_value) == "2"
929
930 def test_enum_char_hex_oct(self):
931 ffi = FFI(backend=self.Backend())
932 ffi.cdef(r"enum foo{A='!', B='\'', C=0x10, D=010, E=- 0x10, F=-010};")
933 assert ffi.string(ffi.cast("enum foo", ord('!'))) == "A"
934 assert ffi.string(ffi.cast("enum foo", ord("'"))) == "B"
935 assert ffi.string(ffi.cast("enum foo", 16)) == "C"
936 assert ffi.string(ffi.cast("enum foo", 8)) == "D"
937 assert ffi.string(ffi.cast("enum foo", -16)) == "E"
938 assert ffi.string(ffi.cast("enum foo", -8)) == "F"
939
940 def test_enum_partial(self):
941 ffi = FFI(backend=self.Backend())
942 ffi.cdef(r"enum foo {A, ...}; enum bar { B, C };")
943 needs_dlopen_none()
944 lib = ffi.dlopen(None)
945 assert lib.B == 0
946 py.test.raises(VerificationMissing, getattr, lib, "A")
947 assert lib.C == 1
948
949 def test_array_of_struct(self):
950 ffi = FFI(backend=self.Backend())
951 ffi.cdef("struct foo { int a, b; };")
952 s = ffi.new("struct foo[1]")
953 py.test.raises(AttributeError, 's.b')
954 py.test.raises(AttributeError, 's.b = 412')
955 s[0].b = 412
956 assert s[0].b == 412
957 py.test.raises(IndexError, 's[1]')
958
959 def test_pointer_to_array(self):
960 ffi = FFI(backend=self.Backend())
961 p = ffi.new("int(**)[5]")
962 assert repr(p) == "<cdata 'int(* *)[5]' owning %d bytes>" % SIZE_OF_PTR
963
964 def test_iterate_array(self):
965 ffi = FFI(backend=self.Backend())
966 a = ffi.new("char[]", b"hello")
967 assert list(a) == [b"h", b"e", b"l", b"l", b"o", b"\0"]
968 assert list(iter(a)) == [b"h", b"e", b"l", b"l", b"o", b"\0"]
969 #
970 py.test.raises(TypeError, iter, ffi.cast("char *", a))
971 py.test.raises(TypeError, list, ffi.cast("char *", a))
972 py.test.raises(TypeError, iter, ffi.new("int *"))
973 py.test.raises(TypeError, list, ffi.new("int *"))
974
975 def test_offsetof(self):
976 ffi = FFI(backend=self.Backend())
977 ffi.cdef("struct foo { int a, b, c; };")
978 assert ffi.offsetof("struct foo", "a") == 0
979 assert ffi.offsetof("struct foo", "b") == 4
980 assert ffi.offsetof("struct foo", "c") == 8
981
982 def test_offsetof_nested(self):
983 ffi = FFI(backend=self.Backend())
984 ffi.cdef("struct foo { int a, b, c; };"
985 "struct bar { struct foo d, e; };")
986 assert ffi.offsetof("struct bar", "e") == 12
987 py.test.raises(KeyError, ffi.offsetof, "struct bar", "e.a")
988 assert ffi.offsetof("struct bar", "e", "a") == 12
989 assert ffi.offsetof("struct bar", "e", "b") == 16
990 assert ffi.offsetof("struct bar", "e", "c") == 20
991
992 def test_offsetof_array(self):
993 ffi = FFI(backend=self.Backend())
994 assert ffi.offsetof("int[]", 51) == 51 * ffi.sizeof("int")
995 assert ffi.offsetof("int *", 51) == 51 * ffi.sizeof("int")
996 ffi.cdef("struct bar { int a, b; int c[99]; };")
997 assert ffi.offsetof("struct bar", "c") == 2 * ffi.sizeof("int")
998 assert ffi.offsetof("struct bar", "c", 0) == 2 * ffi.sizeof("int")
999 assert ffi.offsetof("struct bar", "c", 51) == 53 * ffi.sizeof("int")
1000
1001 def test_alignof(self):
1002 ffi = FFI(backend=self.Backend())
1003 ffi.cdef("struct foo { char a; short b; char c; };")
1004 assert ffi.alignof("int") == 4
1005 assert ffi.alignof("double") in (4, 8)
1006 assert ffi.alignof("struct foo") == 2
1007
1008 def test_bitfield(self):
1009 ffi = FFI(backend=self.Backend())
1010 ffi.cdef("struct foo { int a:10, b:20, c:3; };")
1011 assert ffi.sizeof("struct foo") == 8
1012 s = ffi.new("struct foo *")
1013 s.a = 511
1014 py.test.raises(OverflowError, "s.a = 512")
1015 py.test.raises(OverflowError, "s[0].a = 512")
1016 assert s.a == 511
1017 s.a = -512
1018 py.test.raises(OverflowError, "s.a = -513")
1019 py.test.raises(OverflowError, "s[0].a = -513")
1020 assert s.a == -512
1021 s.c = 3
1022 assert s.c == 3
1023 py.test.raises(OverflowError, "s.c = 4")
1024 py.test.raises(OverflowError, "s[0].c = 4")
1025 s.c = -4
1026 assert s.c == -4
1027
1028 def test_bitfield_enum(self):
1029 ffi = FFI(backend=self.Backend())
1030 ffi.cdef("""
1031 typedef enum { AA, BB, CC } foo_e;
1032 typedef struct { foo_e f:2; } foo_s;
1033 """)
1034 s = ffi.new("foo_s *")
1035 s.f = 2
1036 assert s.f == 2
1037
1038 def test_anonymous_struct(self):
1039 ffi = FFI(backend=self.Backend())
1040 ffi.cdef("typedef struct { int a; } foo_t;")
1041 ffi.cdef("typedef struct { char b, c; } bar_t;")
1042 f = ffi.new("foo_t *", [12345])
1043 b = ffi.new("bar_t *", [b"B", b"C"])
1044 assert f.a == 12345
1045 assert b.b == b"B"
1046 assert b.c == b"C"
1047 assert repr(b).startswith("<cdata 'bar_t *'")
1048
1049 def test_struct_with_two_usages(self):
1050 for name in ['foo_s', '']: # anonymous or not
1051 ffi = FFI(backend=self.Backend())
1052 ffi.cdef("typedef struct %s { int a; } foo_t, *foo_p;" % name)
1053 f = ffi.new("foo_t *", [12345])
1054 ps = ffi.new("foo_p[]", [f])
1055
1056 def test_pointer_arithmetic(self):
1057 ffi = FFI(backend=self.Backend())
1058 s = ffi.new("short[]", list(range(100, 110)))
1059 p = ffi.cast("short *", s)
1060 assert p[2] == 102
1061 assert p+1 == p+1
1062 assert p+1 != p+0
1063 assert p == p+0 == p-0
1064 assert (p+1)[0] == 101
1065 assert (p+19)[-10] == 109
1066 assert (p+5) - (p+1) == 4
1067 assert p == s+0
1068 assert p+1 == s+1
1069
1070 def test_pointer_comparison(self):
1071 ffi = FFI(backend=self.Backend())
1072 s = ffi.new("short[]", list(range(100)))
1073 p = ffi.cast("short *", s)
1074 assert (p < s) is False
1075 assert (p <= s) is True
1076 assert (p == s) is True
1077 assert (p != s) is False
1078 assert (p > s) is False
1079 assert (p >= s) is True
1080 assert (s < p) is False
1081 assert (s <= p) is True
1082 assert (s == p) is True
1083 assert (s != p) is False
1084 assert (s > p) is False
1085 assert (s >= p) is True
1086 q = p + 1
1087 assert (q < s) is False
1088 assert (q <= s) is False
1089 assert (q == s) is False
1090 assert (q != s) is True
1091 assert (q > s) is True
1092 assert (q >= s) is True
1093 assert (s < q) is True
1094 assert (s <= q) is True
1095 assert (s == q) is False
1096 assert (s != q) is True
1097 assert (s > q) is False
1098 assert (s >= q) is False
1099 assert (q < p) is False
1100 assert (q <= p) is False
1101 assert (q == p) is False
1102 assert (q != p) is True
1103 assert (q > p) is True
1104 assert (q >= p) is True
1105 assert (p < q) is True
1106 assert (p <= q) is True
1107 assert (p == q) is False
1108 assert (p != q) is True
1109 assert (p > q) is False
1110 assert (p >= q) is False
1111 #
1112 assert (None == s) is False
1113 assert (None != s) is True
1114 assert (s == None) is False
1115 assert (s != None) is True
1116 assert (None == q) is False
1117 assert (None != q) is True
1118 assert (q == None) is False
1119 assert (q != None) is True
1120
1121 def test_integer_comparison(self):
1122 ffi = FFI(backend=self.Backend())
1123 x = ffi.cast("int", 123)
1124 y = ffi.cast("int", 456)
1125 assert x < y
1126 #
1127 z = ffi.cast("double", 78.9)
1128 assert x > z
1129 assert y > z
1130
1131 def test_ffi_buffer_ptr(self):
1132 ffi = FFI(backend=self.Backend())
1133 a = ffi.new("short *", 100)
1134 try:
1135 b = ffi.buffer(a)
1136 except NotImplementedError as e:
1137 py.test.skip(str(e))
1138 assert type(b) is ffi.buffer
1139 content = b[:]
1140 assert len(content) == len(b) == 2
1141 if sys.byteorder == 'little':
1142 assert content == b'\x64\x00'
1143 assert b[0] == b'\x64'
1144 b[0] = b'\x65'
1145 else:
1146 assert content == b'\x00\x64'
1147 assert b[1] == b'\x64'
1148 b[1] = b'\x65'
1149 assert a[0] == 101
1150
1151 def test_ffi_buffer_array(self):
1152 ffi = FFI(backend=self.Backend())
1153 a = ffi.new("int[]", list(range(100, 110)))
1154 try:
1155 b = ffi.buffer(a)
1156 except NotImplementedError as e:
1157 py.test.skip(str(e))
1158 content = b[:]
1159 if sys.byteorder == 'little':
1160 assert content.startswith(b'\x64\x00\x00\x00\x65\x00\x00\x00')
1161 b[4] = b'\x45'
1162 else:
1163 assert content.startswith(b'\x00\x00\x00\x64\x00\x00\x00\x65')
1164 b[7] = b'\x45'
1165 assert len(content) == 4 * 10
1166 assert a[1] == 0x45
1167
1168 def test_ffi_buffer_ptr_size(self):
1169 ffi = FFI(backend=self.Backend())
1170 a = ffi.new("short *", 0x4243)
1171 try:
1172 b = ffi.buffer(a, 1)
1173 except NotImplementedError as e:
1174 py.test.skip(str(e))
1175 content = b[:]
1176 assert len(content) == 1
1177 if sys.byteorder == 'little':
1178 assert content == b'\x43'
1179 b[0] = b'\x62'
1180 assert a[0] == 0x4262
1181 else:
1182 assert content == b'\x42'
1183 b[0] = b'\x63'
1184 assert a[0] == 0x6343
1185
1186 def test_ffi_buffer_array_size(self):
1187 ffi = FFI(backend=self.Backend())
1188 a1 = ffi.new("int[]", list(range(100, 110)))
1189 a2 = ffi.new("int[]", list(range(100, 115)))
1190 try:
1191 ffi.buffer(a1)
1192 except NotImplementedError as e:
1193 py.test.skip(str(e))
1194 assert ffi.buffer(a1)[:] == ffi.buffer(a2, 4*10)[:]
1195
1196 def test_ffi_buffer_with_file(self):
1197 ffi = FFI(backend=self.Backend())
1198 import tempfile, os, array
1199 fd, filename = tempfile.mkstemp()
1200 f = os.fdopen(fd, 'r+b')
1201 a = ffi.new("int[]", list(range(1005)))
1202 try:
1203 ffi.buffer(a, 512)
1204 except NotImplementedError as e:
1205 py.test.skip(str(e))
1206 f.write(ffi.buffer(a, 1000 * ffi.sizeof("int")))
1207 f.seek(0)
1208 assert f.read() == array.array('i', range(1000)).tostring()
1209 f.seek(0)
1210 b = ffi.new("int[]", 1005)
1211 f.readinto(ffi.buffer(b, 1000 * ffi.sizeof("int")))
1212 assert list(a)[:1000] + [0] * (len(a)-1000) == list(b)
1213 f.close()
1214 os.unlink(filename)
1215
1216 def test_ffi_buffer_with_io(self):
1217 ffi = FFI(backend=self.Backend())
1218 import io, array
1219 f = io.BytesIO()
1220 a = ffi.new("int[]", list(range(1005)))
1221 try:
1222 ffi.buffer(a, 512)
1223 except NotImplementedError as e:
1224 py.test.skip(str(e))
1225 f.write(ffi.buffer(a, 1000 * ffi.sizeof("int")))
1226 f.seek(0)
1227 assert f.read() == array.array('i', range(1000)).tostring()
1228 f.seek(0)
1229 b = ffi.new("int[]", 1005)
1230 f.readinto(ffi.buffer(b, 1000 * ffi.sizeof("int")))
1231 assert list(a)[:1000] + [0] * (len(a)-1000) == list(b)
1232 f.close()
1233
1234 def test_ffi_buffer_comparisons(self):
1235 ffi = FFI(backend=self.Backend())
1236 ba = bytearray(range(100, 110))
1237 if sys.version_info >= (2, 7):
1238 assert ba == memoryview(ba) # justification for the following
1239 a = ffi.new("uint8_t[]", list(ba))
1240 c = ffi.new("uint8_t[]", [99] + list(ba))
1241 try:
1242 b_full = ffi.buffer(a)
1243 b_short = ffi.buffer(a, 3)
1244 b_mid = ffi.buffer(a, 6)
1245 b_other = ffi.buffer(c, 6)
1246 except NotImplementedError as e:
1247 py.test.skip(str(e))
1248 else:
1249 content = b_full[:]
1250 assert content == b_full == ba
1251 assert b_other < b_short < b_mid < b_full
1252 assert ba > b_mid > ba[0:2]
1253 assert b_short != ba[1:4]
1254
1255 def test_array_in_struct(self):
1256 ffi = FFI(backend=self.Backend())
1257 ffi.cdef("struct foo_s { int len; short data[5]; };")
1258 p = ffi.new("struct foo_s *")
1259 p.data[3] = 5
1260 assert p.data[3] == 5
1261 assert repr(p.data).startswith("<cdata 'short[5]' 0x")
1262
1263 def test_struct_containing_array_varsize_workaround(self):
1264 ffi = FFI(backend=self.Backend())
1265 ffi.cdef("struct foo_s { int len; short data[0]; };")
1266 p = ffi.new("char[]", ffi.sizeof("struct foo_s") + 7 * SIZE_OF_SHORT)
1267 q = ffi.cast("struct foo_s *", p)
1268 assert q.len == 0
1269 # 'q.data' gets not a 'short[0]', but just a 'short *' instead
1270 assert repr(q.data).startswith("<cdata 'short *' 0x")
1271 assert q.data[6] == 0
1272 q.data[6] = 15
1273 assert q.data[6] == 15
1274
1275 def test_new_struct_containing_array_varsize(self):
1276 py.test.skip("later?")
1277 ffi = FFI(backend=self.Backend())
1278 ffi.cdef("struct foo_s { int len; short data[]; };")
1279 p = ffi.new("struct foo_s *", 10) # a single integer is the length
1280 assert p.len == 0
1281 assert p.data[9] == 0
1282 py.test.raises(IndexError, "p.data[10]")
1283
1284 def test_ffi_typeof_getcname(self):
1285 ffi = FFI(backend=self.Backend())
1286 assert ffi.getctype("int") == "int"
1287 assert ffi.getctype("int", 'x') == "int x"
1288 assert ffi.getctype("int*") == "int *"
1289 assert ffi.getctype("int*", '') == "int *"
1290 assert ffi.getctype("int*", 'x') == "int * x"
1291 assert ffi.getctype("int", '*') == "int *"
1292 assert ffi.getctype("int", ' * x ') == "int * x"
1293 assert ffi.getctype(ffi.typeof("int*"), '*') == "int * *"
1294 assert ffi.getctype("int", '[5]') == "int[5]"
1295 assert ffi.getctype("int[5]", '[6]') == "int[6][5]"
1296 assert ffi.getctype("int[5]", '(*)') == "int(*)[5]"
1297 # special-case for convenience: automatically put '()' around '*'
1298 assert ffi.getctype("int[5]", '*') == "int(*)[5]"
1299 assert ffi.getctype("int[5]", '*foo') == "int(*foo)[5]"
1300 assert ffi.getctype("int[5]", ' ** foo ') == "int(** foo)[5]"
1301
1302 def test_array_of_func_ptr(self):
1303 ffi = FFI(backend=self.Backend())
1304 f = ffi.cast("int(*)(int)", 42)
1305 assert f != ffi.NULL
1306 py.test.raises(CDefError, ffi.cast, "int(int)", 42)
1307 py.test.raises(CDefError, ffi.new, "int([5])(int)")
1308 a = ffi.new("int(*[5])(int)", [f])
1309 assert ffi.getctype(ffi.typeof(a)) == "int(*[5])(int)"
1310 assert len(a) == 5
1311 assert a[0] == f
1312 assert a[1] == ffi.NULL
1313 py.test.raises(TypeError, ffi.cast, "int(*)(int)[5]", 0)
1314 #
1315 def cb(n):
1316 return n + 1
1317 f = ffi.callback("int(*)(int)", cb)
1318 a = ffi.new("int(*[5])(int)", [f, f])
1319 assert a[1](42) == 43
1320
1321 def test_callback_as_function_argument(self):
1322 # In C, function arguments can be declared with a function type,
1323 # which is automatically replaced with the ptr-to-function type.
1324 ffi = FFI(backend=self.Backend())
1325 def cb(a, b):
1326 return chr(ord(a) + ord(b)).encode()
1327 f = ffi.callback("char cb(char, char)", cb)
1328 assert f(b'A', b'\x01') == b'B'
1329 def g(callback):
1330 return callback(b'A', b'\x01')
1331 g = ffi.callback("char g(char cb(char, char))", g)
1332 assert g(f) == b'B'
1333
1334 def test_vararg_callback(self):
1335 py.test.skip("callback with '...'")
1336 ffi = FFI(backend=self.Backend())
1337 def cb(i, va_list):
1338 j = ffi.va_arg(va_list, "int")
1339 k = ffi.va_arg(va_list, "long long")
1340 return i * 2 + j * 3 + k * 5
1341 f = ffi.callback("long long cb(long i, ...)", cb)
1342 res = f(10, ffi.cast("int", 100), ffi.cast("long long", 1000))
1343 assert res == 20 + 300 + 5000
1344
1345 def test_callback_decorator(self):
1346 ffi = FFI(backend=self.Backend())
1347 #
1348 @ffi.callback("long(long, long)", error=42)
1349 def cb(a, b):
1350 return a - b
1351 #
1352 assert cb(-100, -10) == -90
1353 sz = ffi.sizeof("long")
1354 assert cb((1 << (sz*8-1)) - 1, -10) == 42
1355
1356 def test_unique_types(self):
1357 ffi1 = FFI(backend=self.Backend())
1358 ffi2 = FFI(backend=self.Backend())
1359 assert ffi1.typeof("char") is ffi2.typeof("char ")
1360 assert ffi1.typeof("long") is ffi2.typeof("signed long int")
1361 assert ffi1.typeof("double *") is ffi2.typeof("double*")
1362 assert ffi1.typeof("int ***") is ffi2.typeof(" int * * *")
1363 assert ffi1.typeof("int[]") is ffi2.typeof("signed int[]")
1364 assert ffi1.typeof("signed int*[17]") is ffi2.typeof("int *[17]")
1365 assert ffi1.typeof("void") is ffi2.typeof("void")
1366 assert ffi1.typeof("int(*)(int,int)") is ffi2.typeof("int(*)(int,int)")
1367 #
1368 # these depend on user-defined data, so should not be shared
1369 assert ffi1.typeof("struct foo") is not ffi2.typeof("struct foo")
1370 assert ffi1.typeof("union foo *") is not ffi2.typeof("union foo*")
1371 # the following test is an opaque enum, which we no longer support
1372 #assert ffi1.typeof("enum foo") is not ffi2.typeof("enum foo")
1373 # sanity check: twice 'ffi1'
1374 assert ffi1.typeof("struct foo*") is ffi1.typeof("struct foo *")
1375
1376 def test_anonymous_enum(self):
1377 ffi = FFI(backend=self.Backend())
1378 ffi.cdef("typedef enum { Value0 = 0 } e, *pe;\n"
1379 "typedef enum { Value1 = 1 } e1;")
1380 assert ffi.getctype("e*") == 'e *'
1381 assert ffi.getctype("pe") == 'e *'
1382 assert ffi.getctype("e1*") == 'e1 *'
1383
1384 def test_opaque_enum(self):
1385 import warnings
1386 ffi = FFI(backend=self.Backend())
1387 ffi.cdef("enum foo;")
1388 with warnings.catch_warnings(record=True) as log:
1389 warnings.simplefilter("always")
1390 n = ffi.cast("enum foo", -1)
1391 assert int(n) == 0xffffffff
1392 assert str(log[0].message) == (
1393 "'enum foo' has no values explicitly defined; "
1394 "guessing that it is equivalent to 'unsigned int'")
1395
1396 def test_new_ctype(self):
1397 ffi = FFI(backend=self.Backend())
1398 p = ffi.new("int *")
1399 py.test.raises(TypeError, ffi.new, p)
1400 p = ffi.new(ffi.typeof("int *"), 42)
1401 assert p[0] == 42
1402
1403 def test_enum_with_non_injective_mapping(self):
1404 ffi = FFI(backend=self.Backend())
1405 ffi.cdef("enum e { AA=0, BB=0, CC=0, DD=0 };")
1406 e = ffi.cast("enum e", 0)
1407 assert ffi.string(e) == "AA" # pick the first one arbitrarily
1408
1409 def test_enum_refer_previous_enum_value(self):
1410 ffi = FFI(backend=self.Backend())
1411 ffi.cdef("enum e { AA, BB=2, CC=4, DD=BB, EE, FF=CC, GG=FF };")
1412 assert ffi.string(ffi.cast("enum e", 2)) == "BB"
1413 assert ffi.string(ffi.cast("enum e", 3)) == "EE"
1414 assert ffi.sizeof("char[DD]") == 2
1415 assert ffi.sizeof("char[EE]") == 3
1416 assert ffi.sizeof("char[FF]") == 4
1417 assert ffi.sizeof("char[GG]") == 4
1418
1419 def test_nested_anonymous_struct(self):
1420 ffi = FFI(backend=self.Backend())
1421 ffi.cdef("""
1422 struct foo_s {
1423 struct { int a, b; };
1424 union { int c, d; };
1425 };
1426 """)
1427 assert ffi.sizeof("struct foo_s") == 3 * SIZE_OF_INT
1428 p = ffi.new("struct foo_s *", [1, 2, 3])
1429 assert p.a == 1
1430 assert p.b == 2
1431 assert p.c == 3
1432 assert p.d == 3
1433 p.d = 17
1434 assert p.c == 17
1435 p.b = 19
1436 assert p.a == 1
1437 assert p.b == 19
1438 assert p.c == 17
1439 assert p.d == 17
1440 p = ffi.new("struct foo_s *", {'b': 12, 'd': 14})
1441 assert p.a == 0
1442 assert p.b == 12
1443 assert p.c == 14
1444 assert p.d == 14
1445 py.test.raises(ValueError, ffi.new, "struct foo_s *", [0, 0, 0, 0])
1446
1447 def test_nested_field_offset_align(self):
1448 ffi = FFI(backend=self.Backend())
1449 ffi.cdef("""
1450 struct foo_s {
1451 struct { int a; char b; };
1452 union { char c; };
1453 };
1454 """)
1455 assert ffi.offsetof("struct foo_s", "c") == 2 * SIZE_OF_INT
1456 assert ffi.sizeof("struct foo_s") == 3 * SIZE_OF_INT
1457
1458 def test_nested_anonymous_union(self):
1459 ffi = FFI(backend=self.Backend())
1460 ffi.cdef("""
1461 union foo_u {
1462 struct { int a, b; };
1463 union { int c, d; };
1464 };
1465 """)
1466 assert ffi.sizeof("union foo_u") == 2 * SIZE_OF_INT
1467 p = ffi.new("union foo_u *", [5])
1468 assert p.a == 5
1469 assert p.b == 0
1470 assert p.c == 5
1471 assert p.d == 5
1472 p.d = 17
1473 assert p.c == 17
1474 assert p.a == 17
1475 p.b = 19
1476 assert p.a == 17
1477 assert p.b == 19
1478 assert p.c == 17
1479 assert p.d == 17
1480 p = ffi.new("union foo_u *", {'d': 14})
1481 assert p.a == 14
1482 assert p.b == 0
1483 assert p.c == 14
1484 assert p.d == 14
1485 p = ffi.new("union foo_u *", {'a': -63, 'b': 12})
1486 assert p.a == -63
1487 assert p.b == 12
1488 assert p.c == -63
1489 assert p.d == -63
1490 p = ffi.new("union foo_u *", [123, 456])
1491 assert p.a == 123
1492 assert p.b == 456
1493 assert p.c == 123
1494 assert p.d == 123
1495 py.test.raises(ValueError, ffi.new, "union foo_u *", [0, 0, 0])
1496
1497 def test_nested_anonymous_struct_2(self):
1498 ffi = FFI(backend=self.Backend())
1499 ffi.cdef("""
1500 struct foo_s {
1501 int a;
1502 union { int b; union { int c, d; }; };
1503 int e;
1504 };
1505 """)
1506 assert ffi.sizeof("struct foo_s") == 3 * SIZE_OF_INT
1507 p = ffi.new("struct foo_s *", [11, 22, 33])
1508 assert p.a == 11
1509 assert p.b == p.c == p.d == 22
1510 assert p.e == 33
1511 py.test.raises(ValueError, ffi.new, "struct foo_s *", [11, 22, 33, 44])
1512 FOO = ffi.typeof("struct foo_s")
1513 fields = [(name, fld.offset, fld.flags) for (name, fld) in FOO.fields]
1514 assert fields == [
1515 ('a', 0 * SIZE_OF_INT, 0),
1516 ('b', 1 * SIZE_OF_INT, 0),
1517 ('c', 1 * SIZE_OF_INT, 1),
1518 ('d', 1 * SIZE_OF_INT, 1),
1519 ('e', 2 * SIZE_OF_INT, 0),
1520 ]
1521
1522 def test_cast_to_array_type(self):
1523 ffi = FFI(backend=self.Backend())
1524 p = ffi.new("int[4]", [-5])
1525 q = ffi.cast("int[3]", p)
1526 assert q[0] == -5
1527 assert repr(q).startswith("<cdata 'int[3]' 0x")
1528
1529 def test_gc(self):
1530 ffi = FFI(backend=self.Backend())
1531 p = ffi.new("int *", 123)
1532 seen = []
1533 def destructor(p1):
1534 assert p1 is p
1535 assert p1[0] == 123
1536 seen.append(1)
1537 q = ffi.gc(p, destructor)
1538 assert ffi.typeof(q) is ffi.typeof(p)
1539 import gc; gc.collect()
1540 assert seen == []
1541 del q
1542 import gc; gc.collect(); gc.collect(); gc.collect()
1543 assert seen == [1]
1544
1545 def test_gc_2(self):
1546 ffi = FFI(backend=self.Backend())
1547 p = ffi.new("int *", 123)
1548 seen = []
1549 q1 = ffi.gc(p, lambda p: seen.append(1))
1550 q2 = ffi.gc(q1, lambda p: seen.append(2))
1551 import gc; gc.collect()
1552 assert seen == []
1553 del q1, q2
1554 import gc; gc.collect(); gc.collect(); gc.collect(); gc.collect()
1555 assert seen == [2, 1]
1556
1557 def test_gc_3(self):
1558 ffi = FFI(backend=self.Backend())
1559 p = ffi.new("int *", 123)
1560 r = ffi.new("int *", 123)
1561 seen = []
1562 seen_r = []
1563 q1 = ffi.gc(p, lambda p: seen.append(1))
1564 s1 = ffi.gc(r, lambda r: seen_r.append(4))
1565 q2 = ffi.gc(q1, lambda p: seen.append(2))
1566 s2 = ffi.gc(s1, lambda r: seen_r.append(5))
1567 q3 = ffi.gc(q2, lambda p: seen.append(3))
1568 import gc; gc.collect()
1569 assert seen == []
1570 assert seen_r == []
1571 del q1, q2, q3, s2, s1
1572 import gc; gc.collect(); gc.collect(); gc.collect(); gc.collect()
1573 assert seen == [3, 2, 1]
1574 assert seen_r == [5, 4]
1575
1576 def test_gc_4(self):
1577 ffi = FFI(backend=self.Backend())
1578 p = ffi.new("int *", 123)
1579 seen = []
1580 q1 = ffi.gc(p, lambda p: seen.append(1))
1581 q2 = ffi.gc(q1, lambda p: seen.append(2))
1582 q3 = ffi.gc(q2, lambda p: seen.append(3))
1583 import gc; gc.collect()
1584 assert seen == []
1585 del q1, q3 # q2 remains, and has a hard ref to q1
1586 import gc; gc.collect(); gc.collect(); gc.collect()
1587 assert seen == [3]
1588
1589 def test_gc_disable(self):
1590 ffi = FFI(backend=self.Backend())
1591 p = ffi.new("int *", 123)
1592 py.test.raises(TypeError, ffi.gc, p, None)
1593 seen = []
1594 q1 = ffi.gc(p, lambda p: seen.append(1))
1595 q2 = ffi.gc(q1, lambda p: seen.append(2))
1596 import gc; gc.collect()
1597 assert seen == []
1598 assert ffi.gc(q1, None) is None
1599 del q1, q2
1600 import gc; gc.collect(); gc.collect(); gc.collect()
1601 assert seen == [2]
1602
1603 def test_gc_finite_list(self):
1604 ffi = FFI(backend=self.Backend())
1605 p = ffi.new("int *", 123)
1606 keepalive = []
1607 for i in range(10):
1608 keepalive.append(ffi.gc(p, lambda p: None))
1609 del keepalive[:]
1610 import gc; gc.collect(); gc.collect()
1611 for i in range(10):
1612 keepalive.append(ffi.gc(p, lambda p: None))
1613
1614 def test_CData_CType(self):
1615 ffi = FFI(backend=self.Backend())
1616 assert isinstance(ffi.cast("int", 0), ffi.CData)
1617 assert isinstance(ffi.new("int *"), ffi.CData)
1618 assert not isinstance(ffi.typeof("int"), ffi.CData)
1619 assert not isinstance(ffi.cast("int", 0), ffi.CType)
1620 assert not isinstance(ffi.new("int *"), ffi.CType)
1621
1622 def test_CData_CType_2(self):
1623 ffi = FFI(backend=self.Backend())
1624 assert isinstance(ffi.typeof("int"), ffi.CType)
1625
1626 def test_bool(self):
1627 ffi = FFI(backend=self.Backend())
1628 assert int(ffi.cast("_Bool", 0.1)) == 1
1629 assert int(ffi.cast("_Bool", -0.0)) == 0
1630 assert int(ffi.cast("_Bool", b'\x02')) == 1
1631 assert int(ffi.cast("_Bool", b'\x00')) == 0
1632 assert int(ffi.cast("_Bool", b'\x80')) == 1
1633 assert ffi.new("_Bool *", False)[0] == 0
1634 assert ffi.new("_Bool *", 1)[0] == 1
1635 py.test.raises(OverflowError, ffi.new, "_Bool *", 2)
1636 py.test.raises(TypeError, ffi.string, ffi.cast("_Bool", 2))
1637
1638 def test_use_own_bool(self):
1639 ffi = FFI(backend=self.Backend())
1640 ffi.cdef("""typedef int bool;""")
1641
1642 def test_ordering_bug1(self):
1643 ffi = FFI(backend=self.Backend())
1644 ffi.cdef("""
1645 struct foo_s {
1646 struct bar_s *p;
1647 };
1648 struct bar_s {
1649 struct foo_s foo;
1650 };
1651 """)
1652 q = ffi.new("struct foo_s *")
1653 bar = ffi.new("struct bar_s *")
1654 q.p = bar
1655 assert q.p.foo.p == ffi.NULL
1656
1657 def test_ordering_bug2(self):
1658 ffi = FFI(backend=self.Backend())
1659 ffi.cdef("""
1660 struct bar_s;
1661
1662 struct foo_s {
1663 void (*foo)(struct bar_s[]);
1664 };
1665
1666 struct bar_s {
1667 struct foo_s foo;
1668 };
1669 """)
1670 q = ffi.new("struct foo_s *")
1671
1672 def test_addressof(self):
1673 ffi = FFI(backend=self.Backend())
1674 ffi.cdef("struct foo_s { int x, y; };")
1675 p = ffi.new("struct foo_s *")
1676 a = ffi.addressof(p[0])
1677 assert repr(a).startswith("<cdata 'struct foo_s *' 0x")
1678 assert a == p
1679 py.test.raises(TypeError, ffi.addressof, p)
1680 py.test.raises((AttributeError, TypeError), ffi.addressof, 5)
1681 py.test.raises(TypeError, ffi.addressof, ffi.cast("int", 5))
1682
1683 def test_addressof_field(self):
1684 ffi = FFI(backend=self.Backend())
1685 ffi.cdef("struct foo_s { int x, y; };")
1686 p = ffi.new("struct foo_s *")
1687 a = ffi.addressof(p[0], 'y')
1688 assert repr(a).startswith("<cdata 'int *' 0x")
1689 assert int(ffi.cast("uintptr_t", a)) == (
1690 int(ffi.cast("uintptr_t", p)) + ffi.sizeof("int"))
1691 assert a == ffi.addressof(p, 'y')
1692 assert a != ffi.addressof(p, 'x')
1693
1694 def test_addressof_field_nested(self):
1695 ffi = FFI(backend=self.Backend())
1696 ffi.cdef("struct foo_s { int x, y; };"
1697 "struct bar_s { struct foo_s a, b; };")
1698 p = ffi.new("struct bar_s *")
1699 py.test.raises(KeyError, ffi.addressof, p[0], 'b.y')
1700 a = ffi.addressof(p[0], 'b', 'y')
1701 assert int(ffi.cast("uintptr_t", a)) == (
1702 int(ffi.cast("uintptr_t", p)) +
1703 ffi.sizeof("struct foo_s") + ffi.sizeof("int"))
1704
1705 def test_addressof_anonymous_struct(self):
1706 ffi = FFI()
1707 ffi.cdef("typedef struct { int x; } foo_t;")
1708 p = ffi.new("foo_t *")
1709 a = ffi.addressof(p[0])
1710 assert a == p
1711
1712 def test_addressof_array(self):
1713 ffi = FFI()
1714 p = ffi.new("int[52]")
1715 p0 = ffi.addressof(p)
1716 assert p0 == p
1717 assert ffi.typeof(p0) is ffi.typeof("int(*)[52]")
1718 py.test.raises(TypeError, ffi.addressof, p0)
1719 #
1720 p1 = ffi.addressof(p, 25)
1721 assert ffi.typeof(p1) is ffi.typeof("int *")
1722 assert (p1 - p) == 25
1723 assert ffi.addressof(p, 0) == p
1724
1725 def test_addressof_pointer(self):
1726 ffi = FFI()
1727 array = ffi.new("int[50]")
1728 p = ffi.cast("int *", array)
1729 py.test.raises(TypeError, ffi.addressof, p)
1730 assert ffi.addressof(p, 0) == p
1731 assert ffi.addressof(p, 25) == p + 25
1732 assert ffi.typeof(ffi.addressof(p, 25)) == ffi.typeof(p)
1733 #
1734 ffi.cdef("struct foo { int a, b; };")
1735 array = ffi.new("struct foo[50]")
1736 p = ffi.cast("int *", array)
1737 py.test.raises(TypeError, ffi.addressof, p)
1738 assert ffi.addressof(p, 0) == p
1739 assert ffi.addressof(p, 25) == p + 25
1740 assert ffi.typeof(ffi.addressof(p, 25)) == ffi.typeof(p)
1741
1742 def test_addressof_array_in_struct(self):
1743 ffi = FFI()
1744 ffi.cdef("struct foo { int a, b; int c[50]; };")
1745 p = ffi.new("struct foo *")
1746 p1 = ffi.addressof(p, "c", 25)
1747 assert ffi.typeof(p1) is ffi.typeof("int *")
1748 assert p1 == ffi.cast("int *", p) + 27
1749 assert ffi.addressof(p, "c") == ffi.cast("int *", p) + 2
1750 assert ffi.addressof(p, "c", 0) == ffi.cast("int *", p) + 2
1751 p2 = ffi.addressof(p, 1)
1752 assert ffi.typeof(p2) is ffi.typeof("struct foo *")
1753 assert p2 == p + 1
1754
1755 def test_multiple_independent_structs(self):
1756 ffi1 = FFI(); ffi1.cdef("struct foo { int x; };")
1757 ffi2 = FFI(); ffi2.cdef("struct foo { int y, z; };")
1758 foo1 = ffi1.new("struct foo *", [10])
1759 foo2 = ffi2.new("struct foo *", [20, 30])
1760 assert foo1.x == 10
1761 assert foo2.y == 20
1762 assert foo2.z == 30
1763
1764 def test_missing_include(self):
1765 backend = self.Backend()
1766 ffi1 = FFI(backend=backend)
1767 ffi2 = FFI(backend=backend)
1768 ffi1.cdef("typedef signed char schar_t;")
1769 py.test.raises(CDefError, ffi2.cast, "schar_t", 142)
1770
1771 def test_include_typedef(self):
1772 backend = self.Backend()
1773 ffi1 = FFI(backend=backend)
1774 ffi2 = FFI(backend=backend)
1775 ffi1.cdef("typedef signed char schar_t;")
1776 ffi2.include(ffi1)
1777 p = ffi2.cast("schar_t", 142)
1778 assert int(p) == 142 - 256
1779
1780 def test_include_struct(self):
1781 backend = self.Backend()
1782 ffi1 = FFI(backend=backend)
1783 ffi2 = FFI(backend=backend)
1784 ffi1.cdef("struct foo { int x; };")
1785 ffi2.include(ffi1)
1786 p = ffi2.new("struct foo *", [142])
1787 assert p.x == 142
1788
1789 def test_include_union(self):
1790 backend = self.Backend()
1791 ffi1 = FFI(backend=backend)
1792 ffi2 = FFI(backend=backend)
1793 ffi1.cdef("union foo { int x; };")
1794 ffi2.include(ffi1)
1795 p = ffi2.new("union foo *", [142])
1796 assert p.x == 142
1797
1798 def test_include_enum(self):
1799 backend = self.Backend()
1800 ffi1 = FFI(backend=backend)
1801 ffi2 = FFI(backend=backend)
1802 ffi1.cdef("enum foo { FA, FB, FC };")
1803 ffi2.include(ffi1)
1804 p = ffi2.cast("enum foo", 1)
1805 assert ffi2.string(p) == "FB"
1806 assert ffi2.sizeof("char[FC]") == 2
1807
1808 def test_include_typedef_2(self):
1809 backend = self.Backend()
1810 ffi1 = FFI(backend=backend)
1811 ffi2 = FFI(backend=backend)
1812 ffi1.cdef("typedef struct { int x; } *foo_p;")
1813 ffi2.include(ffi1)
1814 p = ffi2.new("foo_p", [142])
1815 assert p.x == 142
1816
1817 def test_ignore_multiple_declarations_of_constant(self):
1818 ffi = FFI(backend=self.Backend())
1819 ffi.cdef("#define FOO 42")
1820 ffi.cdef("#define FOO 42")
1821 py.test.raises(FFIError, ffi.cdef, "#define FOO 43")
1822
1823 def test_struct_packed(self):
1824 ffi = FFI(backend=self.Backend())
1825 ffi.cdef("struct nonpacked { char a; int b; };")
1826 ffi.cdef("struct is_packed { char a; int b; };", packed=True)
1827 ffi.cdef("struct is_packed1 { char a; int b; };", pack=1)
1828 ffi.cdef("struct is_packed2 { char a; int b; };", pack=2)
1829 ffi.cdef("struct is_packed4 { char a; int b; };", pack=4)
1830 ffi.cdef("struct is_packed8 { char a; int b; };", pack=8)
1831 assert ffi.sizeof("struct nonpacked") == 8
1832 assert ffi.sizeof("struct is_packed") == 5
1833 assert ffi.sizeof("struct is_packed1") == 5
1834 assert ffi.sizeof("struct is_packed2") == 6
1835 assert ffi.sizeof("struct is_packed4") == 8
1836 assert ffi.sizeof("struct is_packed8") == 8
1837 assert ffi.alignof("struct nonpacked") == 4
1838 assert ffi.alignof("struct is_packed") == 1
1839 assert ffi.alignof("struct is_packed1") == 1
1840 assert ffi.alignof("struct is_packed2") == 2
1841 assert ffi.alignof("struct is_packed4") == 4
1842 assert ffi.alignof("struct is_packed8") == 4
1843 for name in ['is_packed', 'is_packed1', 'is_packed2',
1844 'is_packed4', 'is_packed8']:
1845 s = ffi.new("struct %s[2]" % name)
1846 s[0].b = 42623381
1847 s[0].a = b'X'
1848 s[1].b = -4892220
1849 s[1].a = b'Y'
1850 assert s[0].b == 42623381
1851 assert s[0].a == b'X'
1852 assert s[1].b == -4892220
1853 assert s[1].a == b'Y'
1854
1855 def test_pack_valueerror(self):
1856 ffi = FFI(backend=self.Backend())
1857 py.test.raises(ValueError, ffi.cdef, "", pack=3)
1858 py.test.raises(ValueError, ffi.cdef, "", packed=2)
1859 py.test.raises(ValueError, ffi.cdef, "", packed=True, pack=1)
1860
1861 def test_define_integer_constant(self):
1862 ffi = FFI(backend=self.Backend())
1863 ffi.cdef("""
1864 #define DOT_0 0
1865 #define DOT 100
1866 #define DOT_OCT 0100l
1867 #define DOT_HEX 0x100u
1868 #define DOT_HEX2 0X10
1869 #define DOT_UL 1000UL
1870 enum foo {AA, BB=DOT, CC};
1871 """)
1872 needs_dlopen_none()
1873 lib = ffi.dlopen(None)
1874 assert ffi.string(ffi.cast("enum foo", 100)) == "BB"
1875 assert lib.DOT_0 == 0
1876 assert lib.DOT == 100
1877 assert lib.DOT_OCT == 0o100
1878 assert lib.DOT_HEX == 0x100
1879 assert lib.DOT_HEX2 == 0x10
1880 assert lib.DOT_UL == 1000
1881
1882 def test_opaque_struct_becomes_nonopaque(self):
1883 # Issue #193: if we use a struct between the first cdef() where it is
1884 # declared and another cdef() where its fields are defined, then the
1885 # definition was ignored.
1886 ffi = FFI(backend=self.Backend())
1887 ffi.cdef("struct foo_s;")
1888 py.test.raises(TypeError, ffi.new, "struct foo_s *")
1889 ffi.cdef("struct foo_s { int x; };")
1890 ffi.new("struct foo_s *")
1891
1892 def test_ffi_self_include(self):
1893 ffi = FFI(backend=self.Backend())
1894 py.test.raises(ValueError, ffi.include, ffi)
1895
1896 def test_anonymous_enum_include(self):
1897 ffi1 = FFI()
1898 ffi1.cdef("enum { EE1 };")
1899 ffi = FFI()
1900 ffi.include(ffi1)
1901 ffi.cdef("enum { EE2, EE3 };")
1902 needs_dlopen_none()
1903 lib = ffi.dlopen(None)
1904 assert lib.EE1 == 0
1905 assert lib.EE2 == 0
1906 assert lib.EE3 == 1
1907
1908 def test_init_once(self):
1909 def do_init():
1910 seen.append(1)
1911 return 42
1912 ffi = FFI()
1913 seen = []
1914 for i in range(3):
1915 res = ffi.init_once(do_init, "tag1")
1916 assert res == 42
1917 assert seen == [1]
1918 for i in range(3):
1919 res = ffi.init_once(do_init, "tag2")
1920 assert res == 42
1921 assert seen == [1, 1]
1922
1923 def test_init_once_multithread(self):
1924 import sys, time
1925 if sys.version_info < (3,):
1926 import thread
1927 else:
1928 import _thread as thread
1929 #
1930 def do_init():
1931 seen.append('init!')
1932 time.sleep(1)
1933 seen.append('init done')
1934 return 7
1935 ffi = FFI()
1936 seen = []
1937 for i in range(6):
1938 def f():
1939 res = ffi.init_once(do_init, "tag")
1940 seen.append(res)
1941 thread.start_new_thread(f, ())
1942 time.sleep(1.5)
1943 assert seen == ['init!', 'init done'] + 6 * [7]
1944
1945 def test_sizeof_struct_directly(self):
1946 # only works with the Python FFI instances
1947 ffi = FFI(backend=self.Backend())
1948 assert ffi.sizeof("struct{int a;}") == ffi.sizeof("int")
1949
1950 def test_callback_large_struct(self):
1951 ffi = FFI(backend=self.Backend())
1952 # more than 8 bytes
1953 ffi.cdef("struct foo_s { unsigned long a, b, c; };")
1954 #
1955 @ffi.callback("void(struct foo_s)")
1956 def cb(s):
1957 seen.append(ffi.typeof(s))
1958 s.a += 1
1959 s.b += 2
1960 s.c += 3
1961 seen.append(s.a)
1962 seen.append(s.b)
1963 seen.append(s.c)
1964 #
1965 s1 = ffi.new("struct foo_s *", {'a': 100, 'b': 200, 'c': 300})
1966 seen = []
1967 cb(s1[0])
1968 assert len(seen) == 4
1969 assert s1.a == 100 # unmodified
1970 assert s1.b == 200
1971 assert s1.c == 300
1972 assert seen[0] == ffi.typeof("struct foo_s")
1973 assert seen[1] == 101
1974 assert seen[2] == 202
1975 assert seen[3] == 303
1976
1977 def test_ffi_array_as_init(self):
1978 ffi = FFI(backend=self.Backend())
1979 p = ffi.new("int[4]", [10, 20, 30, 400])
1980 q = ffi.new("int[4]", p)
1981 assert list(q) == [10, 20, 30, 400]
1982 py.test.raises(TypeError, ffi.new, "int[3]", p)
1983 py.test.raises(TypeError, ffi.new, "int[5]", p)
1984 py.test.raises(TypeError, ffi.new, "int16_t[4]", p)
1985 s = ffi.new("struct {int i[4];}*", {'i': p})
1986 assert list(s.i) == [10, 20, 30, 400]
1987
1988 def test_too_many_initializers(self):
1989 ffi = FFI(backend=self.Backend())
1990 py.test.raises(IndexError, ffi.new, "int[4]", [10, 20, 30, 40, 50])
0 # Generated by pypy/tool/import_cffi.py
1 import sys, time
2 sys.path.insert(0, sys.argv[1])
3 from cffi import FFI
4
5 def _run_callback_in_thread():
6 ffi = FFI()
7 ffi.cdef("""
8 typedef int (*mycallback_func_t)(int, int);
9 int threaded_ballback_test(mycallback_func_t mycb);
10 """)
11 lib = ffi.verify("""
12 #include <pthread.h>
13 typedef int (*mycallback_func_t)(int, int);
14 void *my_wait_function(void *ptr) {
15 mycallback_func_t cbfunc = (mycallback_func_t)ptr;
16 cbfunc(10, 10);
17 cbfunc(12, 15);
18 return NULL;
19 }
20 int threaded_ballback_test(mycallback_func_t mycb) {
21 pthread_t thread;
22 pthread_create(&thread, NULL, my_wait_function, (void*)mycb);
23 return 0;
24 }
25 """, extra_compile_args=['-pthread'])
26 seen = []
27 @ffi.callback('int(*)(int,int)')
28 def mycallback(x, y):
29 time.sleep(0.022)
30 seen.append((x, y))
31 return 0
32 lib.threaded_ballback_test(mycallback)
33 count = 300
34 while len(seen) != 2:
35 time.sleep(0.01)
36 count -= 1
37 assert count > 0, "timeout"
38 assert seen == [(10, 10), (12, 15)]
39
40 print('STARTING')
41 _run_callback_in_thread()
42 print('DONE')
0 # Generated by pypy/tool/import_cffi.py
1
2 from distutils.core import setup
3 import snip_basic_verify
4
5 setup(
6 py_modules=['snip_basic_verify'],
7 ext_modules=[snip_basic_verify.ffi.verifier.get_extension()])
0 # Generated by pypy/tool/import_cffi.py
1
2 from cffi import FFI
3 import sys
4
5 ffi = FFI()
6 ffi.cdef(""" // some declarations from the man page
7 struct passwd {
8 char *pw_name;
9 ...;
10 };
11 struct passwd *getpwuid(int uid);
12 """)
13 C = ffi.verify(""" // passed to the real C compiler
14 #include <sys/types.h>
15 #include <pwd.h>
16 """, libraries=[], # or a list of libraries to link with
17 force_generic_engine=hasattr(sys, '_force_generic_engine_'))
0 # Generated by pypy/tool/import_cffi.py
1
2 from distutils.core import setup
3 import snip_basic_verify1
4
5 setup(
6 packages=['snip_basic_verify1'],
7 ext_modules=[snip_basic_verify1.ffi.verifier.get_extension()])
0 # Generated by pypy/tool/import_cffi.py
1
2 from cffi import FFI
3 import sys
4
5 ffi = FFI()
6 ffi.cdef(""" // some declarations from the man page
7 struct passwd {
8 char *pw_name;
9 ...;
10 };
11 struct passwd *getpwuid(int uid);
12 """)
13 C = ffi.verify(""" // passed to the real C compiler
14 #include <sys/types.h>
15 #include <pwd.h>
16 """, libraries=[], # or a list of libraries to link with
17 force_generic_engine=hasattr(sys, '_force_generic_engine_'))
0 # Generated by pypy/tool/import_cffi.py
1
2 from distutils.core import setup
3 import snip_basic_verify2
4
5 setup(
6 packages=['snip_basic_verify2'],
7 ext_package='snip_basic_verify2',
8 ext_modules=[snip_basic_verify2.ffi.verifier.get_extension()])
0 # Generated by pypy/tool/import_cffi.py
1
2 from cffi import FFI
3 import sys
4
5 ffi = FFI()
6 ffi.cdef(""" // some declarations from the man page
7 struct passwd {
8 char *pw_name;
9 ...;
10 };
11 struct passwd *getpwuid(int uid);
12 """)
13 C = ffi.verify(""" // passed to the real C compiler
14 #include <sys/types.h>
15 #include <pwd.h>
16 """, libraries=[], # or a list of libraries to link with
17 ext_package='snip_basic_verify2',
18 force_generic_engine=hasattr(sys, '_force_generic_engine_'))
0 # Generated by pypy/tool/import_cffi.py
1
2 from distutils.core import setup
3
4 setup(packages=['snip_infrastructure'],
5 requires=['cffi'])
0 # Generated by pypy/tool/import_cffi.py
1
2 def func():
3 return 42
0 # Generated by pypy/tool/import_cffi.py
1
2 from setuptools import setup
3 import snip_setuptools_verify
4
5 setup(
6 zip_safe=False,
7 py_modules=['snip_setuptools_verify'],
8 ext_modules=[snip_setuptools_verify.ffi.verifier.get_extension()])
0 # Generated by pypy/tool/import_cffi.py
1
2 from cffi import FFI
3 import sys
4
5 ffi = FFI()
6 ffi.cdef(""" // some declarations from the man page
7 struct passwd {
8 char *pw_name;
9 ...;
10 };
11 struct passwd *getpwuid(int uid);
12 """)
13 C = ffi.verify(""" // passed to the real C compiler
14 #include <sys/types.h>
15 #include <pwd.h>
16 """, libraries=[], # or a list of libraries to link with
17 force_generic_engine=hasattr(sys, '_force_generic_engine_'))
0 # Generated by pypy/tool/import_cffi.py
1
2 from setuptools import setup
3 import snip_setuptools_verify1
4
5 setup(
6 zip_safe=False,
7 packages=['snip_setuptools_verify1'],
8 ext_modules=[snip_setuptools_verify1.ffi.verifier.get_extension()])
0 # Generated by pypy/tool/import_cffi.py
1
2 from cffi import FFI
3 import sys
4
5 ffi = FFI()
6 ffi.cdef(""" // some declarations from the man page
7 struct passwd {
8 char *pw_name;
9 ...;
10 };
11 struct passwd *getpwuid(int uid);
12 """)
13 C = ffi.verify(""" // passed to the real C compiler
14 #include <sys/types.h>
15 #include <pwd.h>
16 """, libraries=[], # or a list of libraries to link with
17 force_generic_engine=hasattr(sys, '_force_generic_engine_'))
0 # Generated by pypy/tool/import_cffi.py
1
2 from setuptools import setup
3 import snip_setuptools_verify2
4
5 setup(
6 zip_safe=False,
7 packages=['snip_setuptools_verify2'],
8 ext_package='snip_setuptools_verify2',
9 ext_modules=[snip_setuptools_verify2.ffi.verifier.get_extension()])
0 # Generated by pypy/tool/import_cffi.py
1
2 from cffi import FFI
3 import sys
4
5 ffi = FFI()
6 ffi.cdef(""" // some declarations from the man page
7 struct passwd {
8 char *pw_name;
9 ...;
10 };
11 struct passwd *getpwuid(int uid);
12 """)
13 C = ffi.verify(""" // passed to the real C compiler
14 #include <sys/types.h>
15 #include <pwd.h>
16 """, libraries=[], # or a list of libraries to link with
17 ext_package='snip_setuptools_verify2',
18 force_generic_engine=hasattr(sys, '_force_generic_engine_'))
0 # Generated by pypy/tool/import_cffi.py
1 import py
2 from cffi import FFI
3
4 class FakeBackend(object):
5
6 def nonstandard_integer_types(self):
7 return {}
8
9 def sizeof(self, name):
10 return 1
11
12 def load_library(self, path):
13 return "fake library"
14
15 def new_primitive_type(self, name):
16 return FakeType("primitive " + name)
17
18 def new_void_type(self):
19 return FakeType("void")
20 def new_pointer_type(self, x):
21 return FakeType('ptr-to-%r' % (x,))
22 def new_array_type(self, x, y):
23 return FakeType('array-from-%r-len-%r' % (x, y))
24 def cast(self, x, y):
25 return 'casted!'
26 def _get_types(self):
27 return "CData", "CType"
28
29 buffer = "buffer type"
30
31
32 class FakeType(object):
33 def __init__(self, cdecl):
34 self.cdecl = cdecl
35
36
37 def test_typeof():
38 ffi = FFI(backend=FakeBackend())
39 clong = ffi.typeof("signed long int")
40 assert isinstance(clong, FakeType)
41 assert clong.cdecl == 'primitive long'
0 # Generated by pypy/tool/import_cffi.py
1 import py, sys
2 from extra_tests.cffi_tests.cffi0 import backend_tests
3 from cffi.backend_ctypes import CTypesBackend
4
5
6 class TestCTypes(backend_tests.BackendTests):
7 # for individual tests see
8 # ====> backend_tests.py
9
10 Backend = CTypesBackend
11 TypeRepr = "<class 'ffi.CData<%s>'>"
12
13 def test_array_of_func_ptr(self):
14 py.test.skip("ctypes backend: not supported: "
15 "initializers for function pointers")
16
17 def test_structptr_argument(self):
18 py.test.skip("ctypes backend: not supported: passing a list "
19 "for a pointer argument")
20
21 def test_array_argument_as_list(self):
22 py.test.skip("ctypes backend: not supported: passing a list "
23 "for a pointer argument")
24
25 def test_cast_to_array_type(self):
26 py.test.skip("ctypes backend: not supported: casting to array")
27
28 def test_nested_anonymous_struct(self):
29 py.test.skip("ctypes backend: not supported: nested anonymous struct")
30
31 def test_nested_field_offset_align(self):
32 py.test.skip("ctypes backend: not supported: nested anonymous struct")
33
34 def test_nested_anonymous_union(self):
35 py.test.skip("ctypes backend: not supported: nested anonymous union")
36
37 def test_nested_anonymous_struct_2(self):
38 py.test.skip("ctypes backend: not supported: nested anonymous union")
39
40 def test_CData_CType_2(self):
41 if sys.version_info >= (3,):
42 py.test.skip("ctypes backend: not supported in Python 3: CType")
43 backend_tests.BackendTests.test_CData_CType_2(self)
0 # Generated by pypy/tool/import_cffi.py
1 import py, sys, platform
2 import pytest
3 from extra_tests.cffi_tests.cffi0 import backend_tests, test_function, test_ownlib
4 from extra_tests.cffi_tests.support import u
5 from cffi import FFI
6 import _cffi_backend
7
8
9 class TestFFI(backend_tests.BackendTests,
10 test_function.TestFunction,
11 test_ownlib.TestOwnLib):
12 TypeRepr = "<ctype '%s'>"
13
14 @staticmethod
15 def Backend():
16 return _cffi_backend
17
18 def test_not_supported_bitfield_in_result(self):
19 ffi = FFI(backend=self.Backend())
20 ffi.cdef("struct foo_s { int a,b,c,d,e; int x:1; };")
21 e = py.test.raises(NotImplementedError, ffi.callback,
22 "struct foo_s foo(void)", lambda: 42)
23 assert str(e.value) == ("struct foo_s(*)(): "
24 "callback with unsupported argument or return type or with '...'")
25
26 def test_inspecttype(self):
27 ffi = FFI(backend=self.Backend())
28 assert ffi.typeof("long").kind == "primitive"
29 assert ffi.typeof("long(*)(long, long**, ...)").cname == (
30 "long(*)(long, long * *, ...)")
31 assert ffi.typeof("long(*)(long, long**, ...)").ellipsis is True
32
33 def test_new_handle(self):
34 ffi = FFI(backend=self.Backend())
35 o = [2, 3, 4]
36 p = ffi.new_handle(o)
37 assert ffi.typeof(p) == ffi.typeof("void *")
38 assert ffi.from_handle(p) is o
39 assert ffi.from_handle(ffi.cast("char *", p)) is o
40 py.test.raises(RuntimeError, ffi.from_handle, ffi.NULL)
41
42 def test_callback_onerror(self):
43 ffi = FFI(backend=self.Backend())
44 seen = []
45 def oops(*args):
46 seen.append(args)
47 def otherfunc():
48 raise LookupError
49 def cb(n):
50 otherfunc()
51 a = ffi.callback("int(*)(int)", cb, error=42, onerror=oops)
52 res = a(234)
53 assert res == 42
54 assert len(seen) == 1
55 exc, val, tb = seen[0]
56 assert exc is LookupError
57 assert isinstance(val, LookupError)
58 assert tb.tb_frame.f_code.co_name == 'cb'
59 assert tb.tb_frame.f_locals['n'] == 234
60
61 def test_ffi_new_allocator_2(self):
62 ffi = FFI(backend=self.Backend())
63 seen = []
64 def myalloc(size):
65 seen.append(size)
66 return ffi.new("char[]", b"X" * size)
67 def myfree(raw):
68 seen.append(raw)
69 alloc1 = ffi.new_allocator(myalloc, myfree)
70 alloc2 = ffi.new_allocator(alloc=myalloc, free=myfree,
71 should_clear_after_alloc=False)
72 p1 = alloc1("int[10]")
73 p2 = alloc2("int[]", 10)
74 assert seen == [40, 40]
75 assert ffi.typeof(p1) == ffi.typeof("int[10]")
76 assert ffi.sizeof(p1) == 40
77 assert ffi.typeof(p2) == ffi.typeof("int[]")
78 assert ffi.sizeof(p2) == 40
79 assert p1[5] == 0
80 assert p2[6] == ord('X') * 0x01010101
81 raw1 = ffi.cast("char *", p1)
82 raw2 = ffi.cast("char *", p2)
83 del p1, p2
84 retries = 0
85 while len(seen) != 4:
86 retries += 1
87 assert retries <= 5
88 import gc; gc.collect()
89 assert seen == [40, 40, raw1, raw2]
90 assert repr(seen[2]) == "<cdata 'char[]' owning 41 bytes>"
91 assert repr(seen[3]) == "<cdata 'char[]' owning 41 bytes>"
92
93 def test_ffi_new_allocator_3(self):
94 ffi = FFI(backend=self.Backend())
95 seen = []
96 def myalloc(size):
97 seen.append(size)
98 return ffi.new("char[]", b"X" * size)
99 alloc1 = ffi.new_allocator(myalloc) # no 'free'
100 p1 = alloc1("int[10]")
101 assert seen == [40]
102 assert ffi.typeof(p1) == ffi.typeof("int[10]")
103 assert ffi.sizeof(p1) == 40
104 assert p1[5] == 0
105
106 def test_ffi_new_allocator_4(self):
107 ffi = FFI(backend=self.Backend())
108 py.test.raises(TypeError, ffi.new_allocator, free=lambda x: None)
109 #
110 def myalloc2(size):
111 raise LookupError
112 alloc2 = ffi.new_allocator(myalloc2)
113 py.test.raises(LookupError, alloc2, "int[5]")
114 #
115 def myalloc3(size):
116 return 42
117 alloc3 = ffi.new_allocator(myalloc3)
118 e = py.test.raises(TypeError, alloc3, "int[5]")
119 assert str(e.value) == "alloc() must return a cdata object (got int)"
120 #
121 def myalloc4(size):
122 return ffi.cast("int", 42)
123 alloc4 = ffi.new_allocator(myalloc4)
124 e = py.test.raises(TypeError, alloc4, "int[5]")
125 assert str(e.value) == "alloc() must return a cdata pointer, not 'int'"
126 #
127 def myalloc5(size):
128 return ffi.NULL
129 alloc5 = ffi.new_allocator(myalloc5)
130 py.test.raises(MemoryError, alloc5, "int[5]")
131
132
133 class TestBitfield:
134 def check(self, source, expected_ofs_y, expected_align, expected_size):
135 # NOTE: 'expected_*' is the numbers expected from GCC.
136 # The numbers expected from MSVC are not explicitly written
137 # in this file, and will just be taken from the compiler.
138 ffi = FFI()
139 ffi.cdef("struct s1 { %s };" % source)
140 ctype = ffi.typeof("struct s1")
141 # verify the information with gcc
142 ffi1 = FFI()
143 ffi1.cdef("""
144 static const int Gofs_y, Galign, Gsize;
145 struct s1 *try_with_value(int fieldnum, long long value);
146 """)
147 fnames = [name for name, cfield in ctype.fields
148 if name and cfield.bitsize > 0]
149 setters = ['case %d: s.%s = value; break;' % iname
150 for iname in enumerate(fnames)]
151 lib = ffi1.verify("""
152 struct s1 { %s };
153 struct sa { char a; struct s1 b; };
154 #define Gofs_y offsetof(struct s1, y)
155 #define Galign offsetof(struct sa, b)
156 #define Gsize sizeof(struct s1)
157 struct s1 *try_with_value(int fieldnum, long long value)
158 {
159 static struct s1 s;
160 memset(&s, 0, sizeof(s));
161 switch (fieldnum) { %s }
162 return &s;
163 }
164 """ % (source, ' '.join(setters)))
165 if sys.platform == 'win32':
166 expected_ofs_y = lib.Gofs_y
167 expected_align = lib.Galign
168 expected_size = lib.Gsize
169 else:
170 assert (lib.Gofs_y, lib.Galign, lib.Gsize) == (
171 expected_ofs_y, expected_align, expected_size)
172 # the real test follows
173 assert ffi.offsetof("struct s1", "y") == expected_ofs_y
174 assert ffi.alignof("struct s1") == expected_align
175 assert ffi.sizeof("struct s1") == expected_size
176 # compare the actual storage of the two
177 for name, cfield in ctype.fields:
178 if cfield.bitsize < 0 or not name:
179 continue
180 if int(ffi.cast(cfield.type, -1)) == -1: # signed
181 min_value = -(1 << (cfield.bitsize-1))
182 max_value = (1 << (cfield.bitsize-1)) - 1
183 else:
184 min_value = 0
185 max_value = (1 << cfield.bitsize) - 1
186 for t in [1, 2, 4, 8, 16, 128, 2813, 89728, 981729,
187 -1,-2,-4,-8,-16,-128,-2813,-89728,-981729]:
188 if min_value <= t <= max_value:
189 self._fieldcheck(ffi, lib, fnames, name, t)
190
191 def _fieldcheck(self, ffi, lib, fnames, name, value):
192 s = ffi.new("struct s1 *")
193 setattr(s, name, value)
194 assert getattr(s, name) == value
195 raw1 = ffi.buffer(s)[:]
196 buff1 = ffi.buffer(s)
197 t = lib.try_with_value(fnames.index(name), value)
198 raw2 = ffi.buffer(t, len(raw1))[:]
199 assert raw1 == raw2
200 buff2 = ffi.buffer(t, len(buff1))
201 assert buff1 == buff2
202
203 def test_bitfield_basic(self):
204 self.check("int a; int b:9; int c:20; int y;", 8, 4, 12)
205 self.check("int a; short b:9; short c:7; int y;", 8, 4, 12)
206 self.check("int a; short b:9; short c:9; int y;", 8, 4, 12)
207
208 def test_bitfield_reuse_if_enough_space(self):
209 self.check("int a:2; char y;", 1, 4, 4)
210 self.check("int a:1; char b ; int c:1; char y;", 3, 4, 4)
211 self.check("int a:1; char b:8; int c:1; char y;", 3, 4, 4)
212 self.check("char a; int b:9; char y;", 3, 4, 4)
213 self.check("char a; short b:9; char y;", 4, 2, 6)
214 self.check("int a:2; char b:6; char y;", 1, 4, 4)
215 self.check("int a:2; char b:7; char y;", 2, 4, 4)
216 self.check("int a:2; short b:15; char c:2; char y;", 5, 4, 8)
217 self.check("int a:2; char b:1; char c:1; char y;", 1, 4, 4)
218
219 @pytest.mark.skipif("platform.machine().startswith(('arm', 'aarch64'))")
220 def test_bitfield_anonymous_no_align(self):
221 L = FFI().alignof("long long")
222 self.check("char y; int :1;", 0, 1, 2)
223 self.check("char x; int z:1; char y;", 2, 4, 4)
224 self.check("char x; int :1; char y;", 2, 1, 3)
225 self.check("char x; long long z:48; char y;", 7, L, 8)
226 self.check("char x; long long :48; char y;", 7, 1, 8)
227 self.check("char x; long long z:56; char y;", 8, L, 8 + L)
228 self.check("char x; long long :56; char y;", 8, 1, 9)
229 self.check("char x; long long z:57; char y;", L + 8, L, L + 8 + L)
230 self.check("char x; long long :57; char y;", L + 8, 1, L + 9)
231
232 @pytest.mark.skipif(
233 "not platform.machine().startswith(('arm', 'aarch64'))")
234 def test_bitfield_anonymous_align_arm(self):
235 L = FFI().alignof("long long")
236 self.check("char y; int :1;", 0, 4, 4)
237 self.check("char x; int z:1; char y;", 2, 4, 4)
238 self.check("char x; int :1; char y;", 2, 4, 4)
239 self.check("char x; long long z:48; char y;", 7, L, 8)
240 self.check("char x; long long :48; char y;", 7, 8, 8)
241 self.check("char x; long long z:56; char y;", 8, L, 8 + L)
242 self.check("char x; long long :56; char y;", 8, L, 8 + L)
243 self.check("char x; long long z:57; char y;", L + 8, L, L + 8 + L)
244 self.check("char x; long long :57; char y;", L + 8, L, L + 8 + L)
245
246 @pytest.mark.skipif("platform.machine().startswith(('arm', 'aarch64'))")
247 def test_bitfield_zero(self):
248 L = FFI().alignof("long long")
249 self.check("char y; int :0;", 0, 1, 4)
250 self.check("char x; int :0; char y;", 4, 1, 5)
251 self.check("char x; int :0; int :0; char y;", 4, 1, 5)
252 self.check("char x; long long :0; char y;", L, 1, L + 1)
253 self.check("short x, y; int :0; int :0;", 2, 2, 4)
254 self.check("char x; int :0; short b:1; char y;", 5, 2, 6)
255 self.check("int a:1; int :0; int b:1; char y;", 5, 4, 8)
256
257 @pytest.mark.skipif(
258 "not platform.machine().startswith(('arm', 'aarch64'))")
259 def test_bitfield_zero_arm(self):
260 L = FFI().alignof("long long")
261 self.check("char y; int :0;", 0, 4, 4)
262 self.check("char x; int :0; char y;", 4, 4, 8)
263 self.check("char x; int :0; int :0; char y;", 4, 4, 8)
264 self.check("char x; long long :0; char y;", L, 8, L + 8)
265 self.check("short x, y; int :0; int :0;", 2, 4, 4)
266 self.check("char x; int :0; short b:1; char y;", 5, 4, 8)
267 self.check("int a:1; int :0; int b:1; char y;", 5, 4, 8)
268
269 def test_error_cases(self):
270 ffi = FFI()
271 py.test.raises(TypeError,
272 'ffi.cdef("struct s1 { float x:1; };"); ffi.new("struct s1 *")')
273 py.test.raises(TypeError,
274 'ffi.cdef("struct s2 { char x:0; };"); ffi.new("struct s2 *")')
275 py.test.raises(TypeError,
276 'ffi.cdef("struct s3 { char x:9; };"); ffi.new("struct s3 *")')
277
278 def test_struct_with_typedef(self):
279 ffi = FFI()
280 ffi.cdef("typedef struct { float x; } foo_t;")
281 p = ffi.new("foo_t *", [5.2])
282 assert repr(p).startswith("<cdata 'foo_t *' ")
283
284 def test_struct_array_no_length(self):
285 ffi = FFI()
286 ffi.cdef("struct foo_s { int x; int a[]; };")
287 p = ffi.new("struct foo_s *", [100, [200, 300, 400]])
288 assert p.x == 100
289 assert ffi.typeof(p.a) is ffi.typeof("int[]")
290 assert len(p.a) == 3 # length recorded
291 assert p.a[0] == 200
292 assert p.a[1] == 300
293 assert p.a[2] == 400
294 assert list(p.a) == [200, 300, 400]
295 q = ffi.cast("struct foo_s *", p)
296 assert q.x == 100
297 assert ffi.typeof(q.a) is ffi.typeof("int *") # no length recorded
298 py.test.raises(TypeError, len, q.a)
299 assert q.a[0] == 200
300 assert q.a[1] == 300
301 assert q.a[2] == 400
302 py.test.raises(TypeError, list, q.a)
303
304 @pytest.mark.skipif("sys.platform != 'win32'")
305 def test_getwinerror(self):
306 ffi = FFI()
307 code, message = ffi.getwinerror(1155)
308 assert code == 1155
309 assert message == ("No application is associated with the "
310 "specified file for this operation")
311 ffi.cdef("void SetLastError(int);")
312 lib = ffi.dlopen("Kernel32.dll")
313 lib.SetLastError(2)
314 code, message = ffi.getwinerror()
315 assert code == 2
316 assert message == "The system cannot find the file specified"
317 code, message = ffi.getwinerror(-1)
318 assert code == 2
319 assert message == "The system cannot find the file specified"
320
321 def test_from_buffer(self):
322 import array
323 ffi = FFI()
324 a = array.array('H', [10000, 20000, 30000])
325 c = ffi.from_buffer(a)
326 assert ffi.typeof(c) is ffi.typeof("char[]")
327 assert len(c) == 6
328 ffi.cast("unsigned short *", c)[1] += 500
329 assert list(a) == [10000, 20500, 30000]
330 assert c == ffi.from_buffer("char[]", a, True)
331 assert c == ffi.from_buffer(a, require_writable=True)
332 #
333 c = ffi.from_buffer("unsigned short[]", a)
334 assert len(c) == 3
335 assert c[1] == 20500
336 #
337 p = ffi.from_buffer(b"abcd")
338 assert p[2] == b"c"
339 #
340 assert p == ffi.from_buffer(b"abcd", require_writable=False)
341 py.test.raises((TypeError, BufferError), ffi.from_buffer,
342 "char[]", b"abcd", True)
343 py.test.raises((TypeError, BufferError), ffi.from_buffer, b"abcd",
344 require_writable=True)
345
346 def test_release(self):
347 ffi = FFI()
348 p = ffi.new("int[]", 123)
349 ffi.release(p)
350 # here, reading p[0] might give garbage or segfault...
351 ffi.release(p) # no effect
352
353 def test_memmove(self):
354 ffi = FFI()
355 p = ffi.new("short[]", [-1234, -2345, -3456, -4567, -5678])
356 ffi.memmove(p, p + 1, 4)
357 assert list(p) == [-2345, -3456, -3456, -4567, -5678]
358 p[2] = 999
359 ffi.memmove(p + 2, p, 6)
360 assert list(p) == [-2345, -3456, -2345, -3456, 999]
361 ffi.memmove(p + 4, ffi.new("char[]", b"\x71\x72"), 2)
362 if sys.byteorder == 'little':
363 assert list(p) == [-2345, -3456, -2345, -3456, 0x7271]
364 else:
365 assert list(p) == [-2345, -3456, -2345, -3456, 0x7172]
366
367 def test_memmove_buffer(self):
368 import array
369 ffi = FFI()
370 a = array.array('H', [10000, 20000, 30000])
371 p = ffi.new("short[]", 5)
372 ffi.memmove(p, a, 6)
373 assert list(p) == [10000, 20000, 30000, 0, 0]
374 ffi.memmove(p + 1, a, 6)
375 assert list(p) == [10000, 10000, 20000, 30000, 0]
376 b = array.array('h', [-1000, -2000, -3000])
377 ffi.memmove(b, a, 4)
378 assert b.tolist() == [10000, 20000, -3000]
379 assert a.tolist() == [10000, 20000, 30000]
380 p[0] = 999
381 p[1] = 998
382 p[2] = 997
383 p[3] = 996
384 p[4] = 995
385 ffi.memmove(b, p, 2)
386 assert b.tolist() == [999, 20000, -3000]
387 ffi.memmove(b, p + 2, 4)
388 assert b.tolist() == [997, 996, -3000]
389 p[2] = -p[2]
390 p[3] = -p[3]
391 ffi.memmove(b, p + 2, 6)
392 assert b.tolist() == [-997, -996, 995]
393
394 def test_memmove_readonly_readwrite(self):
395 ffi = FFI()
396 p = ffi.new("signed char[]", 5)
397 ffi.memmove(p, b"abcde", 3)
398 assert list(p) == [ord("a"), ord("b"), ord("c"), 0, 0]
399 ffi.memmove(p, bytearray(b"ABCDE"), 2)
400 assert list(p) == [ord("A"), ord("B"), ord("c"), 0, 0]
401 py.test.raises((TypeError, BufferError), ffi.memmove, b"abcde", p, 3)
402 ba = bytearray(b"xxxxx")
403 ffi.memmove(dest=ba, src=p, n=3)
404 assert ba == bytearray(b"ABcxx")
405
406 def test_all_primitives(self):
407 ffi = FFI()
408 for name in [
409 "char",
410 "short",
411 "int",
412 "long",
413 "long long",
414 "signed char",
415 "unsigned char",
416 "unsigned short",
417 "unsigned int",
418 "unsigned long",
419 "unsigned long long",
420 "float",
421 "double",
422 "long double",
423 "wchar_t",
424 "char16_t",
425 "char32_t",
426 "_Bool",
427 "int8_t",
428 "uint8_t",
429 "int16_t",
430 "uint16_t",
431 "int32_t",
432 "uint32_t",
433 "int64_t",
434 "uint64_t",
435 "int_least8_t",
436 "uint_least8_t",
437 "int_least16_t",
438 "uint_least16_t",
439 "int_least32_t",
440 "uint_least32_t",
441 "int_least64_t",
442 "uint_least64_t",
443 "int_fast8_t",
444 "uint_fast8_t",
445 "int_fast16_t",
446 "uint_fast16_t",
447 "int_fast32_t",
448 "uint_fast32_t",
449 "int_fast64_t",
450 "uint_fast64_t",
451 "intptr_t",
452 "uintptr_t",
453 "intmax_t",
454 "uintmax_t",
455 "ptrdiff_t",
456 "size_t",
457 "ssize_t",
458 ]:
459 x = ffi.sizeof(name)
460 assert 1 <= x <= 16
461
462 def test_ffi_def_extern(self):
463 ffi = FFI()
464 py.test.raises(ValueError, ffi.def_extern)
465
466 def test_introspect_typedef(self):
467 ffi = FFI()
468 ffi.cdef("typedef int foo_t;")
469 assert ffi.list_types() == (['foo_t'], [], [])
470 assert ffi.typeof('foo_t').kind == 'primitive'
471 assert ffi.typeof('foo_t').cname == 'int'
472 #
473 ffi.cdef("typedef signed char a_t, c_t, g_t, b_t;")
474 assert ffi.list_types() == (['a_t', 'b_t', 'c_t', 'foo_t', 'g_t'],
475 [], [])
476
477 def test_introspect_struct(self):
478 ffi = FFI()
479 ffi.cdef("struct foo_s { int a; };")
480 assert ffi.list_types() == ([], ['foo_s'], [])
481 assert ffi.typeof('struct foo_s').kind == 'struct'
482 assert ffi.typeof('struct foo_s').cname == 'struct foo_s'
483
484 def test_introspect_union(self):
485 ffi = FFI()
486 ffi.cdef("union foo_s { int a; };")
487 assert ffi.list_types() == ([], [], ['foo_s'])
488 assert ffi.typeof('union foo_s').kind == 'union'
489 assert ffi.typeof('union foo_s').cname == 'union foo_s'
490
491 def test_introspect_struct_and_typedef(self):
492 ffi = FFI()
493 ffi.cdef("typedef struct { int a; } foo_t;")
494 assert ffi.list_types() == (['foo_t'], [], [])
495 assert ffi.typeof('foo_t').kind == 'struct'
496 assert ffi.typeof('foo_t').cname == 'foo_t'
497
498 def test_introspect_included_type(self):
499 ffi1 = FFI()
500 ffi2 = FFI()
501 ffi1.cdef("typedef signed char schar_t; struct sint_t { int x; };")
502 ffi2.include(ffi1)
503 assert ffi1.list_types() == ffi2.list_types() == (
504 ['schar_t'], ['sint_t'], [])
505
506 def test_introspect_order(self):
507 ffi = FFI()
508 ffi.cdef("union CFFIaaa { int a; }; typedef struct CFFIccc { int a; } CFFIb;")
509 ffi.cdef("union CFFIg { int a; }; typedef struct CFFIcc { int a; } CFFIbbb;")
510 ffi.cdef("union CFFIaa { int a; }; typedef struct CFFIa { int a; } CFFIbb;")
511 assert ffi.list_types() == (['CFFIb', 'CFFIbb', 'CFFIbbb'],
512 ['CFFIa', 'CFFIcc', 'CFFIccc'],
513 ['CFFIaa', 'CFFIaaa', 'CFFIg'])
514
515 def test_unpack(self):
516 ffi = FFI()
517 p = ffi.new("char[]", b"abc\x00def")
518 assert ffi.unpack(p+1, 7) == b"bc\x00def\x00"
519 p = ffi.new("int[]", [-123456789])
520 assert ffi.unpack(p, 1) == [-123456789]
521
522 def test_negative_array_size(self):
523 ffi = FFI()
524 py.test.raises(ValueError, ffi.cast, "int[-5]", 0)
525
526 def test_cannot_instantiate_manually(self):
527 ffi = FFI()
528 ct = type(ffi.typeof("void *"))
529 py.test.raises(TypeError, ct)
530 py.test.raises(TypeError, ct, ffi.NULL)
531 for cd in [type(ffi.cast("void *", 0)),
532 type(ffi.new("char[]", 3)),
533 type(ffi.gc(ffi.NULL, lambda x: None))]:
534 py.test.raises(TypeError, cd)
535 py.test.raises(TypeError, cd, ffi.NULL)
536 py.test.raises(TypeError, cd, ffi.typeof("void *"))
537
538 def test_explicitly_defined_char16_t(self):
539 ffi = FFI()
540 ffi.cdef("typedef uint16_t char16_t;")
541 x = ffi.cast("char16_t", 1234)
542 assert ffi.typeof(x) is ffi.typeof("uint16_t")
543
544 def test_char16_t(self):
545 ffi = FFI()
546 x = ffi.new("char16_t[]", 5)
547 assert len(x) == 5 and ffi.sizeof(x) == 10
548 x[2] = u+'\u1324'
549 assert x[2] == u+'\u1324'
550 y = ffi.new("char16_t[]", u+'\u1234\u5678')
551 assert len(y) == 3
552 assert list(y) == [u+'\u1234', u+'\u5678', u+'\x00']
553 assert ffi.string(y) == u+'\u1234\u5678'
554 z = ffi.new("char16_t[]", u+'\U00012345')
555 assert len(z) == 3
556 assert list(z) == [u+'\ud808', u+'\udf45', u+'\x00']
557 assert ffi.string(z) == u+'\U00012345'
558
559 def test_char32_t(self):
560 ffi = FFI()
561 x = ffi.new("char32_t[]", 5)
562 assert len(x) == 5 and ffi.sizeof(x) == 20
563 x[3] = u+'\U00013245'
564 assert x[3] == u+'\U00013245'
565 y = ffi.new("char32_t[]", u+'\u1234\u5678')
566 assert len(y) == 3
567 assert list(y) == [u+'\u1234', u+'\u5678', u+'\x00']
568 py_uni = u+'\U00012345'
569 z = ffi.new("char32_t[]", py_uni)
570 assert len(z) == 2
571 assert list(z) == [py_uni, u+'\x00'] # maybe a 2-unichars string
572 assert ffi.string(z) == py_uni
573 if len(py_uni) == 1: # 4-bytes unicodes in Python
574 s = ffi.new("char32_t[]", u+'\ud808\udf00')
575 assert len(s) == 3
576 assert list(s) == [u+'\ud808', u+'\udf00', u+'\x00']
0 # Generated by pypy/tool/import_cffi.py
1 import py
2 from cffi import FFI, CDefError
3 import math, os, sys
4 import ctypes.util
5 from cffi.backend_ctypes import CTypesBackend
6 from extra_tests.cffi_tests.udir import udir
7 from extra_tests.cffi_tests.support import FdWriteCapture
8 from .backend_tests import needs_dlopen_none
9
10 try:
11 from StringIO import StringIO
12 except ImportError:
13 from io import StringIO
14
15
16 lib_m = 'm'
17 if sys.platform == 'win32':
18 #there is a small chance this fails on Mingw via environ $CC
19 import distutils.ccompiler
20 if distutils.ccompiler.get_default_compiler() == 'msvc':
21 lib_m = 'msvcrt'
22
23 class TestFunction(object):
24 Backend = CTypesBackend
25
26 def test_sin(self):
27 ffi = FFI(backend=self.Backend())
28 ffi.cdef("""
29 double sin(double x);
30 """)
31 m = ffi.dlopen(lib_m)
32 x = m.sin(1.23)
33 assert x == math.sin(1.23)
34
35 def test_sinf(self):
36 if sys.platform == 'win32':
37 py.test.skip("no sinf found in the Windows stdlib")
38 ffi = FFI(backend=self.Backend())
39 ffi.cdef("""
40 float sinf(float x);
41 """)
42 m = ffi.dlopen(lib_m)
43 x = m.sinf(1.23)
44 assert type(x) is float
45 assert x != math.sin(1.23) # rounding effects
46 assert abs(x - math.sin(1.23)) < 1E-6
47
48 def test_getenv_no_return_value(self):
49 # check that 'void'-returning functions work too
50 ffi = FFI(backend=self.Backend())
51 ffi.cdef("""
52 void getenv(char *);
53 """)
54 needs_dlopen_none()
55 m = ffi.dlopen(None)
56 x = m.getenv(b"FOO")
57 assert x is None
58
59 def test_dlopen_filename(self):
60 path = ctypes.util.find_library(lib_m)
61 if not path:
62 py.test.skip("%s not found" % lib_m)
63 ffi = FFI(backend=self.Backend())
64 ffi.cdef("""
65 double cos(double x);
66 """)
67 m = ffi.dlopen(path)
68 x = m.cos(1.23)
69 assert x == math.cos(1.23)
70
71 m = ffi.dlopen(os.path.basename(path))
72 x = m.cos(1.23)
73 assert x == math.cos(1.23)
74
75 def test_dlopen_flags(self):
76 ffi = FFI(backend=self.Backend())
77 ffi.cdef("""
78 double cos(double x);
79 """)
80 m = ffi.dlopen(lib_m, ffi.RTLD_LAZY | ffi.RTLD_LOCAL)
81 x = m.cos(1.23)
82 assert x == math.cos(1.23)
83
84 def test_dlopen_constant(self):
85 ffi = FFI(backend=self.Backend())
86 ffi.cdef("""
87 #define FOOBAR 42
88 static const float baz = 42.5; /* not visible */
89 double sin(double x);
90 """)
91 m = ffi.dlopen(lib_m)
92 assert m.FOOBAR == 42
93 py.test.raises(NotImplementedError, "m.baz")
94
95 def test_tlsalloc(self):
96 if sys.platform != 'win32':
97 py.test.skip("win32 only")
98 if self.Backend is CTypesBackend:
99 py.test.skip("ctypes complains on wrong calling conv")
100 ffi = FFI(backend=self.Backend())
101 ffi.cdef("long TlsAlloc(void); int TlsFree(long);")
102 lib = ffi.dlopen('KERNEL32.DLL')
103 x = lib.TlsAlloc()
104 assert x != 0
105 y = lib.TlsFree(x)
106 assert y != 0
107
108 def test_fputs(self):
109 if not sys.platform.startswith('linux'):
110 py.test.skip("probably no symbol 'stderr' in the lib")
111 ffi = FFI(backend=self.Backend())
112 ffi.cdef("""
113 int fputs(const char *, void *);
114 void *stderr;
115 """)
116 needs_dlopen_none()
117 ffi.C = ffi.dlopen(None)
118 ffi.C.fputs # fetch before capturing, for easier debugging
119 with FdWriteCapture() as fd:
120 ffi.C.fputs(b"hello\n", ffi.C.stderr)
121 ffi.C.fputs(b" world\n", ffi.C.stderr)
122 res = fd.getvalue()
123 assert res == b'hello\n world\n'
124
125 def test_fputs_without_const(self):
126 if not sys.platform.startswith('linux'):
127 py.test.skip("probably no symbol 'stderr' in the lib")
128 ffi = FFI(backend=self.Backend())
129 ffi.cdef("""
130 int fputs(char *, void *);
131 void *stderr;
132 """)
133 needs_dlopen_none()
134 ffi.C = ffi.dlopen(None)
135 ffi.C.fputs # fetch before capturing, for easier debugging
136 with FdWriteCapture() as fd:
137 ffi.C.fputs(b"hello\n", ffi.C.stderr)
138 ffi.C.fputs(b" world\n", ffi.C.stderr)
139 res = fd.getvalue()
140 assert res == b'hello\n world\n'
141
142 def test_vararg(self):
143 if not sys.platform.startswith('linux'):
144 py.test.skip("probably no symbol 'stderr' in the lib")
145 ffi = FFI(backend=self.Backend())
146 ffi.cdef("""
147 int fprintf(void *, const char *format, ...);
148 void *stderr;
149 """)
150 needs_dlopen_none()
151 ffi.C = ffi.dlopen(None)
152 with FdWriteCapture() as fd:
153 ffi.C.fprintf(ffi.C.stderr, b"hello with no arguments\n")
154 ffi.C.fprintf(ffi.C.stderr,
155 b"hello, %s!\n", ffi.new("char[]", b"world"))
156 ffi.C.fprintf(ffi.C.stderr,
157 ffi.new("char[]", b"hello, %s!\n"),
158 ffi.new("char[]", b"world2"))
159 ffi.C.fprintf(ffi.C.stderr,
160 b"hello int %d long %ld long long %lld\n",
161 ffi.cast("int", 42),
162 ffi.cast("long", 84),
163 ffi.cast("long long", 168))
164 ffi.C.fprintf(ffi.C.stderr, b"hello %p\n", ffi.NULL)
165 res = fd.getvalue()
166 assert res == (b"hello with no arguments\n"
167 b"hello, world!\n"
168 b"hello, world2!\n"
169 b"hello int 42 long 84 long long 168\n"
170 b"hello (nil)\n")
171
172 def test_must_specify_type_of_vararg(self):
173 ffi = FFI(backend=self.Backend())
174 ffi.cdef("""
175 int printf(const char *format, ...);
176 """)
177 needs_dlopen_none()
178 ffi.C = ffi.dlopen(None)
179 e = py.test.raises(TypeError, ffi.C.printf, b"hello %d\n", 42)
180 assert str(e.value) == ("argument 2 passed in the variadic part "
181 "needs to be a cdata object (got int)")
182
183 def test_function_has_a_c_type(self):
184 ffi = FFI(backend=self.Backend())
185 ffi.cdef("""
186 int puts(const char *);
187 """)
188 needs_dlopen_none()
189 ffi.C = ffi.dlopen(None)
190 fptr = ffi.C.puts
191 assert ffi.typeof(fptr) == ffi.typeof("int(*)(const char*)")
192 if self.Backend is CTypesBackend:
193 assert repr(fptr).startswith("<cdata 'int puts(char *)' 0x")
194
195 def test_function_pointer(self):
196 ffi = FFI(backend=self.Backend())
197 def cb(charp):
198 assert repr(charp).startswith("<cdata 'char *' 0x")
199 return 42
200 fptr = ffi.callback("int(*)(const char *txt)", cb)
201 assert fptr != ffi.callback("int(*)(const char *)", cb)
202 assert repr(fptr) == "<cdata 'int(*)(char *)' calling %r>" % (cb,)
203 res = fptr(b"Hello")
204 assert res == 42
205 #
206 if not sys.platform.startswith('linux'):
207 py.test.skip("probably no symbol 'stderr' in the lib")
208 ffi.cdef("""
209 int fputs(const char *, void *);
210 void *stderr;
211 """)
212 needs_dlopen_none()
213 ffi.C = ffi.dlopen(None)
214 fptr = ffi.cast("int(*)(const char *txt, void *)", ffi.C.fputs)
215 assert fptr == ffi.C.fputs
216 assert repr(fptr).startswith("<cdata 'int(*)(char *, void *)' 0x")
217 with FdWriteCapture() as fd:
218 fptr(b"world\n", ffi.C.stderr)
219 res = fd.getvalue()
220 assert res == b'world\n'
221
222 def test_callback_returning_void(self):
223 ffi = FFI(backend=self.Backend())
224 for returnvalue in [None, 42]:
225 def cb():
226 return returnvalue
227 fptr = ffi.callback("void(*)(void)", cb)
228 old_stderr = sys.stderr
229 try:
230 sys.stderr = StringIO()
231 returned = fptr()
232 printed = sys.stderr.getvalue()
233 finally:
234 sys.stderr = old_stderr
235 assert returned is None
236 if returnvalue is None:
237 assert printed == ''
238 else:
239 assert "None" in printed
240
241 def test_passing_array(self):
242 ffi = FFI(backend=self.Backend())
243 ffi.cdef("""
244 int strlen(char[]);
245 """)
246 needs_dlopen_none()
247 ffi.C = ffi.dlopen(None)
248 p = ffi.new("char[]", b"hello")
249 res = ffi.C.strlen(p)
250 assert res == 5
251
252 def test_write_variable(self):
253 if not sys.platform.startswith('linux'):
254 py.test.skip("probably no symbol 'stdout' in the lib")
255 ffi = FFI(backend=self.Backend())
256 ffi.cdef("""
257 void *stdout;
258 """)
259 needs_dlopen_none()
260 C = ffi.dlopen(None)
261 pout = C.stdout
262 C.stdout = ffi.NULL
263 assert C.stdout == ffi.NULL
264 C.stdout = pout
265 assert C.stdout == pout
266
267 def test_strchr(self):
268 ffi = FFI(backend=self.Backend())
269 ffi.cdef("""
270 char *strchr(const char *s, int c);
271 """)
272 needs_dlopen_none()
273 ffi.C = ffi.dlopen(None)
274 p = ffi.new("char[]", b"hello world!")
275 q = ffi.C.strchr(p, ord('w'))
276 assert ffi.string(q) == b"world!"
277
278 def test_function_with_struct_argument(self):
279 if sys.platform == 'win32':
280 py.test.skip("no 'inet_ntoa'")
281 if (self.Backend is CTypesBackend and
282 '__pypy__' in sys.builtin_module_names):
283 py.test.skip("ctypes limitation on pypy")
284 ffi = FFI(backend=self.Backend())
285 ffi.cdef("""
286 struct in_addr { unsigned int s_addr; };
287 char *inet_ntoa(struct in_addr in);
288 """)
289 needs_dlopen_none()
290 ffi.C = ffi.dlopen(None)
291 ina = ffi.new("struct in_addr *", [0x04040404])
292 a = ffi.C.inet_ntoa(ina[0])
293 assert ffi.string(a) == b'4.4.4.4'
294
295 def test_function_typedef(self):
296 ffi = FFI(backend=self.Backend())
297 ffi.cdef("""
298 typedef double func_t(double);
299 func_t sin;
300 """)
301 m = ffi.dlopen(lib_m)
302 x = m.sin(1.23)
303 assert x == math.sin(1.23)
304
305 def test_fputs_custom_FILE(self):
306 if self.Backend is CTypesBackend:
307 py.test.skip("FILE not supported with the ctypes backend")
308 filename = str(udir.join('fputs_custom_FILE'))
309 ffi = FFI(backend=self.Backend())
310 ffi.cdef("int fputs(const char *, FILE *);")
311 needs_dlopen_none()
312 C = ffi.dlopen(None)
313 with open(filename, 'wb') as f:
314 f.write(b'[')
315 C.fputs(b"hello from custom file", f)
316 f.write(b'][')
317 C.fputs(b"some more output", f)
318 f.write(b']')
319 with open(filename, 'rb') as f:
320 res = f.read()
321 assert res == b'[hello from custom file][some more output]'
322
323 def test_constants_on_lib(self):
324 ffi = FFI(backend=self.Backend())
325 ffi.cdef("""enum foo_e { AA, BB, CC=5, DD };
326 typedef enum { EE=-5, FF } some_enum_t;""")
327 needs_dlopen_none()
328 lib = ffi.dlopen(None)
329 assert lib.AA == 0
330 assert lib.BB == 1
331 assert lib.CC == 5
332 assert lib.DD == 6
333 assert lib.EE == -5
334 assert lib.FF == -4
335
336 def test_void_star_accepts_string(self):
337 ffi = FFI(backend=self.Backend())
338 ffi.cdef("""int strlen(const void *);""")
339 needs_dlopen_none()
340 lib = ffi.dlopen(None)
341 res = lib.strlen(b"hello")
342 assert res == 5
343
344 def test_signed_char_star_accepts_string(self):
345 if self.Backend is CTypesBackend:
346 py.test.skip("not supported by the ctypes backend")
347 ffi = FFI(backend=self.Backend())
348 ffi.cdef("""int strlen(signed char *);""")
349 needs_dlopen_none()
350 lib = ffi.dlopen(None)
351 res = lib.strlen(b"hello")
352 assert res == 5
353
354 def test_unsigned_char_star_accepts_string(self):
355 if self.Backend is CTypesBackend:
356 py.test.skip("not supported by the ctypes backend")
357 ffi = FFI(backend=self.Backend())
358 ffi.cdef("""int strlen(unsigned char *);""")
359 needs_dlopen_none()
360 lib = ffi.dlopen(None)
361 res = lib.strlen(b"hello")
362 assert res == 5
363
364 def test_missing_function(self):
365 ffi = FFI(backend=self.Backend())
366 ffi.cdef("""
367 int nonexistent();
368 """)
369 m = ffi.dlopen(lib_m)
370 assert not hasattr(m, 'nonexistent')
371
372 def test_wraps_from_stdlib(self):
373 import functools
374 ffi = FFI(backend=self.Backend())
375 ffi.cdef("""
376 double sin(double x);
377 """)
378 def my_decorator(f):
379 @functools.wraps(f)
380 def wrapper(*args):
381 return f(*args) + 100
382 return wrapper
383 m = ffi.dlopen(lib_m)
384 sin100 = my_decorator(m.sin)
385 x = sin100(1.23)
386 assert x == math.sin(1.23) + 100
387
388 def test_free_callback_cycle(self):
389 if self.Backend is CTypesBackend:
390 py.test.skip("seems to fail with the ctypes backend on windows")
391 import weakref
392 def make_callback(data):
393 container = [data]
394 callback = ffi.callback('int()', lambda: len(container))
395 container.append(callback)
396 # Ref cycle: callback -> lambda (closure) -> container -> callback
397 return callback
398
399 class Data(object):
400 pass
401 ffi = FFI(backend=self.Backend())
402 data = Data()
403 callback = make_callback(data)
404 wr = weakref.ref(data)
405 del callback, data
406 for i in range(3):
407 if wr() is not None:
408 import gc; gc.collect()
409 assert wr() is None # 'data' does not leak
410
411 def test_windows_stdcall(self):
412 if sys.platform != 'win32':
413 py.test.skip("Windows-only test")
414 if self.Backend is CTypesBackend:
415 py.test.skip("not with the ctypes backend")
416 ffi = FFI(backend=self.Backend())
417 ffi.cdef("""
418 BOOL QueryPerformanceFrequency(LONGLONG *lpFrequency);
419 """)
420 m = ffi.dlopen("Kernel32.dll")
421 p_freq = ffi.new("LONGLONG *")
422 res = m.QueryPerformanceFrequency(p_freq)
423 assert res != 0
424 assert p_freq[0] != 0
425
426 def test_explicit_cdecl_stdcall(self):
427 if sys.platform != 'win32':
428 py.test.skip("Windows-only test")
429 if self.Backend is CTypesBackend:
430 py.test.skip("not with the ctypes backend")
431 win64 = (sys.maxsize > 2**32)
432 #
433 ffi = FFI(backend=self.Backend())
434 ffi.cdef("""
435 BOOL QueryPerformanceFrequency(LONGLONG *lpFrequency);
436 """)
437 m = ffi.dlopen("Kernel32.dll")
438 tp = ffi.typeof(m.QueryPerformanceFrequency)
439 assert str(tp) == "<ctype 'int(*)(long long *)'>"
440 #
441 ffi = FFI(backend=self.Backend())
442 ffi.cdef("""
443 BOOL __cdecl QueryPerformanceFrequency(LONGLONG *lpFrequency);
444 """)
445 m = ffi.dlopen("Kernel32.dll")
446 tpc = ffi.typeof(m.QueryPerformanceFrequency)
447 assert tpc is tp
448 #
449 ffi = FFI(backend=self.Backend())
450 ffi.cdef("""
451 BOOL WINAPI QueryPerformanceFrequency(LONGLONG *lpFrequency);
452 """)
453 m = ffi.dlopen("Kernel32.dll")
454 tps = ffi.typeof(m.QueryPerformanceFrequency)
455 if win64:
456 assert tps is tpc
457 else:
458 assert tps is not tpc
459 assert str(tps) == "<ctype 'int(__stdcall *)(long long *)'>"
460 #
461 ffi = FFI(backend=self.Backend())
462 ffi.cdef("typedef int (__cdecl *fnc_t)(int);")
463 ffi.cdef("typedef int (__stdcall *fns_t)(int);")
464 tpc = ffi.typeof("fnc_t")
465 tps = ffi.typeof("fns_t")
466 assert str(tpc) == "<ctype 'int(*)(int)'>"
467 if win64:
468 assert tps is tpc
469 else:
470 assert str(tps) == "<ctype 'int(__stdcall *)(int)'>"
471 #
472 fnc = ffi.cast("fnc_t", 0)
473 fns = ffi.cast("fns_t", 0)
474 ffi.new("fnc_t[]", [fnc])
475 if not win64:
476 py.test.raises(TypeError, ffi.new, "fnc_t[]", [fns])
477 py.test.raises(TypeError, ffi.new, "fns_t[]", [fnc])
478 ffi.new("fns_t[]", [fns])
479
480 def test_stdcall_only_on_windows(self):
481 ffi = FFI(backend=self.Backend())
482 ffi.cdef("double __stdcall sin(double x);") # stdcall ignored
483 m = ffi.dlopen(lib_m)
484 if (sys.platform == 'win32' and sys.maxsize < 2**32 and
485 self.Backend is not CTypesBackend):
486 assert "double(__stdcall *)(double)" in str(ffi.typeof(m.sin))
487 else:
488 assert "double(*)(double)" in str(ffi.typeof(m.sin))
489 x = m.sin(1.23)
490 assert x == math.sin(1.23)
491
492 def test_dir_on_dlopen_lib(self):
493 ffi = FFI(backend=self.Backend())
494 ffi.cdef("""
495 typedef enum { MYE1, MYE2 } myenum_t;
496 double myfunc(double);
497 double myvar;
498 const double myconst;
499 #define MYFOO 42
500 """)
501 m = ffi.dlopen(lib_m)
502 assert dir(m) == ['MYE1', 'MYE2', 'MYFOO', 'myconst', 'myfunc', 'myvar']
503
504 def test_dlclose(self):
505 if self.Backend is CTypesBackend:
506 py.test.skip("not with the ctypes backend")
507 ffi = FFI(backend=self.Backend())
508 ffi.cdef("int foobar(void); int foobaz;")
509 lib = ffi.dlopen(lib_m)
510 ffi.dlclose(lib)
511 e = py.test.raises(ValueError, getattr, lib, 'foobar')
512 assert str(e.value).startswith("library '")
513 assert str(e.value).endswith("' has already been closed")
514 e = py.test.raises(ValueError, getattr, lib, 'foobaz')
515 assert str(e.value).startswith("library '")
516 assert str(e.value).endswith("' has already been closed")
517 e = py.test.raises(ValueError, setattr, lib, 'foobaz', 42)
518 assert str(e.value).startswith("library '")
519 assert str(e.value).endswith("' has already been closed")
520 ffi.dlclose(lib) # does not raise
0 # Generated by pypy/tool/import_cffi.py
1 from cffi.model import *
2
3
4 def test_void_type():
5 assert void_type.get_c_name() == "void"
6 assert void_type.get_c_name("foo") == "void foo"
7 assert void_type.get_c_name("*foo") == "void *foo"
8
9 def test_primitive_type():
10 int_type = PrimitiveType("int")
11 assert int_type.get_c_name() == "int"
12 assert int_type.get_c_name("foo") == "int foo"
13 assert int_type.get_c_name("*foo") == "int *foo"
14 assert int_type.get_c_name("[5]") == "int[5]"
15
16 def test_raw_function_type():
17 int_type = PrimitiveType("int")
18 fn_type = RawFunctionType([], int_type, False)
19 assert fn_type.get_c_name() == "int()(void)"
20 assert fn_type.get_c_name("*") == "int( *)(void)"
21 assert fn_type.get_c_name("*foo") == "int( *foo)(void)"
22 fn_type = RawFunctionType([int_type], int_type, False)
23 assert fn_type.get_c_name() == "int()(int)"
24 fn_type = RawFunctionType([int_type] * 2, int_type, False)
25 assert fn_type.get_c_name() == "int()(int, int)"
26 #
27 fn_type = RawFunctionType([int_type], int_type, True)
28 assert fn_type.get_c_name() == "int()(int, ...)"
29 assert fn_type.get_c_name("*foo") == "int( *foo)(int, ...)"
30 #
31 res_type = FunctionPtrType([int_type], int_type, True)
32 fn_type = RawFunctionType([int_type], res_type, True)
33 assert fn_type.get_c_name("x") == "int(*( x)(int, ...))(int, ...)"
34
35 def test_function_ptr_type():
36 int_type = PrimitiveType("int")
37 fn_type = FunctionPtrType([], int_type, False)
38 assert fn_type.get_c_name() == "int(*)(void)"
39 assert fn_type.get_c_name("*") == "int(* *)(void)"
40 assert fn_type.get_c_name("*foo") == "int(* *foo)(void)"
41 fn_type = FunctionPtrType([int_type], int_type, False)
42 assert fn_type.get_c_name() == "int(*)(int)"
43 fn_type = FunctionPtrType([int_type] * 2, int_type, False)
44 assert fn_type.get_c_name() == "int(*)(int, int)"
45 #
46 fn_type = FunctionPtrType([int_type], int_type, True)
47 assert fn_type.get_c_name() == "int(*)(int, ...)"
48
49 def test_pointer_type():
50 ptr_type = PointerType(PrimitiveType("int"))
51 assert ptr_type.get_c_name("x") == "int * x"
52
53 def test_const_pointer_type():
54 ptr_type = ConstPointerType(PrimitiveType("int"))
55 assert ptr_type.get_c_name("x") == "int const * x"
56 ptr_type = ConstPointerType(ArrayType(PrimitiveType("int"), 5))
57 assert ptr_type.get_c_name("") == "int(const *)[5]"
58 assert ptr_type.get_c_name("*x") == "int(const * *x)[5]"
59
60 def test_qual_pointer_type():
61 ptr_type = PointerType(PrimitiveType("long long"), Q_RESTRICT)
62 assert ptr_type.get_c_name("") == "long long __restrict *"
63 assert const_voidp_type.get_c_name("") == "void const *"
64
65 def test_unknown_pointer_type():
66 ptr_type = unknown_ptr_type("foo_p")
67 assert ptr_type.get_c_name("") == "foo_p"
68 assert ptr_type.get_c_name("x") == "foo_p x"
69
70 def test_unknown_type():
71 u_type = unknown_type("foo_t")
72 assert u_type.get_c_name("") == "foo_t"
73 assert u_type.get_c_name("x") == "foo_t x"
74
75 def test_array_type():
76 a_type = ArrayType(PrimitiveType("int"), None)
77 assert a_type.get_c_name("") == "int[]"
78 assert a_type.get_c_name("x") == "int x[]"
79 assert a_type.get_c_name("*x") == "int(*x)[]"
80 assert a_type.get_c_name(" *x") == "int(*x)[]"
81 assert a_type.get_c_name("[5]") == "int[5][]"
82 a_type = ArrayType(unknown_type("foo_t"), 5)
83 assert a_type.get_c_name("") == "foo_t[5]"
84 assert a_type.get_c_name("x") == "foo_t x[5]"
85 assert a_type.get_c_name("*x") == "foo_t(*x)[5]"
86 a_type = ArrayType(unknown_ptr_type("foo_p"), None)
87 assert a_type.get_c_name("") == "foo_p[]"
88 assert a_type.get_c_name("x") == "foo_p x[]"
89 assert a_type.get_c_name("*x") == "foo_p(*x)[]"
90 a_type = ArrayType(ConstPointerType(PrimitiveType("int")), None)
91 assert a_type.get_c_name("") == "int const *[]"
92 assert a_type.get_c_name("x") == "int const * x[]"
93 assert a_type.get_c_name("*x") == "int const *(*x)[]"
94 fn_type = FunctionPtrType([], PrimitiveType("int"), False)
95 a_type = ArrayType(fn_type, 5)
96 assert a_type.get_c_name("") == "int(*[5])(void)"
97 assert a_type.get_c_name("x") == "int(* x[5])(void)"
98 assert a_type.get_c_name("*x") == "int(*(*x)[5])(void)"
99
100 def test_struct_type():
101 struct_type = StructType("foo_s", None, None, None)
102 assert struct_type.get_c_name() == "struct foo_s"
103 assert struct_type.get_c_name("*x") == "struct foo_s *x"
104
105 def test_union_type():
106 union_type = UnionType("foo_s", None, None, None)
107 assert union_type.get_c_name() == "union foo_s"
108
109 def test_enum_type():
110 enum_type = EnumType("foo_e", [], [])
111 assert enum_type.get_c_name() == "enum foo_e"
0 # Generated by pypy/tool/import_cffi.py
1 import py, sys, os
2 import subprocess, weakref
3 from cffi import FFI
4 from cffi.backend_ctypes import CTypesBackend
5 from extra_tests.cffi_tests.support import u
6
7
8 SOURCE = """\
9 #include <errno.h>
10
11 #ifdef _WIN32
12 #define EXPORT __declspec(dllexport)
13 #else
14 #define EXPORT
15 #endif
16
17 EXPORT int test_getting_errno(void) {
18 errno = 123;
19 return -1;
20 }
21
22 EXPORT int test_setting_errno(void) {
23 return errno;
24 };
25
26 typedef struct {
27 long x;
28 long y;
29 } POINT;
30
31 typedef struct {
32 long left;
33 long top;
34 long right;
35 long bottom;
36 } RECT;
37
38
39 EXPORT int PointInRect(RECT *prc, POINT pt)
40 {
41 if (pt.x < prc->left)
42 return 0;
43 if (pt.x > prc->right)
44 return 0;
45 if (pt.y < prc->top)
46 return 0;
47 if (pt.y > prc->bottom)
48 return 0;
49 return 1;
50 };
51
52 EXPORT long left = 10;
53 EXPORT long top = 20;
54 EXPORT long right = 30;
55 EXPORT long bottom = 40;
56
57 EXPORT RECT ReturnRect(int i, RECT ar, RECT* br, POINT cp, RECT dr,
58 RECT *er, POINT fp, RECT gr)
59 {
60 /*Check input */
61 if (ar.left + br->left + dr.left + er->left + gr.left != left * 5)
62 {
63 ar.left = 100;
64 return ar;
65 }
66 if (ar.right + br->right + dr.right + er->right + gr.right != right * 5)
67 {
68 ar.right = 100;
69 return ar;
70 }
71 if (cp.x != fp.x)
72 {
73 ar.left = -100;
74 }
75 if (cp.y != fp.y)
76 {
77 ar.left = -200;
78 }
79 switch(i)
80 {
81 case 0:
82 return ar;
83 break;
84 case 1:
85 return dr;
86 break;
87 case 2:
88 return gr;
89 break;
90
91 }
92 return ar;
93 }
94
95 EXPORT int my_array[7] = {0, 1, 2, 3, 4, 5, 6};
96
97 EXPORT unsigned short foo_2bytes(unsigned short a)
98 {
99 return (unsigned short)(a + 42);
100 }
101 EXPORT unsigned int foo_4bytes(unsigned int a)
102 {
103 return (unsigned int)(a + 42);
104 }
105
106 EXPORT void modify_struct_value(RECT r)
107 {
108 r.left = r.right = r.top = r.bottom = 500;
109 }
110 """
111
112 class TestOwnLib(object):
113 Backend = CTypesBackend
114
115 def setup_class(cls):
116 cls.module = None
117 from extra_tests.cffi_tests.udir import udir
118 udir.join('testownlib.c').write(SOURCE)
119 if sys.platform == 'win32':
120 # did we already build it?
121 if cls.Backend is CTypesBackend:
122 dll_path = str(udir) + '\\testownlib1.dll' # only ascii for the ctypes backend
123 else:
124 dll_path = str(udir) + '\\' + (u+'testownlib\u03be.dll') # non-ascii char
125 if os.path.exists(dll_path):
126 cls.module = dll_path
127 return
128 # try (not too hard) to find the version used to compile this python
129 # no mingw
130 from distutils.msvc9compiler import get_build_version
131 version = get_build_version()
132 toolskey = "VS%0.f0COMNTOOLS" % version
133 toolsdir = os.environ.get(toolskey, None)
134 if toolsdir is None:
135 return
136 productdir = os.path.join(toolsdir, os.pardir, os.pardir, "VC")
137 productdir = os.path.abspath(productdir)
138 vcvarsall = os.path.join(productdir, "vcvarsall.bat")
139 # 64?
140 arch = 'x86'
141 if sys.maxsize > 2**32:
142 arch = 'amd64'
143 if os.path.isfile(vcvarsall):
144 cmd = '"%s" %s' % (vcvarsall, arch) + ' & cl.exe testownlib.c ' \
145 ' /LD /Fetestownlib.dll'
146 subprocess.check_call(cmd, cwd = str(udir), shell=True)
147 os.rename(str(udir) + '\\testownlib.dll', dll_path)
148 cls.module = dll_path
149 else:
150 encoded = None
151 if cls.Backend is not CTypesBackend:
152 try:
153 unicode_name = u+'testownlibcaf\xe9'
154 encoded = unicode_name.encode(sys.getfilesystemencoding())
155 if sys.version_info >= (3,):
156 encoded = str(unicode_name)
157 except UnicodeEncodeError:
158 pass
159 if encoded is None:
160 unicode_name = u+'testownlib'
161 encoded = str(unicode_name)
162 subprocess.check_call(
163 "cc testownlib.c -shared -fPIC -o '%s.so'" % (encoded,),
164 cwd=str(udir), shell=True)
165 cls.module = os.path.join(str(udir), unicode_name + (u+'.so'))
166 print(repr(cls.module))
167
168 def test_getting_errno(self):
169 if self.module is None:
170 py.test.skip("fix the auto-generation of the tiny test lib")
171 if sys.platform == 'win32':
172 py.test.skip("fails, errno at multiple addresses")
173 ffi = FFI(backend=self.Backend())
174 ffi.cdef("""
175 int test_getting_errno(void);
176 """)
177 ownlib = ffi.dlopen(self.module)
178 res = ownlib.test_getting_errno()
179 assert res == -1
180 assert ffi.errno == 123
181
182 def test_setting_errno(self):
183 if self.module is None:
184 py.test.skip("fix the auto-generation of the tiny test lib")
185 if sys.platform == 'win32':
186 py.test.skip("fails, errno at multiple addresses")
187 if self.Backend is CTypesBackend and '__pypy__' in sys.modules:
188 py.test.skip("XXX errno issue with ctypes on pypy?")
189 ffi = FFI(backend=self.Backend())
190 ffi.cdef("""
191 int test_setting_errno(void);
192 """)
193 ownlib = ffi.dlopen(self.module)
194 ffi.errno = 42
195 res = ownlib.test_setting_errno()
196 assert res == 42
197 assert ffi.errno == 42
198
199 def test_my_array_7(self):
200 if self.module is None:
201 py.test.skip("fix the auto-generation of the tiny test lib")
202 ffi = FFI(backend=self.Backend())
203 ffi.cdef("""
204 int my_array[7];
205 """)
206 ownlib = ffi.dlopen(self.module)
207 for i in range(7):
208 assert ownlib.my_array[i] == i
209 assert len(ownlib.my_array) == 7
210 if self.Backend is CTypesBackend:
211 py.test.skip("not supported by the ctypes backend")
212 ownlib.my_array = list(range(10, 17))
213 for i in range(7):
214 assert ownlib.my_array[i] == 10 + i
215 ownlib.my_array = list(range(7))
216 for i in range(7):
217 assert ownlib.my_array[i] == i
218
219 def test_my_array_no_length(self):
220 if self.module is None:
221 py.test.skip("fix the auto-generation of the tiny test lib")
222 if self.Backend is CTypesBackend:
223 py.test.skip("not supported by the ctypes backend")
224 ffi = FFI(backend=self.Backend())
225 ffi.cdef("""
226 int my_array[];
227 """)
228 ownlib = ffi.dlopen(self.module)
229 for i in range(7):
230 assert ownlib.my_array[i] == i
231 py.test.raises(TypeError, len, ownlib.my_array)
232 ownlib.my_array = list(range(10, 17))
233 for i in range(7):
234 assert ownlib.my_array[i] == 10 + i
235 ownlib.my_array = list(range(7))
236 for i in range(7):
237 assert ownlib.my_array[i] == i
238
239 def test_keepalive_lib(self):
240 if self.module is None:
241 py.test.skip("fix the auto-generation of the tiny test lib")
242 ffi = FFI(backend=self.Backend())
243 ffi.cdef("""
244 int test_getting_errno(void);
245 """)
246 ownlib = ffi.dlopen(self.module)
247 ffi_r = weakref.ref(ffi)
248 ownlib_r = weakref.ref(ownlib)
249 func = ownlib.test_getting_errno
250 del ffi
251 import gc; gc.collect() # ownlib stays alive
252 assert ownlib_r() is not None
253 assert ffi_r() is not None # kept alive by ownlib
254 res = func()
255 assert res == -1
256
257 def test_keepalive_ffi(self):
258 if self.module is None:
259 py.test.skip("fix the auto-generation of the tiny test lib")
260 ffi = FFI(backend=self.Backend())
261 ffi.cdef("""
262 int test_getting_errno(void);
263 """)
264 ownlib = ffi.dlopen(self.module)
265 ffi_r = weakref.ref(ffi)
266 ownlib_r = weakref.ref(ownlib)
267 func = ownlib.test_getting_errno
268 del ownlib
269 import gc; gc.collect() # ffi stays alive
270 assert ffi_r() is not None
271 assert ownlib_r() is not None # kept alive by ffi
272 res = func()
273 assert res == -1
274 if sys.platform != 'win32': # else, errno at multiple addresses
275 assert ffi.errno == 123
276
277 def test_struct_by_value(self):
278 if self.module is None:
279 py.test.skip("fix the auto-generation of the tiny test lib")
280 ffi = FFI(backend=self.Backend())
281 ffi.cdef("""
282 typedef struct {
283 long x;
284 long y;
285 } POINT;
286
287 typedef struct {
288 long left;
289 long top;
290 long right;
291 long bottom;
292 } RECT;
293
294 long left, top, right, bottom;
295
296 RECT ReturnRect(int i, RECT ar, RECT* br, POINT cp, RECT dr,
297 RECT *er, POINT fp, RECT gr);
298 """)
299 ownlib = ffi.dlopen(self.module)
300
301 rect = ffi.new('RECT[1]')
302 pt = ffi.new('POINT[1]')
303 pt[0].x = 15
304 pt[0].y = 25
305 rect[0].left = ownlib.left
306 rect[0].right = ownlib.right
307 rect[0].top = ownlib.top
308 rect[0].bottom = ownlib.bottom
309
310 for i in range(4):
311 ret = ownlib.ReturnRect(i, rect[0], rect, pt[0], rect[0],
312 rect, pt[0], rect[0])
313 assert ret.left == ownlib.left
314 assert ret.right == ownlib.right
315 assert ret.top == ownlib.top
316 assert ret.bottom == ownlib.bottom
317
318 def test_addressof_lib(self):
319 if self.module is None:
320 py.test.skip("fix the auto-generation of the tiny test lib")
321 if self.Backend is CTypesBackend:
322 py.test.skip("not implemented with the ctypes backend")
323 ffi = FFI(backend=self.Backend())
324 ffi.cdef("long left; int test_getting_errno(void);")
325 lib = ffi.dlopen(self.module)
326 lib.left = 123456
327 p = ffi.addressof(lib, "left")
328 assert ffi.typeof(p) == ffi.typeof("long *")
329 assert p[0] == 123456
330 p[0] += 1
331 assert lib.left == 123457
332 pfn = ffi.addressof(lib, "test_getting_errno")
333 assert ffi.typeof(pfn) == ffi.typeof("int(*)(void)")
334 assert pfn == lib.test_getting_errno
335
336 def test_char16_char32_t(self):
337 if self.module is None:
338 py.test.skip("fix the auto-generation of the tiny test lib")
339 if self.Backend is CTypesBackend:
340 py.test.skip("not implemented with the ctypes backend")
341 ffi = FFI(backend=self.Backend())
342 ffi.cdef("""
343 char16_t foo_2bytes(char16_t);
344 char32_t foo_4bytes(char32_t);
345 """)
346 lib = ffi.dlopen(self.module)
347 assert lib.foo_2bytes(u+'\u1234') == u+'\u125e'
348 assert lib.foo_4bytes(u+'\u1234') == u+'\u125e'
349 assert lib.foo_4bytes(u+'\U00012345') == u+'\U0001236f'
350
351 def test_modify_struct_value(self):
352 if self.module is None:
353 py.test.skip("fix the auto-generation of the tiny test lib")
354 ffi = FFI(backend=self.Backend())
355 ffi.cdef("""
356 typedef struct {
357 long left;
358 long top;
359 long right;
360 long bottom;
361 } RECT;
362
363 void modify_struct_value(RECT r);
364 """)
365 lib = ffi.dlopen(self.module)
366 s = ffi.new("RECT *", [11, 22, 33, 44])
367 lib.modify_struct_value(s[0])
368 assert s.left == 11
369 assert s.top == 22
370 assert s.right == 33
371 assert s.bottom == 44
0 # Generated by pypy/tool/import_cffi.py
1 import py, sys, re
2 from cffi import FFI, FFIError, CDefError, VerificationError
3 from .backend_tests import needs_dlopen_none
4
5
6 class FakeBackend(object):
7
8 def nonstandard_integer_types(self):
9 return {}
10
11 def sizeof(self, name):
12 return 1
13
14 def load_library(self, name, flags):
15 if sys.platform == 'win32':
16 assert name is None or "msvcr" in name
17 else:
18 assert name is None or "libc" in name or "libm" in name
19 return FakeLibrary()
20
21 def new_function_type(self, args, result, has_varargs):
22 args = [arg.cdecl for arg in args]
23 result = result.cdecl
24 return FakeType(
25 '<func (%s), %s, %s>' % (', '.join(args), result, has_varargs))
26
27 def new_primitive_type(self, name):
28 assert name == name.lower()
29 return FakeType('<%s>' % name)
30
31 def new_pointer_type(self, itemtype):
32 return FakeType('<pointer to %s>' % (itemtype,))
33
34 def new_struct_type(self, name):
35 return FakeStruct(name)
36
37 def complete_struct_or_union(self, s, fields, tp=None,
38 totalsize=-1, totalalignment=-1, sflags=0):
39 assert isinstance(s, FakeStruct)
40 s.fields = fields
41
42 def new_array_type(self, ptrtype, length):
43 return FakeType('<array %s x %s>' % (ptrtype, length))
44
45 def new_void_type(self):
46 return FakeType("<void>")
47 def cast(self, x, y):
48 return 'casted!'
49 def _get_types(self):
50 return "CData", "CType"
51
52 buffer = "buffer type"
53
54 class FakeType(object):
55 def __init__(self, cdecl):
56 self.cdecl = cdecl
57 def __str__(self):
58 return self.cdecl
59
60 class FakeStruct(object):
61 def __init__(self, name):
62 self.name = name
63 def __str__(self):
64 return ', '.join([str(y) + str(x) for x, y, z in self.fields])
65
66 class FakeLibrary(object):
67
68 def load_function(self, BType, name):
69 return FakeFunction(BType, name)
70
71 class FakeFunction(object):
72
73 def __init__(self, BType, name):
74 self.BType = str(BType)
75 self.name = name
76
77 lib_m = "m"
78 if sys.platform == 'win32':
79 #there is a small chance this fails on Mingw via environ $CC
80 import distutils.ccompiler
81 if distutils.ccompiler.get_default_compiler() == 'msvc':
82 lib_m = 'msvcrt'
83
84 def test_simple():
85 ffi = FFI(backend=FakeBackend())
86 ffi.cdef("double sin(double x);")
87 m = ffi.dlopen(lib_m)
88 func = m.sin # should be a callable on real backends
89 assert func.name == 'sin'
90 assert func.BType == '<func (<double>), <double>, False>'
91
92 def test_pipe():
93 ffi = FFI(backend=FakeBackend())
94 ffi.cdef("int pipe(int pipefd[2]);")
95 needs_dlopen_none()
96 C = ffi.dlopen(None)
97 func = C.pipe
98 assert func.name == 'pipe'
99 assert func.BType == '<func (<pointer to <int>>), <int>, False>'
100
101 def test_vararg():
102 ffi = FFI(backend=FakeBackend())
103 ffi.cdef("short foo(int, ...);")
104 needs_dlopen_none()
105 C = ffi.dlopen(None)
106 func = C.foo
107 assert func.name == 'foo'
108 assert func.BType == '<func (<int>), <short>, True>'
109
110 def test_no_args():
111 ffi = FFI(backend=FakeBackend())
112 ffi.cdef("""
113 int foo(void);
114 """)
115 needs_dlopen_none()
116 C = ffi.dlopen(None)
117 assert C.foo.BType == '<func (), <int>, False>'
118
119 def test_typedef():
120 ffi = FFI(backend=FakeBackend())
121 ffi.cdef("""
122 typedef unsigned int UInt;
123 typedef UInt UIntReally;
124 UInt foo(void);
125 """)
126 needs_dlopen_none()
127 C = ffi.dlopen(None)
128 assert str(ffi.typeof("UIntReally")) == '<unsigned int>'
129 assert C.foo.BType == '<func (), <unsigned int>, False>'
130
131 def test_typedef_more_complex():
132 ffi = FFI(backend=FakeBackend())
133 ffi.cdef("""
134 typedef struct { int a, b; } foo_t, *foo_p;
135 int foo(foo_p[]);
136 """)
137 needs_dlopen_none()
138 C = ffi.dlopen(None)
139 assert str(ffi.typeof("foo_t")) == '<int>a, <int>b'
140 assert str(ffi.typeof("foo_p")) == '<pointer to <int>a, <int>b>'
141 assert C.foo.BType == ('<func (<pointer to <pointer to '
142 '<int>a, <int>b>>), <int>, False>')
143
144 def test_typedef_array_convert_array_to_pointer():
145 ffi = FFI(backend=FakeBackend())
146 ffi.cdef("""
147 typedef int (*fn_t)(int[5]);
148 """)
149 with ffi._lock:
150 type = ffi._parser.parse_type("fn_t")
151 BType = ffi._get_cached_btype(type)
152 assert str(BType) == '<func (<pointer to <int>>), <int>, False>'
153
154 def test_remove_comments():
155 ffi = FFI(backend=FakeBackend())
156 ffi.cdef("""
157 double /*comment here*/ sin // blah blah
158 /* multi-
159 line-
160 //comment */ (
161 // foo
162 double // bar /* <- ignored, because it's in a comment itself
163 x, double/*several*//*comment*/y) /*on the same line*/
164 ;
165 """)
166 m = ffi.dlopen(lib_m)
167 func = m.sin
168 assert func.name == 'sin'
169 assert func.BType == '<func (<double>, <double>), <double>, False>'
170
171 def test_remove_line_continuation_comments():
172 ffi = FFI(backend=FakeBackend())
173 ffi.cdef("""
174 double // blah \\
175 more comments
176 x(void);
177 double // blah\\\\
178 y(void);
179 double // blah\\ \
180 etc
181 z(void);
182 """)
183 m = ffi.dlopen(lib_m)
184 m.x
185 m.y
186 m.z
187
188 def test_line_continuation_in_defines():
189 ffi = FFI(backend=FakeBackend())
190 ffi.cdef("""
191 #define ABC\\
192 42
193 #define BCD \\
194 43
195 """)
196 m = ffi.dlopen(lib_m)
197 assert m.ABC == 42
198 assert m.BCD == 43
199
200 def test_define_not_supported_for_now():
201 ffi = FFI(backend=FakeBackend())
202 e = py.test.raises(CDefError, ffi.cdef, '#define FOO "blah"')
203 assert str(e.value) == (
204 'only supports one of the following syntax:\n'
205 ' #define FOO ... (literally dot-dot-dot)\n'
206 ' #define FOO NUMBER (with NUMBER an integer'
207 ' constant, decimal/hex/octal)\n'
208 'got:\n'
209 ' #define FOO "blah"')
210
211 def test_unnamed_struct():
212 ffi = FFI(backend=FakeBackend())
213 ffi.cdef("typedef struct { int x; } foo_t;\n"
214 "typedef struct { int y; } *bar_p;\n")
215 assert 'typedef foo_t' in ffi._parser._declarations
216 assert 'typedef bar_p' in ffi._parser._declarations
217 assert 'anonymous foo_t' in ffi._parser._declarations
218 type_foo = ffi._parser.parse_type("foo_t")
219 type_bar = ffi._parser.parse_type("bar_p").totype
220 assert repr(type_foo) == "<foo_t>"
221 assert repr(type_bar) == "<struct $1>"
222 py.test.raises(VerificationError, type_bar.get_c_name)
223 assert type_foo.get_c_name() == "foo_t"
224
225 def test_override():
226 ffi = FFI(backend=FakeBackend())
227 needs_dlopen_none()
228 C = ffi.dlopen(None)
229 ffi.cdef("int foo(void);")
230 py.test.raises(FFIError, ffi.cdef, "long foo(void);")
231 assert C.foo.BType == '<func (), <int>, False>'
232 ffi.cdef("long foo(void);", override=True)
233 assert C.foo.BType == '<func (), <long>, False>'
234
235 def test_cannot_have_only_variadic_part():
236 # this checks that we get a sensible error if we try "int foo(...);"
237 ffi = FFI()
238 e = py.test.raises(CDefError, ffi.cdef, "int foo(...);")
239 assert str(e.value) == (
240 "<cdef source string>:1: foo: a function with only '(...)' "
241 "as argument is not correct C")
242
243 def test_parse_error():
244 ffi = FFI()
245 e = py.test.raises(CDefError, ffi.cdef, " x y z ")
246 assert str(e.value).startswith(
247 'cannot parse "x y z"\n<cdef source string>:1:')
248 e = py.test.raises(CDefError, ffi.cdef, "\n\n\n x y z ")
249 assert str(e.value).startswith(
250 'cannot parse "x y z"\n<cdef source string>:4:')
251
252 def test_error_custom_lineno():
253 ffi = FFI()
254 e = py.test.raises(CDefError, ffi.cdef, """
255 # 42 "foobar"
256
257 a b c d
258 """)
259 assert str(e.value).startswith('parse error\nfoobar:43:')
260
261 def test_cannot_declare_enum_later():
262 ffi = FFI()
263 e = py.test.raises(NotImplementedError, ffi.cdef,
264 "typedef enum foo_e foo_t; enum foo_e { AA, BB };")
265 assert str(e.value) == (
266 "enum foo_e: the '{}' declaration should appear on the "
267 "first time the enum is mentioned, not later")
268
269 def test_unknown_name():
270 ffi = FFI()
271 e = py.test.raises(CDefError, ffi.cast, "foobarbazunknown", 0)
272 assert str(e.value) == "unknown identifier 'foobarbazunknown'"
273 e = py.test.raises(CDefError, ffi.cast, "foobarbazunknown*", 0)
274 assert str(e.value).startswith('cannot parse "foobarbazunknown*"')
275 e = py.test.raises(CDefError, ffi.cast, "int(*)(foobarbazunknown)", 0)
276 assert str(e.value).startswith('cannot parse "int(*)(foobarbazunknown)"')
277
278 def test_redefine_common_type():
279 prefix = "" if sys.version_info < (3,) else "b"
280 ffi = FFI()
281 ffi.cdef("typedef char FILE;")
282 assert repr(ffi.cast("FILE", 123)) == "<cdata 'char' %s'{'>" % prefix
283 ffi.cdef("typedef char int32_t;")
284 assert repr(ffi.cast("int32_t", 123)) == "<cdata 'char' %s'{'>" % prefix
285 ffi = FFI()
286 ffi.cdef("typedef int bool, *FILE;")
287 assert repr(ffi.cast("bool", 123)) == "<cdata 'int' 123>"
288 assert re.match(r"<cdata 'int [*]' 0[xX]?0*7[bB]>",
289 repr(ffi.cast("FILE", 123)))
290 ffi = FFI()
291 ffi.cdef("typedef bool (*fn_t)(bool, bool);") # "bool," but within "( )"
292
293 def test_bool():
294 ffi = FFI()
295 ffi.cdef("void f(bool);")
296 #
297 ffi = FFI()
298 ffi.cdef("typedef _Bool bool; void f(bool);")
299
300 def test_unknown_argument_type():
301 ffi = FFI()
302 e = py.test.raises(CDefError, ffi.cdef, "void f(foobarbazzz);")
303 assert str(e.value) == ("<cdef source string>:1: f arg 1:"
304 " unknown type 'foobarbazzz' (if you meant"
305 " to use the old C syntax of giving untyped"
306 " arguments, it is not supported)")
307
308 def test_void_renamed_as_only_arg():
309 ffi = FFI()
310 ffi.cdef("typedef void void_t1;"
311 "typedef void_t1 void_t;"
312 "typedef int (*func_t)(void_t);")
313 assert ffi.typeof("func_t").args == ()
314
315 def test_WPARAM_on_windows():
316 if sys.platform != 'win32':
317 py.test.skip("Only for Windows")
318 ffi = FFI()
319 ffi.cdef("void f(WPARAM);")
320 #
321 # WPARAM -> UINT_PTR -> unsigned 32/64-bit integer
322 ffi = FFI()
323 value = int(ffi.cast("WPARAM", -42))
324 assert value == sys.maxsize * 2 - 40
325
326 def test__is_constant_globalvar():
327 for input, expected_output in [
328 ("int a;", False),
329 ("const int a;", True),
330 ("int *a;", False),
331 ("const int *a;", False),
332 ("int const *a;", False),
333 ("int *const a;", True),
334 ("int a[5];", False),
335 ("const int a[5];", False),
336 ("int *a[5];", False),
337 ("const int *a[5];", False),
338 ("int const *a[5];", False),
339 ("int *const a[5];", False),
340 ("int a[5][6];", False),
341 ("const int a[5][6];", False),
342 ]:
343 ffi = FFI()
344 ffi.cdef(input)
345 declarations = ffi._parser._declarations
346 assert ('constant a' in declarations) == expected_output
347 assert ('variable a' in declarations) == (not expected_output)
348
349 def test_restrict():
350 from cffi import model
351 for input, expected_output in [
352 ("int a;", False),
353 ("restrict int a;", True),
354 ("int *a;", False),
355 ]:
356 ffi = FFI()
357 ffi.cdef(input)
358 tp, quals = ffi._parser._declarations['variable a']
359 assert bool(quals & model.Q_RESTRICT) == expected_output
360
361 def test_different_const_funcptr_types():
362 lst = []
363 for input in [
364 "int(*)(int *a)",
365 "int(*)(int const *a)",
366 "int(*)(int * const a)",
367 "int(*)(int const a[])"]:
368 ffi = FFI(backend=FakeBackend())
369 lst.append(ffi._parser.parse_type(input))
370 assert lst[0] != lst[1]
371 assert lst[0] == lst[2]
372 assert lst[1] == lst[3]
373
374 def test_const_pointer_to_pointer():
375 from cffi import model
376 ffi = FFI(backend=FakeBackend())
377 #
378 tp, qual = ffi._parser.parse_type_and_quals("char * * (* const)")
379 assert (str(tp), qual) == ("<char * * *>", model.Q_CONST)
380 tp, qual = ffi._parser.parse_type_and_quals("char * (* const (*))")
381 assert (str(tp), qual) == ("<char * * const *>", 0)
382 tp, qual = ffi._parser.parse_type_and_quals("char (* const (* (*)))")
383 assert (str(tp), qual) == ("<char * const * *>", 0)
384 tp, qual = ffi._parser.parse_type_and_quals("char const * * *")
385 assert (str(tp), qual) == ("<char const * * *>", 0)
386 tp, qual = ffi._parser.parse_type_and_quals("const char * * *")
387 assert (str(tp), qual) == ("<char const * * *>", 0)
388 #
389 tp, qual = ffi._parser.parse_type_and_quals("char * * * const const")
390 assert (str(tp), qual) == ("<char * * *>", model.Q_CONST)
391 tp, qual = ffi._parser.parse_type_and_quals("char * * volatile *")
392 assert (str(tp), qual) == ("<char * * volatile *>", 0)
393 tp, qual = ffi._parser.parse_type_and_quals("char * volatile restrict * *")
394 assert (str(tp), qual) == ("<char * __restrict volatile * *>", 0)
395 tp, qual = ffi._parser.parse_type_and_quals("char const volatile * * *")
396 assert (str(tp), qual) == ("<char volatile const * * *>", 0)
397 tp, qual = ffi._parser.parse_type_and_quals("const char * * *")
398 assert (str(tp), qual) == ("<char const * * *>", 0)
399 #
400 tp, qual = ffi._parser.parse_type_and_quals(
401 "int(char*const*, short****const*)")
402 assert (str(tp), qual) == (
403 "<int()(char * const *, short * * * * const *)>", 0)
404 tp, qual = ffi._parser.parse_type_and_quals(
405 "char*const*(short*const****)")
406 assert (str(tp), qual) == (
407 "<char * const *()(short * const * * * *)>", 0)
408
409 def test_enum():
410 ffi = FFI()
411 ffi.cdef("""
412 enum Enum { POS = +1, TWO = 2, NIL = 0, NEG = -1, OP = (POS+TWO)-1};
413 """)
414 needs_dlopen_none()
415 C = ffi.dlopen(None)
416 assert C.POS == 1
417 assert C.TWO == 2
418 assert C.NIL == 0
419 assert C.NEG == -1
420 assert C.OP == 2
421
422 def test_stdcall():
423 ffi = FFI()
424 tp = ffi.typeof("int(*)(int __stdcall x(int),"
425 " long (__cdecl*y)(void),"
426 " short(WINAPI *z)(short))")
427 if sys.platform == 'win32' and sys.maxsize < 2**32:
428 stdcall = '__stdcall '
429 else:
430 stdcall = ''
431 assert str(tp) == (
432 "<ctype 'int(*)(int(%s*)(int), "
433 "long(*)(), "
434 "short(%s*)(short))'>" % (stdcall, stdcall))
435
436 def test_extern_python():
437 ffi = FFI()
438 ffi.cdef("""
439 int bok(int, int);
440 extern "Python" int foobar(int, int);
441 int baz(int, int);
442 """)
443 assert sorted(ffi._parser._declarations) == [
444 'extern_python foobar', 'function baz', 'function bok']
445 assert (ffi._parser._declarations['function bok'] ==
446 ffi._parser._declarations['extern_python foobar'] ==
447 ffi._parser._declarations['function baz'])
448
449 def test_extern_python_group():
450 ffi = FFI()
451 ffi.cdef("""
452 int bok(int);
453 extern "Python" {int foobar(int, int);int bzrrr(int);}
454 int baz(int, int);
455 """)
456 assert sorted(ffi._parser._declarations) == [
457 'extern_python bzrrr', 'extern_python foobar',
458 'function baz', 'function bok']
459 assert (ffi._parser._declarations['function baz'] ==
460 ffi._parser._declarations['extern_python foobar'] !=
461 ffi._parser._declarations['function bok'] ==
462 ffi._parser._declarations['extern_python bzrrr'])
463
464 def test_error_invalid_syntax_for_cdef():
465 ffi = FFI()
466 e = py.test.raises(CDefError, ffi.cdef, 'void foo(void) {}')
467 assert str(e.value) == ('<cdef source string>:1: unexpected <FuncDef>: '
468 'this construct is valid C but not valid in cdef()')
0 # Generated by pypy/tool/import_cffi.py
1 import os
2 from cffi.ffiplatform import maybe_relative_path, flatten
3
4
5 def test_not_absolute():
6 assert maybe_relative_path('foo/bar') == 'foo/bar'
7 assert maybe_relative_path('test_platform.py') == 'test_platform.py'
8
9 def test_different_absolute():
10 p = os.path.join('..', 'baz.py')
11 assert maybe_relative_path(p) == p
12
13 def test_absolute_mapping():
14 p = os.path.abspath('baz.py')
15 assert maybe_relative_path(p) == 'baz.py'
16 foobaz = os.path.join('foo', 'baz.py')
17 assert maybe_relative_path(os.path.abspath(foobaz)) == foobaz
18
19 def test_flatten():
20 assert flatten("foo") == "3sfoo"
21 assert flatten(-10000000000000000000000000000) == \
22 "-10000000000000000000000000000i"
23 assert flatten([4, 5]) == "2l4i5i"
24 assert flatten({4: 5}) == "1d4i5i"
25 assert flatten({"foo": ("bar", "baaz")}) == "1d3sfoo2l3sbar4sbaaz"
0 # Generated by pypy/tool/import_cffi.py
1 #
2 # ----------------------------------------------
3 # WARNING, ALL LITERALS IN THIS FILE ARE UNICODE
4 # ----------------------------------------------
5 #
6 from __future__ import unicode_literals
7 #
8 #
9 #
10 import sys, math
11 from cffi import FFI
12
13 lib_m = "m"
14 if sys.platform == 'win32':
15 #there is a small chance this fails on Mingw via environ $CC
16 import distutils.ccompiler
17 if distutils.ccompiler.get_default_compiler() == 'msvc':
18 lib_m = 'msvcrt'
19
20
21 def test_cast():
22 ffi = FFI()
23 assert int(ffi.cast("int", 3.14)) == 3 # unicode literal
24
25 def test_new():
26 ffi = FFI()
27 assert ffi.new("int[]", [3, 4, 5])[2] == 5 # unicode literal
28
29 def test_typeof():
30 ffi = FFI()
31 tp = ffi.typeof("int[51]") # unicode literal
32 assert tp.length == 51
33
34 def test_sizeof():
35 ffi = FFI()
36 assert ffi.sizeof("int[51]") == 51 * 4 # unicode literal
37
38 def test_alignof():
39 ffi = FFI()
40 assert ffi.alignof("int[51]") == 4 # unicode literal
41
42 def test_getctype():
43 ffi = FFI()
44 assert ffi.getctype("int**") == "int * *" # unicode literal
45 assert type(ffi.getctype("int**")) is str
46
47 def test_cdef():
48 ffi = FFI()
49 ffi.cdef("typedef int foo_t[50];") # unicode literal
50
51 def test_offsetof():
52 ffi = FFI()
53 ffi.cdef("typedef struct { int x, y; } foo_t;")
54 assert ffi.offsetof("foo_t", "y") == 4 # unicode literal
55
56 def test_enum():
57 ffi = FFI()
58 ffi.cdef("enum foo_e { AA, BB, CC };") # unicode literal
59 x = ffi.cast("enum foo_e", 1)
60 assert int(ffi.cast("int", x)) == 1
61
62 def test_dlopen():
63 ffi = FFI()
64 ffi.cdef("double sin(double x);")
65 m = ffi.dlopen(lib_m) # unicode literal
66 x = m.sin(1.23)
67 assert x == math.sin(1.23)
68
69 def test_verify():
70 ffi = FFI()
71 ffi.cdef("double test_verify_1(double x);") # unicode literal
72 lib = ffi.verify("double test_verify_1(double x) { return x * 42.0; }")
73 assert lib.test_verify_1(-1.5) == -63.0
74
75 def test_callback():
76 ffi = FFI()
77 cb = ffi.callback("int(int)", # unicode literal
78 lambda x: x + 42)
79 assert cb(5) == 47
0 # Generated by pypy/tool/import_cffi.py
1 import py, re
2 import sys, os, math, weakref
3 from cffi import FFI, VerificationError, VerificationMissing, model, FFIError
4 from extra_tests.cffi_tests.support import *
5
6
7 lib_m = ['m']
8 if sys.platform == 'win32':
9 #there is a small chance this fails on Mingw via environ $CC
10 import distutils.ccompiler
11 if distutils.ccompiler.get_default_compiler() == 'msvc':
12 lib_m = ['msvcrt']
13 pass # no obvious -Werror equivalent on MSVC
14 else:
15 if (sys.platform == 'darwin' and
16 [int(x) for x in os.uname()[2].split('.')] >= [11, 0, 0]):
17 # assume a standard clang or gcc
18 extra_compile_args = ['-Werror', '-Wall', '-Wextra', '-Wconversion']
19 # special things for clang
20 extra_compile_args.append('-Qunused-arguments')
21 else:
22 # assume a standard gcc
23 extra_compile_args = ['-Werror', '-Wall', '-Wextra', '-Wconversion']
24
25 class FFI(FFI):
26 def verify(self, *args, **kwds):
27 return super(FFI, self).verify(
28 *args, extra_compile_args=extra_compile_args, **kwds)
29
30 def setup_module():
31 import cffi.verifier
32 cffi.verifier.cleanup_tmpdir()
33 #
34 # check that no $ sign is produced in the C file; it used to be the
35 # case that anonymous enums would produce '$enum_$1', which was
36 # used as part of a function name. GCC accepts such names, but it's
37 # apparently non-standard.
38 _r_comment = re.compile(r"/\*.*?\*/|//.*?$", re.DOTALL | re.MULTILINE)
39 _r_string = re.compile(r'\".*?\"')
40 def _write_source_and_check(self, file=None):
41 base_write_source(self, file)
42 if file is None:
43 f = open(self.sourcefilename)
44 data = f.read()
45 f.close()
46 data = _r_comment.sub(' ', data)
47 data = _r_string.sub('"skipped"', data)
48 assert '$' not in data
49 base_write_source = cffi.verifier.Verifier._write_source
50 cffi.verifier.Verifier._write_source = _write_source_and_check
51
52
53 def test_module_type():
54 import cffi.verifier
55 ffi = FFI()
56 lib = ffi.verify()
57 if hasattr(lib, '_cffi_python_module'):
58 print('verify got a PYTHON module')
59 if hasattr(lib, '_cffi_generic_module'):
60 print('verify got a GENERIC module')
61 expected_generic = (cffi.verifier._FORCE_GENERIC_ENGINE or
62 '__pypy__' in sys.builtin_module_names)
63 assert hasattr(lib, '_cffi_python_module') == (not expected_generic)
64 assert hasattr(lib, '_cffi_generic_module') == expected_generic
65
66 def test_missing_function(ffi=None):
67 # uses the FFI hacked above with '-Werror'
68 if ffi is None:
69 ffi = FFI()
70 ffi.cdef("void some_completely_unknown_function();")
71 try:
72 lib = ffi.verify()
73 except (VerificationError, OSError):
74 pass # expected case: we get a VerificationError
75 else:
76 # but depending on compiler and loader details, maybe
77 # 'lib' could actually be imported but will fail if we
78 # actually try to call the unknown function... Hard
79 # to test anything more.
80 pass
81
82 def test_missing_function_import_error():
83 # uses the original FFI that just gives a warning during compilation
84 import cffi
85 test_missing_function(ffi=cffi.FFI())
86
87 def test_simple_case():
88 ffi = FFI()
89 ffi.cdef("double sin(double x);")
90 lib = ffi.verify('#include <math.h>', libraries=lib_m)
91 assert lib.sin(1.23) == math.sin(1.23)
92
93 def _Wconversion(cdef, source, **kargs):
94 if sys.platform in ('win32', 'darwin'):
95 py.test.skip("needs GCC")
96 ffi = FFI()
97 ffi.cdef(cdef)
98 py.test.raises(VerificationError, ffi.verify, source, **kargs)
99 extra_compile_args_orig = extra_compile_args[:]
100 extra_compile_args.remove('-Wconversion')
101 try:
102 lib = ffi.verify(source, **kargs)
103 finally:
104 extra_compile_args[:] = extra_compile_args_orig
105 return lib
106
107 def test_Wconversion_unsigned():
108 _Wconversion("unsigned foo(void);",
109 "int foo(void) { return -1;}")
110
111 def test_Wconversion_integer():
112 _Wconversion("short foo(void);",
113 "long long foo(void) { return 1<<sizeof(short);}")
114
115 def test_Wconversion_floating():
116 lib = _Wconversion("float sin(double);",
117 "#include <math.h>", libraries=lib_m)
118 res = lib.sin(1.23)
119 assert res != math.sin(1.23) # not exact, because of double->float
120 assert abs(res - math.sin(1.23)) < 1E-5
121
122 def test_Wconversion_float2int():
123 _Wconversion("int sinf(float);",
124 "#include <math.h>", libraries=lib_m)
125
126 def test_Wconversion_double2int():
127 _Wconversion("int sin(double);",
128 "#include <math.h>", libraries=lib_m)
129
130 def test_rounding_1():
131 ffi = FFI()
132 ffi.cdef("double sinf(float x);")
133 lib = ffi.verify('#include <math.h>', libraries=lib_m)
134 res = lib.sinf(1.23)
135 assert res != math.sin(1.23) # not exact, because of double->float
136 assert abs(res - math.sin(1.23)) < 1E-5
137
138 def test_rounding_2():
139 ffi = FFI()
140 ffi.cdef("double sin(float x);")
141 lib = ffi.verify('#include <math.h>', libraries=lib_m)
142 res = lib.sin(1.23)
143 assert res != math.sin(1.23) # not exact, because of double->float
144 assert abs(res - math.sin(1.23)) < 1E-5
145
146 def test_strlen_exact():
147 ffi = FFI()
148 ffi.cdef("size_t strlen(const char *s);")
149 lib = ffi.verify("#include <string.h>")
150 assert lib.strlen(b"hi there!") == 9
151
152 def test_strlen_approximate():
153 lib = _Wconversion("int strlen(char *s);",
154 "#include <string.h>")
155 assert lib.strlen(b"hi there!") == 9
156
157 def test_return_approximate():
158 for typename in ['short', 'int', 'long', 'long long']:
159 ffi = FFI()
160 ffi.cdef("%s foo(signed char x);" % typename)
161 lib = ffi.verify("signed char foo(signed char x) { return x;}")
162 assert lib.foo(-128) == -128
163 assert lib.foo(+127) == +127
164
165 def test_strlen_array_of_char():
166 ffi = FFI()
167 ffi.cdef("size_t strlen(char[]);")
168 lib = ffi.verify("#include <string.h>")
169 assert lib.strlen(b"hello") == 5
170
171 def test_longdouble():
172 ffi = FFI()
173 ffi.cdef("long double sinl(long double x);")
174 lib = ffi.verify('#include <math.h>', libraries=lib_m)
175 for input in [1.23,
176 ffi.cast("double", 1.23),
177 ffi.cast("long double", 1.23)]:
178 x = lib.sinl(input)
179 assert repr(x).startswith("<cdata 'long double'")
180 assert (float(x) - math.sin(1.23)) < 1E-10
181
182 def test_longdouble_precision():
183 # Test that we don't loose any precision of 'long double' when
184 # passing through Python and CFFI.
185 ffi = FFI()
186 ffi.cdef("long double step1(long double x);")
187 SAME_SIZE = ffi.sizeof("long double") == ffi.sizeof("double")
188 lib = ffi.verify("""
189 long double step1(long double x)
190 {
191 return 4*x-x*x;
192 }
193 """)
194 def do(cast_to_double):
195 x = 0.9789
196 for i in range(10000):
197 x = lib.step1(x)
198 if cast_to_double:
199 x = float(x)
200 return float(x)
201
202 more_precise = do(False)
203 less_precise = do(True)
204 if SAME_SIZE:
205 assert more_precise == less_precise
206 else:
207 assert abs(more_precise - less_precise) > 0.1
208 # Check the particular results on Intel
209 import platform
210 if (platform.machine().startswith('i386') or
211 platform.machine().startswith('i486') or
212 platform.machine().startswith('i586') or
213 platform.machine().startswith('i686') or
214 platform.machine().startswith('x86')):
215 assert abs(more_precise - 0.656769) < 0.001
216 assert abs(less_precise - 3.99091) < 0.001
217 else:
218 py.test.skip("don't know the very exact precision of 'long double'")
219
220
221 all_primitive_types = model.PrimitiveType.ALL_PRIMITIVE_TYPES
222 if sys.platform == 'win32':
223 all_primitive_types = all_primitive_types.copy()
224 del all_primitive_types['ssize_t']
225 all_integer_types = sorted(tp for tp in all_primitive_types
226 if all_primitive_types[tp] == 'i')
227 all_float_types = sorted(tp for tp in all_primitive_types
228 if all_primitive_types[tp] == 'f')
229
230 def all_signed_integer_types(ffi):
231 return [x for x in all_integer_types if int(ffi.cast(x, -1)) < 0]
232
233 def all_unsigned_integer_types(ffi):
234 return [x for x in all_integer_types if int(ffi.cast(x, -1)) > 0]
235
236
237 def test_primitive_category():
238 for typename in all_primitive_types:
239 tp = model.PrimitiveType(typename)
240 C = tp.is_char_type()
241 F = tp.is_float_type()
242 X = tp.is_complex_type()
243 I = tp.is_integer_type()
244 assert C == (typename in ('char', 'wchar_t', 'char16_t', 'char32_t'))
245 assert F == (typename in ('float', 'double', 'long double'))
246 assert X == (typename in ('float _Complex', 'double _Complex'))
247 assert I + F + C + X == 1 # one and only one of them is true
248
249 def test_all_integer_and_float_types():
250 typenames = []
251 for typename in all_primitive_types:
252 if (all_primitive_types[typename] == 'c' or
253 all_primitive_types[typename] == 'j' or # complex
254 typename == '_Bool' or typename == 'long double'):
255 pass
256 else:
257 typenames.append(typename)
258 #
259 ffi = FFI()
260 ffi.cdef('\n'.join(["%s foo_%s(%s);" % (tp, tp.replace(' ', '_'), tp)
261 for tp in typenames]))
262 lib = ffi.verify('\n'.join(["%s foo_%s(%s x) { return (%s)(x+1); }" %
263 (tp, tp.replace(' ', '_'), tp, tp)
264 for tp in typenames]))
265 for typename in typenames:
266 foo = getattr(lib, 'foo_%s' % typename.replace(' ', '_'))
267 assert foo(42) == 43
268 if sys.version < '3':
269 assert foo(long(44)) == 45
270 assert foo(ffi.cast(typename, 46)) == 47
271 py.test.raises(TypeError, foo, ffi.NULL)
272 #
273 # check for overflow cases
274 if all_primitive_types[typename] == 'f':
275 continue
276 for value in [-2**80, -2**40, -2**20, -2**10, -2**5, -1,
277 2**5, 2**10, 2**20, 2**40, 2**80]:
278 overflows = int(ffi.cast(typename, value)) != value
279 if overflows:
280 py.test.raises(OverflowError, foo, value)
281 else:
282 assert foo(value) == value + 1
283
284 def test_var_signed_integer_types():
285 ffi = FFI()
286 lst = all_signed_integer_types(ffi)
287 csource = "\n".join(["%s somevar_%s;" % (tp, tp.replace(' ', '_'))
288 for tp in lst])
289 ffi.cdef(csource)
290 lib = ffi.verify(csource)
291 for tp in lst:
292 varname = 'somevar_%s' % tp.replace(' ', '_')
293 sz = ffi.sizeof(tp)
294 max = (1 << (8*sz-1)) - 1
295 min = -(1 << (8*sz-1))
296 setattr(lib, varname, max)
297 assert getattr(lib, varname) == max
298 setattr(lib, varname, min)
299 assert getattr(lib, varname) == min
300 py.test.raises(OverflowError, setattr, lib, varname, max+1)
301 py.test.raises(OverflowError, setattr, lib, varname, min-1)
302
303 def test_var_unsigned_integer_types():
304 ffi = FFI()
305 lst = all_unsigned_integer_types(ffi)
306 csource = "\n".join(["%s somevar_%s;" % (tp, tp.replace(' ', '_'))
307 for tp in lst])
308 ffi.cdef(csource)
309 lib = ffi.verify(csource)
310 for tp in lst:
311 varname = 'somevar_%s' % tp.replace(' ', '_')
312 sz = ffi.sizeof(tp)
313 if tp != '_Bool':
314 max = (1 << (8*sz)) - 1
315 else:
316 max = 1
317 setattr(lib, varname, max)
318 assert getattr(lib, varname) == max
319 setattr(lib, varname, 0)
320 assert getattr(lib, varname) == 0
321 py.test.raises(OverflowError, setattr, lib, varname, max+1)
322 py.test.raises(OverflowError, setattr, lib, varname, -1)
323
324 def test_fn_signed_integer_types():
325 ffi = FFI()
326 lst = all_signed_integer_types(ffi)
327 cdefsrc = "\n".join(["%s somefn_%s(%s);" % (tp, tp.replace(' ', '_'), tp)
328 for tp in lst])
329 ffi.cdef(cdefsrc)
330 verifysrc = "\n".join(["%s somefn_%s(%s x) { return x; }" %
331 (tp, tp.replace(' ', '_'), tp) for tp in lst])
332 lib = ffi.verify(verifysrc)
333 for tp in lst:
334 fnname = 'somefn_%s' % tp.replace(' ', '_')
335 sz = ffi.sizeof(tp)
336 max = (1 << (8*sz-1)) - 1
337 min = -(1 << (8*sz-1))
338 fn = getattr(lib, fnname)
339 assert fn(max) == max
340 assert fn(min) == min
341 py.test.raises(OverflowError, fn, max + 1)
342 py.test.raises(OverflowError, fn, min - 1)
343
344 def test_fn_unsigned_integer_types():
345 ffi = FFI()
346 lst = all_unsigned_integer_types(ffi)
347 cdefsrc = "\n".join(["%s somefn_%s(%s);" % (tp, tp.replace(' ', '_'), tp)
348 for tp in lst])
349 ffi.cdef(cdefsrc)
350 verifysrc = "\n".join(["%s somefn_%s(%s x) { return x; }" %
351 (tp, tp.replace(' ', '_'), tp) for tp in lst])
352 lib = ffi.verify(verifysrc)
353 for tp in lst:
354 fnname = 'somefn_%s' % tp.replace(' ', '_')
355 sz = ffi.sizeof(tp)
356 if tp != '_Bool':
357 max = (1 << (8*sz)) - 1
358 else:
359 max = 1
360 fn = getattr(lib, fnname)
361 assert fn(max) == max
362 assert fn(0) == 0
363 py.test.raises(OverflowError, fn, max + 1)
364 py.test.raises(OverflowError, fn, -1)
365
366 def test_char_type():
367 ffi = FFI()
368 ffi.cdef("char foo(char);")
369 lib = ffi.verify("char foo(char x) { return ++x; }")
370 assert lib.foo(b"A") == b"B"
371 py.test.raises(TypeError, lib.foo, b"bar")
372 py.test.raises(TypeError, lib.foo, "bar")
373
374 def test_wchar_type():
375 ffi = FFI()
376 if ffi.sizeof('wchar_t') == 2:
377 uniexample1 = u+'\u1234'
378 uniexample2 = u+'\u1235'
379 else:
380 uniexample1 = u+'\U00012345'
381 uniexample2 = u+'\U00012346'
382 #
383 ffi.cdef("wchar_t foo(wchar_t);")
384 lib = ffi.verify("wchar_t foo(wchar_t x) { return x+1; }")
385 assert lib.foo(uniexample1) == uniexample2
386
387 def test_char16_char32_type():
388 py.test.skip("XXX test or fully prevent char16_t and char32_t from "
389 "working in ffi.verify() mode")
390
391 def test_no_argument():
392 ffi = FFI()
393 ffi.cdef("int foo(void);")
394 lib = ffi.verify("int foo(void) { return 42; }")
395 assert lib.foo() == 42
396
397 def test_two_arguments():
398 ffi = FFI()
399 ffi.cdef("int foo(int, int);")
400 lib = ffi.verify("int foo(int a, int b) { return a - b; }")
401 assert lib.foo(40, -2) == 42
402
403 def test_macro():
404 ffi = FFI()
405 ffi.cdef("int foo(int, int);")
406 lib = ffi.verify("#define foo(a, b) ((a) * (b))")
407 assert lib.foo(-6, -7) == 42
408
409 def test_ptr():
410 ffi = FFI()
411 ffi.cdef("int *foo(int *);")
412 lib = ffi.verify("int *foo(int *a) { return a; }")
413 assert lib.foo(ffi.NULL) == ffi.NULL
414 p = ffi.new("int *", 42)
415 q = ffi.new("int *", 42)
416 assert lib.foo(p) == p
417 assert lib.foo(q) != p
418
419 def test_bogus_ptr():
420 ffi = FFI()
421 ffi.cdef("int *foo(int *);")
422 lib = ffi.verify("int *foo(int *a) { return a; }")
423 py.test.raises(TypeError, lib.foo, ffi.new("short *", 42))
424
425
426 def test_verify_typedefs():
427 py.test.skip("ignored so far")
428 types = ['signed char', 'unsigned char', 'int', 'long']
429 for cdefed in types:
430 for real in types:
431 ffi = FFI()
432 ffi.cdef("typedef %s foo_t;" % cdefed)
433 if cdefed == real:
434 ffi.verify("typedef %s foo_t;" % real)
435 else:
436 py.test.raises(VerificationError, ffi.verify,
437 "typedef %s foo_t;" % real)
438
439 def test_nondecl_struct():
440 ffi = FFI()
441 ffi.cdef("typedef struct foo_s foo_t; int bar(foo_t *);")
442 lib = ffi.verify("typedef struct foo_s foo_t;\n"
443 "int bar(foo_t *f) { (void)f; return 42; }\n")
444 assert lib.bar(ffi.NULL) == 42
445
446 def test_ffi_full_struct():
447 ffi = FFI()
448 ffi.cdef("struct foo_s { char x; int y; long *z; };")
449 ffi.verify("struct foo_s { char x; int y; long *z; };")
450 #
451 if sys.platform != 'win32': # XXX fixme: only gives warnings
452 py.test.raises(VerificationError, ffi.verify,
453 "struct foo_s { char x; int y; int *z; };")
454 #
455 py.test.raises(VerificationError, ffi.verify,
456 "struct foo_s { int y; long *z; };")
457 #
458 e = py.test.raises(VerificationError, ffi.verify,
459 "struct foo_s { int y; char x; long *z; };")
460 assert str(e.value) == (
461 "struct foo_s: wrong offset for field 'x'"
462 " (we have 0, but C compiler says 4)")
463 #
464 e = py.test.raises(VerificationError, ffi.verify,
465 "struct foo_s { char x; int y; long *z; char extra; };")
466 assert str(e.value) == (
467 "struct foo_s: wrong total size"
468 " (we have %d, but C compiler says %d)" % (
469 ffi.sizeof("struct foo_s"),
470 ffi.sizeof("struct foo_s") + ffi.sizeof("long*")))
471 #
472 # a corner case that we cannot really detect, but where it has no
473 # bad consequences: the size is the same, but there is an extra field
474 # that replaces what is just padding in our declaration above
475 ffi.verify("struct foo_s { char x, extra; int y; long *z; };")
476 #
477 e = py.test.raises(VerificationError, ffi.verify,
478 "struct foo_s { char x; short pad; short y; long *z; };")
479 assert str(e.value) == (
480 "struct foo_s: wrong size for field 'y'"
481 " (we have 4, but C compiler says 2)")
482
483 def test_ffi_nonfull_struct():
484 ffi = FFI()
485 ffi.cdef("""
486 struct foo_s {
487 int x;
488 ...;
489 };
490 """)
491 py.test.raises(VerificationMissing, ffi.sizeof, 'struct foo_s')
492 py.test.raises(VerificationMissing, ffi.offsetof, 'struct foo_s', 'x')
493 py.test.raises(VerificationMissing, ffi.new, 'struct foo_s *')
494 ffi.verify("""
495 struct foo_s {
496 int a, b, x, c, d, e;
497 };
498 """)
499 assert ffi.sizeof('struct foo_s') == 6 * ffi.sizeof('int')
500 assert ffi.offsetof('struct foo_s', 'x') == 2 * ffi.sizeof('int')
501
502 def test_ffi_nonfull_alignment():
503 ffi = FFI()
504 ffi.cdef("struct foo_s { char x; ...; };")
505 ffi.verify("struct foo_s { int a, b; char x; };")
506 assert ffi.sizeof('struct foo_s') == 3 * ffi.sizeof('int')
507 assert ffi.alignof('struct foo_s') == ffi.sizeof('int')
508
509 def _check_field_match(typename, real, expect_mismatch):
510 ffi = FFI()
511 testing_by_size = (expect_mismatch == 'by_size')
512 if testing_by_size:
513 expect_mismatch = ffi.sizeof(typename) != ffi.sizeof(real)
514 ffi.cdef("struct foo_s { %s x; ...; };" % typename)
515 try:
516 ffi.verify("struct foo_s { %s x; };" % real)
517 except VerificationError:
518 if not expect_mismatch:
519 if testing_by_size and typename != real:
520 print("ignoring mismatch between %s* and %s* even though "
521 "they have the same size" % (typename, real))
522 return
523 raise AssertionError("unexpected mismatch: %s should be accepted "
524 "as equal to %s" % (typename, real))
525 else:
526 if expect_mismatch:
527 raise AssertionError("mismatch not detected: "
528 "%s != %s" % (typename, real))
529
530 def test_struct_bad_sized_integer():
531 for typename in ['int8_t', 'int16_t', 'int32_t', 'int64_t']:
532 for real in ['int8_t', 'int16_t', 'int32_t', 'int64_t']:
533 _check_field_match(typename, real, "by_size")
534
535 def test_struct_bad_sized_float():
536 for typename in all_float_types:
537 for real in all_float_types:
538 _check_field_match(typename, real, "by_size")
539
540 def test_struct_signedness_ignored():
541 _check_field_match("int", "unsigned int", expect_mismatch=False)
542 _check_field_match("unsigned short", "signed short", expect_mismatch=False)
543
544 def test_struct_float_vs_int():
545 if sys.platform == 'win32':
546 py.test.skip("XXX fixme: only gives warnings")
547 ffi = FFI()
548 for typename in all_signed_integer_types(ffi):
549 for real in all_float_types:
550 _check_field_match(typename, real, expect_mismatch=True)
551 for typename in all_float_types:
552 for real in all_signed_integer_types(ffi):
553 _check_field_match(typename, real, expect_mismatch=True)
554
555 def test_struct_array_field():
556 ffi = FFI()
557 ffi.cdef("struct foo_s { int a[17]; ...; };")
558 ffi.verify("struct foo_s { int x; int a[17]; int y; };")
559 assert ffi.sizeof('struct foo_s') == 19 * ffi.sizeof('int')
560 s = ffi.new("struct foo_s *")
561 assert ffi.sizeof(s.a) == 17 * ffi.sizeof('int')
562
563 def test_struct_array_no_length():
564 ffi = FFI()
565 ffi.cdef("struct foo_s { int a[]; int y; ...; };\n"
566 "int bar(struct foo_s *);\n")
567 lib = ffi.verify("struct foo_s { int x; int a[17]; int y; };\n"
568 "int bar(struct foo_s *f) { return f->a[14]; }\n")
569 assert ffi.sizeof('struct foo_s') == 19 * ffi.sizeof('int')
570 s = ffi.new("struct foo_s *")
571 assert ffi.typeof(s.a) is ffi.typeof('int[]') # implicit max length
572 assert len(s.a) == 18 # max length, computed from the size and start offset
573 s.a[14] = 4242
574 assert lib.bar(s) == 4242
575 # with no declared length, out-of-bound accesses are not detected
576 s.a[17] = -521
577 assert s.y == s.a[17] == -521
578 #
579 s = ffi.new("struct foo_s *", {'a': list(range(17))})
580 assert s.a[16] == 16
581 # overflows at construction time not detected either
582 s = ffi.new("struct foo_s *", {'a': list(range(18))})
583 assert s.y == s.a[17] == 17
584
585 def test_struct_array_guess_length():
586 ffi = FFI()
587 ffi.cdef("struct foo_s { int a[...]; };")
588 ffi.verify("struct foo_s { int x; int a[17]; int y; };")
589 assert ffi.sizeof('struct foo_s') == 19 * ffi.sizeof('int')
590 s = ffi.new("struct foo_s *")
591 assert ffi.sizeof(s.a) == 17 * ffi.sizeof('int')
592 py.test.raises(IndexError, 's.a[17]')
593
594 def test_struct_array_c99_1():
595 if sys.platform == 'win32':
596 py.test.skip("requires C99")
597 ffi = FFI()
598 ffi.cdef("struct foo_s { int x; int a[]; };")
599 ffi.verify("struct foo_s { int x; int a[]; };")
600 assert ffi.sizeof('struct foo_s') == 1 * ffi.sizeof('int')
601 s = ffi.new("struct foo_s *", [424242, 4])
602 assert ffi.sizeof(ffi.typeof(s[0])) == 1 * ffi.sizeof('int')
603 assert ffi.sizeof(s[0]) == 5 * ffi.sizeof('int')
604 # ^^^ explanation: if you write in C: "char x[5];", then
605 # "sizeof(x)" will evaluate to 5. The behavior above is
606 # a generalization of that to "struct foo_s[len(a)=5] x;"
607 # if you could do that in C.
608 assert s.a[3] == 0
609 s = ffi.new("struct foo_s *", [424242, [-40, -30, -20, -10]])
610 assert ffi.sizeof(s[0]) == 5 * ffi.sizeof('int')
611 assert s.a[3] == -10
612 s = ffi.new("struct foo_s *")
613 assert ffi.sizeof(s[0]) == 1 * ffi.sizeof('int')
614 s = ffi.new("struct foo_s *", [424242])
615 assert ffi.sizeof(s[0]) == 1 * ffi.sizeof('int')
616
617 def test_struct_array_c99_2():
618 if sys.platform == 'win32':
619 py.test.skip("requires C99")
620 ffi = FFI()
621 ffi.cdef("struct foo_s { int x; int a[]; ...; };")
622 ffi.verify("struct foo_s { int x, y; int a[]; };")
623 assert ffi.sizeof('struct foo_s') == 2 * ffi.sizeof('int')
624 s = ffi.new("struct foo_s *", [424242, 4])
625 assert ffi.sizeof(s[0]) == 6 * ffi.sizeof('int')
626 assert s.a[3] == 0
627 s = ffi.new("struct foo_s *", [424242, [-40, -30, -20, -10]])
628 assert ffi.sizeof(s[0]) == 6 * ffi.sizeof('int')
629 assert s.a[3] == -10
630 s = ffi.new("struct foo_s *")
631 assert ffi.sizeof(s[0]) == 2 * ffi.sizeof('int')
632 s = ffi.new("struct foo_s *", [424242])
633 assert ffi.sizeof(s[0]) == 2 * ffi.sizeof('int')
634
635 def test_struct_ptr_to_array_field():
636 ffi = FFI()
637 ffi.cdef("struct foo_s { int (*a)[17]; ...; }; struct bar_s { ...; };")
638 ffi.verify("struct foo_s { int x; int (*a)[17]; int y; };\n"
639 "struct bar_s { int x; int *a; int y; };")
640 assert ffi.sizeof('struct foo_s') == ffi.sizeof("struct bar_s")
641 s = ffi.new("struct foo_s *")
642 assert ffi.sizeof(s.a) == ffi.sizeof('int(*)[17]') == ffi.sizeof("int *")
643
644 def test_struct_with_bitfield_exact():
645 ffi = FFI()
646 ffi.cdef("struct foo_s { int a:2, b:3; };")
647 ffi.verify("struct foo_s { int a:2, b:3; };")
648 s = ffi.new("struct foo_s *")
649 s.b = 3
650 py.test.raises(OverflowError, "s.b = 4")
651 assert s.b == 3
652
653 def test_struct_with_bitfield_enum():
654 ffi = FFI()
655 code = """
656 typedef enum { AA, BB, CC } foo_e;
657 typedef struct { foo_e f:2; } foo_s;
658 """
659 ffi.cdef(code)
660 ffi.verify(code)
661 s = ffi.new("foo_s *")
662 s.f = 2
663 assert s.f == 2
664
665 def test_unsupported_struct_with_bitfield_ellipsis():
666 ffi = FFI()
667 py.test.raises(NotImplementedError, ffi.cdef,
668 "struct foo_s { int a:2, b:3; ...; };")
669
670 def test_global_constants():
671 ffi = FFI()
672 # use 'static const int', as generally documented, although in this
673 # case the 'static' is completely ignored.
674 ffi.cdef("static const int AA, BB, CC, DD;")
675 lib = ffi.verify("#define AA 42\n"
676 "#define BB (-43) // blah\n"
677 "#define CC (22*2) /* foobar */\n"
678 "#define DD ((unsigned int)142) /* foo\nbar */\n")
679 assert lib.AA == 42
680 assert lib.BB == -43
681 assert lib.CC == 44
682 assert lib.DD == 142
683
684 def test_global_const_int_size():
685 # integer constants: ignore the declared type, always just use the value
686 for value in [-2**63, -2**31, -2**15,
687 2**15-1, 2**15, 2**31-1, 2**31, 2**32-1, 2**32,
688 2**63-1, 2**63, 2**64-1]:
689 ffi = FFI()
690 if value == int(ffi.cast("long long", value)):
691 if value < 0:
692 vstr = '(-%dLL-1)' % (~value,)
693 else:
694 vstr = '%dLL' % value
695 elif value == int(ffi.cast("unsigned long long", value)):
696 vstr = '%dULL' % value
697 else:
698 raise AssertionError(value)
699 ffi.cdef("static const unsigned short AA;")
700 lib = ffi.verify("#define AA %s\n" % vstr)
701 assert lib.AA == value
702 assert type(lib.AA) is type(int(lib.AA))
703
704 def test_global_constants_non_int():
705 ffi = FFI()
706 ffi.cdef("static char *const PP;")
707 lib = ffi.verify('static char *const PP = "testing!";\n')
708 assert ffi.typeof(lib.PP) == ffi.typeof("char *")
709 assert ffi.string(lib.PP) == b"testing!"
710
711 def test_nonfull_enum():
712 ffi = FFI()
713 ffi.cdef("enum ee { EE1, EE2, EE3, ... \n \t };")
714 py.test.raises(VerificationMissing, ffi.cast, 'enum ee', 'EE2')
715 ffi.verify("enum ee { EE1=10, EE2, EE3=-10, EE4 };")
716 assert ffi.string(ffi.cast('enum ee', 11)) == "EE2"
717 assert ffi.string(ffi.cast('enum ee', -10)) == "EE3"
718 #
719 # try again
720 ffi.verify("enum ee { EE1=10, EE2, EE3=-10, EE4 };")
721 assert ffi.string(ffi.cast('enum ee', 11)) == "EE2"
722 #
723 assert ffi.typeof("enum ee").relements == {'EE1': 10, 'EE2': 11, 'EE3': -10}
724 assert ffi.typeof("enum ee").elements == {10: 'EE1', 11: 'EE2', -10: 'EE3'}
725
726 def test_full_enum():
727 ffi = FFI()
728 ffi.cdef("enum ee { EE1, EE2, EE3 };")
729 ffi.verify("enum ee { EE1, EE2, EE3 };")
730 py.test.raises(VerificationError, ffi.verify, "enum ee { EE1, EE2 };")
731 e = py.test.raises(VerificationError, ffi.verify,
732 "enum ee { EE1, EE3, EE2 };")
733 assert str(e.value) == 'enum ee: EE2 has the real value 2, not 1'
734 # extra items cannot be seen and have no bad consequence anyway
735 lib = ffi.verify("enum ee { EE1, EE2, EE3, EE4 };")
736 assert lib.EE3 == 2
737
738 def test_enum_usage():
739 ffi = FFI()
740 ffi.cdef("enum ee { EE1,EE2 }; typedef struct { enum ee x; } *sp;")
741 lib = ffi.verify("enum ee { EE1,EE2 }; typedef struct { enum ee x; } *sp;")
742 assert lib.EE2 == 1
743 s = ffi.new("sp", [lib.EE2])
744 assert s.x == 1
745 s.x = 17
746 assert s.x == 17
747
748 def test_anonymous_enum():
749 ffi = FFI()
750 ffi.cdef("enum { EE1 }; enum { EE2, EE3 };")
751 lib = ffi.verify("enum { EE1 }; enum { EE2, EE3 };")
752 assert lib.EE1 == 0
753 assert lib.EE2 == 0
754 assert lib.EE3 == 1
755
756 def test_nonfull_anonymous_enum():
757 ffi = FFI()
758 ffi.cdef("enum { EE1, ... }; enum { EE3, ... };")
759 lib = ffi.verify("enum { EE2, EE1 }; enum { EE3 };")
760 assert lib.EE1 == 1
761 assert lib.EE3 == 0
762
763 def test_nonfull_enum_syntax2():
764 ffi = FFI()
765 ffi.cdef("enum ee { EE1, EE2=\t..., EE3 };")
766 py.test.raises(VerificationMissing, ffi.cast, 'enum ee', 'EE1')
767 ffi.verify("enum ee { EE1=10, EE2, EE3=-10, EE4 };")
768 assert ffi.string(ffi.cast('enum ee', 11)) == 'EE2'
769 assert ffi.string(ffi.cast('enum ee', -10)) == 'EE3'
770 #
771 ffi = FFI()
772 ffi.cdef("enum ee { EE1, EE2=\t... };")
773 py.test.raises(VerificationMissing, ffi.cast, 'enum ee', 'EE1')
774 ffi.verify("enum ee { EE1=10, EE2, EE3=-10, EE4 };")
775 assert ffi.string(ffi.cast('enum ee', 11)) == 'EE2'
776 #
777 ffi = FFI()
778 ffi.cdef("enum ee2 { EE4=..., EE5=..., ... };")
779 ffi.verify("enum ee2 { EE4=-1234-5, EE5 }; ")
780 assert ffi.string(ffi.cast('enum ee2', -1239)) == 'EE4'
781 assert ffi.string(ffi.cast('enum ee2', -1238)) == 'EE5'
782
783 def test_nonfull_enum_bug3():
784 ffi = FFI()
785 ffi.cdef("enum ee2 { EE4=..., EE5=... };")
786 ffi.cdef("enum ee6 { EE7=10, EE8=..., EE9=... };")
787
788 def test_get_set_errno():
789 ffi = FFI()
790 ffi.cdef("int foo(int);")
791 lib = ffi.verify("""
792 static int foo(int x)
793 {
794 errno += 1;
795 return x * 7;
796 }
797 """)
798 ffi.errno = 15
799 assert lib.foo(6) == 42
800 assert ffi.errno == 16
801
802 def test_define_int():
803 ffi = FFI()
804 ffi.cdef("#define FOO ...\n"
805 "\t#\tdefine\tBAR\t...\t\n"
806 "#define BAZ ...\n")
807 lib = ffi.verify("#define FOO 42\n"
808 "#define BAR (-44)\n"
809 "#define BAZ 0xffffffffffffffffULL\n")
810 assert lib.FOO == 42
811 assert lib.BAR == -44
812 assert lib.BAZ == 0xffffffffffffffff
813
814 def test_access_variable():
815 ffi = FFI()
816 ffi.cdef("int foo(void);\n"
817 "int somenumber;")
818 lib = ffi.verify("""
819 static int somenumber = 2;
820 static int foo(void) {
821 return somenumber * 7;
822 }
823 """)
824 assert lib.somenumber == 2
825 assert lib.foo() == 14
826 lib.somenumber = -6
827 assert lib.foo() == -42
828 assert lib.somenumber == -6
829 lib.somenumber = 2 # reset for the next run, if any
830
831 def test_access_address_of_variable():
832 # access the address of 'somenumber': need a trick
833 ffi = FFI()
834 ffi.cdef("int somenumber; static int *const somenumberptr;")
835 lib = ffi.verify("""
836 static int somenumber = 2;
837 #define somenumberptr (&somenumber)
838 """)
839 assert lib.somenumber == 2
840 lib.somenumberptr[0] = 42
841 assert lib.somenumber == 42
842 lib.somenumber = 2 # reset for the next run, if any
843
844 def test_access_array_variable(length=5):
845 ffi = FFI()
846 ffi.cdef("int foo(int);\n"
847 "int somenumber[%s];" % (length,))
848 lib = ffi.verify("""
849 static int somenumber[] = {2, 2, 3, 4, 5};
850 static int foo(int i) {
851 return somenumber[i] * 7;
852 }
853 """)
854 if length == '':
855 # a global variable of an unknown array length is implicitly
856 # transformed into a global pointer variable, because we can only
857 # work with array instances whose length we know. using a pointer
858 # instead of an array gives the correct effects.
859 assert repr(lib.somenumber).startswith("<cdata 'int *' 0x")
860 py.test.raises(TypeError, len, lib.somenumber)
861 else:
862 assert repr(lib.somenumber).startswith("<cdata 'int[%s]' 0x" % length)
863 assert len(lib.somenumber) == 5
864 assert lib.somenumber[3] == 4
865 assert lib.foo(3) == 28
866 lib.somenumber[3] = -6
867 assert lib.foo(3) == -42
868 assert lib.somenumber[3] == -6
869 assert lib.somenumber[4] == 5
870 lib.somenumber[3] = 4 # reset for the next run, if any
871
872 def test_access_array_variable_length_hidden():
873 test_access_array_variable(length='')
874
875 def test_access_struct_variable():
876 ffi = FFI()
877 ffi.cdef("struct foo { int x; ...; };\n"
878 "int foo(int);\n"
879 "struct foo stuff;")
880 lib = ffi.verify("""
881 struct foo { int x, y, z; };
882 static struct foo stuff = {2, 5, 8};
883 static int foo(int i) {
884 switch (i) {
885 case 0: return stuff.x * 7;
886 case 1: return stuff.y * 7;
887 case 2: return stuff.z * 7;
888 }
889 return -1;
890 }
891 """)
892 assert lib.stuff.x == 2
893 assert lib.foo(0) == 14
894 assert lib.foo(1) == 35
895 assert lib.foo(2) == 56
896 lib.stuff.x = -6
897 assert lib.foo(0) == -42
898 assert lib.foo(1) == 35
899 lib.stuff.x = 2 # reset for the next run, if any
900
901 def test_access_callback():
902 ffi = FFI()
903 ffi.cdef("int (*cb)(int);\n"
904 "int foo(int);\n"
905 "void reset_cb(void);")
906 lib = ffi.verify("""
907 static int g(int x) { return x * 7; }
908 static int (*cb)(int);
909 static int foo(int i) { return cb(i) - 1; }
910 static void reset_cb(void) { cb = g; }
911 """)
912 lib.reset_cb()
913 assert lib.foo(6) == 41
914 my_callback = ffi.callback("int(*)(int)", lambda n: n * 222)
915 lib.cb = my_callback
916 assert lib.foo(4) == 887
917
918 def test_access_callback_function_typedef():
919 ffi = FFI()
920 ffi.cdef("typedef int mycallback_t(int);\n"
921 "mycallback_t *cb;\n"
922 "int foo(int);\n"
923 "void reset_cb(void);")
924 lib = ffi.verify("""
925 static int g(int x) { return x * 7; }
926 static int (*cb)(int);
927 static int foo(int i) { return cb(i) - 1; }
928 static void reset_cb(void) { cb = g; }
929 """)
930 lib.reset_cb()
931 assert lib.foo(6) == 41
932 my_callback = ffi.callback("int(*)(int)", lambda n: n * 222)
933 lib.cb = my_callback
934 assert lib.foo(4) == 887
935
936 def test_ctypes_backend_forces_generic_engine():
937 from cffi.backend_ctypes import CTypesBackend
938 ffi = FFI(backend=CTypesBackend())
939 ffi.cdef("int func(int a);")
940 lib = ffi.verify("int func(int a) { return a * 42; }")
941 assert not hasattr(lib, '_cffi_python_module')
942 assert hasattr(lib, '_cffi_generic_module')
943 assert lib.func(100) == 4200
944
945 def test_call_with_struct_ptr():
946 ffi = FFI()
947 ffi.cdef("typedef struct { int x; ...; } foo_t; int foo(foo_t *);")
948 lib = ffi.verify("""
949 typedef struct { int y, x; } foo_t;
950 static int foo(foo_t *f) { return f->x * 7; }
951 """)
952 f = ffi.new("foo_t *")
953 f.x = 6
954 assert lib.foo(f) == 42
955
956 def test_unknown_type():
957 ffi = FFI()
958 ffi.cdef("""
959 typedef ... token_t;
960 int foo(token_t *);
961 #define TOKEN_SIZE ...
962 """)
963 lib = ffi.verify("""
964 typedef float token_t;
965 static int foo(token_t *tk) {
966 if (!tk)
967 return -42;
968 *tk += 1.601f;
969 return (int)*tk;
970 }
971 #define TOKEN_SIZE sizeof(token_t)
972 """)
973 # we cannot let ffi.new("token_t *") work, because we don't know ahead of
974 # time if it's ok to ask 'sizeof(token_t)' in the C code or not.
975 # See test_unknown_type_2. Workaround.
976 tkmem = ffi.new("char[]", lib.TOKEN_SIZE) # zero-initialized
977 tk = ffi.cast("token_t *", tkmem)
978 results = [lib.foo(tk) for i in range(6)]
979 assert results == [1, 3, 4, 6, 8, 9]
980 assert lib.foo(ffi.NULL) == -42
981
982 def test_unknown_type_2():
983 ffi = FFI()
984 ffi.cdef("typedef ... token_t;")
985 lib = ffi.verify("typedef struct token_s token_t;")
986 # assert did not crash, even though 'sizeof(token_t)' is not valid in C.
987
988 def test_unknown_type_3():
989 ffi = FFI()
990 ffi.cdef("""
991 typedef ... *token_p;
992 token_p foo(token_p);
993 """)
994 lib = ffi.verify("""
995 typedef struct _token_s *token_p;
996 token_p foo(token_p arg) {
997 if (arg)
998 return (token_p)0x12347;
999 else
1000 return (token_p)0x12345;
1001 }
1002 """)
1003 p = lib.foo(ffi.NULL)
1004 assert int(ffi.cast("intptr_t", p)) == 0x12345
1005 q = lib.foo(p)
1006 assert int(ffi.cast("intptr_t", q)) == 0x12347
1007
1008 def test_varargs():
1009 ffi = FFI()
1010 ffi.cdef("int foo(int x, ...);")
1011 lib = ffi.verify("""
1012 int foo(int x, ...) {
1013 va_list vargs;
1014 va_start(vargs, x);
1015 x -= va_arg(vargs, int);
1016 x -= va_arg(vargs, int);
1017 va_end(vargs);
1018 return x;
1019 }
1020 """)
1021 assert lib.foo(50, ffi.cast("int", 5), ffi.cast("int", 3)) == 42
1022
1023 def test_varargs_exact():
1024 if sys.platform == 'win32':
1025 py.test.skip("XXX fixme: only gives warnings")
1026 ffi = FFI()
1027 ffi.cdef("int foo(int x, ...);")
1028 py.test.raises(VerificationError, ffi.verify, """
1029 int foo(long long x, ...) {
1030 return x;
1031 }
1032 """)
1033
1034 def test_varargs_struct():
1035 ffi = FFI()
1036 ffi.cdef("struct foo_s { char a; int b; }; int foo(int x, ...);")
1037 lib = ffi.verify("""
1038 struct foo_s {
1039 char a; int b;
1040 };
1041 int foo(int x, ...) {
1042 va_list vargs;
1043 struct foo_s s;
1044 va_start(vargs, x);
1045 s = va_arg(vargs, struct foo_s);
1046 va_end(vargs);
1047 return s.a - s.b;
1048 }
1049 """)
1050 s = ffi.new("struct foo_s *", [b'B', 1])
1051 assert lib.foo(50, s[0]) == ord('A')
1052
1053 def test_autofilled_struct_as_argument():
1054 ffi = FFI()
1055 ffi.cdef("struct foo_s { long a; double b; ...; };\n"
1056 "int foo(struct foo_s);")
1057 lib = ffi.verify("""
1058 struct foo_s {
1059 double b;
1060 long a;
1061 };
1062 int foo(struct foo_s s) {
1063 return (int)s.a - (int)s.b;
1064 }
1065 """)
1066 s = ffi.new("struct foo_s *", [100, 1])
1067 assert lib.foo(s[0]) == 99
1068 assert lib.foo([100, 1]) == 99
1069
1070 def test_autofilled_struct_as_argument_dynamic():
1071 ffi = FFI()
1072 ffi.cdef("struct foo_s { long a; ...; };\n"
1073 "int (*foo)(struct foo_s);")
1074 lib = ffi.verify("""
1075 struct foo_s {
1076 double b;
1077 long a;
1078 };
1079 int foo1(struct foo_s s) {
1080 return (int)s.a - (int)s.b;
1081 }
1082 int (*foo)(struct foo_s s) = &foo1;
1083 """)
1084 e = py.test.raises(NotImplementedError, lib.foo, "?")
1085 msg = ("ctype 'struct foo_s' not supported as argument. It is a struct "
1086 'declared with "...;", but the C calling convention may depend on '
1087 "the missing fields; or, it contains anonymous struct/unions. "
1088 "Such structs are only supported as argument "
1089 "if the function is 'API mode' and non-variadic (i.e. declared "
1090 "inside ffibuilder.cdef()+ffibuilder.set_source() and not taking "
1091 "a final '...' argument)")
1092 assert str(e.value) == msg
1093
1094 def test_func_returns_struct():
1095 ffi = FFI()
1096 ffi.cdef("""
1097 struct foo_s { int aa, bb; };
1098 struct foo_s foo(int a, int b);
1099 """)
1100 lib = ffi.verify("""
1101 struct foo_s { int aa, bb; };
1102 struct foo_s foo(int a, int b) {
1103 struct foo_s r;
1104 r.aa = a*a;
1105 r.bb = b*b;
1106 return r;
1107 }
1108 """)
1109 s = lib.foo(6, 7)
1110 assert repr(s) == "<cdata 'struct foo_s' owning 8 bytes>"
1111 assert s.aa == 36
1112 assert s.bb == 49
1113
1114 def test_func_as_funcptr():
1115 ffi = FFI()
1116 ffi.cdef("int *(*const fooptr)(void);")
1117 lib = ffi.verify("""
1118 int *foo(void) {
1119 return (int*)"foobar";
1120 }
1121 int *(*fooptr)(void) = foo;
1122 """)
1123 foochar = ffi.cast("char *(*)(void)", lib.fooptr)
1124 s = foochar()
1125 assert ffi.string(s) == b"foobar"
1126
1127 def test_funcptr_as_argument():
1128 ffi = FFI()
1129 ffi.cdef("""
1130 void qsort(void *base, size_t nel, size_t width,
1131 int (*compar)(const void *, const void *));
1132 """)
1133 ffi.verify("#include <stdlib.h>")
1134
1135 def test_func_as_argument():
1136 ffi = FFI()
1137 ffi.cdef("""
1138 void qsort(void *base, size_t nel, size_t width,
1139 int compar(const void *, const void *));
1140 """)
1141 ffi.verify("#include <stdlib.h>")
1142
1143 def test_array_as_argument():
1144 ffi = FFI()
1145 ffi.cdef("""
1146 size_t strlen(char string[]);
1147 """)
1148 ffi.verify("#include <string.h>")
1149
1150 def test_enum_as_argument():
1151 ffi = FFI()
1152 ffi.cdef("""
1153 enum foo_e { AA, BB, ... };
1154 int foo_func(enum foo_e);
1155 """)
1156 lib = ffi.verify("""
1157 enum foo_e { AA, CC, BB };
1158 int foo_func(enum foo_e e) { return (int)e; }
1159 """)
1160 assert lib.foo_func(lib.BB) == 2
1161 py.test.raises(TypeError, lib.foo_func, "BB")
1162
1163 def test_enum_as_function_result():
1164 ffi = FFI()
1165 ffi.cdef("""
1166 enum foo_e { AA, BB, ... };
1167 enum foo_e foo_func(int x);
1168 """)
1169 lib = ffi.verify("""
1170 enum foo_e { AA, CC, BB };
1171 enum foo_e foo_func(int x) { return (enum foo_e)x; }
1172 """)
1173 assert lib.foo_func(lib.BB) == lib.BB == 2
1174
1175 def test_enum_values():
1176 ffi = FFI()
1177 ffi.cdef("enum enum1_e { AA, BB };")
1178 lib = ffi.verify("enum enum1_e { AA, BB };")
1179 assert lib.AA == 0
1180 assert lib.BB == 1
1181 assert ffi.string(ffi.cast("enum enum1_e", 1)) == 'BB'
1182
1183 def test_typedef_complete_enum():
1184 ffi = FFI()
1185 ffi.cdef("typedef enum { AA, BB } enum1_t;")
1186 lib = ffi.verify("typedef enum { AA, BB } enum1_t;")
1187 assert ffi.string(ffi.cast("enum1_t", 1)) == 'BB'
1188 assert lib.AA == 0
1189 assert lib.BB == 1
1190
1191 def test_typedef_broken_complete_enum():
1192 ffi = FFI()
1193 ffi.cdef("typedef enum { AA, BB } enum1_t;")
1194 py.test.raises(VerificationError, ffi.verify,
1195 "typedef enum { AA, CC, BB } enum1_t;")
1196
1197 def test_typedef_incomplete_enum():
1198 ffi = FFI()
1199 ffi.cdef("typedef enum { AA, BB, ... } enum1_t;")
1200 lib = ffi.verify("typedef enum { AA, CC, BB } enum1_t;")
1201 assert ffi.string(ffi.cast("enum1_t", 1)) == '1'
1202 assert ffi.string(ffi.cast("enum1_t", 2)) == 'BB'
1203 assert lib.AA == 0
1204 assert lib.BB == 2
1205
1206 def test_typedef_enum_as_argument():
1207 ffi = FFI()
1208 ffi.cdef("""
1209 typedef enum { AA, BB, ... } foo_t;
1210 int foo_func(foo_t);
1211 """)
1212 lib = ffi.verify("""
1213 typedef enum { AA, CC, BB } foo_t;
1214 int foo_func(foo_t e) { return (int)e; }
1215 """)
1216 assert lib.foo_func(lib.BB) == lib.BB == 2
1217 py.test.raises(TypeError, lib.foo_func, "BB")
1218
1219 def test_typedef_enum_as_function_result():
1220 ffi = FFI()
1221 ffi.cdef("""
1222 typedef enum { AA, BB, ... } foo_t;
1223 foo_t foo_func(int x);
1224 """)
1225 lib = ffi.verify("""
1226 typedef enum { AA, CC, BB } foo_t;
1227 foo_t foo_func(int x) { return (foo_t)x; }
1228 """)
1229 assert lib.foo_func(lib.BB) == lib.BB == 2
1230
1231 def test_function_typedef():
1232 ffi = FFI()
1233 ffi.cdef("""
1234 typedef double func_t(double);
1235 func_t sin;
1236 """)
1237 lib = ffi.verify('#include <math.h>', libraries=lib_m)
1238 assert lib.sin(1.23) == math.sin(1.23)
1239
1240 def test_opaque_integer_as_function_result():
1241 #import platform
1242 #if platform.machine().startswith('sparc'):
1243 # py.test.skip('Breaks horribly on sparc (SIGILL + corrupted stack)')
1244 #elif platform.machine() == 'mips64' and sys.maxsize > 2**32:
1245 # py.test.skip('Segfaults on mips64el')
1246 # XXX bad abuse of "struct { ...; }". It only works a bit by chance
1247 # anyway. XXX think about something better :-(
1248 ffi = FFI()
1249 ffi.cdef("""
1250 typedef struct { ...; } myhandle_t;
1251 myhandle_t foo(void);
1252 """)
1253 lib = ffi.verify("""
1254 typedef short myhandle_t;
1255 myhandle_t foo(void) { return 42; }
1256 """)
1257 h = lib.foo()
1258 assert ffi.sizeof(h) == ffi.sizeof("short")
1259
1260 def test_return_partial_struct():
1261 ffi = FFI()
1262 ffi.cdef("""
1263 typedef struct { int x; ...; } foo_t;
1264 foo_t foo(void);
1265 """)
1266 lib = ffi.verify("""
1267 typedef struct { int y, x; } foo_t;
1268 foo_t foo(void) { foo_t r = { 45, 81 }; return r; }
1269 """)
1270 h = lib.foo()
1271 assert ffi.sizeof(h) == 2 * ffi.sizeof("int")
1272 assert h.x == 81
1273
1274 def test_take_and_return_partial_structs():
1275 ffi = FFI()
1276 ffi.cdef("""
1277 typedef struct { int x; ...; } foo_t;
1278 foo_t foo(foo_t, foo_t);
1279 """)
1280 lib = ffi.verify("""
1281 typedef struct { int y, x; } foo_t;
1282 foo_t foo(foo_t a, foo_t b) {
1283 foo_t r = { 100, a.x * 5 + b.x * 7 };
1284 return r;
1285 }
1286 """)
1287 args = ffi.new("foo_t[3]")
1288 args[0].x = 1000
1289 args[2].x = -498
1290 h = lib.foo(args[0], args[2])
1291 assert ffi.sizeof(h) == 2 * ffi.sizeof("int")
1292 assert h.x == 1000 * 5 - 498 * 7
1293
1294 def test_cannot_name_struct_type():
1295 ffi = FFI()
1296 ffi.cdef("typedef struct { int x; } **sp; void foo(sp);")
1297 e = py.test.raises(VerificationError, ffi.verify,
1298 "typedef struct { int x; } **sp; void foo(sp x) { }")
1299 assert 'in argument of foo: unknown type name' in str(e.value)
1300
1301 def test_dont_check_unnamable_fields():
1302 ffi = FFI()
1303 ffi.cdef("struct foo_s { struct { int x; } someone; };")
1304 ffi.verify("struct foo_s { struct { int x; } someone; };")
1305 # assert did not crash
1306
1307 def test_nested_anonymous_struct_exact():
1308 if sys.platform == 'win32':
1309 py.test.skip("nested anonymous struct/union")
1310 ffi = FFI()
1311 ffi.cdef("""
1312 struct foo_s { struct { int a; char b; }; union { char c, d; }; };
1313 """)
1314 ffi.verify("""
1315 struct foo_s { struct { int a; char b; }; union { char c, d; }; };
1316 """)
1317 p = ffi.new("struct foo_s *")
1318 assert ffi.sizeof(p[0]) == 3 * ffi.sizeof("int") # with alignment
1319 p.a = 1234567
1320 p.b = b'X'
1321 p.c = b'Y'
1322 assert p.a == 1234567
1323 assert p.b == b'X'
1324 assert p.c == b'Y'
1325 assert p.d == b'Y'
1326
1327 def test_nested_anonymous_struct_exact_error():
1328 if sys.platform == 'win32':
1329 py.test.skip("nested anonymous struct/union")
1330 ffi = FFI()
1331 ffi.cdef("""
1332 struct foo_s { struct { int a; char b; }; union { char c, d; }; };
1333 """)
1334 py.test.raises(VerificationError, ffi.verify, """
1335 struct foo_s { struct { int a; short b; }; union { char c, d; }; };
1336 """)
1337 py.test.raises(VerificationError, ffi.verify, """
1338 struct foo_s { struct { int a; char e, b; }; union { char c, d; }; };
1339 """)
1340
1341 def test_nested_anonymous_struct_inexact_1():
1342 ffi = FFI()
1343 ffi.cdef("""
1344 struct foo_s { struct { char b; ...; }; union { char c, d; }; };
1345 """)
1346 ffi.verify("""
1347 struct foo_s { int a, padding; char c, d, b; };
1348 """)
1349 assert ffi.sizeof("struct foo_s") == 3 * ffi.sizeof("int")
1350
1351 def test_nested_anonymous_struct_inexact_2():
1352 ffi = FFI()
1353 ffi.cdef("""
1354 struct foo_s { union { char c, d; }; struct { int a; char b; }; ...; };
1355 """)
1356 ffi.verify("""
1357 struct foo_s { int a, padding; char c, d, b; };
1358 """)
1359 assert ffi.sizeof("struct foo_s") == 3 * ffi.sizeof("int")
1360
1361 def test_ffi_union():
1362 ffi = FFI()
1363 ffi.cdef("union foo_u { char x; long *z; };")
1364 ffi.verify("union foo_u { char x; int y; long *z; };")
1365
1366 def test_ffi_union_partial():
1367 ffi = FFI()
1368 ffi.cdef("union foo_u { char x; ...; };")
1369 ffi.verify("union foo_u { char x; int y; };")
1370 assert ffi.sizeof("union foo_u") == 4
1371
1372 def test_ffi_union_with_partial_struct():
1373 ffi = FFI()
1374 ffi.cdef("struct foo_s { int x; ...; }; union foo_u { struct foo_s s; };")
1375 ffi.verify("struct foo_s { int a; int x; }; "
1376 "union foo_u { char b[32]; struct foo_s s; };")
1377 assert ffi.sizeof("struct foo_s") == 8
1378 assert ffi.sizeof("union foo_u") == 32
1379
1380 def test_ffi_union_partial_2():
1381 ffi = FFI()
1382 ffi.cdef("typedef union { char x; ...; } u1;")
1383 ffi.verify("typedef union { char x; int y; } u1;")
1384 assert ffi.sizeof("u1") == 4
1385
1386 def test_ffi_union_with_partial_struct_2():
1387 ffi = FFI()
1388 ffi.cdef("typedef struct { int x; ...; } s1;"
1389 "typedef union { s1 s; } u1;")
1390 ffi.verify("typedef struct { int a; int x; } s1; "
1391 "typedef union { char b[32]; s1 s; } u1;")
1392 assert ffi.sizeof("s1") == 8
1393 assert ffi.sizeof("u1") == 32
1394 assert ffi.offsetof("u1", "s") == 0
1395
1396 def test_ffi_struct_packed():
1397 if sys.platform == 'win32':
1398 py.test.skip("needs a GCC extension")
1399 ffi = FFI()
1400 ffi.cdef("struct foo_s { int b; ...; };")
1401 ffi.verify("""
1402 struct foo_s {
1403 char a;
1404 int b;
1405 } __attribute__((packed));
1406 """)
1407
1408 def test_tmpdir():
1409 import tempfile, os
1410 from extra_tests.cffi_tests.udir import udir
1411 tmpdir = tempfile.mkdtemp(dir=str(udir))
1412 ffi = FFI()
1413 ffi.cdef("int foo(int);")
1414 lib = ffi.verify("int foo(int a) { return a + 42; }", tmpdir=tmpdir)
1415 assert os.listdir(tmpdir)
1416 assert lib.foo(100) == 142
1417
1418 def test_relative_to():
1419 import tempfile, os
1420 from extra_tests.cffi_tests.udir import udir
1421 tmpdir = tempfile.mkdtemp(dir=str(udir))
1422 ffi = FFI()
1423 ffi.cdef("int foo(int);")
1424 f = open(os.path.join(tmpdir, 'foo.h'), 'w')
1425 f.write("int foo(int a) { return a + 42; }\n")
1426 f.close()
1427 lib = ffi.verify('#include "foo.h"',
1428 include_dirs=['.'],
1429 relative_to=os.path.join(tmpdir, 'x'))
1430 assert lib.foo(100) == 142
1431
1432 def test_bug1():
1433 ffi = FFI()
1434 ffi.cdef("""
1435 typedef struct tdlhandle_s { ...; } *tdl_handle_t;
1436 typedef struct my_error_code_ {
1437 tdl_handle_t *rh;
1438 } my_error_code_t;
1439 """)
1440 ffi.verify("""
1441 typedef struct tdlhandle_s { int foo; } *tdl_handle_t;
1442 typedef struct my_error_code_ {
1443 tdl_handle_t *rh;
1444 } my_error_code_t;
1445 """)
1446
1447 def test_bool():
1448 if sys.platform == 'win32':
1449 py.test.skip("_Bool not in MSVC")
1450 ffi = FFI()
1451 ffi.cdef("struct foo_s { _Bool x; };"
1452 "_Bool foo(_Bool); _Bool (*foop)(_Bool);")
1453 lib = ffi.verify("""
1454 struct foo_s { _Bool x; };
1455 int foo(int arg) {
1456 return !arg;
1457 }
1458 _Bool _foofunc(_Bool x) {
1459 return !x;
1460 }
1461 _Bool (*foop)(_Bool) = _foofunc;
1462 """)
1463 p = ffi.new("struct foo_s *")
1464 p.x = 1
1465 assert p.x is True
1466 py.test.raises(OverflowError, "p.x = -1")
1467 py.test.raises(TypeError, "p.x = 0.0")
1468 assert lib.foop(1) is False
1469 assert lib.foop(True) is False
1470 assert lib.foop(0) is True
1471 py.test.raises(OverflowError, lib.foop, 42)
1472 py.test.raises(TypeError, lib.foop, 0.0)
1473 assert lib.foo(1) is False
1474 assert lib.foo(True) is False
1475 assert lib.foo(0) is True
1476 py.test.raises(OverflowError, lib.foo, 42)
1477 py.test.raises(TypeError, lib.foo, 0.0)
1478 assert int(ffi.cast("_Bool", long(1))) == 1
1479 assert int(ffi.cast("_Bool", long(0))) == 0
1480 assert int(ffi.cast("_Bool", long(-1))) == 1
1481 assert int(ffi.cast("_Bool", 10**200)) == 1
1482 assert int(ffi.cast("_Bool", 10**40000)) == 1
1483 #
1484 class Foo(object):
1485 def __int__(self):
1486 self.seen = 1
1487 return result
1488 f = Foo()
1489 f.seen = 0
1490 result = 42
1491 assert int(ffi.cast("_Bool", f)) == 1
1492 assert f.seen
1493 f.seen = 0
1494 result = 0
1495 assert int(ffi.cast("_Bool", f)) == 0
1496 assert f.seen
1497 #
1498 py.test.raises(TypeError, ffi.cast, "_Bool", [])
1499
1500 def test_bool_on_long_double():
1501 if sys.platform == 'win32':
1502 py.test.skip("_Bool not in MSVC")
1503 f = 1E-250
1504 if f == 0.0 or f*f != 0.0:
1505 py.test.skip("unexpected precision")
1506 ffi = FFI()
1507 ffi.cdef("long double square(long double f); _Bool opposite(_Bool);")
1508 lib = ffi.verify("long double square(long double f) { return f*f; }\n"
1509 "_Bool opposite(_Bool x) { return !x; }")
1510 f0 = lib.square(0.0)
1511 f2 = lib.square(f)
1512 f3 = lib.square(f * 2.0)
1513 if repr(f2) == repr(f3):
1514 py.test.skip("long double doesn't have enough precision")
1515 assert float(f0) == float(f2) == float(f3) == 0.0 # too tiny for 'double'
1516 assert int(ffi.cast("_Bool", f2)) == 1
1517 assert int(ffi.cast("_Bool", f3)) == 1
1518 assert int(ffi.cast("_Bool", f0)) == 0
1519 py.test.raises(TypeError, lib.opposite, f2)
1520
1521 def test_cannot_pass_float():
1522 for basetype in ['char', 'short', 'int', 'long', 'long long']:
1523 for sign in ['signed', 'unsigned']:
1524 type = '%s %s' % (sign, basetype)
1525 ffi = FFI()
1526 ffi.cdef("struct foo_s { %s x; };\n"
1527 "int foo(%s);" % (type, type))
1528 lib = ffi.verify("""
1529 struct foo_s { %s x; };
1530 int foo(%s arg) {
1531 return !arg;
1532 }
1533 """ % (type, type))
1534 p = ffi.new("struct foo_s *")
1535 py.test.raises(TypeError, "p.x = 0.0")
1536 assert lib.foo(42) == 0
1537 assert lib.foo(0) == 1
1538 py.test.raises(TypeError, lib.foo, 0.0)
1539
1540 def test_cast_from_int_type_to_bool():
1541 ffi = FFI()
1542 for basetype in ['char', 'short', 'int', 'long', 'long long']:
1543 for sign in ['signed', 'unsigned']:
1544 type = '%s %s' % (sign, basetype)
1545 assert int(ffi.cast("_Bool", ffi.cast(type, 42))) == 1
1546 assert int(ffi.cast("bool", ffi.cast(type, 42))) == 1
1547 assert int(ffi.cast("_Bool", ffi.cast(type, 0))) == 0
1548
1549 def test_addressof():
1550 ffi = FFI()
1551 ffi.cdef("""
1552 struct point_s { int x, y; };
1553 struct foo_s { int z; struct point_s point; };
1554 struct point_s sum_coord(struct point_s *);
1555 """)
1556 lib = ffi.verify("""
1557 struct point_s { int x, y; };
1558 struct foo_s { int z; struct point_s point; };
1559 struct point_s sum_coord(struct point_s *point) {
1560 struct point_s r;
1561 r.x = point->x + point->y;
1562 r.y = point->x - point->y;
1563 return r;
1564 }
1565 """)
1566 p = ffi.new("struct foo_s *")
1567 p.point.x = 16
1568 p.point.y = 9
1569 py.test.raises(TypeError, lib.sum_coord, p.point)
1570 res = lib.sum_coord(ffi.addressof(p.point))
1571 assert res.x == 25
1572 assert res.y == 7
1573 res2 = lib.sum_coord(ffi.addressof(res))
1574 assert res2.x == 32
1575 assert res2.y == 18
1576 py.test.raises(TypeError, lib.sum_coord, res2)
1577
1578 def test_callback_in_thread():
1579 if sys.platform == 'win32':
1580 py.test.skip("pthread only")
1581 import os, subprocess, imp
1582 arg = os.path.join(os.path.dirname(__file__), 'callback_in_thread.py')
1583 g = subprocess.Popen([sys.executable, arg,
1584 os.path.dirname(imp.find_module('cffi')[1])])
1585 result = g.wait()
1586 assert result == 0
1587
1588 def test_keepalive_lib():
1589 ffi = FFI()
1590 ffi.cdef("int foobar(void);")
1591 lib = ffi.verify("int foobar(void) { return 42; }")
1592 func = lib.foobar
1593 ffi_r = weakref.ref(ffi)
1594 lib_r = weakref.ref(lib)
1595 del ffi
1596 import gc; gc.collect() # lib stays alive
1597 assert lib_r() is not None
1598 assert ffi_r() is not None
1599 assert func() == 42
1600
1601 def test_keepalive_ffi():
1602 ffi = FFI()
1603 ffi.cdef("int foobar(void);")
1604 lib = ffi.verify("int foobar(void) { return 42; }")
1605 func = lib.foobar
1606 ffi_r = weakref.ref(ffi)
1607 lib_r = weakref.ref(lib)
1608 del lib
1609 import gc; gc.collect() # ffi stays alive
1610 assert ffi_r() is not None
1611 assert lib_r() is not None
1612 assert func() == 42
1613
1614 def test_FILE_stored_in_stdout():
1615 if not sys.platform.startswith('linux'):
1616 py.test.skip("likely, we cannot assign to stdout")
1617 ffi = FFI()
1618 ffi.cdef("int printf(const char *, ...); FILE *setstdout(FILE *);")
1619 lib = ffi.verify("""
1620 #include <stdio.h>
1621 FILE *setstdout(FILE *f) {
1622 FILE *result = stdout;
1623 stdout = f;
1624 return result;
1625 }
1626 """)
1627 import os
1628 fdr, fdw = os.pipe()
1629 fw1 = os.fdopen(fdw, 'wb', 256)
1630 old_stdout = lib.setstdout(fw1)
1631 try:
1632 #
1633 fw1.write(b"X")
1634 r = lib.printf(b"hello, %d!\n", ffi.cast("int", 42))
1635 fw1.close()
1636 assert r == len("hello, 42!\n")
1637 #
1638 finally:
1639 lib.setstdout(old_stdout)
1640 #
1641 result = os.read(fdr, 256)
1642 os.close(fdr)
1643 # the 'X' might remain in the user-level buffer of 'fw1' and
1644 # end up showing up after the 'hello, 42!\n'
1645 assert result == b"Xhello, 42!\n" or result == b"hello, 42!\nX"
1646
1647 def test_FILE_stored_explicitly():
1648 ffi = FFI()
1649 ffi.cdef("int myprintf11(const char *, int); FILE *myfile;")
1650 lib = ffi.verify("""
1651 #include <stdio.h>
1652 FILE *myfile;
1653 int myprintf11(const char *out, int value) {
1654 return fprintf(myfile, out, value);
1655 }
1656 """)
1657 import os
1658 fdr, fdw = os.pipe()
1659 fw1 = os.fdopen(fdw, 'wb', 256)
1660 lib.myfile = ffi.cast("FILE *", fw1)
1661 #
1662 fw1.write(b"X")
1663 r = lib.myprintf11(b"hello, %d!\n", ffi.cast("int", 42))
1664 fw1.close()
1665 assert r == len("hello, 42!\n")
1666 #
1667 result = os.read(fdr, 256)
1668 os.close(fdr)
1669 # the 'X' might remain in the user-level buffer of 'fw1' and
1670 # end up showing up after the 'hello, 42!\n'
1671 assert result == b"Xhello, 42!\n" or result == b"hello, 42!\nX"
1672
1673 def test_global_array_with_missing_length():
1674 ffi = FFI()
1675 ffi.cdef("int fooarray[];")
1676 lib = ffi.verify("int fooarray[50];")
1677 assert repr(lib.fooarray).startswith("<cdata 'int *'")
1678
1679 def test_global_array_with_dotdotdot_length():
1680 ffi = FFI()
1681 ffi.cdef("int fooarray[...];")
1682 lib = ffi.verify("int fooarray[50];")
1683 assert repr(lib.fooarray).startswith("<cdata 'int[50]'")
1684
1685 def test_bad_global_array_with_dotdotdot_length():
1686 ffi = FFI()
1687 ffi.cdef("int fooarray[...];")
1688 py.test.raises(VerificationError, ffi.verify, "char fooarray[23];")
1689
1690 def test_struct_containing_struct():
1691 ffi = FFI()
1692 ffi.cdef("struct foo_s { ...; }; struct bar_s { struct foo_s f; ...; };")
1693 ffi.verify("struct foo_s { int x; }; struct bar_s { struct foo_s f; };")
1694 #
1695 ffi = FFI()
1696 ffi.cdef("struct foo_s { struct bar_s f; ...; }; struct bar_s { ...; };")
1697 ffi.verify("struct bar_s { int x; }; struct foo_s { struct bar_s f; };")
1698
1699 def test_struct_returned_by_func():
1700 ffi = FFI()
1701 ffi.cdef("typedef ... foo_t; foo_t myfunc(void);")
1702 e = py.test.raises(TypeError, ffi.verify,
1703 "typedef struct { int x; } foo_t; "
1704 "foo_t myfunc(void) { foo_t x = { 42 }; return x; }")
1705 assert str(e.value) == (
1706 "function myfunc: 'foo_t' is used as result type, but is opaque")
1707
1708 def test_include():
1709 ffi1 = FFI()
1710 ffi1.cdef("typedef struct { int x; ...; } foo_t;")
1711 ffi1.verify("typedef struct { int y, x; } foo_t;")
1712 ffi2 = FFI()
1713 ffi2.include(ffi1)
1714 ffi2.cdef("int myfunc(foo_t *);")
1715 lib = ffi2.verify("typedef struct { int y, x; } foo_t;"
1716 "int myfunc(foo_t *p) { return 42 * p->x; }")
1717 res = lib.myfunc(ffi2.new("foo_t *", {'x': 10}))
1718 assert res == 420
1719 res = lib.myfunc(ffi1.new("foo_t *", {'x': -10}))
1720 assert res == -420
1721
1722 def test_include_enum():
1723 ffi1 = FFI()
1724 ffi1.cdef("enum foo_e { AA, ... };")
1725 lib1 = ffi1.verify("enum foo_e { CC, BB, AA };")
1726 ffi2 = FFI()
1727 ffi2.include(ffi1)
1728 ffi2.cdef("int myfunc(enum foo_e);")
1729 lib2 = ffi2.verify("enum foo_e { CC, BB, AA };"
1730 "int myfunc(enum foo_e x) { return (int)x; }")
1731 res = lib2.myfunc(lib2.AA)
1732 assert res == 2
1733
1734 def test_named_pointer_as_argument():
1735 ffi = FFI()
1736 ffi.cdef("typedef struct { int x; } *mystruct_p;\n"
1737 "mystruct_p ff5a(mystruct_p);")
1738 lib = ffi.verify("typedef struct { int x; } *mystruct_p;\n"
1739 "mystruct_p ff5a(mystruct_p p) { p->x += 40; return p; }")
1740 p = ffi.new("mystruct_p", [-2])
1741 q = lib.ff5a(p)
1742 assert q == p
1743 assert p.x == 38
1744
1745 def test_enum_size():
1746 cases = [('123', 4, 4294967295),
1747 ('4294967295U', 4, 4294967295),
1748 ('-123', 4, -1),
1749 ('-2147483647-1', 4, -1),
1750 ]
1751 if FFI().sizeof("long") == 8:
1752 cases += [('4294967296L', 8, 2**64-1),
1753 ('%dUL' % (2**64-1), 8, 2**64-1),
1754 ('-2147483649L', 8, -1),
1755 ('%dL-1L' % (1-2**63), 8, -1)]
1756 for hidden_value, expected_size, expected_minus1 in cases:
1757 if sys.platform == 'win32' and 'U' in hidden_value:
1758 continue # skipped on Windows
1759 ffi = FFI()
1760 ffi.cdef("enum foo_e { AA, BB, ... };")
1761 lib = ffi.verify("enum foo_e { AA, BB=%s };" % hidden_value)
1762 assert lib.AA == 0
1763 assert lib.BB == eval(hidden_value.replace('U', '').replace('L', ''))
1764 assert ffi.sizeof("enum foo_e") == expected_size
1765 assert int(ffi.cast("enum foo_e", -1)) == expected_minus1
1766 # test with the large value hidden:
1767 # disabled so far, doesn't work
1768 ## for hidden_value, expected_size, expected_minus1 in cases:
1769 ## ffi = FFI()
1770 ## ffi.cdef("enum foo_e { AA, BB, ... };")
1771 ## lib = ffi.verify("enum foo_e { AA, BB=%s };" % hidden_value)
1772 ## assert lib.AA == 0
1773 ## assert ffi.sizeof("enum foo_e") == expected_size
1774 ## assert int(ffi.cast("enum foo_e", -1)) == expected_minus1
1775
1776 def test_enum_bug118():
1777 maxulong = 256 ** FFI().sizeof("unsigned long") - 1
1778 for c1, c2, c2c in [(0xffffffff, -1, ''),
1779 (maxulong, -1, ''),
1780 (-1, 0xffffffff, 'U'),
1781 (-1, maxulong, 'UL')]:
1782 if c2c and sys.platform == 'win32':
1783 continue # enums may always be signed with MSVC
1784 ffi = FFI()
1785 ffi.cdef("enum foo_e { AA=%s };" % c1)
1786 e = py.test.raises(VerificationError, ffi.verify,
1787 "enum foo_e { AA=%s%s };" % (c2, c2c))
1788 assert str(e.value) == ('enum foo_e: AA has the real value %d, not %d'
1789 % (c2, c1))
1790
1791 def test_string_to_voidp_arg():
1792 ffi = FFI()
1793 ffi.cdef("int myfunc(void *);")
1794 lib = ffi.verify("int myfunc(void *p) { return ((signed char *)p)[0]; }")
1795 res = lib.myfunc(b"hi!")
1796 assert res == ord(b"h")
1797 p = ffi.new("char[]", b"gah")
1798 res = lib.myfunc(p)
1799 assert res == ord(b"g")
1800 res = lib.myfunc(ffi.cast("void *", p))
1801 assert res == ord(b"g")
1802 res = lib.myfunc(ffi.cast("int *", p))
1803 assert res == ord(b"g")
1804
1805 def test_callback_indirection():
1806 ffi = FFI()
1807 ffi.cdef("""
1808 int (*python_callback)(int how_many, int *values);
1809 int (*const c_callback)(int,...); /* pass this ptr to C routines */
1810 int some_c_function(int(*cb)(int,...));
1811 """)
1812 lib = ffi.verify("""
1813 #include <stdarg.h>
1814 #ifdef _WIN32
1815 #include <malloc.h>
1816 #define alloca _alloca
1817 #else
1818 # ifdef __FreeBSD__
1819 # include <stdlib.h>
1820 # else
1821 # include <alloca.h>
1822 # endif
1823 #endif
1824 static int (*python_callback)(int how_many, int *values);
1825 static int c_callback(int how_many, ...) {
1826 va_list ap;
1827 /* collect the "..." arguments into the values[] array */
1828 int i, *values = alloca((size_t)how_many * sizeof(int));
1829 va_start(ap, how_many);
1830 for (i=0; i<how_many; i++)
1831 values[i] = va_arg(ap, int);
1832 va_end(ap);
1833 return python_callback(how_many, values);
1834 }
1835 int some_c_function(int(*cb)(int,...)) {
1836 int result = cb(2, 10, 20);
1837 result += cb(3, 30, 40, 50);
1838 return result;
1839 }
1840 """)
1841 seen = []
1842 @ffi.callback("int(int, int*)")
1843 def python_callback(how_many, values):
1844 seen.append([values[i] for i in range(how_many)])
1845 return 42
1846 lib.python_callback = python_callback
1847
1848 res = lib.some_c_function(lib.c_callback)
1849 assert res == 84
1850 assert seen == [[10, 20], [30, 40, 50]]
1851
1852 def test_floatstar_argument():
1853 ffi = FFI()
1854 ffi.cdef("float sum3floats(float *);")
1855 lib = ffi.verify("""
1856 float sum3floats(float *f) {
1857 return f[0] + f[1] + f[2];
1858 }
1859 """)
1860 assert lib.sum3floats((1.5, 2.5, 3.5)) == 7.5
1861 p = ffi.new("float[]", (1.5, 2.5, 3.5))
1862 assert lib.sum3floats(p) == 7.5
1863
1864 def test_charstar_argument():
1865 ffi = FFI()
1866 ffi.cdef("char sum3chars(char *);")
1867 lib = ffi.verify("""
1868 char sum3chars(char *f) {
1869 return (char)(f[0] + f[1] + f[2]);
1870 }
1871 """)
1872 assert lib.sum3chars((b'\x10', b'\x20', b'\x30')) == b'\x60'
1873 p = ffi.new("char[]", b'\x10\x20\x30')
1874 assert lib.sum3chars(p) == b'\x60'
1875
1876 def test_passing_string_or_NULL():
1877 ffi = FFI()
1878 ffi.cdef("int seeme1(char *); int seeme2(int *);")
1879 lib = ffi.verify("""
1880 int seeme1(char *x) {
1881 return (x == NULL);
1882 }
1883 int seeme2(int *x) {
1884 return (x == NULL);
1885 }
1886 """)
1887 assert lib.seeme1(b"foo") == 0
1888 assert lib.seeme1(ffi.NULL) == 1
1889 assert lib.seeme2([42, 43]) == 0
1890 assert lib.seeme2(ffi.NULL) == 1
1891 py.test.raises(TypeError, lib.seeme1, None)
1892 py.test.raises(TypeError, lib.seeme2, None)
1893 py.test.raises(TypeError, lib.seeme1, 0.0)
1894 py.test.raises(TypeError, lib.seeme2, 0.0)
1895 py.test.raises(TypeError, lib.seeme1, 0)
1896 py.test.raises(TypeError, lib.seeme2, 0)
1897 zeroL = 99999999999999999999
1898 zeroL -= 99999999999999999999
1899 py.test.raises(TypeError, lib.seeme2, zeroL)
1900
1901 def test_typeof_function():
1902 ffi = FFI()
1903 ffi.cdef("int foo(int, char);")
1904 lib = ffi.verify("int foo(int x, char y) { (void)x; (void)y; return 42; }")
1905 ctype = ffi.typeof(lib.foo)
1906 assert len(ctype.args) == 2
1907 assert ctype.result == ffi.typeof("int")
1908
1909 def test_call_with_voidstar_arg():
1910 ffi = FFI()
1911 ffi.cdef("int f(void *);")
1912 lib = ffi.verify("int f(void *x) { return ((char*)x)[0]; }")
1913 assert lib.f(b"foobar") == ord(b"f")
1914
1915 def test_dir():
1916 ffi = FFI()
1917 ffi.cdef("""void somefunc(void);
1918 extern int somevar, somearray[2];
1919 static char *const sv2;
1920 enum my_e { AA, BB, ... };
1921 #define FOO ...""")
1922 lib = ffi.verify("""void somefunc(void) { }
1923 int somevar, somearray[2];
1924 #define sv2 "text"
1925 enum my_e { AA, BB };
1926 #define FOO 42""")
1927 assert dir(lib) == ['AA', 'BB', 'FOO', 'somearray',
1928 'somefunc', 'somevar', 'sv2']
1929
1930 def test_typeof_func_with_struct_argument():
1931 ffi = FFI()
1932 ffi.cdef("""struct s { int a; }; int foo(struct s);""")
1933 lib = ffi.verify("""struct s { int a; };
1934 int foo(struct s x) { return x.a; }""")
1935 s = ffi.new("struct s *", [-1234])
1936 m = lib.foo(s[0])
1937 assert m == -1234
1938 assert repr(ffi.typeof(lib.foo)) == "<ctype 'int(*)(struct s)'>"
1939
1940 def test_bug_const_char_ptr_array_1():
1941 ffi = FFI()
1942 ffi.cdef("""const char *a[...];""")
1943 lib = ffi.verify("""const char *a[5];""")
1944 assert repr(ffi.typeof(lib.a)) == "<ctype 'char *[5]'>"
1945
1946 def test_bug_const_char_ptr_array_2():
1947 from cffi import FFI # ignore warnings
1948 ffi = FFI()
1949 ffi.cdef("""const int a[];""")
1950 lib = ffi.verify("""const int a[5];""")
1951 assert repr(ffi.typeof(lib.a)) == "<ctype 'int *'>"
1952
1953 def _test_various_calls(force_libffi):
1954 cdef_source = """
1955 int xvalue;
1956 long long ivalue, rvalue;
1957 float fvalue;
1958 double dvalue;
1959 long double Dvalue;
1960 signed char tf_bb(signed char x, signed char c);
1961 unsigned char tf_bB(signed char x, unsigned char c);
1962 short tf_bh(signed char x, short c);
1963 unsigned short tf_bH(signed char x, unsigned short c);
1964 int tf_bi(signed char x, int c);
1965 unsigned int tf_bI(signed char x, unsigned int c);
1966 long tf_bl(signed char x, long c);
1967 unsigned long tf_bL(signed char x, unsigned long c);
1968 long long tf_bq(signed char x, long long c);
1969 unsigned long long tf_bQ(signed char x, unsigned long long c);
1970 float tf_bf(signed char x, float c);
1971 double tf_bd(signed char x, double c);
1972 long double tf_bD(signed char x, long double c);
1973 """
1974 if force_libffi:
1975 cdef_source = (cdef_source
1976 .replace('tf_', '(*const tf_')
1977 .replace('(signed char x', ')(signed char x'))
1978 ffi = FFI()
1979 ffi.cdef(cdef_source)
1980 lib = ffi.verify("""
1981 int xvalue;
1982 long long ivalue, rvalue;
1983 float fvalue;
1984 double dvalue;
1985 long double Dvalue;
1986
1987 typedef signed char b_t;
1988 typedef unsigned char B_t;
1989 typedef short h_t;
1990 typedef unsigned short H_t;
1991 typedef int i_t;
1992 typedef unsigned int I_t;
1993 typedef long l_t;
1994 typedef unsigned long L_t;
1995 typedef long long q_t;
1996 typedef unsigned long long Q_t;
1997 typedef float f_t;
1998 typedef double d_t;
1999 typedef long double D_t;
2000 #define S(letter) xvalue = (int)x; letter##value = (letter##_t)c;
2001 #define R(letter) return (letter##_t)rvalue;
2002
2003 signed char tf_bb(signed char x, signed char c) { S(i) R(b) }
2004 unsigned char tf_bB(signed char x, unsigned char c) { S(i) R(B) }
2005 short tf_bh(signed char x, short c) { S(i) R(h) }
2006 unsigned short tf_bH(signed char x, unsigned short c) { S(i) R(H) }
2007 int tf_bi(signed char x, int c) { S(i) R(i) }
2008 unsigned int tf_bI(signed char x, unsigned int c) { S(i) R(I) }
2009 long tf_bl(signed char x, long c) { S(i) R(l) }
2010 unsigned long tf_bL(signed char x, unsigned long c) { S(i) R(L) }
2011 long long tf_bq(signed char x, long long c) { S(i) R(q) }
2012 unsigned long long tf_bQ(signed char x, unsigned long long c) { S(i) R(Q) }
2013 float tf_bf(signed char x, float c) { S(f) R(f) }
2014 double tf_bd(signed char x, double c) { S(d) R(d) }
2015 long double tf_bD(signed char x, long double c) { S(D) R(D) }
2016 """)
2017 lib.rvalue = 0x7182838485868788
2018 for kind, cname in [('b', 'signed char'),
2019 ('B', 'unsigned char'),
2020 ('h', 'short'),
2021 ('H', 'unsigned short'),
2022 ('i', 'int'),
2023 ('I', 'unsigned int'),
2024 ('l', 'long'),
2025 ('L', 'unsigned long'),
2026 ('q', 'long long'),
2027 ('Q', 'unsigned long long'),
2028 ('f', 'float'),
2029 ('d', 'double'),
2030 ('D', 'long double')]:
2031 sign = +1 if 'unsigned' in cname else -1
2032 lib.xvalue = 0
2033 lib.ivalue = 0
2034 lib.fvalue = 0
2035 lib.dvalue = 0
2036 lib.Dvalue = 0
2037 fun = getattr(lib, 'tf_b' + kind)
2038 res = fun(-42, sign * 99)
2039 if kind == 'D':
2040 res = float(res)
2041 assert res == int(ffi.cast(cname, 0x7182838485868788))
2042 assert lib.xvalue == -42
2043 if kind in 'fdD':
2044 assert float(getattr(lib, kind + 'value')) == -99.0
2045 else:
2046 assert lib.ivalue == sign * 99
2047
2048 def test_various_calls_direct():
2049 _test_various_calls(force_libffi=False)
2050
2051 def test_various_calls_libffi():
2052 _test_various_calls(force_libffi=True)
2053
2054 def test_ptr_to_opaque():
2055 ffi = FFI()
2056 ffi.cdef("typedef ... foo_t; int f1(foo_t*); foo_t *f2(int);")
2057 lib = ffi.verify("""
2058 #include <stdlib.h>
2059 typedef struct { int x; } foo_t;
2060 int f1(foo_t* p) {
2061 int x = p->x;
2062 free(p);
2063 return x;
2064 }
2065 foo_t *f2(int x) {
2066 foo_t *p = malloc(sizeof(foo_t));
2067 p->x = x;
2068 return p;
2069 }
2070 """)
2071 p = lib.f2(42)
2072 x = lib.f1(p)
2073 assert x == 42
2074
2075 def _run_in_multiple_threads(test1):
2076 test1()
2077 import sys
2078 try:
2079 import thread
2080 except ImportError:
2081 import _thread as thread
2082 errors = []
2083 def wrapper(lock):
2084 try:
2085 test1()
2086 except:
2087 errors.append(sys.exc_info())
2088 lock.release()
2089 locks = []
2090 for i in range(10):
2091 _lock = thread.allocate_lock()
2092 _lock.acquire()
2093 thread.start_new_thread(wrapper, (_lock,))
2094 locks.append(_lock)
2095 for _lock in locks:
2096 _lock.acquire()
2097 if errors:
2098 raise errors[0][1]
2099
2100 def test_errno_working_even_with_pypys_jit():
2101 ffi = FFI()
2102 ffi.cdef("int f(int);")
2103 lib = ffi.verify("""
2104 #include <errno.h>
2105 int f(int x) { return (errno = errno + x); }
2106 """)
2107 @_run_in_multiple_threads
2108 def test1():
2109 ffi.errno = 0
2110 for i in range(10000):
2111 e = lib.f(1)
2112 assert e == i + 1
2113 assert ffi.errno == e
2114 for i in range(10000):
2115 ffi.errno = i
2116 e = lib.f(42)
2117 assert e == i + 42
2118
2119 def test_getlasterror_working_even_with_pypys_jit():
2120 if sys.platform != 'win32':
2121 py.test.skip("win32-only test")
2122 ffi = FFI()
2123 ffi.cdef("void SetLastError(DWORD);")
2124 lib = ffi.dlopen("Kernel32.dll")
2125 @_run_in_multiple_threads
2126 def test1():
2127 for i in range(10000):
2128 n = (1 << 29) + i
2129 lib.SetLastError(n)
2130 assert ffi.getwinerror()[0] == n
2131
2132 def test_verify_dlopen_flags():
2133 # Careful with RTLD_GLOBAL. If by chance the FFI is not deleted
2134 # promptly, like on PyPy, then other tests may see the same
2135 # exported symbols as well. So we must not export a simple name
2136 # like 'foo'!
2137 ffi1 = FFI()
2138 ffi1.cdef("int foo_verify_dlopen_flags;")
2139
2140 lib1 = ffi1.verify("int foo_verify_dlopen_flags;",
2141 flags=ffi1.RTLD_GLOBAL | ffi1.RTLD_LAZY)
2142 lib2 = get_second_lib()
2143
2144 lib1.foo_verify_dlopen_flags = 42
2145 assert lib2.foo_verify_dlopen_flags == 42
2146 lib2.foo_verify_dlopen_flags += 1
2147 assert lib1.foo_verify_dlopen_flags == 43
2148
2149 def get_second_lib():
2150 # Hack, using modulename makes the test fail
2151 ffi2 = FFI()
2152 ffi2.cdef("int foo_verify_dlopen_flags;")
2153 lib2 = ffi2.verify("int foo_verify_dlopen_flags;",
2154 flags=ffi2.RTLD_GLOBAL | ffi2.RTLD_LAZY)
2155 return lib2
2156
2157 def test_consider_not_implemented_function_type():
2158 ffi = FFI()
2159 ffi.cdef("typedef union { int a; float b; } Data;"
2160 "typedef struct { int a:2; } MyStr;"
2161 "typedef void (*foofunc_t)(Data);"
2162 "typedef Data (*bazfunc_t)(void);"
2163 "typedef MyStr (*barfunc_t)(void);")
2164 fooptr = ffi.cast("foofunc_t", 123)
2165 bazptr = ffi.cast("bazfunc_t", 123)
2166 barptr = ffi.cast("barfunc_t", 123)
2167 # assert did not crash so far
2168 e = py.test.raises(NotImplementedError, fooptr, ffi.new("Data *"))
2169 assert str(e.value) == (
2170 "ctype 'Data' not supported as argument by libffi. Unions are only "
2171 "supported as argument if the function is 'API mode' and "
2172 "non-variadic (i.e. declared inside ffibuilder.cdef()+"
2173 "ffibuilder.set_source() and not taking a final '...' argument)")
2174 e = py.test.raises(NotImplementedError, bazptr)
2175 assert str(e.value) == (
2176 "ctype 'Data' not supported as return value by libffi. Unions are "
2177 "only supported as return value if the function is 'API mode' and "
2178 "non-variadic (i.e. declared inside ffibuilder.cdef()+"
2179 "ffibuilder.set_source() and not taking a final '...' argument)")
2180 e = py.test.raises(NotImplementedError, barptr)
2181 assert str(e.value) == (
2182 "ctype 'MyStr' not supported as return value. It is a struct with "
2183 "bit fields, which libffi does not support. Such structs are only "
2184 "supported as return value if the function is 'API mode' and non-"
2185 "variadic (i.e. declared inside ffibuilder.cdef()+ffibuilder."
2186 "set_source() and not taking a final '...' argument)")
2187
2188 def test_verify_extra_arguments():
2189 ffi = FFI()
2190 ffi.cdef("#define ABA ...")
2191 lib = ffi.verify("", define_macros=[('ABA', '42')])
2192 assert lib.ABA == 42
2193
2194 def test_implicit_unicode_on_windows():
2195 if sys.platform != 'win32':
2196 py.test.skip("win32-only test")
2197 ffi = FFI()
2198 e = py.test.raises(FFIError, ffi.cdef, "int foo(LPTSTR);")
2199 assert str(e.value) == ("The Windows type 'LPTSTR' is only available after"
2200 " you call ffi.set_unicode()")
2201 for with_unicode in [True, False]:
2202 ffi = FFI()
2203 ffi.set_unicode(with_unicode)
2204 ffi.cdef("""
2205 DWORD GetModuleFileName(HMODULE hModule, LPTSTR lpFilename,
2206 DWORD nSize);
2207 """)
2208 lib = ffi.verify("""
2209 #include <windows.h>
2210 """, libraries=['Kernel32'])
2211 outbuf = ffi.new("TCHAR[]", 200)
2212 n = lib.GetModuleFileName(ffi.NULL, outbuf, 500)
2213 assert 0 < n < 500
2214 for i in range(n):
2215 #print repr(outbuf[i])
2216 assert ord(outbuf[i]) != 0
2217 assert ord(outbuf[n]) == 0
2218 assert ord(outbuf[0]) < 128 # should be a letter, or '\'
2219
2220 def test_use_local_dir():
2221 ffi = FFI()
2222 lib = ffi.verify("", modulename="test_use_local_dir")
2223 this_dir = os.path.dirname(__file__)
2224 pycache_files = os.listdir(os.path.join(this_dir, '__pycache__'))
2225 assert any('test_use_local_dir' in s for s in pycache_files)
2226
2227 def test_define_known_value():
2228 ffi = FFI()
2229 ffi.cdef("#define FOO 0x123")
2230 lib = ffi.verify("#define FOO 0x123")
2231 assert lib.FOO == 0x123
2232
2233 def test_define_wrong_value():
2234 ffi = FFI()
2235 ffi.cdef("#define FOO 123")
2236 e = py.test.raises(VerificationError, ffi.verify, "#define FOO 124")
2237 assert str(e.value).endswith("FOO has the real value 124, not 123")
2238
2239 def test_static_const_int_known_value():
2240 ffi = FFI()
2241 ffi.cdef("static const int FOO = 0x123;")
2242 lib = ffi.verify("#define FOO 0x123")
2243 assert lib.FOO == 0x123
2244
2245 def test_static_const_int_wrong_value():
2246 ffi = FFI()
2247 ffi.cdef("static const int FOO = 123;")
2248 e = py.test.raises(VerificationError, ffi.verify, "#define FOO 124")
2249 assert str(e.value).endswith("FOO has the real value 124, not 123")
2250
2251 def test_const_struct_global():
2252 ffi = FFI()
2253 ffi.cdef("typedef struct { int x; ...; } T; const T myglob;")
2254 lib = ffi.verify("typedef struct { double y; int x; } T;"
2255 "const T myglob = { 0.1, 42 };")
2256 assert ffi.typeof(lib.myglob) == ffi.typeof("T")
2257 assert lib.myglob.x == 42
2258
2259 def test_dont_support_int_dotdotdot():
2260 ffi = FFI()
2261 ffi.cdef("typedef int... t1;")
2262 e = py.test.raises(VerificationError, ffi.verify, "")
2263 assert str(e.value) == ("feature not supported with ffi.verify(), but only "
2264 "with ffi.set_source(): 'typedef int... t1'")
2265 ffi = FFI()
2266 ffi.cdef("typedef double ... t1;")
2267 e = py.test.raises(VerificationError, ffi.verify, "")
2268 assert str(e.value) == ("feature not supported with ffi.verify(), but only "
2269 "with ffi.set_source(): 'typedef float... t1'")
2270
2271 def test_const_fields():
2272 ffi = FFI()
2273 ffi.cdef("""struct foo_s { const int a; void *const b; };""")
2274 ffi.verify("""struct foo_s { const int a; void *const b; };""")
2275 foo_s = ffi.typeof("struct foo_s")
2276 assert foo_s.fields[0][0] == 'a'
2277 assert foo_s.fields[0][1].type is ffi.typeof("int")
2278 assert foo_s.fields[1][0] == 'b'
2279 assert foo_s.fields[1][1].type is ffi.typeof("void *")
2280
2281 def test_win32_calling_convention_0():
2282 ffi = FFI()
2283 ffi.cdef("""
2284 int call1(int(__cdecl *cb)(int));
2285 int (*const call2)(int(__stdcall *cb)(int));
2286 """)
2287 lib = ffi.verify(r"""
2288 #ifndef _MSC_VER
2289 # define __stdcall /* nothing */
2290 #endif
2291 int call1(int(*cb)(int)) {
2292 int i, result = 0;
2293 //printf("call1: cb = %p\n", cb);
2294 for (i = 0; i < 1000; i++)
2295 result += cb(i);
2296 //printf("result = %d\n", result);
2297 return result;
2298 }
2299 int call2(int(__stdcall *cb)(int)) {
2300 int i, result = 0;
2301 //printf("call2: cb = %p\n", cb);
2302 for (i = 0; i < 1000; i++)
2303 result += cb(-i);
2304 //printf("result = %d\n", result);
2305 return result;
2306 }
2307 """)
2308 @ffi.callback("int(int)")
2309 def cb1(x):
2310 return x * 2
2311 @ffi.callback("int __stdcall(int)")
2312 def cb2(x):
2313 return x * 3
2314 #print 'cb1 =', cb1
2315 res = lib.call1(cb1)
2316 assert res == 500*999*2
2317 #print 'cb2 =', cb2
2318 #print ffi.typeof(lib.call2)
2319 #print 'call2 =', lib.call2
2320 res = lib.call2(cb2)
2321 #print '...'
2322 assert res == -500*999*3
2323 #print 'done'
2324 if sys.platform == 'win32' and sys.maxsize < 2**32:
2325 assert '__stdcall' in str(ffi.typeof(cb2))
2326 assert '__stdcall' not in str(ffi.typeof(cb1))
2327 py.test.raises(TypeError, lib.call1, cb2)
2328 py.test.raises(TypeError, lib.call2, cb1)
2329 else:
2330 assert '__stdcall' not in str(ffi.typeof(cb2))
2331 assert ffi.typeof(cb2) is ffi.typeof(cb1)
2332
2333 def test_win32_calling_convention_1():
2334 ffi = FFI()
2335 ffi.cdef("""
2336 int __cdecl call1(int(__cdecl *cb)(int));
2337 int __stdcall call2(int(__stdcall *cb)(int));
2338 int (__cdecl *const cb1)(int);
2339 int (__stdcall *const cb2)(int);
2340 """)
2341 lib = ffi.verify(r"""
2342 #ifndef _MSC_VER
2343 # define __cdecl
2344 # define __stdcall
2345 #endif
2346 int __cdecl cb1(int x) { return x * 2; }
2347 int __stdcall cb2(int x) { return x * 3; }
2348
2349 int __cdecl call1(int(__cdecl *cb)(int)) {
2350 int i, result = 0;
2351 //printf("here1\n");
2352 //printf("cb = %p, cb1 = %p\n", cb, (void *)cb1);
2353 for (i = 0; i < 1000; i++)
2354 result += cb(i);
2355 //printf("result = %d\n", result);
2356 return result;
2357 }
2358 int __stdcall call2(int(__stdcall *cb)(int)) {
2359 int i, result = 0;
2360 //printf("here1\n");
2361 //printf("cb = %p, cb2 = %p\n", cb, (void *)cb2);
2362 for (i = 0; i < 1000; i++)
2363 result += cb(-i);
2364 //printf("result = %d\n", result);
2365 return result;
2366 }
2367 """)
2368 assert lib.call1(lib.cb1) == 500*999*2
2369 assert lib.call2(lib.cb2) == -500*999*3
2370
2371 def test_win32_calling_convention_2():
2372 # any mistake in the declaration of plain function (including the
2373 # precise argument types and, here, the calling convention) are
2374 # automatically corrected. But this does not apply to the 'cb'
2375 # function pointer argument.
2376 ffi = FFI()
2377 ffi.cdef("""
2378 int __stdcall call1(int(__cdecl *cb)(int));
2379 int __cdecl call2(int(__stdcall *cb)(int));
2380 int (__cdecl *const cb1)(int);
2381 int (__stdcall *const cb2)(int);
2382 """)
2383 lib = ffi.verify(r"""
2384 #ifndef _MSC_VER
2385 # define __cdecl
2386 # define __stdcall
2387 #endif
2388 int __cdecl call1(int(__cdecl *cb)(int)) {
2389 int i, result = 0;
2390 for (i = 0; i < 1000; i++)
2391 result += cb(i);
2392 return result;
2393 }
2394 int __stdcall call2(int(__stdcall *cb)(int)) {
2395 int i, result = 0;
2396 for (i = 0; i < 1000; i++)
2397 result += cb(-i);
2398 return result;
2399 }
2400 int __cdecl cb1(int x) { return x * 2; }
2401 int __stdcall cb2(int x) { return x * 3; }
2402 """)
2403 assert lib.call1(lib.cb1) == 500*999*2
2404 assert lib.call2(lib.cb2) == -500*999*3
2405
2406 def test_win32_calling_convention_3():
2407 ffi = FFI()
2408 ffi.cdef("""
2409 struct point { int x, y; };
2410
2411 int (*const cb1)(struct point);
2412 int (__stdcall *const cb2)(struct point);
2413
2414 struct point __stdcall call1(int(*cb)(struct point));
2415 struct point call2(int(__stdcall *cb)(struct point));
2416 """)
2417 lib = ffi.verify(r"""
2418 #ifndef _MSC_VER
2419 # define __cdecl
2420 # define __stdcall
2421 #endif
2422 struct point { int x, y; };
2423 int cb1(struct point pt) { return pt.x + 10 * pt.y; }
2424 int __stdcall cb2(struct point pt) { return pt.x + 100 * pt.y; }
2425 struct point __stdcall call1(int(__cdecl *cb)(struct point)) {
2426 int i;
2427 struct point result = { 0, 0 };
2428 //printf("here1\n");
2429 //printf("cb = %p, cb1 = %p\n", cb, (void *)cb1);
2430 for (i = 0; i < 1000; i++) {
2431 struct point p = { i, -i };
2432 int r = cb(p);
2433 result.x += r;
2434 result.y -= r;
2435 }
2436 return result;
2437 }
2438 struct point __cdecl call2(int(__stdcall *cb)(struct point)) {
2439 int i;
2440 struct point result = { 0, 0 };
2441 for (i = 0; i < 1000; i++) {
2442 struct point p = { -i, i };
2443 int r = cb(p);
2444 result.x += r;
2445 result.y -= r;
2446 }
2447 return result;
2448 }
2449 """)
2450 if sys.platform == 'win32' and sys.maxsize < 2**32:
2451 py.test.raises(TypeError, lib.call1, lib.cb2)
2452 py.test.raises(TypeError, lib.call2, lib.cb1)
2453 pt = lib.call1(lib.cb1)
2454 assert (pt.x, pt.y) == (-9*500*999, 9*500*999)
2455 pt = lib.call2(lib.cb2)
2456 assert (pt.x, pt.y) == (99*500*999, -99*500*999)
2457
2458 def _only_test_on_linux_intel():
2459 if not sys.platform.startswith('linux'):
2460 py.test.skip('only running the memory-intensive test on Linux')
2461 import platform
2462 machine = platform.machine()
2463 if 'x86' not in machine and 'x64' not in machine:
2464 py.test.skip('only running the memory-intensive test on x86/x64')
2465
2466 def test_ffi_gc_size_arg():
2467 # with PyPy's GC, these calls to ffi.gc() would rapidly consume
2468 # 40 GB of RAM without the third argument
2469 _only_test_on_linux_intel()
2470 ffi = FFI()
2471 ffi.cdef("void *malloc(size_t); void free(void *);")
2472 lib = ffi.verify(r"""
2473 #include <stdlib.h>
2474 """)
2475 for i in range(2000):
2476 p = lib.malloc(20*1024*1024) # 20 MB
2477 p1 = ffi.cast("char *", p)
2478 for j in range(0, 20*1024*1024, 4096):
2479 p1[j] = b'!'
2480 p = ffi.gc(p, lib.free, 20*1024*1024)
2481 del p
2482
2483 def test_ffi_gc_size_arg_2():
2484 # a variant of the above: this "attack" works on cpython's cyclic gc too
2485 # and I found no obvious way to prevent that. So for now, this test
2486 # is skipped on CPython, where it eats all the memory.
2487 if '__pypy__' not in sys.builtin_module_names:
2488 py.test.skip("find a way to tweak the cyclic GC of CPython")
2489 _only_test_on_linux_intel()
2490 ffi = FFI()
2491 ffi.cdef("void *malloc(size_t); void free(void *);")
2492 lib = ffi.verify(r"""
2493 #include <stdlib.h>
2494 """)
2495 class X(object):
2496 pass
2497 for i in range(2000):
2498 p = lib.malloc(50*1024*1024) # 50 MB
2499 p1 = ffi.cast("char *", p)
2500 for j in range(0, 50*1024*1024, 4096):
2501 p1[j] = b'!'
2502 p = ffi.gc(p, lib.free, 50*1024*1024)
2503 x = X()
2504 x.p = p
2505 x.cyclic = x
2506 del p, x
2507
2508 def test_ffi_new_with_cycles():
2509 # still another variant, with ffi.new()
2510 if '__pypy__' not in sys.builtin_module_names:
2511 py.test.skip("find a way to tweak the cyclic GC of CPython")
2512 ffi = FFI()
2513 ffi.cdef("")
2514 lib = ffi.verify("")
2515 class X(object):
2516 pass
2517 for i in range(2000):
2518 p = ffi.new("char[]", 50*1024*1024) # 50 MB
2519 for j in range(0, 50*1024*1024, 4096):
2520 p[j] = b'!'
2521 x = X()
2522 x.p = p
2523 x.cyclic = x
2524 del p, x
0 # Generated by pypy/tool/import_cffi.py
1 from .test_verify import *
2
3 # This test file runs normally after test_verify. We only clean up the .c
4 # sources, to check that it also works when we have only the .so. The
5 # tests should run much faster than test_verify.
6
7 def setup_module():
8 import cffi.verifier
9 cffi.verifier.cleanup_tmpdir(keep_so=True)
0 # Generated by pypy/tool/import_cffi.py
1 import py, os, sys
2 import cffi, _cffi_backend
3
4 def setup_module(mod):
5 if '_cffi_backend' in sys.builtin_module_names:
6 py.test.skip("this is embedded version")
7
8 #BACKEND_VERSIONS = {
9 # '0.4.2': '0.4', # did not change
10 # '0.7.1': '0.7', # did not change
11 # '0.7.2': '0.7', # did not change
12 # '0.8.1': '0.8', # did not change (essentially)
13 # '0.8.4': '0.8.3', # did not change
14 # }
15
16 def test_version():
17 v = cffi.__version__
18 version_info = '.'.join(str(i) for i in cffi.__version_info__)
19 version_info = version_info.replace('.beta.', 'b')
20 version_info = version_info.replace('.plus', '+')
21 assert v == version_info
22 #v = BACKEND_VERSIONS.get(v, v)
23 assert v == _cffi_backend.__version__
24
25 def test_doc_version():
26 parent = os.path.dirname(os.path.dirname(cffi.__file__))
27 p = os.path.join(parent, 'doc', 'source', 'conf.py')
28 content = open(p).read()
29 #
30 v = cffi.__version__
31 assert ("version = '%s'\n" % v[:4]) in content
32 assert ("release = '%s'\n" % v) in content
33
34 def test_doc_version_file():
35 parent = os.path.dirname(os.path.dirname(cffi.__file__))
36 v = cffi.__version__.replace('+', '')
37 p = os.path.join(parent, 'doc', 'source', 'installation.rst')
38 content = open(p).read()
39 assert (" package version %s:" % v) in content
40
41 def test_setup_version():
42 parent = os.path.dirname(os.path.dirname(cffi.__file__))
43 p = os.path.join(parent, 'setup.py')
44 content = open(p).read()
45 #
46 v = cffi.__version__.replace('+', '')
47 assert ("version='%s'" % v) in content
48
49 def test_c_version():
50 parent = os.path.dirname(os.path.dirname(cffi.__file__))
51 v = cffi.__version__
52 p = os.path.join(parent, 'c', 'test_c.py')
53 content = open(p).read()
54 #v = BACKEND_VERSIONS.get(v, v)
55 assert (('assert __version__ == "%s"' % v) in content)
56
57 def test_embedding_h():
58 parent = os.path.dirname(os.path.dirname(cffi.__file__))
59 v = cffi.__version__
60 p = os.path.join(parent, 'cffi', '_embedding.h')
61 content = open(p).read()
62 assert ('cffi version: %s"' % (v,)) in content
0 # Generated by pypy/tool/import_cffi.py
1 import cffi.verifier
2 from .test_verify import *
3
4
5 def setup_module():
6 cffi.verifier.cleanup_tmpdir()
7 cffi.verifier._FORCE_GENERIC_ENGINE = True
8 # Runs all tests with _FORCE_GENERIC_ENGINE = True, to make sure we
9 # also test vengine_gen.py.
10
11 def teardown_module():
12 cffi.verifier._FORCE_GENERIC_ENGINE = False
0 # Generated by pypy/tool/import_cffi.py
1 import cffi.verifier
2 from .test_vgen import *
3
4 # This test file runs normally after test_vgen. We only clean up the .c
5 # sources, to check that it also works when we have only the .so. The
6 # tests should run much faster than test_vgen.
7
8 def setup_module():
9 cffi.verifier.cleanup_tmpdir(keep_so=True)
10 cffi.verifier._FORCE_GENERIC_ENGINE = True
11
12 def teardown_module():
13 cffi.verifier._FORCE_GENERIC_ENGINE = False
0 # Generated by pypy/tool/import_cffi.py
1 import sys, os, imp, math, shutil
2 import py
3 from cffi import FFI, FFIError
4 from cffi.verifier import Verifier, _locate_engine_class, _get_so_suffixes
5 from cffi.ffiplatform import maybe_relative_path
6 from extra_tests.cffi_tests.udir import udir
7
8
9 class DistUtilsTest(object):
10 def setup_class(self):
11 self.lib_m = "m"
12 if sys.platform == 'win32':
13 #there is a small chance this fails on Mingw via environ $CC
14 import distutils.ccompiler
15 if distutils.ccompiler.get_default_compiler() == 'msvc':
16 self.lib_m = 'msvcrt'
17
18 def teardown_class(self):
19 if udir.isdir():
20 udir.remove(ignore_errors=True)
21 udir.ensure(dir=1)
22
23 def test_locate_engine_class(self):
24 cls = _locate_engine_class(FFI(), self.generic)
25 if self.generic:
26 # asked for the generic engine, which must not generate a
27 # CPython extension module
28 assert not cls._gen_python_module
29 else:
30 # asked for the CPython engine: check that we got it, unless
31 # we are running on top of PyPy, where the generic engine is
32 # always better
33 if '__pypy__' not in sys.builtin_module_names:
34 assert cls._gen_python_module
35
36 def test_write_source(self):
37 ffi = FFI()
38 ffi.cdef("double sin(double x);")
39 csrc = '/*hi there %s!*/\n#include <math.h>\n' % self
40 v = Verifier(ffi, csrc, force_generic_engine=self.generic,
41 libraries=[self.lib_m])
42 v.write_source()
43 with open(v.sourcefilename, 'r') as f:
44 data = f.read()
45 assert csrc in data
46
47 def test_write_source_explicit_filename(self):
48 ffi = FFI()
49 ffi.cdef("double sin(double x);")
50 csrc = '/*hi there %s!*/\n#include <math.h>\n' % self
51 v = Verifier(ffi, csrc, force_generic_engine=self.generic,
52 libraries=[self.lib_m])
53 v.sourcefilename = filename = str(udir.join('write_source.c'))
54 v.write_source()
55 assert filename == v.sourcefilename
56 with open(filename, 'r') as f:
57 data = f.read()
58 assert csrc in data
59
60 def test_write_source_to_file_obj(self):
61 ffi = FFI()
62 ffi.cdef("double sin(double x);")
63 csrc = '/*hi there %s!*/\n#include <math.h>\n' % self
64 v = Verifier(ffi, csrc, force_generic_engine=self.generic,
65 libraries=[self.lib_m])
66 try:
67 from StringIO import StringIO
68 except ImportError:
69 from io import StringIO
70 f = StringIO()
71 v.write_source(file=f)
72 assert csrc in f.getvalue()
73
74 def test_compile_module(self):
75 ffi = FFI()
76 ffi.cdef("double sin(double x);")
77 csrc = '/*hi there %s!*/\n#include <math.h>\n' % self
78 v = Verifier(ffi, csrc, force_generic_engine=self.generic,
79 libraries=[self.lib_m])
80 v.compile_module()
81 assert v.get_module_name().startswith('_cffi_')
82 if v.generates_python_module():
83 mod = imp.load_dynamic(v.get_module_name(), v.modulefilename)
84 assert hasattr(mod, '_cffi_setup')
85
86 def test_compile_module_explicit_filename(self):
87 ffi = FFI()
88 ffi.cdef("double sin(double x);")
89 csrc = '/*hi there %s!2*/\n#include <math.h>\n' % self
90 v = Verifier(ffi, csrc, force_generic_engine=self.generic,
91 libraries=[self.lib_m])
92 basename = self.__class__.__name__ + 'test_compile_module'
93 v.modulefilename = filename = str(udir.join(basename + '.so'))
94 v.compile_module()
95 assert filename == v.modulefilename
96 assert v.get_module_name() == basename
97 if v.generates_python_module():
98 mod = imp.load_dynamic(v.get_module_name(), v.modulefilename)
99 assert hasattr(mod, '_cffi_setup')
100
101 def test_name_from_checksum_of_cdef(self):
102 names = []
103 for csrc in ['double', 'double', 'float']:
104 ffi = FFI()
105 ffi.cdef("%s sin(double x);" % csrc)
106 v = Verifier(ffi, "#include <math.h>",
107 force_generic_engine=self.generic,
108 libraries=[self.lib_m])
109 names.append(v.get_module_name())
110 assert names[0] == names[1] != names[2]
111
112 def test_name_from_checksum_of_csrc(self):
113 names = []
114 for csrc in ['123', '123', '1234']:
115 ffi = FFI()
116 ffi.cdef("double sin(double x);")
117 v = Verifier(ffi, csrc, force_generic_engine=self.generic)
118 names.append(v.get_module_name())
119 assert names[0] == names[1] != names[2]
120
121 def test_load_library(self):
122 ffi = FFI()
123 ffi.cdef("double sin(double x);")
124 csrc = '/*hi there %s!3*/\n#include <math.h>\n' % self
125 v = Verifier(ffi, csrc, force_generic_engine=self.generic,
126 libraries=[self.lib_m])
127 library = v.load_library()
128 assert library.sin(12.3) == math.sin(12.3)
129
130 def test_verifier_args(self):
131 ffi = FFI()
132 ffi.cdef("double sin(double x);")
133 csrc = '/*hi there %s!4*/#include "test_verifier_args.h"\n' % self
134 udir.join('test_verifier_args.h').write('#include <math.h>\n')
135 v = Verifier(ffi, csrc, include_dirs=[str(udir)],
136 force_generic_engine=self.generic,
137 libraries=[self.lib_m])
138 library = v.load_library()
139 assert library.sin(12.3) == math.sin(12.3)
140
141 def test_verifier_object_from_ffi(self):
142 ffi = FFI()
143 ffi.cdef("double sin(double x);")
144 csrc = "/*6%s*/\n#include <math.h>" % self
145 lib = ffi.verify(csrc, force_generic_engine=self.generic,
146 libraries=[self.lib_m])
147 assert lib.sin(12.3) == math.sin(12.3)
148 assert isinstance(ffi.verifier, Verifier)
149 with open(ffi.verifier.sourcefilename, 'r') as f:
150 data = f.read()
151 assert csrc in data
152
153 def test_extension_object(self):
154 ffi = FFI()
155 ffi.cdef("double sin(double x);")
156 csrc = '/*7%s*/' % self + '''
157 #include <math.h>
158 #ifndef TEST_EXTENSION_OBJECT
159 # error "define_macros missing"
160 #endif
161 '''
162 lib = ffi.verify(csrc, define_macros=[('TEST_EXTENSION_OBJECT', '1')],
163 force_generic_engine=self.generic,
164 libraries=[self.lib_m])
165 assert lib.sin(12.3) == math.sin(12.3)
166 v = ffi.verifier
167 ext = v.get_extension()
168 assert 'distutils.extension.Extension' in str(ext.__class__) or \
169 'setuptools.extension.Extension' in str(ext.__class__)
170 assert ext.sources == [maybe_relative_path(v.sourcefilename)]
171 assert ext.name == v.get_module_name()
172 assert ext.define_macros == [('TEST_EXTENSION_OBJECT', '1')]
173
174 def test_extension_forces_write_source(self):
175 ffi = FFI()
176 ffi.cdef("double sin(double x);")
177 csrc = '/*hi there9!%s*/\n#include <math.h>\n' % self
178 v = Verifier(ffi, csrc, force_generic_engine=self.generic,
179 libraries=[self.lib_m])
180 assert not os.path.exists(v.sourcefilename)
181 v.get_extension()
182 assert os.path.exists(v.sourcefilename)
183
184 def test_extension_object_extra_sources(self):
185 ffi = FFI()
186 ffi.cdef("double test1eoes(double x);")
187 extra_source = str(udir.join('extension_extra_sources.c'))
188 with open(extra_source, 'w') as f:
189 f.write('double test1eoes(double x) { return x * 6.0; }\n')
190 csrc = '/*9%s*/' % self + '''
191 double test1eoes(double x); /* or #include "extra_sources.h" */
192 '''
193 lib = ffi.verify(csrc, sources=[extra_source],
194 force_generic_engine=self.generic)
195 assert lib.test1eoes(7.0) == 42.0
196 v = ffi.verifier
197 ext = v.get_extension()
198 assert 'distutils.extension.Extension' in str(ext.__class__) or \
199 'setuptools.extension.Extension' in str(ext.__class__)
200 assert ext.sources == [maybe_relative_path(v.sourcefilename),
201 extra_source]
202 assert ext.name == v.get_module_name()
203
204 def test_install_and_reload_module(self, targetpackage='', ext_package=''):
205 KEY = repr(self)
206 if not hasattr(os, 'fork'):
207 py.test.skip("test requires os.fork()")
208
209 if targetpackage:
210 udir.ensure(targetpackage, dir=1).ensure('__init__.py')
211 sys.path.insert(0, str(udir))
212
213 def make_ffi(**verifier_args):
214 ffi = FFI()
215 ffi.cdef("/* %s, %s, %s */" % (KEY, targetpackage, ext_package))
216 ffi.cdef("double test1iarm(double x);")
217 csrc = "double test1iarm(double x) { return x * 42.0; }"
218 lib = ffi.verify(csrc, force_generic_engine=self.generic,
219 ext_package=ext_package,
220 **verifier_args)
221 return ffi, lib
222
223 childpid = os.fork()
224 if childpid == 0:
225 # in the child
226 ffi, lib = make_ffi()
227 assert lib.test1iarm(1.5) == 63.0
228 # "install" the module by moving it into udir (/targetpackage)
229 if targetpackage:
230 target = udir.join(targetpackage)
231 else:
232 target = udir
233 shutil.move(ffi.verifier.modulefilename, str(target))
234 os._exit(0)
235 # in the parent
236 _, status = os.waitpid(childpid, 0)
237 if not (os.WIFEXITED(status) and os.WEXITSTATUS(status) == 0):
238 raise AssertionError # see error above in subprocess
239
240 from cffi import ffiplatform
241 prev_compile = ffiplatform.compile
242 try:
243 if targetpackage == ext_package:
244 ffiplatform.compile = lambda *args: dont_call_me_any_more
245 # won't find it in tmpdir, but should find it correctly
246 # installed in udir
247 ffi, lib = make_ffi()
248 assert lib.test1iarm(0.5) == 21.0
249 finally:
250 ffiplatform.compile = prev_compile
251
252 def test_install_and_reload_module_package(self):
253 self.test_install_and_reload_module(targetpackage='foo_iarmp',
254 ext_package='foo_iarmp')
255
256 def test_install_and_reload_module_ext_package_not_found(self):
257 self.test_install_and_reload_module(targetpackage='foo_epnf',
258 ext_package='not_found')
259
260 def test_tag(self):
261 ffi = FFI()
262 ffi.cdef("/* %s test_tag */ double test1tag(double x);" % self)
263 csrc = "double test1tag(double x) { return x - 42.0; }"
264 lib = ffi.verify(csrc, force_generic_engine=self.generic,
265 tag='xxtest_tagxx')
266 assert lib.test1tag(143) == 101.0
267 assert '_cffi_xxtest_tagxx_' in ffi.verifier.modulefilename
268
269 def test_modulename(self):
270 ffi = FFI()
271 ffi.cdef("/* %s test_modulename */ double test1foo(double x);" % self)
272 csrc = "double test1foo(double x) { return x - 63.0; }"
273 modname = 'xxtest_modulenamexx%d' % (self.generic,)
274 lib = ffi.verify(csrc, force_generic_engine=self.generic,
275 modulename=modname)
276 assert lib.test1foo(143) == 80.0
277 suffix = _get_so_suffixes()[0]
278 fn1 = os.path.join(ffi.verifier.tmpdir, modname + '.c')
279 fn2 = os.path.join(ffi.verifier.tmpdir, modname + suffix)
280 assert ffi.verifier.sourcefilename == fn1
281 assert ffi.verifier.modulefilename == fn2
282
283
284 class TestDistUtilsCPython(DistUtilsTest):
285 generic = False
286
287 class TestDistUtilsGeneric(DistUtilsTest):
288 generic = True
0 # Generated by pypy/tool/import_cffi.py
1 import py, os, sys, shutil
2 import subprocess
3 from extra_tests.cffi_tests.udir import udir
4
5 if sys.platform == 'win32':
6 py.test.skip('snippets do not run on win32')
7 if sys.version_info < (2, 7):
8 py.test.skip('fails e.g. on a Debian/Ubuntu which patches virtualenv'
9 ' in a non-2.6-friendly way')
10
11 def create_venv(name):
12 tmpdir = udir.join(name)
13 try:
14 subprocess.check_call(['virtualenv',
15 #'--never-download', <= could be added, but causes failures
16 # in random cases on random machines
17 '-p', os.path.abspath(sys.executable),
18 str(tmpdir)])
19 except OSError as e:
20 py.test.skip("Cannot execute virtualenv: %s" % (e,))
21
22 site_packages = None
23 for dirpath, dirnames, filenames in os.walk(str(tmpdir)):
24 if os.path.basename(dirpath) == 'site-packages':
25 site_packages = dirpath
26 break
27 paths = ""
28 if site_packages:
29 try:
30 from cffi import _pycparser
31 modules = ('cffi', '_cffi_backend')
32 except ImportError:
33 modules = ('cffi', '_cffi_backend', 'pycparser')
34 try:
35 import ply
36 except ImportError:
37 pass
38 else:
39 modules += ('ply',) # needed for older versions of pycparser
40 paths = []
41 for module in modules:
42 target = __import__(module, None, None, [])
43 if not hasattr(target, '__file__'): # for _cffi_backend on pypy
44 continue
45 src = os.path.abspath(target.__file__)
46 for end in ['__init__.pyc', '__init__.pyo', '__init__.py']:
47 if src.lower().endswith(end):
48 src = src[:-len(end)-1]
49 break
50 paths.append(os.path.dirname(src))
51 paths = os.pathsep.join(paths)
52 return tmpdir, paths
53
54 SNIPPET_DIR = py.path.local(__file__).join('..', 'snippets')
55
56 def really_run_setup_and_program(dirname, venv_dir_and_paths, python_snippet):
57 venv_dir, paths = venv_dir_and_paths
58 def remove(dir):
59 dir = str(SNIPPET_DIR.join(dirname, dir))
60 shutil.rmtree(dir, ignore_errors=True)
61 remove('build')
62 remove('__pycache__')
63 for basedir in os.listdir(str(SNIPPET_DIR.join(dirname))):
64 remove(os.path.join(basedir, '__pycache__'))
65 olddir = os.getcwd()
66 python_f = udir.join('x.py')
67 python_f.write(py.code.Source(python_snippet))
68 try:
69 os.chdir(str(SNIPPET_DIR.join(dirname)))
70 if os.name == 'nt':
71 bindir = 'Scripts'
72 else:
73 bindir = 'bin'
74 vp = str(venv_dir.join(bindir).join('python'))
75 env = os.environ.copy()
76 env['PYTHONPATH'] = paths
77 subprocess.check_call((vp, 'setup.py', 'clean'), env=env)
78 subprocess.check_call((vp, 'setup.py', 'install'), env=env)
79 subprocess.check_call((vp, str(python_f)), env=env)
80 finally:
81 os.chdir(olddir)
82
83 def run_setup_and_program(dirname, python_snippet):
84 venv_dir = create_venv(dirname + '-cpy')
85 really_run_setup_and_program(dirname, venv_dir, python_snippet)
86 #
87 sys._force_generic_engine_ = True
88 try:
89 venv_dir = create_venv(dirname + '-gen')
90 really_run_setup_and_program(dirname, venv_dir, python_snippet)
91 finally:
92 del sys._force_generic_engine_
93 # the two files lextab.py and yacctab.py are created by not-correctly-
94 # installed versions of pycparser.
95 assert not os.path.exists(str(SNIPPET_DIR.join(dirname, 'lextab.py')))
96 assert not os.path.exists(str(SNIPPET_DIR.join(dirname, 'yacctab.py')))
97
98 class TestZIntegration(object):
99 def teardown_class(self):
100 if udir.isdir():
101 udir.remove(ignore_errors=True)
102 udir.ensure(dir=1)
103
104 def test_infrastructure(self):
105 run_setup_and_program('infrastructure', '''
106 import snip_infrastructure
107 assert snip_infrastructure.func() == 42
108 ''')
109
110 def test_distutils_module(self):
111 run_setup_and_program("distutils_module", '''
112 import snip_basic_verify
113 p = snip_basic_verify.C.getpwuid(0)
114 assert snip_basic_verify.ffi.string(p.pw_name) == b"root"
115 ''')
116
117 def test_distutils_package_1(self):
118 run_setup_and_program("distutils_package_1", '''
119 import snip_basic_verify1
120 p = snip_basic_verify1.C.getpwuid(0)
121 assert snip_basic_verify1.ffi.string(p.pw_name) == b"root"
122 ''')
123
124 def test_distutils_package_2(self):
125 run_setup_and_program("distutils_package_2", '''
126 import snip_basic_verify2
127 p = snip_basic_verify2.C.getpwuid(0)
128 assert snip_basic_verify2.ffi.string(p.pw_name) == b"root"
129 ''')
130
131 def test_setuptools_module(self):
132 run_setup_and_program("setuptools_module", '''
133 import snip_setuptools_verify
134 p = snip_setuptools_verify.C.getpwuid(0)
135 assert snip_setuptools_verify.ffi.string(p.pw_name) == b"root"
136 ''')
137
138 def test_setuptools_package_1(self):
139 run_setup_and_program("setuptools_package_1", '''
140 import snip_setuptools_verify1
141 p = snip_setuptools_verify1.C.getpwuid(0)
142 assert snip_setuptools_verify1.ffi.string(p.pw_name) == b"root"
143 ''')
144
145 def test_setuptools_package_2(self):
146 run_setup_and_program("setuptools_package_2", '''
147 import snip_setuptools_verify2
148 p = snip_setuptools_verify2.C.getpwuid(0)
149 assert snip_setuptools_verify2.ffi.string(p.pw_name) == b"root"
150 ''')
151
152 def test_set_py_limited_api(self):
153 from cffi.setuptools_ext import _set_py_limited_api
154 try:
155 import setuptools
156 except ImportError as e:
157 py.test.skip(str(e))
158 orig_version = setuptools.__version__
159 expecting_limited_api = not hasattr(sys, 'gettotalrefcount')
160 try:
161 setuptools.__version__ = '26.0.0'
162 from setuptools import Extension
163
164 kwds = _set_py_limited_api(Extension, {})
165 assert kwds.get('py_limited_api', False) == expecting_limited_api
166
167 setuptools.__version__ = '25.0'
168 kwds = _set_py_limited_api(Extension, {})
169 assert kwds.get('py_limited_api', False) == False
170
171 setuptools.__version__ = 'development'
172 kwds = _set_py_limited_api(Extension, {})
173 assert kwds.get('py_limited_api', False) == expecting_limited_api
174
175 finally:
176 setuptools.__version__ = orig_version
0 # Generated by pypy/tool/import_cffi.py
0 # Generated by pypy/tool/import_cffi.py
1 import py, sys, os
2 import _cffi_backend
3
4 def test_no_unknown_exported_symbols():
5 if not hasattr(_cffi_backend, '__file__'):
6 py.test.skip("_cffi_backend module is built-in")
7 if not sys.platform.startswith('linux'):
8 py.test.skip("linux-only")
9 g = os.popen("objdump -T '%s'" % _cffi_backend.__file__, 'r')
10 for line in g:
11 if not line.startswith('0'):
12 continue
13 if '*UND*' in line:
14 continue
15 name = line.split()[-1]
16 if name.startswith('_') or name.startswith('.'):
17 continue
18 if name not in ('init_cffi_backend', 'PyInit__cffi_backend'):
19 raise Exception("Unexpected exported name %r" % (name,))
20 g.close()
0 # Generated by pypy/tool/import_cffi.py
1 import py, os, cffi, re
2 import _cffi_backend
3
4
5 def getlines():
6 try:
7 f = open(os.path.join(os.path.dirname(cffi.__file__),
8 '..', 'c', 'commontypes.c'))
9 except IOError:
10 py.test.skip("cannot find ../c/commontypes.c")
11 lines = [line for line in f.readlines() if line.strip().startswith('EQ(')]
12 f.close()
13 return lines
14
15 def test_alphabetical_order():
16 lines = getlines()
17 assert lines == sorted(lines)
18
19 def test_dependencies():
20 r = re.compile(r'EQ[(]"([^"]+)",(?:\s*"([A-Z0-9_]+)\s*[*]*"[)])?')
21 lines = getlines()
22 d = {}
23 for line in lines:
24 match = r.search(line)
25 if match is not None:
26 d[match.group(1)] = match.group(2)
27 for value in d.values():
28 if value:
29 assert value in d
30
31 def test_get_common_types():
32 d = {}
33 _cffi_backend._get_common_types(d)
34 assert d["bool"] == "_Bool"
0 # Generated by pypy/tool/import_cffi.py
1 import py
2 from cffi import FFI, VerificationError, CDefError
3 from cffi.recompiler import make_py_source
4 from extra_tests.cffi_tests.udir import udir
5
6
7 def test_simple():
8 ffi = FFI()
9 ffi.cdef("int close(int); static const int BB = 42; int somevar;")
10 target = udir.join('test_simple.py')
11 make_py_source(ffi, 'test_simple', str(target))
12 assert target.read() == r"""# auto-generated file
13 import _cffi_backend
14
15 ffi = _cffi_backend.FFI('test_simple',
16 _version = 0x2601,
17 _types = b'\x00\x00\x01\x0D\x00\x00\x07\x01\x00\x00\x00\x0F',
18 _globals = (b'\xFF\xFF\xFF\x1FBB',42,b'\x00\x00\x00\x23close',0,b'\x00\x00\x01\x21somevar',0),
19 )
20 """
21
22 def test_global_constant():
23 ffi = FFI()
24 ffi.cdef("static const long BB; static const float BF = 12;")
25 target = udir.join('test_valid_global_constant.py')
26 make_py_source(ffi, 'test_valid_global_constant', str(target))
27 assert target.read() == r"""# auto-generated file
28 import _cffi_backend
29
30 ffi = _cffi_backend.FFI('test_valid_global_constant',
31 _version = 0x2601,
32 _types = b'\x00\x00\x0D\x01\x00\x00\x09\x01',
33 _globals = (b'\x00\x00\x01\x25BB',0,b'\x00\x00\x00\x25BF',0),
34 )
35 """
36
37 def test_invalid_global_constant_3():
38 ffi = FFI()
39 e = py.test.raises(CDefError, ffi.cdef, "#define BB 12.34")
40 assert str(e.value).startswith(
41 "only supports one of the following syntax:")
42
43 def test_invalid_dotdotdot_in_macro():
44 ffi = FFI()
45 ffi.cdef("#define FOO ...")
46 target = udir.join('test_invalid_dotdotdot_in_macro.py')
47 e = py.test.raises(VerificationError, make_py_source, ffi,
48 'test_invalid_dotdotdot_in_macro', str(target))
49 assert str(e.value) == ("macro FOO: cannot use the syntax '...' in "
50 "'#define FOO ...' when using the ABI mode")
51
52 def test_typename():
53 ffi = FFI()
54 ffi.cdef("typedef int foobar_t;")
55 target = udir.join('test_typename.py')
56 make_py_source(ffi, 'test_typename', str(target))
57 assert target.read() == r"""# auto-generated file
58 import _cffi_backend
59
60 ffi = _cffi_backend.FFI('test_typename',
61 _version = 0x2601,
62 _types = b'\x00\x00\x07\x01',
63 _typenames = (b'\x00\x00\x00\x00foobar_t',),
64 )
65 """
66
67 def test_enum():
68 ffi = FFI()
69 ffi.cdef("enum myenum_e { AA, BB, CC=-42 };")
70 target = udir.join('test_enum.py')
71 make_py_source(ffi, 'test_enum', str(target))
72 assert target.read() == r"""# auto-generated file
73 import _cffi_backend
74
75 ffi = _cffi_backend.FFI('test_enum',
76 _version = 0x2601,
77 _types = b'\x00\x00\x00\x0B',
78 _globals = (b'\xFF\xFF\xFF\x0BAA',0,b'\xFF\xFF\xFF\x0BBB',1,b'\xFF\xFF\xFF\x0BCC',-42),
79 _enums = (b'\x00\x00\x00\x00\x00\x00\x00\x15myenum_e\x00AA,BB,CC',),
80 )
81 """
82
83 def test_struct():
84 ffi = FFI()
85 ffi.cdef("struct foo_s { int a; signed char b[]; }; struct bar_s;")
86 target = udir.join('test_struct.py')
87 make_py_source(ffi, 'test_struct', str(target))
88 assert target.read() == r"""# auto-generated file
89 import _cffi_backend
90
91 ffi = _cffi_backend.FFI('test_struct',
92 _version = 0x2601,
93 _types = b'\x00\x00\x07\x01\x00\x00\x03\x01\x00\x00\x01\x07\x00\x00\x00\x09\x00\x00\x01\x09',
94 _struct_unions = ((b'\x00\x00\x00\x03\x00\x00\x00\x10bar_s',),(b'\x00\x00\x00\x04\x00\x00\x00\x02foo_s',b'\x00\x00\x00\x11a',b'\x00\x00\x02\x11b')),
95 )
96 """
97
98 def test_include():
99 ffi = FFI()
100 ffi.cdef("#define ABC 123")
101 ffi.set_source('test_include', None)
102 target = udir.join('test_include.py')
103 make_py_source(ffi, 'test_include', str(target))
104 assert target.read() == r"""# auto-generated file
105 import _cffi_backend
106
107 ffi = _cffi_backend.FFI('test_include',
108 _version = 0x2601,
109 _types = b'',
110 _globals = (b'\xFF\xFF\xFF\x1FABC',123,),
111 )
112 """
113 #
114 ffi2 = FFI()
115 ffi2.include(ffi)
116 target2 = udir.join('test2_include.py')
117 make_py_source(ffi2, 'test2_include', str(target2))
118 assert target2.read() == r"""# auto-generated file
119 import _cffi_backend
120 from test_include import ffi as _ffi0
121
122 ffi = _cffi_backend.FFI('test2_include',
123 _version = 0x2601,
124 _types = b'',
125 _includes = (_ffi0,),
126 )
127 """
128
129 def test_negative_constant():
130 ffi = FFI()
131 ffi.cdef("static const int BB = -42;")
132 target = udir.join('test_negative_constant.py')
133 make_py_source(ffi, 'test_negative_constant', str(target))
134 assert target.read() == r"""# auto-generated file
135 import _cffi_backend
136
137 ffi = _cffi_backend.FFI('test_negative_constant',
138 _version = 0x2601,
139 _types = b'',
140 _globals = (b'\xFF\xFF\xFF\x1FBB',-42,),
141 )
142 """
143
144 def test_struct_included():
145 baseffi = FFI()
146 baseffi.cdef("struct foo_s { int x; };")
147 baseffi.set_source('test_struct_included_base', None)
148 #
149 ffi = FFI()
150 ffi.include(baseffi)
151 target = udir.join('test_struct_included.py')
152 make_py_source(ffi, 'test_struct_included', str(target))
153 assert target.read() == r"""# auto-generated file
154 import _cffi_backend
155 from test_struct_included_base import ffi as _ffi0
156
157 ffi = _cffi_backend.FFI('test_struct_included',
158 _version = 0x2601,
159 _types = b'\x00\x00\x00\x09',
160 _struct_unions = ((b'\x00\x00\x00\x00\x00\x00\x00\x08foo_s',),),
161 _includes = (_ffi0,),
162 )
163 """
164
165 def test_no_cross_include():
166 baseffi = FFI()
167 baseffi.set_source('test_no_cross_include_base', "..source..")
168 #
169 ffi = FFI()
170 ffi.include(baseffi)
171 target = udir.join('test_no_cross_include.py')
172 py.test.raises(VerificationError, make_py_source,
173 ffi, 'test_no_cross_include', str(target))
174
175 def test_array():
176 ffi = FFI()
177 ffi.cdef("typedef int32_t my_array_t[42];")
178 target = udir.join('test_array.py')
179 make_py_source(ffi, 'test_array', str(target))
180 assert target.read() == r"""# auto-generated file
181 import _cffi_backend
182
183 ffi = _cffi_backend.FFI('test_array',
184 _version = 0x2601,
185 _types = b'\x00\x00\x15\x01\x00\x00\x00\x05\x00\x00\x00\x2A',
186 _typenames = (b'\x00\x00\x00\x01my_array_t',),
187 )
188 """
189
190 def test_array_overflow():
191 ffi = FFI()
192 ffi.cdef("typedef int32_t my_array_t[3000000000];")
193 target = udir.join('test_array_overflow.py')
194 py.test.raises(OverflowError, make_py_source,
195 ffi, 'test_array_overflow', str(target))
196
197 def test_global_var():
198 ffi = FFI()
199 ffi.cdef("int myglob;")
200 target = udir.join('test_global_var.py')
201 make_py_source(ffi, 'test_global_var', str(target))
202 assert target.read() == r"""# auto-generated file
203 import _cffi_backend
204
205 ffi = _cffi_backend.FFI('test_global_var',
206 _version = 0x2601,
207 _types = b'\x00\x00\x07\x01',
208 _globals = (b'\x00\x00\x00\x21myglob',0,),
209 )
210 """
211
212 def test_bitfield():
213 ffi = FFI()
214 ffi.cdef("struct foo_s { int y:10; short x:5; };")
215 target = udir.join('test_bitfield.py')
216 make_py_source(ffi, 'test_bitfield', str(target))
217 assert target.read() == r"""# auto-generated file
218 import _cffi_backend
219
220 ffi = _cffi_backend.FFI('test_bitfield',
221 _version = 0x2601,
222 _types = b'\x00\x00\x07\x01\x00\x00\x05\x01\x00\x00\x00\x09',
223 _struct_unions = ((b'\x00\x00\x00\x02\x00\x00\x00\x02foo_s',b'\x00\x00\x00\x13\x00\x00\x00\x0Ay',b'\x00\x00\x01\x13\x00\x00\x00\x05x'),),
224 )
225 """
0 # Generated by pypy/tool/import_cffi.py
1 import py, os
2
3 s = """from __future__ import unicode_literals
4 """
5
6 with open(os.path.join(os.path.dirname(__file__), 'test_dlopen.py')) as f:
7 s += f.read()
8
9 exec(py.code.compile(s))
0 # Generated by pypy/tool/import_cffi.py
1 import py, sys
2 import _cffi_backend as _cffi1_backend
3
4
5 def test_ffi_new():
6 ffi = _cffi1_backend.FFI()
7 p = ffi.new("int *")
8 p[0] = -42
9 assert p[0] == -42
10 assert type(ffi) is ffi.__class__ is _cffi1_backend.FFI
11
12 def test_ffi_subclass():
13 class FOO(_cffi1_backend.FFI):
14 def __init__(self, x):
15 self.x = x
16 foo = FOO(42)
17 assert foo.x == 42
18 p = foo.new("int *")
19 assert p[0] == 0
20 assert type(foo) is foo.__class__ is FOO
21
22 def test_ffi_no_argument():
23 py.test.raises(TypeError, _cffi1_backend.FFI, 42)
24
25 def test_ffi_cache_type():
26 ffi = _cffi1_backend.FFI()
27 t1 = ffi.typeof("int **")
28 t2 = ffi.typeof("int *")
29 assert t2.item is t1.item.item
30 assert t2 is t1.item
31 assert ffi.typeof("int[][10]") is ffi.typeof("int[][10]")
32 assert ffi.typeof("int(*)()") is ffi.typeof("int(*)()")
33
34 def test_ffi_type_not_immortal():
35 import weakref, gc
36 ffi = _cffi1_backend.FFI()
37 t1 = ffi.typeof("int **")
38 t2 = ffi.typeof("int *")
39 w1 = weakref.ref(t1)
40 w2 = weakref.ref(t2)
41 del t1, ffi
42 gc.collect()
43 assert w1() is None
44 assert w2() is t2
45 ffi = _cffi1_backend.FFI()
46 assert ffi.typeof(ffi.new("int **")[0]) is t2
47 #
48 ffi = _cffi1_backend.FFI()
49 t1 = ffi.typeof("int ***")
50 t2 = ffi.typeof("int **")
51 w1 = weakref.ref(t1)
52 w2 = weakref.ref(t2)
53 del t2, ffi
54 gc.collect()
55 assert w1() is t1
56 assert w2() is not None # kept alive by t1
57 ffi = _cffi1_backend.FFI()
58 assert ffi.typeof("int * *") is t1.item
59
60 def test_ffi_cache_type_globally():
61 ffi1 = _cffi1_backend.FFI()
62 ffi2 = _cffi1_backend.FFI()
63 t1 = ffi1.typeof("int *")
64 t2 = ffi2.typeof("int *")
65 assert t1 is t2
66
67 def test_ffi_invalid():
68 ffi = _cffi1_backend.FFI()
69 # array of 10 times an "int[]" is invalid
70 py.test.raises(ValueError, ffi.typeof, "int[10][]")
71
72 def test_ffi_docstrings():
73 # check that all methods of the FFI class have a docstring.
74 check_type = type(_cffi1_backend.FFI.new)
75 for methname in dir(_cffi1_backend.FFI):
76 if not methname.startswith('_'):
77 method = getattr(_cffi1_backend.FFI, methname)
78 if isinstance(method, check_type):
79 assert method.__doc__, "method FFI.%s() has no docstring" % (
80 methname,)
81
82 def test_ffi_NULL():
83 NULL = _cffi1_backend.FFI.NULL
84 assert _cffi1_backend.FFI().typeof(NULL).cname == "void *"
85
86 def test_ffi_no_attr():
87 ffi = _cffi1_backend.FFI()
88 py.test.raises(AttributeError, "ffi.no_such_name")
89 py.test.raises(AttributeError, "ffi.no_such_name = 42")
90 py.test.raises(AttributeError, "del ffi.no_such_name")
91
92 def test_ffi_string():
93 ffi = _cffi1_backend.FFI()
94 p = ffi.new("char[]", init=b"foobar\x00baz")
95 assert ffi.string(p) == b"foobar"
96 assert ffi.string(cdata=p, maxlen=3) == b"foo"
97
98 def test_ffi_errno():
99 # xxx not really checking errno, just checking that we can read/write it
100 ffi = _cffi1_backend.FFI()
101 ffi.errno = 42
102 assert ffi.errno == 42
103
104 def test_ffi_alignof():
105 ffi = _cffi1_backend.FFI()
106 assert ffi.alignof("int") == 4
107 assert ffi.alignof("int[]") == 4
108 assert ffi.alignof("int[41]") == 4
109 assert ffi.alignof("short[41]") == 2
110 assert ffi.alignof(ffi.new("int[41]")) == 4
111 assert ffi.alignof(ffi.new("int[]", 41)) == 4
112
113 def test_ffi_sizeof():
114 ffi = _cffi1_backend.FFI()
115 assert ffi.sizeof("int") == 4
116 py.test.raises(ffi.error, ffi.sizeof, "int[]")
117 assert ffi.sizeof("int[41]") == 41 * 4
118 assert ffi.sizeof(ffi.new("int[41]")) == 41 * 4
119 assert ffi.sizeof(ffi.new("int[]", 41)) == 41 * 4
120
121 def test_ffi_callback():
122 ffi = _cffi1_backend.FFI()
123 assert ffi.callback("int(int)", lambda x: x + 42)(10) == 52
124 assert ffi.callback("int(*)(int)", lambda x: x + 42)(10) == 52
125 assert ffi.callback("int(int)", lambda x: x + "", -66)(10) == -66
126 assert ffi.callback("int(int)", lambda x: x + "", error=-66)(10) == -66
127
128 def test_ffi_callback_decorator():
129 ffi = _cffi1_backend.FFI()
130 assert ffi.callback(ffi.typeof("int(*)(int)"))(lambda x: x + 42)(10) == 52
131 deco = ffi.callback("int(int)", error=-66)
132 assert deco(lambda x: x + "")(10) == -66
133 assert deco(lambda x: x + 42)(10) == 52
134
135 def test_ffi_callback_onerror():
136 ffi = _cffi1_backend.FFI()
137 seen = []
138 def oops(*args):
139 seen.append(args)
140
141 @ffi.callback("int(int)", onerror=oops)
142 def fn1(x):
143 return x + ""
144 assert fn1(10) == 0
145
146 @ffi.callback("int(int)", onerror=oops, error=-66)
147 def fn2(x):
148 return x + ""
149 assert fn2(10) == -66
150
151 assert len(seen) == 2
152 exc, val, tb = seen[0]
153 assert exc is TypeError
154 assert isinstance(val, TypeError)
155 assert tb.tb_frame.f_code.co_name == "fn1"
156 exc, val, tb = seen[1]
157 assert exc is TypeError
158 assert isinstance(val, TypeError)
159 assert tb.tb_frame.f_code.co_name == "fn2"
160 #
161 py.test.raises(TypeError, ffi.callback, "int(int)",
162 lambda x: x, onerror=42) # <- not callable
163
164 def test_ffi_getctype():
165 ffi = _cffi1_backend.FFI()
166 assert ffi.getctype("int") == "int"
167 assert ffi.getctype("int", 'x') == "int x"
168 assert ffi.getctype("int*") == "int *"
169 assert ffi.getctype("int*", '') == "int *"
170 assert ffi.getctype("int*", 'x') == "int * x"
171 assert ffi.getctype("int", '*') == "int *"
172 assert ffi.getctype("int", replace_with=' * x ') == "int * x"
173 assert ffi.getctype(ffi.typeof("int*"), '*') == "int * *"
174 assert ffi.getctype("int", '[5]') == "int[5]"
175 assert ffi.getctype("int[5]", '[6]') == "int[6][5]"
176 assert ffi.getctype("int[5]", '(*)') == "int(*)[5]"
177 # special-case for convenience: automatically put '()' around '*'
178 assert ffi.getctype("int[5]", '*') == "int(*)[5]"
179 assert ffi.getctype("int[5]", '*foo') == "int(*foo)[5]"
180 assert ffi.getctype("int[5]", ' ** foo ') == "int(** foo)[5]"
181
182 def test_addressof():
183 ffi = _cffi1_backend.FFI()
184 a = ffi.new("int[10]")
185 b = ffi.addressof(a, 5)
186 b[2] = -123
187 assert a[7] == -123
188
189 def test_handle():
190 ffi = _cffi1_backend.FFI()
191 x = [2, 4, 6]
192 xp = ffi.new_handle(x)
193 assert ffi.typeof(xp) == ffi.typeof("void *")
194 assert ffi.from_handle(xp) is x
195 yp = ffi.new_handle([6, 4, 2])
196 assert ffi.from_handle(yp) == [6, 4, 2]
197
198 def test_handle_unique():
199 ffi = _cffi1_backend.FFI()
200 assert ffi.new_handle(None) is not ffi.new_handle(None)
201 assert ffi.new_handle(None) != ffi.new_handle(None)
202
203 def test_ffi_cast():
204 ffi = _cffi1_backend.FFI()
205 assert ffi.cast("int(*)(int)", 0) == ffi.NULL
206 ffi.callback("int(int)") # side-effect of registering this string
207 py.test.raises(ffi.error, ffi.cast, "int(int)", 0)
208
209 def test_ffi_invalid_type():
210 ffi = _cffi1_backend.FFI()
211 e = py.test.raises(ffi.error, ffi.cast, "", 0)
212 assert str(e.value) == ("identifier expected\n"
213 "\n"
214 "^")
215 e = py.test.raises(ffi.error, ffi.cast, "struct struct", 0)
216 assert str(e.value) == ("struct or union name expected\n"
217 "struct struct\n"
218 " ^")
219 e = py.test.raises(ffi.error, ffi.cast, "struct never_heard_of_s", 0)
220 assert str(e.value) == ("undefined struct/union name\n"
221 "struct never_heard_of_s\n"
222 " ^")
223 e = py.test.raises(ffi.error, ffi.cast, "\t\n\x01\x1f~\x7f\x80\xff", 0)
224 marks = "?" if sys.version_info < (3,) else "??"
225 assert str(e.value) == ("identifier expected\n"
226 " ??~?%s%s\n"
227 " ^" % (marks, marks))
228 e = py.test.raises(ffi.error, ffi.cast, "X" * 600, 0)
229 assert str(e.value) == ("undefined type name")
230
231 def test_ffi_buffer():
232 ffi = _cffi1_backend.FFI()
233 a = ffi.new("signed char[]", [5, 6, 7])
234 assert ffi.buffer(a)[:] == b'\x05\x06\x07'
235 assert ffi.buffer(cdata=a, size=2)[:] == b'\x05\x06'
236 assert type(ffi.buffer(a)) is ffi.buffer
237
238 def test_ffi_from_buffer():
239 import array
240 ffi = _cffi1_backend.FFI()
241 a = array.array('H', [10000, 20000, 30000, 40000])
242 c = ffi.from_buffer(a)
243 assert ffi.typeof(c) is ffi.typeof("char[]")
244 assert len(c) == 8
245 ffi.cast("unsigned short *", c)[1] += 500
246 assert list(a) == [10000, 20500, 30000, 40000]
247 py.test.raises(TypeError, ffi.from_buffer, a, True)
248 assert c == ffi.from_buffer("char[]", a, True)
249 assert c == ffi.from_buffer(a, require_writable=True)
250 #
251 c = ffi.from_buffer("unsigned short[]", a)
252 assert len(c) == 4
253 assert c[1] == 20500
254 #
255 c = ffi.from_buffer("unsigned short[2][2]", a)
256 assert len(c) == 2
257 assert len(c[0]) == 2
258 assert c[0][1] == 20500
259 #
260 p = ffi.from_buffer(b"abcd")
261 assert p[2] == b"c"
262 #
263 assert p == ffi.from_buffer(b"abcd", require_writable=False)
264 py.test.raises((TypeError, BufferError), ffi.from_buffer,
265 "char[]", b"abcd", True)
266 py.test.raises((TypeError, BufferError), ffi.from_buffer, b"abcd",
267 require_writable=True)
268
269 def test_memmove():
270 ffi = _cffi1_backend.FFI()
271 p = ffi.new("short[]", [-1234, -2345, -3456, -4567, -5678])
272 ffi.memmove(p, p + 1, 4)
273 assert list(p) == [-2345, -3456, -3456, -4567, -5678]
274 p[2] = 999
275 ffi.memmove(p + 2, p, 6)
276 assert list(p) == [-2345, -3456, -2345, -3456, 999]
277 ffi.memmove(p + 4, ffi.new("char[]", b"\x71\x72"), 2)
278 if sys.byteorder == 'little':
279 assert list(p) == [-2345, -3456, -2345, -3456, 0x7271]
280 else:
281 assert list(p) == [-2345, -3456, -2345, -3456, 0x7172]
282
283 def test_memmove_buffer():
284 import array
285 ffi = _cffi1_backend.FFI()
286 a = array.array('H', [10000, 20000, 30000])
287 p = ffi.new("short[]", 5)
288 ffi.memmove(p, a, 6)
289 assert list(p) == [10000, 20000, 30000, 0, 0]
290 ffi.memmove(p + 1, a, 6)
291 assert list(p) == [10000, 10000, 20000, 30000, 0]
292 b = array.array('h', [-1000, -2000, -3000])
293 ffi.memmove(b, a, 4)
294 assert b.tolist() == [10000, 20000, -3000]
295 assert a.tolist() == [10000, 20000, 30000]
296 p[0] = 999
297 p[1] = 998
298 p[2] = 997
299 p[3] = 996
300 p[4] = 995
301 ffi.memmove(b, p, 2)
302 assert b.tolist() == [999, 20000, -3000]
303 ffi.memmove(b, p + 2, 4)
304 assert b.tolist() == [997, 996, -3000]
305 p[2] = -p[2]
306 p[3] = -p[3]
307 ffi.memmove(b, p + 2, 6)
308 assert b.tolist() == [-997, -996, 995]
309
310 def test_memmove_readonly_readwrite():
311 ffi = _cffi1_backend.FFI()
312 p = ffi.new("signed char[]", 5)
313 ffi.memmove(p, b"abcde", 3)
314 assert list(p) == [ord("a"), ord("b"), ord("c"), 0, 0]
315 ffi.memmove(p, bytearray(b"ABCDE"), 2)
316 assert list(p) == [ord("A"), ord("B"), ord("c"), 0, 0]
317 py.test.raises((TypeError, BufferError), ffi.memmove, b"abcde", p, 3)
318 ba = bytearray(b"xxxxx")
319 ffi.memmove(dest=ba, src=p, n=3)
320 assert ba == bytearray(b"ABcxx")
321
322 def test_ffi_types():
323 CData = _cffi1_backend.FFI.CData
324 CType = _cffi1_backend.FFI.CType
325 ffi = _cffi1_backend.FFI()
326 assert isinstance(ffi.cast("int", 42), CData)
327 assert isinstance(ffi.typeof("int"), CType)
328
329 def test_ffi_getwinerror():
330 if sys.platform != "win32":
331 py.test.skip("for windows")
332 ffi = _cffi1_backend.FFI()
333 n = (1 << 29) + 42
334 code, message = ffi.getwinerror(code=n)
335 assert code == n
336
337 def test_ffi_new_allocator_1():
338 ffi = _cffi1_backend.FFI()
339 alloc1 = ffi.new_allocator()
340 alloc2 = ffi.new_allocator(should_clear_after_alloc=False)
341 for retry in range(100):
342 p1 = alloc1("int[10]")
343 p2 = alloc2("int[10]")
344 combination = 0
345 for i in range(10):
346 assert p1[i] == 0
347 combination |= p2[i]
348 p1[i] = -42
349 p2[i] = -43
350 if combination != 0:
351 break
352 del p1, p2
353 import gc; gc.collect()
354 else:
355 raise AssertionError("cannot seem to get an int[10] not "
356 "completely cleared")
357
358 def test_ffi_new_allocator_2():
359 ffi = _cffi1_backend.FFI()
360 seen = []
361 def myalloc(size):
362 seen.append(size)
363 return ffi.new("char[]", b"X" * size)
364 def myfree(raw):
365 seen.append(raw)
366 alloc1 = ffi.new_allocator(myalloc, myfree)
367 alloc2 = ffi.new_allocator(alloc=myalloc, free=myfree,
368 should_clear_after_alloc=False)
369 p1 = alloc1("int[10]")
370 p2 = alloc2("int[]", 10)
371 assert seen == [40, 40]
372 assert ffi.typeof(p1) == ffi.typeof("int[10]")
373 assert ffi.sizeof(p1) == 40
374 assert ffi.typeof(p2) == ffi.typeof("int[]")
375 assert ffi.sizeof(p2) == 40
376 assert p1[5] == 0
377 assert p2[6] == ord('X') * 0x01010101
378 raw1 = ffi.cast("char *", p1)
379 raw2 = ffi.cast("char *", p2)
380 del p1, p2
381 retries = 0
382 while len(seen) != 4:
383 retries += 1
384 assert retries <= 5
385 import gc; gc.collect()
386 assert (seen == [40, 40, raw1, raw2] or
387 seen == [40, 40, raw2, raw1])
388 assert repr(seen[2]) == "<cdata 'char[]' owning 41 bytes>"
389 assert repr(seen[3]) == "<cdata 'char[]' owning 41 bytes>"
390
391 def test_ffi_new_allocator_3():
392 ffi = _cffi1_backend.FFI()
393 seen = []
394 def myalloc(size):
395 seen.append(size)
396 return ffi.new("char[]", b"X" * size)
397 alloc1 = ffi.new_allocator(myalloc) # no 'free'
398 p1 = alloc1("int[10]")
399 assert seen == [40]
400 assert ffi.typeof(p1) == ffi.typeof("int[10]")
401 assert ffi.sizeof(p1) == 40
402 assert p1[5] == 0
403
404 def test_ffi_new_allocator_4():
405 ffi = _cffi1_backend.FFI()
406 py.test.raises(TypeError, ffi.new_allocator, free=lambda x: None)
407 #
408 def myalloc2(size):
409 raise LookupError
410 alloc2 = ffi.new_allocator(myalloc2)
411 py.test.raises(LookupError, alloc2, "int[5]")
412 #
413 def myalloc3(size):
414 return 42
415 alloc3 = ffi.new_allocator(myalloc3)
416 e = py.test.raises(TypeError, alloc3, "int[5]")
417 assert str(e.value) == "alloc() must return a cdata object (got int)"
418 #
419 def myalloc4(size):
420 return ffi.cast("int", 42)
421 alloc4 = ffi.new_allocator(myalloc4)
422 e = py.test.raises(TypeError, alloc4, "int[5]")
423 assert str(e.value) == "alloc() must return a cdata pointer, not 'int'"
424 #
425 def myalloc5(size):
426 return ffi.NULL
427 alloc5 = ffi.new_allocator(myalloc5)
428 py.test.raises(MemoryError, alloc5, "int[5]")
429
430 def test_bool_issue228():
431 ffi = _cffi1_backend.FFI()
432 fntype = ffi.typeof("int(*callback)(bool is_valid)")
433 assert repr(fntype.args[0]) == "<ctype '_Bool'>"
434
435 def test_FILE_issue228():
436 fntype1 = _cffi1_backend.FFI().typeof("FILE *")
437 fntype2 = _cffi1_backend.FFI().typeof("FILE *")
438 assert repr(fntype1) == "<ctype 'FILE *'>"
439 assert fntype1 is fntype2
440
441 def test_cast_from_int_type_to_bool():
442 ffi = _cffi1_backend.FFI()
443 for basetype in ['char', 'short', 'int', 'long', 'long long']:
444 for sign in ['signed', 'unsigned']:
445 type = '%s %s' % (sign, basetype)
446 assert int(ffi.cast("_Bool", ffi.cast(type, 42))) == 1
447 assert int(ffi.cast("bool", ffi.cast(type, 42))) == 1
448 assert int(ffi.cast("_Bool", ffi.cast(type, 0))) == 0
449
450 def test_init_once():
451 def do_init():
452 seen.append(1)
453 return 42
454 ffi = _cffi1_backend.FFI()
455 seen = []
456 for i in range(3):
457 res = ffi.init_once(do_init, "tag1")
458 assert res == 42
459 assert seen == [1]
460 for i in range(3):
461 res = ffi.init_once(do_init, "tag2")
462 assert res == 42
463 assert seen == [1, 1]
464
465 def test_init_once_multithread():
466 if sys.version_info < (3,):
467 import thread
468 else:
469 import _thread as thread
470 import time
471 #
472 def do_init():
473 print('init!')
474 seen.append('init!')
475 time.sleep(1)
476 seen.append('init done')
477 print('init done')
478 return 7
479 ffi = _cffi1_backend.FFI()
480 seen = []
481 for i in range(6):
482 def f():
483 res = ffi.init_once(do_init, "tag")
484 seen.append(res)
485 thread.start_new_thread(f, ())
486 time.sleep(1.5)
487 assert seen == ['init!', 'init done'] + 6 * [7]
488
489 def test_init_once_failure():
490 def do_init():
491 seen.append(1)
492 raise ValueError
493 ffi = _cffi1_backend.FFI()
494 seen = []
495 for i in range(5):
496 py.test.raises(ValueError, ffi.init_once, do_init, "tag")
497 assert seen == [1] * (i + 1)
498
499 def test_init_once_multithread_failure():
500 if sys.version_info < (3,):
501 import thread
502 else:
503 import _thread as thread
504 import time
505 def do_init():
506 seen.append('init!')
507 time.sleep(1)
508 seen.append('oops')
509 raise ValueError
510 ffi = _cffi1_backend.FFI()
511 seen = []
512 for i in range(3):
513 def f():
514 py.test.raises(ValueError, ffi.init_once, do_init, "tag")
515 thread.start_new_thread(f, ())
516 i = 0
517 while len(seen) < 6:
518 i += 1
519 assert i < 20
520 time.sleep(0.51)
521 assert seen == ['init!', 'oops'] * 3
522
523 def test_unpack():
524 ffi = _cffi1_backend.FFI()
525 p = ffi.new("char[]", b"abc\x00def")
526 assert ffi.unpack(p+1, 7) == b"bc\x00def\x00"
527 p = ffi.new("int[]", [-123456789])
528 assert ffi.unpack(p, 1) == [-123456789]
529
530 def test_negative_array_size():
531 ffi = _cffi1_backend.FFI()
532 py.test.raises(ffi.error, ffi.cast, "int[-5]", 0)
0 # Generated by pypy/tool/import_cffi.py
1 import py
2 import platform, imp
3 import sys, os, ctypes
4 import cffi
5 from extra_tests.cffi_tests.udir import udir
6 from extra_tests.cffi_tests.support import *
7 from cffi.recompiler import recompile
8 from cffi.cffi_opcode import PRIMITIVE_TO_INDEX
9
10 SIZE_OF_INT = ctypes.sizeof(ctypes.c_int)
11 SIZE_OF_LONG = ctypes.sizeof(ctypes.c_long)
12 SIZE_OF_SHORT = ctypes.sizeof(ctypes.c_short)
13 SIZE_OF_PTR = ctypes.sizeof(ctypes.c_void_p)
14 SIZE_OF_WCHAR = ctypes.sizeof(ctypes.c_wchar)
15
16
17 def setup_module():
18 global ffi, construction_params
19 ffi1 = cffi.FFI()
20 DEFS = r"""
21 struct repr { short a, b, c; };
22 struct simple { int a; short b, c; };
23 struct array { int a[2]; char b[3]; };
24 struct recursive { int value; struct recursive *next; };
25 union simple_u { int a; short b, c; };
26 union init_u { char a; int b; };
27 struct four_s { int a; short b, c, d; };
28 union four_u { int a; short b, c, d; };
29 struct string { const char *name; };
30 struct ustring { const wchar_t *name; };
31 struct voidp { void *p; int *q; short *r; };
32 struct ab { int a, b; };
33 struct abc { int a, b, c; };
34
35 /* don't use A0, B0, CC0, D0 because termios.h might be included
36 and it has its own #defines for these names */
37 enum foq { cffiA0, cffiB0, cffiCC0, cffiD0 };
38 enum bar { A1, B1=-2, CC1, D1, E1 };
39 enum baz { A2=0x1000, B2=0x2000 };
40 enum foo2 { A3, B3, C3, D3 };
41 struct bar_with_e { enum foo2 e; };
42 enum noncont { A4, B4=42, C4 };
43 enum etypes {A5='!', B5='\'', C5=0x10, D5=010, E5=- 0x10, F5=-010};
44 typedef enum { Value0 = 0 } e_t, *pe_t;
45 enum e_noninj { AA3=0, BB3=0, CC3=0, DD3=0 };
46 enum e_prev { AA4, BB4=2, CC4=4, DD4=BB4, EE4, FF4=CC4, GG4=FF4 };
47
48 struct nesting { struct abc d, e; };
49 struct array2 { int a, b; int c[99]; };
50 struct align { char a; short b; char c; };
51 struct bitfield { int a:10, b:20, c:3; };
52 typedef enum { AA2, BB2, CC2 } foo_e_t;
53 typedef struct { foo_e_t f:2; } bfenum_t;
54 typedef struct { int a; } anon_foo_t;
55 typedef struct { char b, c; } anon_bar_t;
56 typedef struct named_foo_s { int a; } named_foo_t, *named_foo_p;
57 typedef struct { int a; } unnamed_foo_t, *unnamed_foo_p;
58 struct nonpacked { char a; int b; };
59 struct array0 { int len; short data[0]; };
60 struct array_no_length { int x; int a[]; };
61
62 struct nested_anon {
63 struct { int a, b; };
64 union { int c, d; };
65 };
66 struct nested_field_ofs_s {
67 struct { int a; char b; };
68 union { char c; };
69 };
70 union nested_anon_u {
71 struct { int a, b; };
72 union { int c, d; };
73 };
74 struct abc50 { int a, b; int c[50]; };
75 struct ints_and_bitfield { int a,b,c,d,e; int x:1; };
76 """
77 DEFS_PACKED = """
78 struct is_packed { char a; int b; } /*here*/;
79 """
80 if sys.platform == "win32":
81 DEFS = DEFS.replace('data[0]', 'data[1]') # not supported
82 CCODE = (DEFS + "\n#pragma pack(push,1)\n" + DEFS_PACKED +
83 "\n#pragma pack(pop)\n")
84 else:
85 CCODE = (DEFS +
86 DEFS_PACKED.replace('/*here*/', '__attribute__((packed))'))
87
88 ffi1.cdef(DEFS)
89 ffi1.cdef(DEFS_PACKED, packed=True)
90 ffi1.set_source("test_new_ffi_1", CCODE)
91
92 outputfilename = recompile(ffi1, "test_new_ffi_1", CCODE,
93 tmpdir=str(udir))
94 module = imp.load_dynamic("test_new_ffi_1", outputfilename)
95 ffi = module.ffi
96 construction_params = (ffi1, CCODE)
97
98
99 class TestNewFFI1:
100
101 def test_integer_ranges(self):
102 for (c_type, size) in [('char', 1),
103 ('short', 2),
104 ('short int', 2),
105 ('', 4),
106 ('int', 4),
107 ('long', SIZE_OF_LONG),
108 ('long int', SIZE_OF_LONG),
109 ('long long', 8),
110 ('long long int', 8),
111 ]:
112 for unsigned in [None, False, True]:
113 c_decl = {None: '',
114 False: 'signed ',
115 True: 'unsigned '}[unsigned] + c_type
116 if c_decl == 'char' or c_decl == '':
117 continue
118 self._test_int_type(ffi, c_decl, size, unsigned)
119
120 def test_fixedsize_int(self):
121 for size in [1, 2, 4, 8]:
122 self._test_int_type(ffi, 'int%d_t' % (8*size), size, False)
123 self._test_int_type(ffi, 'uint%d_t' % (8*size), size, True)
124 self._test_int_type(ffi, 'intptr_t', SIZE_OF_PTR, False)
125 self._test_int_type(ffi, 'uintptr_t', SIZE_OF_PTR, True)
126 self._test_int_type(ffi, 'ptrdiff_t', SIZE_OF_PTR, False)
127 self._test_int_type(ffi, 'size_t', SIZE_OF_PTR, True)
128 self._test_int_type(ffi, 'ssize_t', SIZE_OF_PTR, False)
129
130 def _test_int_type(self, ffi, c_decl, size, unsigned):
131 if unsigned:
132 min = 0
133 max = (1 << (8*size)) - 1
134 else:
135 min = -(1 << (8*size-1))
136 max = (1 << (8*size-1)) - 1
137 min = int(min)
138 max = int(max)
139 p = ffi.cast(c_decl, min)
140 assert p == min
141 assert bool(p) is bool(min)
142 assert int(p) == min
143 p = ffi.cast(c_decl, max)
144 assert int(p) == max
145 p = ffi.cast(c_decl, long(max))
146 assert int(p) == max
147 q = ffi.cast(c_decl, min - 1)
148 assert ffi.typeof(q) is ffi.typeof(p) and int(q) == max
149 q = ffi.cast(c_decl, long(min - 1))
150 assert ffi.typeof(q) is ffi.typeof(p) and int(q) == max
151 assert q == p
152 assert int(q) == int(p)
153 assert hash(q) == hash(p)
154 c_decl_ptr = '%s *' % c_decl
155 py.test.raises(OverflowError, ffi.new, c_decl_ptr, min - 1)
156 py.test.raises(OverflowError, ffi.new, c_decl_ptr, max + 1)
157 py.test.raises(OverflowError, ffi.new, c_decl_ptr, long(min - 1))
158 py.test.raises(OverflowError, ffi.new, c_decl_ptr, long(max + 1))
159 assert ffi.new(c_decl_ptr, min)[0] == min
160 assert ffi.new(c_decl_ptr, max)[0] == max
161 assert ffi.new(c_decl_ptr, long(min))[0] == min
162 assert ffi.new(c_decl_ptr, long(max))[0] == max
163
164 def test_new_unsupported_type(self):
165 e = py.test.raises(TypeError, ffi.new, "int")
166 assert str(e.value) == "expected a pointer or array ctype, got 'int'"
167
168 def test_new_single_integer(self):
169 p = ffi.new("int *") # similar to ffi.new("int[1]")
170 assert p[0] == 0
171 p[0] = -123
172 assert p[0] == -123
173 p = ffi.new("int *", -42)
174 assert p[0] == -42
175 assert repr(p) == "<cdata 'int *' owning %d bytes>" % SIZE_OF_INT
176
177 def test_new_array_no_arg(self):
178 p = ffi.new("int[10]")
179 # the object was zero-initialized:
180 for i in range(10):
181 assert p[i] == 0
182
183 def test_array_indexing(self):
184 p = ffi.new("int[10]")
185 p[0] = 42
186 p[9] = 43
187 assert p[0] == 42
188 assert p[9] == 43
189 py.test.raises(IndexError, "p[10]")
190 py.test.raises(IndexError, "p[10] = 44")
191 py.test.raises(IndexError, "p[-1]")
192 py.test.raises(IndexError, "p[-1] = 44")
193
194 def test_new_array_args(self):
195 # this tries to be closer to C: where we say "int x[5] = {10, 20, ..}"
196 # then here we must enclose the items in a list
197 p = ffi.new("int[5]", [10, 20, 30, 40, 50])
198 assert p[0] == 10
199 assert p[1] == 20
200 assert p[2] == 30
201 assert p[3] == 40
202 assert p[4] == 50
203 p = ffi.new("int[4]", [25])
204 assert p[0] == 25
205 assert p[1] == 0 # follow C convention rather than LuaJIT's
206 assert p[2] == 0
207 assert p[3] == 0
208 p = ffi.new("int[4]", [ffi.cast("int", -5)])
209 assert p[0] == -5
210 assert repr(p) == "<cdata 'int[4]' owning %d bytes>" % (4*SIZE_OF_INT)
211
212 def test_new_array_varsize(self):
213 p = ffi.new("int[]", 10) # a single integer is the length
214 assert p[9] == 0
215 py.test.raises(IndexError, "p[10]")
216 #
217 py.test.raises(TypeError, ffi.new, "int[]")
218 #
219 p = ffi.new("int[]", [-6, -7]) # a list is all the items, like C
220 assert p[0] == -6
221 assert p[1] == -7
222 py.test.raises(IndexError, "p[2]")
223 assert repr(p) == "<cdata 'int[]' owning %d bytes>" % (2*SIZE_OF_INT)
224 #
225 p = ffi.new("int[]", 0)
226 py.test.raises(IndexError, "p[0]")
227 py.test.raises(ValueError, ffi.new, "int[]", -1)
228 assert repr(p) == "<cdata 'int[]' owning 0 bytes>"
229
230 def test_pointer_init(self):
231 n = ffi.new("int *", 24)
232 a = ffi.new("int *[10]", [ffi.NULL, ffi.NULL, n, n, ffi.NULL])
233 for i in range(10):
234 if i not in (2, 3):
235 assert a[i] == ffi.NULL
236 assert a[2] == a[3] == n
237
238 def test_cannot_cast(self):
239 a = ffi.new("short int[10]")
240 e = py.test.raises(TypeError, ffi.new, "long int **", a)
241 msg = str(e.value)
242 assert "'short[10]'" in msg and "'long *'" in msg
243
244 def test_new_pointer_to_array(self):
245 a = ffi.new("int[4]", [100, 102, 104, 106])
246 p = ffi.new("int **", a)
247 assert p[0] == ffi.cast("int *", a)
248 assert p[0][2] == 104
249 p = ffi.cast("int *", a)
250 assert p[0] == 100
251 assert p[1] == 102
252 assert p[2] == 104
253 assert p[3] == 106
254 # keepalive: a
255
256 def test_pointer_direct(self):
257 p = ffi.cast("int*", 0)
258 assert p is not None
259 assert bool(p) is False
260 assert p == ffi.cast("int*", 0)
261 assert p != None
262 assert repr(p) == "<cdata 'int *' NULL>"
263 a = ffi.new("int[]", [123, 456])
264 p = ffi.cast("int*", a)
265 assert bool(p) is True
266 assert p == ffi.cast("int*", a)
267 assert p != ffi.cast("int*", 0)
268 assert p[0] == 123
269 assert p[1] == 456
270
271 def test_repr(self):
272 typerepr = "<ctype '%s'>"
273 p = ffi.cast("short unsigned int", 0)
274 assert repr(p) == "<cdata 'unsigned short' 0>"
275 assert repr(ffi.typeof(p)) == typerepr % "unsigned short"
276 p = ffi.cast("unsigned short int", 0)
277 assert repr(p) == "<cdata 'unsigned short' 0>"
278 assert repr(ffi.typeof(p)) == typerepr % "unsigned short"
279 p = ffi.cast("int*", 0)
280 assert repr(p) == "<cdata 'int *' NULL>"
281 assert repr(ffi.typeof(p)) == typerepr % "int *"
282 #
283 p = ffi.new("int*")
284 assert repr(p) == "<cdata 'int *' owning %d bytes>" % SIZE_OF_INT
285 assert repr(ffi.typeof(p)) == typerepr % "int *"
286 p = ffi.new("int**")
287 assert repr(p) == "<cdata 'int * *' owning %d bytes>" % SIZE_OF_PTR
288 assert repr(ffi.typeof(p)) == typerepr % "int * *"
289 p = ffi.new("int [2]")
290 assert repr(p) == "<cdata 'int[2]' owning %d bytes>" % (2*SIZE_OF_INT)
291 assert repr(ffi.typeof(p)) == typerepr % "int[2]"
292 p = ffi.new("int*[2][3]")
293 assert repr(p) == "<cdata 'int *[2][3]' owning %d bytes>" % (
294 6*SIZE_OF_PTR)
295 assert repr(ffi.typeof(p)) == typerepr % "int *[2][3]"
296 p = ffi.new("struct repr *")
297 assert repr(p) == "<cdata 'struct repr *' owning %d bytes>" % (
298 3*SIZE_OF_SHORT)
299 assert repr(ffi.typeof(p)) == typerepr % "struct repr *"
300 #
301 q = ffi.cast("short", -123)
302 assert repr(q) == "<cdata 'short' -123>"
303 assert repr(ffi.typeof(q)) == typerepr % "short"
304 p = ffi.new("int*")
305 q = ffi.cast("short*", p)
306 assert repr(q).startswith("<cdata 'short *' 0x")
307 assert repr(ffi.typeof(q)) == typerepr % "short *"
308 p = ffi.new("int [2]")
309 q = ffi.cast("int*", p)
310 assert repr(q).startswith("<cdata 'int *' 0x")
311 assert repr(ffi.typeof(q)) == typerepr % "int *"
312 p = ffi.new("struct repr*")
313 q = ffi.cast("struct repr *", p)
314 assert repr(q).startswith("<cdata 'struct repr *' 0x")
315 assert repr(ffi.typeof(q)) == typerepr % "struct repr *"
316 prevrepr = repr(q)
317 q = q[0]
318 assert repr(q) == prevrepr.replace(' *', ' &')
319 assert repr(ffi.typeof(q)) == typerepr % "struct repr"
320
321 def test_new_array_of_array(self):
322 p = ffi.new("int[3][4]")
323 p[0][0] = 10
324 p[2][3] = 33
325 assert p[0][0] == 10
326 assert p[2][3] == 33
327 py.test.raises(IndexError, "p[1][-1]")
328
329 def test_constructor_array_of_array(self):
330 p = ffi.new("int[3][2]", [[10, 11], [12, 13], [14, 15]])
331 assert p[2][1] == 15
332
333 def test_new_array_of_pointer_1(self):
334 n = ffi.new("int*", 99)
335 p = ffi.new("int*[4]")
336 p[3] = n
337 a = p[3]
338 assert repr(a).startswith("<cdata 'int *' 0x")
339 assert a[0] == 99
340
341 def test_new_array_of_pointer_2(self):
342 n = ffi.new("int[1]", [99])
343 p = ffi.new("int*[4]")
344 p[3] = n
345 a = p[3]
346 assert repr(a).startswith("<cdata 'int *' 0x")
347 assert a[0] == 99
348
349 def test_char(self):
350 assert ffi.new("char*", b"\xff")[0] == b'\xff'
351 assert ffi.new("char*")[0] == b'\x00'
352 assert int(ffi.cast("char", 300)) == 300 - 256
353 assert not bool(ffi.cast("char", 0))
354 assert bool(ffi.cast("char", 1))
355 assert bool(ffi.cast("char", 255))
356 py.test.raises(TypeError, ffi.new, "char*", 32)
357 py.test.raises(TypeError, ffi.new, "char*", u+"x")
358 py.test.raises(TypeError, ffi.new, "char*", b"foo")
359 #
360 p = ffi.new("char[]", [b'a', b'b', b'\x9c'])
361 assert len(p) == 3
362 assert p[0] == b'a'
363 assert p[1] == b'b'
364 assert p[2] == b'\x9c'
365 p[0] = b'\xff'
366 assert p[0] == b'\xff'
367 p = ffi.new("char[]", b"abcd")
368 assert len(p) == 5
369 assert p[4] == b'\x00' # like in C, with: char[] p = "abcd";
370 #
371 p = ffi.new("char[4]", b"ab")
372 assert len(p) == 4
373 assert [p[i] for i in range(4)] == [b'a', b'b', b'\x00', b'\x00']
374 p = ffi.new("char[2]", b"ab")
375 assert len(p) == 2
376 assert [p[i] for i in range(2)] == [b'a', b'b']
377 py.test.raises(IndexError, ffi.new, "char[2]", b"abc")
378
379 def check_wchar_t(self, ffi):
380 try:
381 ffi.cast("wchar_t", 0)
382 except NotImplementedError:
383 py.test.skip("NotImplementedError: wchar_t")
384
385 def test_wchar_t(self):
386 self.check_wchar_t(ffi)
387 assert ffi.new("wchar_t*", u+'x')[0] == u+'x'
388 assert ffi.new("wchar_t*", u+'\u1234')[0] == u+'\u1234'
389 if SIZE_OF_WCHAR > 2:
390 assert ffi.new("wchar_t*", u+'\U00012345')[0] == u+'\U00012345'
391 else:
392 py.test.raises(TypeError, ffi.new, "wchar_t*", u+'\U00012345')
393 assert ffi.new("wchar_t*")[0] == u+'\x00'
394 assert int(ffi.cast("wchar_t", 300)) == 300
395 assert not bool(ffi.cast("wchar_t", 0))
396 assert bool(ffi.cast("wchar_t", 1))
397 assert bool(ffi.cast("wchar_t", 65535))
398 if SIZE_OF_WCHAR > 2:
399 assert bool(ffi.cast("wchar_t", 65536))
400 py.test.raises(TypeError, ffi.new, "wchar_t*", 32)
401 py.test.raises(TypeError, ffi.new, "wchar_t*", "foo")
402 #
403 p = ffi.new("wchar_t[]", [u+'a', u+'b', u+'\u1234'])
404 assert len(p) == 3
405 assert p[0] == u+'a'
406 assert p[1] == u+'b' and type(p[1]) is unicode
407 assert p[2] == u+'\u1234'
408 p[0] = u+'x'
409 assert p[0] == u+'x' and type(p[0]) is unicode
410 p[1] = u+'\u1357'
411 assert p[1] == u+'\u1357'
412 p = ffi.new("wchar_t[]", u+"abcd")
413 assert len(p) == 5
414 assert p[4] == u+'\x00'
415 p = ffi.new("wchar_t[]", u+"a\u1234b")
416 assert len(p) == 4
417 assert p[1] == u+'\u1234'
418 #
419 p = ffi.new("wchar_t[]", u+'\U00023456')
420 if SIZE_OF_WCHAR == 2:
421 assert len(p) == 3
422 assert p[0] == u+'\ud84d'
423 assert p[1] == u+'\udc56'
424 assert p[2] == u+'\x00'
425 else:
426 assert len(p) == 2
427 assert p[0] == u+'\U00023456'
428 assert p[1] == u+'\x00'
429 #
430 p = ffi.new("wchar_t[4]", u+"ab")
431 assert len(p) == 4
432 assert [p[i] for i in range(4)] == [u+'a', u+'b', u+'\x00', u+'\x00']
433 p = ffi.new("wchar_t[2]", u+"ab")
434 assert len(p) == 2
435 assert [p[i] for i in range(2)] == [u+'a', u+'b']
436 py.test.raises(IndexError, ffi.new, "wchar_t[2]", u+"abc")
437
438 def test_none_as_null_doesnt_work(self):
439 p = ffi.new("int*[1]")
440 assert p[0] is not None
441 assert p[0] != None
442 assert p[0] == ffi.NULL
443 assert repr(p[0]) == "<cdata 'int *' NULL>"
444 #
445 n = ffi.new("int*", 99)
446 p = ffi.new("int*[]", [n])
447 assert p[0][0] == 99
448 py.test.raises(TypeError, "p[0] = None")
449 p[0] = ffi.NULL
450 assert p[0] == ffi.NULL
451
452 def test_float(self):
453 p = ffi.new("float[]", [-2, -2.5])
454 assert p[0] == -2.0
455 assert p[1] == -2.5
456 p[1] += 17.75
457 assert p[1] == 15.25
458 #
459 p = ffi.new("float*", 15.75)
460 assert p[0] == 15.75
461 py.test.raises(TypeError, int, p)
462 py.test.raises(TypeError, float, p)
463 p[0] = 0.0
464 assert bool(p) is True
465 #
466 p = ffi.new("float*", 1.1)
467 f = p[0]
468 assert f != 1.1 # because of rounding effect
469 assert abs(f - 1.1) < 1E-7
470 #
471 INF = 1E200 * 1E200
472 assert 1E200 != INF
473 p[0] = 1E200
474 assert p[0] == INF # infinite, not enough precision
475
476 def test_struct_simple(self):
477 s = ffi.new("struct simple*")
478 assert s.a == s.b == s.c == 0
479 s.b = -23
480 assert s.b == -23
481 py.test.raises(OverflowError, "s.b = 32768")
482 #
483 s = ffi.new("struct simple*", [-2, -3])
484 assert s.a == -2
485 assert s.b == -3
486 assert s.c == 0
487 py.test.raises((AttributeError, TypeError), "del s.a")
488 assert repr(s) == "<cdata 'struct simple *' owning %d bytes>" % (
489 SIZE_OF_INT + 2 * SIZE_OF_SHORT)
490 #
491 py.test.raises(ValueError, ffi.new, "struct simple*", [1, 2, 3, 4])
492
493 def test_constructor_struct_from_dict(self):
494 s = ffi.new("struct simple*", {'b': 123, 'c': 456})
495 assert s.a == 0
496 assert s.b == 123
497 assert s.c == 456
498 py.test.raises(KeyError, ffi.new, "struct simple*", {'d': 456})
499
500 def test_struct_pointer(self):
501 s = ffi.new("struct simple*")
502 assert s[0].a == s[0].b == s[0].c == 0
503 s[0].b = -23
504 assert s[0].b == s.b == -23
505 py.test.raises(OverflowError, "s[0].b = -32769")
506 py.test.raises(IndexError, "s[1]")
507
508 def test_struct_opaque(self):
509 py.test.raises(ffi.error, ffi.new, "struct baz*")
510 # should 'ffi.new("struct baz **") work? it used to, but it was
511 # not particularly useful...
512 py.test.raises(ffi.error, ffi.new, "struct baz**")
513
514 def test_pointer_to_struct(self):
515 s = ffi.new("struct simple *")
516 s.a = -42
517 assert s[0].a == -42
518 p = ffi.new("struct simple **", s)
519 assert p[0].a == -42
520 assert p[0][0].a == -42
521 p[0].a = -43
522 assert s.a == -43
523 assert s[0].a == -43
524 p[0][0].a = -44
525 assert s.a == -44
526 assert s[0].a == -44
527 s.a = -45
528 assert p[0].a == -45
529 assert p[0][0].a == -45
530 s[0].a = -46
531 assert p[0].a == -46
532 assert p[0][0].a == -46
533
534 def test_constructor_struct_of_array(self):
535 s = ffi.new("struct array *", [[10, 11], [b'a', b'b', b'c']])
536 assert s.a[1] == 11
537 assert s.b[2] == b'c'
538 s.b[1] = b'X'
539 assert s.b[0] == b'a'
540 assert s.b[1] == b'X'
541 assert s.b[2] == b'c'
542
543 def test_recursive_struct(self):
544 s = ffi.new("struct recursive*")
545 t = ffi.new("struct recursive*")
546 s.value = 123
547 s.next = t
548 t.value = 456
549 assert s.value == 123
550 assert s.next.value == 456
551
552 def test_union_simple(self):
553 u = ffi.new("union simple_u*")
554 assert u.a == u.b == u.c == 0
555 u.b = -23
556 assert u.b == -23
557 assert u.a != 0
558 py.test.raises(OverflowError, "u.b = 32768")
559 #
560 u = ffi.new("union simple_u*", [-2])
561 assert u.a == -2
562 py.test.raises((AttributeError, TypeError), "del u.a")
563 assert repr(u) == "<cdata 'union simple_u *' owning %d bytes>" % (
564 SIZE_OF_INT,)
565
566 def test_union_opaque(self):
567 py.test.raises(ffi.error, ffi.new, "union baz*")
568 # should 'ffi.new("union baz **") work? it used to, but it was
569 # not particularly useful...
570 py.test.raises(ffi.error, ffi.new, "union baz**")
571
572 def test_union_initializer(self):
573 py.test.raises(TypeError, ffi.new, "union init_u*", b'A')
574 py.test.raises(TypeError, ffi.new, "union init_u*", 5)
575 py.test.raises(ValueError, ffi.new, "union init_u*", [b'A', 5])
576 u = ffi.new("union init_u*", [b'A'])
577 assert u.a == b'A'
578 py.test.raises(TypeError, ffi.new, "union init_u*", [1005])
579 u = ffi.new("union init_u*", {'b': 12345})
580 assert u.b == 12345
581 u = ffi.new("union init_u*", [])
582 assert u.a == b'\x00'
583 assert u.b == 0
584
585 def test_sizeof_type(self):
586 for c_type, expected_size in [
587 ('char', 1),
588 ('unsigned int', 4),
589 ('char *', SIZE_OF_PTR),
590 ('int[5]', 20),
591 ('struct four_s', 12),
592 ('union four_u', 4),
593 ]:
594 size = ffi.sizeof(c_type)
595 assert size == expected_size, (size, expected_size, ctype)
596
597 def test_sizeof_cdata(self):
598 assert ffi.sizeof(ffi.new("short*")) == SIZE_OF_PTR
599 assert ffi.sizeof(ffi.cast("short", 123)) == SIZE_OF_SHORT
600 #
601 a = ffi.new("int[]", [10, 11, 12, 13, 14])
602 assert len(a) == 5
603 assert ffi.sizeof(a) == 5 * SIZE_OF_INT
604
605 def test_string_from_char_pointer(self):
606 x = ffi.new("char*", b"x")
607 assert str(x) == repr(x)
608 assert ffi.string(x) == b"x"
609 assert ffi.string(ffi.new("char*", b"\x00")) == b""
610 py.test.raises(TypeError, ffi.new, "char*", unicode("foo"))
611
612 def test_unicode_from_wchar_pointer(self):
613 self.check_wchar_t(ffi)
614 x = ffi.new("wchar_t*", u+"x")
615 assert unicode(x) == unicode(repr(x))
616 assert ffi.string(x) == u+"x"
617 assert ffi.string(ffi.new("wchar_t*", u+"\x00")) == u+""
618
619 def test_string_from_char_array(self):
620 p = ffi.new("char[]", b"hello.")
621 p[5] = b'!'
622 assert ffi.string(p) == b"hello!"
623 p[6] = b'?'
624 assert ffi.string(p) == b"hello!?"
625 p[3] = b'\x00'
626 assert ffi.string(p) == b"hel"
627 assert ffi.string(p, 2) == b"he"
628 py.test.raises(IndexError, "p[7] = b'X'")
629 #
630 a = ffi.new("char[]", b"hello\x00world")
631 assert len(a) == 12
632 p = ffi.cast("char *", a)
633 assert ffi.string(p) == b'hello'
634
635 def test_string_from_wchar_array(self):
636 self.check_wchar_t(ffi)
637 assert ffi.string(ffi.cast("wchar_t", "x")) == u+"x"
638 assert ffi.string(ffi.cast("wchar_t", u+"x")) == u+"x"
639 x = ffi.cast("wchar_t", "x")
640 assert str(x) == repr(x)
641 assert ffi.string(x) == u+"x"
642 #
643 p = ffi.new("wchar_t[]", u+"hello.")
644 p[5] = u+'!'
645 assert ffi.string(p) == u+"hello!"
646 p[6] = u+'\u04d2'
647 assert ffi.string(p) == u+"hello!\u04d2"
648 p[3] = u+'\x00'
649 assert ffi.string(p) == u+"hel"
650 assert ffi.string(p, 123) == u+"hel"
651 py.test.raises(IndexError, "p[7] = u+'X'")
652 #
653 a = ffi.new("wchar_t[]", u+"hello\x00world")
654 assert len(a) == 12
655 p = ffi.cast("wchar_t *", a)
656 assert ffi.string(p) == u+'hello'
657 assert ffi.string(p, 123) == u+'hello'
658 assert ffi.string(p, 5) == u+'hello'
659 assert ffi.string(p, 2) == u+'he'
660
661 def test_fetch_const_char_p_field(self):
662 # 'const' is ignored so far, in the declaration of 'struct string'
663 t = ffi.new("const char[]", b"testing")
664 s = ffi.new("struct string*", [t])
665 assert type(s.name) not in (bytes, str, unicode)
666 assert ffi.string(s.name) == b"testing"
667 py.test.raises(TypeError, "s.name = None")
668 s.name = ffi.NULL
669 assert s.name == ffi.NULL
670
671 def test_fetch_const_wchar_p_field(self):
672 # 'const' is ignored so far
673 self.check_wchar_t(ffi)
674 t = ffi.new("const wchar_t[]", u+"testing")
675 s = ffi.new("struct ustring*", [t])
676 assert type(s.name) not in (bytes, str, unicode)
677 assert ffi.string(s.name) == u+"testing"
678 s.name = ffi.NULL
679 assert s.name == ffi.NULL
680
681 def test_voidp(self):
682 py.test.raises(TypeError, ffi.new, "void*")
683 p = ffi.new("void **")
684 assert p[0] == ffi.NULL
685 a = ffi.new("int[]", [10, 11, 12])
686 p = ffi.new("void **", a)
687 vp = p[0]
688 py.test.raises(TypeError, "vp[0]")
689 py.test.raises(TypeError, ffi.new, "short **", a)
690 #
691 s = ffi.new("struct voidp *")
692 s.p = a # works
693 s.q = a # works
694 py.test.raises(TypeError, "s.r = a") # fails
695 b = ffi.cast("int *", a)
696 s.p = b # works
697 s.q = b # works
698 py.test.raises(TypeError, "s.r = b") # fails
699
700 def test_functionptr_simple(self):
701 py.test.raises(TypeError, ffi.callback, "int(*)(int)", 0)
702 def cb(n):
703 return n + 1
704 cb.__qualname__ = 'cb'
705 p = ffi.callback("int(*)(int)", cb)
706 res = p(41) # calling an 'int(*)(int)', i.e. a function pointer
707 assert res == 42 and type(res) is int
708 res = p(ffi.cast("int", -41))
709 assert res == -40 and type(res) is int
710 assert repr(p).startswith(
711 "<cdata 'int(*)(int)' calling <function cb at 0x")
712 assert ffi.typeof(p) is ffi.typeof("int(*)(int)")
713 q = ffi.new("int(**)(int)", p)
714 assert repr(q) == "<cdata 'int(* *)(int)' owning %d bytes>" % (
715 SIZE_OF_PTR)
716 py.test.raises(TypeError, "q(43)")
717 res = q[0](43)
718 assert res == 44
719 q = ffi.cast("int(*)(int)", p)
720 assert repr(q).startswith("<cdata 'int(*)(int)' 0x")
721 res = q(45)
722 assert res == 46
723
724 def test_functionptr_advanced(self):
725 t = ffi.typeof("int(*(*)(int))(int)")
726 assert repr(t) == "<ctype '%s'>" % "int(*(*)(int))(int)"
727
728 def test_functionptr_voidptr_return(self):
729 def cb():
730 return ffi.NULL
731 p = ffi.callback("void*(*)()", cb)
732 res = p()
733 assert res is not None
734 assert res == ffi.NULL
735 int_ptr = ffi.new('int*')
736 void_ptr = ffi.cast('void*', int_ptr)
737 def cb():
738 return void_ptr
739 p = ffi.callback("void*(*)()", cb)
740 res = p()
741 assert res == void_ptr
742
743 def test_functionptr_intptr_return(self):
744 def cb():
745 return ffi.NULL
746 p = ffi.callback("int*(*)()", cb)
747 res = p()
748 assert res == ffi.NULL
749 int_ptr = ffi.new('int*')
750 def cb():
751 return int_ptr
752 p = ffi.callback("int*(*)()", cb)
753 res = p()
754 assert repr(res).startswith("<cdata 'int *' 0x")
755 assert res == int_ptr
756 int_array_ptr = ffi.new('int[1]')
757 def cb():
758 return int_array_ptr
759 p = ffi.callback("int*(*)()", cb)
760 res = p()
761 assert repr(res).startswith("<cdata 'int *' 0x")
762 assert res == int_array_ptr
763
764 def test_functionptr_void_return(self):
765 def foo():
766 pass
767 foo_cb = ffi.callback("void foo()", foo)
768 result = foo_cb()
769 assert result is None
770
771 def test_char_cast(self):
772 p = ffi.cast("int", b'\x01')
773 assert ffi.typeof(p) is ffi.typeof("int")
774 assert int(p) == 1
775 p = ffi.cast("int", ffi.cast("char", b"a"))
776 assert int(p) == ord("a")
777 p = ffi.cast("int", ffi.cast("char", b"\x80"))
778 assert int(p) == 0x80 # "char" is considered unsigned in this case
779 p = ffi.cast("int", b"\x81")
780 assert int(p) == 0x81
781
782 def test_wchar_cast(self):
783 self.check_wchar_t(ffi)
784 p = ffi.cast("int", ffi.cast("wchar_t", u+'\u1234'))
785 assert int(p) == 0x1234
786 p = ffi.cast("long long", ffi.cast("wchar_t", -1))
787 if SIZE_OF_WCHAR == 2: # 2 bytes, unsigned
788 assert int(p) == 0xffff
789 elif (sys.platform.startswith('linux') and
790 platform.machine().startswith('x86')): # known to be signed
791 assert int(p) == -1
792 else: # in general, it can be either signed or not
793 assert int(p) in [-1, 0xffffffff] # e.g. on arm, both cases occur
794 p = ffi.cast("int", u+'\u1234')
795 assert int(p) == 0x1234
796
797 def test_cast_array_to_charp(self):
798 a = ffi.new("short int[]", [0x1234, 0x5678])
799 p = ffi.cast("char*", a)
800 data = b''.join([p[i] for i in range(4)])
801 if sys.byteorder == 'little':
802 assert data == b'\x34\x12\x78\x56'
803 else:
804 assert data == b'\x12\x34\x56\x78'
805
806 def test_cast_between_pointers(self):
807 a = ffi.new("short int[]", [0x1234, 0x5678])
808 p = ffi.cast("short*", a)
809 p2 = ffi.cast("int*", p)
810 q = ffi.cast("char*", p2)
811 data = b''.join([q[i] for i in range(4)])
812 if sys.byteorder == 'little':
813 assert data == b'\x34\x12\x78\x56'
814 else:
815 assert data == b'\x12\x34\x56\x78'
816
817 def test_cast_pointer_and_int(self):
818 a = ffi.new("short int[]", [0x1234, 0x5678])
819 l1 = ffi.cast("intptr_t", a)
820 p = ffi.cast("short*", a)
821 l2 = ffi.cast("intptr_t", p)
822 assert int(l1) == int(l2) != 0
823 q = ffi.cast("short*", l1)
824 assert q == ffi.cast("short*", int(l1))
825 assert q[0] == 0x1234
826 assert int(ffi.cast("intptr_t", ffi.NULL)) == 0
827
828 def test_cast_functionptr_and_int(self):
829 def cb(n):
830 return n + 1
831 a = ffi.callback("int(*)(int)", cb)
832 p = ffi.cast("void *", a)
833 assert p
834 b = ffi.cast("int(*)(int)", p)
835 assert b(41) == 42
836 assert a == b
837 assert hash(a) == hash(b)
838
839 def test_callback_crash(self):
840 def cb(n):
841 raise Exception
842 a = ffi.callback("int(*)(int)", cb, error=42)
843 res = a(1) # and the error reported to stderr
844 assert res == 42
845
846 def test_structptr_argument(self):
847 def cb(p):
848 return p[0].a * 1000 + p[0].b * 100 + p[1].a * 10 + p[1].b
849 a = ffi.callback("int(*)(struct ab[])", cb)
850 res = a([[5, 6], {'a': 7, 'b': 8}])
851 assert res == 5678
852 res = a([[5], {'b': 8}])
853 assert res == 5008
854
855 def test_array_argument_as_list(self):
856 seen = []
857 def cb(argv):
858 seen.append(ffi.string(argv[0]))
859 seen.append(ffi.string(argv[1]))
860 a = ffi.callback("void(*)(char *[])", cb)
861 a([ffi.new("char[]", b"foobar"), ffi.new("char[]", b"baz")])
862 assert seen == [b"foobar", b"baz"]
863
864 def test_cast_float(self):
865 a = ffi.cast("float", 12)
866 assert float(a) == 12.0
867 a = ffi.cast("float", 12.5)
868 assert float(a) == 12.5
869 a = ffi.cast("float", b"A")
870 assert float(a) == ord("A")
871 a = ffi.cast("int", 12.9)
872 assert int(a) == 12
873 a = ffi.cast("char", 66.9 + 256)
874 assert ffi.string(a) == b"B"
875 #
876 a = ffi.cast("float", ffi.cast("int", 12))
877 assert float(a) == 12.0
878 a = ffi.cast("float", ffi.cast("double", 12.5))
879 assert float(a) == 12.5
880 a = ffi.cast("float", ffi.cast("char", b"A"))
881 assert float(a) == ord("A")
882 a = ffi.cast("int", ffi.cast("double", 12.9))
883 assert int(a) == 12
884 a = ffi.cast("char", ffi.cast("double", 66.9 + 256))
885 assert ffi.string(a) == b"B"
886
887 def test_enum(self):
888 # enum foq { A0, B0, CC0, D0 };
889 assert ffi.string(ffi.cast("enum foq", 0)) == "cffiA0"
890 assert ffi.string(ffi.cast("enum foq", 2)) == "cffiCC0"
891 assert ffi.string(ffi.cast("enum foq", 3)) == "cffiD0"
892 assert ffi.string(ffi.cast("enum foq", 4)) == "4"
893 # enum bar { A1, B1=-2, CC1, D1, E1 };
894 assert ffi.string(ffi.cast("enum bar", 0)) == "A1"
895 assert ffi.string(ffi.cast("enum bar", -2)) == "B1"
896 assert ffi.string(ffi.cast("enum bar", -1)) == "CC1"
897 assert ffi.string(ffi.cast("enum bar", 1)) == "E1"
898 assert ffi.cast("enum bar", -2) == ffi.cast("enum bar", -2)
899 assert ffi.cast("enum foq", 0) == ffi.cast("enum bar", 0)
900 assert ffi.cast("enum bar", 0) == ffi.cast("int", 0)
901 assert repr(ffi.cast("enum bar", -1)) == "<cdata 'enum bar' -1: CC1>"
902 assert repr(ffi.cast("enum foq", -1)) == ( # enums are unsigned, if
903 "<cdata 'enum foq' 4294967295>") or ( # they contain no neg value
904 sys.platform == "win32") # (but not on msvc)
905 # enum baz { A2=0x1000, B2=0x2000 };
906 assert ffi.string(ffi.cast("enum baz", 0x1000)) == "A2"
907 assert ffi.string(ffi.cast("enum baz", 0x2000)) == "B2"
908
909 def test_enum_in_struct(self):
910 # enum foo2 { A3, B3, C3, D3 };
911 # struct bar_with_e { enum foo2 e; };
912 s = ffi.new("struct bar_with_e *")
913 s.e = 0
914 assert s.e == 0
915 s.e = 3
916 assert s.e == 3
917 assert s[0].e == 3
918 s[0].e = 2
919 assert s.e == 2
920 assert s[0].e == 2
921 s.e = ffi.cast("enum foo2", -1)
922 assert s.e in (4294967295, -1) # two choices
923 assert s[0].e in (4294967295, -1)
924 s.e = s.e
925 py.test.raises(TypeError, "s.e = 'B3'")
926 py.test.raises(TypeError, "s.e = '2'")
927 py.test.raises(TypeError, "s.e = '#2'")
928 py.test.raises(TypeError, "s.e = '#7'")
929
930 def test_enum_non_contiguous(self):
931 # enum noncont { A4, B4=42, C4 };
932 assert ffi.string(ffi.cast("enum noncont", 0)) == "A4"
933 assert ffi.string(ffi.cast("enum noncont", 42)) == "B4"
934 assert ffi.string(ffi.cast("enum noncont", 43)) == "C4"
935 invalid_value = ffi.cast("enum noncont", 2)
936 assert int(invalid_value) == 2
937 assert ffi.string(invalid_value) == "2"
938
939 def test_enum_char_hex_oct(self):
940 # enum etypes {A5='!', B5='\'', C5=0x10, D5=010, E5=- 0x10, F5=-010};
941 assert ffi.string(ffi.cast("enum etypes", ord('!'))) == "A5"
942 assert ffi.string(ffi.cast("enum etypes", ord("'"))) == "B5"
943 assert ffi.string(ffi.cast("enum etypes", 16)) == "C5"
944 assert ffi.string(ffi.cast("enum etypes", 8)) == "D5"
945 assert ffi.string(ffi.cast("enum etypes", -16)) == "E5"
946 assert ffi.string(ffi.cast("enum etypes", -8)) == "F5"
947
948 def test_array_of_struct(self):
949 s = ffi.new("struct ab[1]")
950 py.test.raises(AttributeError, 's.b')
951 py.test.raises(AttributeError, 's.b = 412')
952 s[0].b = 412
953 assert s[0].b == 412
954 py.test.raises(IndexError, 's[1]')
955
956 def test_pointer_to_array(self):
957 p = ffi.new("int(**)[5]")
958 assert repr(p) == "<cdata 'int(* *)[5]' owning %d bytes>" % SIZE_OF_PTR
959
960 def test_iterate_array(self):
961 a = ffi.new("char[]", b"hello")
962 assert list(a) == [b"h", b"e", b"l", b"l", b"o", b"\0"]
963 assert list(iter(a)) == [b"h", b"e", b"l", b"l", b"o", b"\0"]
964 #
965 py.test.raises(TypeError, iter, ffi.cast("char *", a))
966 py.test.raises(TypeError, list, ffi.cast("char *", a))
967 py.test.raises(TypeError, iter, ffi.new("int *"))
968 py.test.raises(TypeError, list, ffi.new("int *"))
969
970 def test_offsetof(self):
971 # struct abc { int a, b, c; };
972 assert ffi.offsetof("struct abc", "a") == 0
973 assert ffi.offsetof("struct abc", "b") == 4
974 assert ffi.offsetof("struct abc", "c") == 8
975
976 def test_offsetof_nested(self):
977 # struct nesting { struct abc d, e; };
978 assert ffi.offsetof("struct nesting", "e") == 12
979 py.test.raises(KeyError, ffi.offsetof, "struct nesting", "e.a")
980 assert ffi.offsetof("struct nesting", "e", "a") == 12
981 assert ffi.offsetof("struct nesting", "e", "b") == 16
982 assert ffi.offsetof("struct nesting", "e", "c") == 20
983
984 def test_offsetof_array(self):
985 assert ffi.offsetof("int[]", 51) == 51 * ffi.sizeof("int")
986 assert ffi.offsetof("int *", 51) == 51 * ffi.sizeof("int")
987 # struct array2 { int a, b; int c[99]; };
988 assert ffi.offsetof("struct array2", "c") == 2 * ffi.sizeof("int")
989 assert ffi.offsetof("struct array2", "c", 0) == 2 * ffi.sizeof("int")
990 assert ffi.offsetof("struct array2", "c", 51) == 53 * ffi.sizeof("int")
991
992 def test_alignof(self):
993 # struct align { char a; short b; char c; };
994 assert ffi.alignof("int") == 4
995 assert ffi.alignof("double") in (4, 8)
996 assert ffi.alignof("struct align") == 2
997
998 def test_bitfield(self):
999 # struct bitfield { int a:10, b:20, c:3; };
1000 assert ffi.sizeof("struct bitfield") == 8
1001 s = ffi.new("struct bitfield *")
1002 s.a = 511
1003 py.test.raises(OverflowError, "s.a = 512")
1004 py.test.raises(OverflowError, "s[0].a = 512")
1005 assert s.a == 511
1006 s.a = -512
1007 py.test.raises(OverflowError, "s.a = -513")
1008 py.test.raises(OverflowError, "s[0].a = -513")
1009 assert s.a == -512
1010 s.c = 3
1011 assert s.c == 3
1012 py.test.raises(OverflowError, "s.c = 4")
1013 py.test.raises(OverflowError, "s[0].c = 4")
1014 s.c = -4
1015 assert s.c == -4
1016
1017 def test_bitfield_enum(self):
1018 # typedef enum { AA1, BB1, CC1 } foo_e_t;
1019 # typedef struct { foo_e_t f:2; } bfenum_t;
1020 if sys.platform == "win32":
1021 py.test.skip("enums are not unsigned")
1022 s = ffi.new("bfenum_t *")
1023 s.f = 2
1024 assert s.f == 2
1025
1026 def test_anonymous_struct(self):
1027 # typedef struct { int a; } anon_foo_t;
1028 # typedef struct { char b, c; } anon_bar_t;
1029 f = ffi.new("anon_foo_t *", [12345])
1030 b = ffi.new("anon_bar_t *", [b"B", b"C"])
1031 assert f.a == 12345
1032 assert b.b == b"B"
1033 assert b.c == b"C"
1034 assert repr(b).startswith("<cdata 'anon_bar_t *'")
1035
1036 def test_struct_with_two_usages(self):
1037 # typedef struct named_foo_s { int a; } named_foo_t, *named_foo_p;
1038 # typedef struct { int a; } unnamed_foo_t, *unnamed_foo_p;
1039 f = ffi.new("named_foo_t *", [12345])
1040 ps = ffi.new("named_foo_p[]", [f])
1041 f = ffi.new("unnamed_foo_t *", [12345])
1042 ps = ffi.new("unnamed_foo_p[]", [f])
1043
1044 def test_pointer_arithmetic(self):
1045 s = ffi.new("short[]", list(range(100, 110)))
1046 p = ffi.cast("short *", s)
1047 assert p[2] == 102
1048 assert p+1 == p+1
1049 assert p+1 != p+0
1050 assert p == p+0 == p-0
1051 assert (p+1)[0] == 101
1052 assert (p+19)[-10] == 109
1053 assert (p+5) - (p+1) == 4
1054 assert p == s+0
1055 assert p+1 == s+1
1056
1057 def test_pointer_comparison(self):
1058 s = ffi.new("short[]", list(range(100)))
1059 p = ffi.cast("short *", s)
1060 assert (p < s) is False
1061 assert (p <= s) is True
1062 assert (p == s) is True
1063 assert (p != s) is False
1064 assert (p > s) is False
1065 assert (p >= s) is True
1066 assert (s < p) is False
1067 assert (s <= p) is True
1068 assert (s == p) is True
1069 assert (s != p) is False
1070 assert (s > p) is False
1071 assert (s >= p) is True
1072 q = p + 1
1073 assert (q < s) is False
1074 assert (q <= s) is False
1075 assert (q == s) is False
1076 assert (q != s) is True
1077 assert (q > s) is True
1078 assert (q >= s) is True
1079 assert (s < q) is True
1080 assert (s <= q) is True
1081 assert (s == q) is False
1082 assert (s != q) is True
1083 assert (s > q) is False
1084 assert (s >= q) is False
1085 assert (q < p) is False
1086 assert (q <= p) is False
1087 assert (q == p) is False
1088 assert (q != p) is True
1089 assert (q > p) is True
1090 assert (q >= p) is True
1091 assert (p < q) is True
1092 assert (p <= q) is True
1093 assert (p == q) is False
1094 assert (p != q) is True
1095 assert (p > q) is False
1096 assert (p >= q) is False
1097 #
1098 assert (None == s) is False
1099 assert (None != s) is True
1100 assert (s == None) is False
1101 assert (s != None) is True
1102 assert (None == q) is False
1103 assert (None != q) is True
1104 assert (q == None) is False
1105 assert (q != None) is True
1106
1107 def test_integer_comparison(self):
1108 x = ffi.cast("int", 123)
1109 y = ffi.cast("int", 456)
1110 assert x < y
1111 #
1112 z = ffi.cast("double", 78.9)
1113 assert x > z
1114 assert y > z
1115
1116 def test_ffi_buffer_ptr(self):
1117 a = ffi.new("short *", 100)
1118 try:
1119 b = ffi.buffer(a)
1120 except NotImplementedError as e:
1121 py.test.skip(str(e))
1122 content = b[:]
1123 assert len(content) == len(b) == 2
1124 if sys.byteorder == 'little':
1125 assert content == b'\x64\x00'
1126 assert b[0] == b'\x64'
1127 b[0] = b'\x65'
1128 else:
1129 assert content == b'\x00\x64'
1130 assert b[1] == b'\x64'
1131 b[1] = b'\x65'
1132 assert a[0] == 101
1133
1134 def test_ffi_buffer_array(self):
1135 a = ffi.new("int[]", list(range(100, 110)))
1136 try:
1137 b = ffi.buffer(a)
1138 except NotImplementedError as e:
1139 py.test.skip(str(e))
1140 content = b[:]
1141 if sys.byteorder == 'little':
1142 assert content.startswith(b'\x64\x00\x00\x00\x65\x00\x00\x00')
1143 b[4] = b'\x45'
1144 else:
1145 assert content.startswith(b'\x00\x00\x00\x64\x00\x00\x00\x65')
1146 b[7] = b'\x45'
1147 assert len(content) == 4 * 10
1148 assert a[1] == 0x45
1149
1150 def test_ffi_buffer_ptr_size(self):
1151 a = ffi.new("short *", 0x4243)
1152 try:
1153 b = ffi.buffer(a, 1)
1154 except NotImplementedError as e:
1155 py.test.skip(str(e))
1156 content = b[:]
1157 assert len(content) == 1
1158 if sys.byteorder == 'little':
1159 assert content == b'\x43'
1160 b[0] = b'\x62'
1161 assert a[0] == 0x4262
1162 else:
1163 assert content == b'\x42'
1164 b[0] = b'\x63'
1165 assert a[0] == 0x6343
1166
1167 def test_ffi_buffer_array_size(self):
1168 a1 = ffi.new("int[]", list(range(100, 110)))
1169 a2 = ffi.new("int[]", list(range(100, 115)))
1170 try:
1171 ffi.buffer(a1)
1172 except NotImplementedError as e:
1173 py.test.skip(str(e))
1174 assert ffi.buffer(a1)[:] == ffi.buffer(a2, 4*10)[:]
1175
1176 def test_ffi_buffer_with_file(self):
1177 import tempfile, os, array
1178 fd, filename = tempfile.mkstemp()
1179 f = os.fdopen(fd, 'r+b')
1180 a = ffi.new("int[]", list(range(1005)))
1181 try:
1182 ffi.buffer(a, 512)
1183 except NotImplementedError as e:
1184 py.test.skip(str(e))
1185 f.write(ffi.buffer(a, 1000 * ffi.sizeof("int")))
1186 f.seek(0)
1187 assert f.read() == array.array('i', range(1000)).tostring()
1188 f.seek(0)
1189 b = ffi.new("int[]", 1005)
1190 f.readinto(ffi.buffer(b, 1000 * ffi.sizeof("int")))
1191 assert list(a)[:1000] + [0] * (len(a)-1000) == list(b)
1192 f.close()
1193 os.unlink(filename)
1194
1195 def test_ffi_buffer_with_io(self):
1196 import io, array
1197 f = io.BytesIO()
1198 a = ffi.new("int[]", list(range(1005)))
1199 try:
1200 ffi.buffer(a, 512)
1201 except NotImplementedError as e:
1202 py.test.skip(str(e))
1203 f.write(ffi.buffer(a, 1000 * ffi.sizeof("int")))
1204 f.seek(0)
1205 assert f.read() == array.array('i', range(1000)).tostring()
1206 f.seek(0)
1207 b = ffi.new("int[]", 1005)
1208 f.readinto(ffi.buffer(b, 1000 * ffi.sizeof("int")))
1209 assert list(a)[:1000] + [0] * (len(a)-1000) == list(b)
1210 f.close()
1211
1212 def test_array_in_struct(self):
1213 # struct array { int a[2]; char b[3]; };
1214 p = ffi.new("struct array *")
1215 p.a[1] = 5
1216 assert p.a[1] == 5
1217 assert repr(p.a).startswith("<cdata 'int[2]' 0x")
1218
1219 def test_struct_containing_array_varsize_workaround(self):
1220 if sys.platform == "win32":
1221 py.test.skip("array of length 0 not supported")
1222 # struct array0 { int len; short data[0]; };
1223 p = ffi.new("char[]", ffi.sizeof("struct array0") + 7 * SIZE_OF_SHORT)
1224 q = ffi.cast("struct array0 *", p)
1225 assert q.len == 0
1226 # 'q.data' gets not a 'short[0]', but just a 'short *' instead
1227 assert repr(q.data).startswith("<cdata 'short *' 0x")
1228 assert q.data[6] == 0
1229 q.data[6] = 15
1230 assert q.data[6] == 15
1231
1232 def test_new_struct_containing_array_varsize(self):
1233 py.test.skip("later?")
1234 ffi.cdef("struct foo_s { int len; short data[]; };")
1235 p = ffi.new("struct foo_s *", 10) # a single integer is the length
1236 assert p.len == 0
1237 assert p.data[9] == 0
1238 py.test.raises(IndexError, "p.data[10]")
1239
1240 def test_ffi_typeof_getcname(self):
1241 assert ffi.getctype("int") == "int"
1242 assert ffi.getctype("int", 'x') == "int x"
1243 assert ffi.getctype("int*") == "int *"
1244 assert ffi.getctype("int*", '') == "int *"
1245 assert ffi.getctype("int*", 'x') == "int * x"
1246 assert ffi.getctype("int", '*') == "int *"
1247 assert ffi.getctype("int", ' * x ') == "int * x"
1248 assert ffi.getctype(ffi.typeof("int*"), '*') == "int * *"
1249 assert ffi.getctype("int", '[5]') == "int[5]"
1250 assert ffi.getctype("int[5]", '[6]') == "int[6][5]"
1251 assert ffi.getctype("int[5]", '(*)') == "int(*)[5]"
1252 # special-case for convenience: automatically put '()' around '*'
1253 assert ffi.getctype("int[5]", '*') == "int(*)[5]"
1254 assert ffi.getctype("int[5]", '*foo') == "int(*foo)[5]"
1255 assert ffi.getctype("int[5]", ' ** foo ') == "int(** foo)[5]"
1256
1257 def test_array_of_func_ptr(self):
1258 f = ffi.cast("int(*)(int)", 42)
1259 assert f != ffi.NULL
1260 py.test.raises(ffi.error, ffi.cast, "int(int)", 42)
1261 py.test.raises(ffi.error, ffi.new, "int([5])(int)")
1262 a = ffi.new("int(*[5])(int)", [f])
1263 assert ffi.getctype(ffi.typeof(a)) == "int(*[5])(int)"
1264 assert len(a) == 5
1265 assert a[0] == f
1266 assert a[1] == ffi.NULL
1267 py.test.raises(TypeError, ffi.cast, "int(*)(int)[5]", 0)
1268 #
1269 def cb(n):
1270 return n + 1
1271 f = ffi.callback("int(*)(int)", cb)
1272 a = ffi.new("int(*[5])(int)", [f, f])
1273 assert a[1](42) == 43
1274
1275 def test_callback_as_function_argument(self):
1276 # In C, function arguments can be declared with a function type,
1277 # which is automatically replaced with the ptr-to-function type.
1278 def cb(a, b):
1279 return chr(ord(a) + ord(b)).encode()
1280 f = ffi.callback("char cb(char, char)", cb)
1281 assert f(b'A', b'\x01') == b'B'
1282 def g(callback):
1283 return callback(b'A', b'\x01')
1284 g = ffi.callback("char g(char cb(char, char))", g)
1285 assert g(f) == b'B'
1286
1287 def test_vararg_callback(self):
1288 py.test.skip("callback with '...'")
1289 def cb(i, va_list):
1290 j = ffi.va_arg(va_list, "int")
1291 k = ffi.va_arg(va_list, "long long")
1292 return i * 2 + j * 3 + k * 5
1293 f = ffi.callback("long long cb(long i, ...)", cb)
1294 res = f(10, ffi.cast("int", 100), ffi.cast("long long", 1000))
1295 assert res == 20 + 300 + 5000
1296
1297 def test_callback_decorator(self):
1298 #
1299 @ffi.callback("long(long, long)", error=42)
1300 def cb(a, b):
1301 return a - b
1302 #
1303 assert cb(-100, -10) == -90
1304 sz = ffi.sizeof("long")
1305 assert cb((1 << (sz*8-1)) - 1, -10) == 42
1306
1307 def test_anonymous_enum(self):
1308 # typedef enum { Value0 = 0 } e_t, *pe_t;
1309 assert ffi.getctype("e_t*") == 'e_t *'
1310 assert ffi.getctype("pe_t") == 'e_t *'
1311 assert ffi.getctype("foo_e_t*") == 'foo_e_t *'
1312
1313 def test_new_ctype(self):
1314 p = ffi.new("int *")
1315 py.test.raises(TypeError, ffi.new, p)
1316 p = ffi.new(ffi.typeof("int *"), 42)
1317 assert p[0] == 42
1318
1319 def test_enum_with_non_injective_mapping(self):
1320 # enum e_noninj { AA3=0, BB3=0, CC3=0, DD3=0 };
1321 e = ffi.cast("enum e_noninj", 0)
1322 assert ffi.string(e) == "AA3" # pick the first one arbitrarily
1323
1324 def test_enum_refer_previous_enum_value(self):
1325 # enum e_prev { AA4, BB4=2, CC4=4, DD4=BB4, EE4, FF4=CC4, GG4=FF4 };
1326 assert ffi.string(ffi.cast("enum e_prev", 2)) == "BB4"
1327 assert ffi.string(ffi.cast("enum e_prev", 3)) == "EE4"
1328 assert ffi.sizeof("char[DD4]") == 2
1329 assert ffi.sizeof("char[EE4]") == 3
1330 assert ffi.sizeof("char[FF4]") == 4
1331 assert ffi.sizeof("char[GG4]") == 4
1332
1333 def test_nested_anonymous_struct(self):
1334 # struct nested_anon {
1335 # struct { int a, b; };
1336 # union { int c, d; };
1337 # };
1338 assert ffi.sizeof("struct nested_anon") == 3 * SIZE_OF_INT
1339 p = ffi.new("struct nested_anon *", [1, 2, 3])
1340 assert p.a == 1
1341 assert p.b == 2
1342 assert p.c == 3
1343 assert p.d == 3
1344 p.d = 17
1345 assert p.c == 17
1346 p.b = 19
1347 assert p.a == 1
1348 assert p.b == 19
1349 assert p.c == 17
1350 assert p.d == 17
1351 p = ffi.new("struct nested_anon *", {'b': 12, 'd': 14})
1352 assert p.a == 0
1353 assert p.b == 12
1354 assert p.c == 14
1355 assert p.d == 14
1356
1357 def test_nested_field_offset_align(self):
1358 # struct nested_field_ofs_s {
1359 # struct { int a; char b; };
1360 # union { char c; };
1361 # };
1362 assert ffi.offsetof("struct nested_field_ofs_s", "c") == 2 * SIZE_OF_INT
1363 assert ffi.sizeof("struct nested_field_ofs_s") == 3 * SIZE_OF_INT
1364
1365 def test_nested_anonymous_union(self):
1366 # union nested_anon_u {
1367 # struct { int a, b; };
1368 # union { int c, d; };
1369 # };
1370 assert ffi.sizeof("union nested_anon_u") == 2 * SIZE_OF_INT
1371 p = ffi.new("union nested_anon_u *", [5])
1372 assert p.a == 5
1373 assert p.b == 0
1374 assert p.c == 5
1375 assert p.d == 5
1376 p.d = 17
1377 assert p.c == 17
1378 assert p.a == 17
1379 p.b = 19
1380 assert p.a == 17
1381 assert p.b == 19
1382 assert p.c == 17
1383 assert p.d == 17
1384 p = ffi.new("union nested_anon_u *", {'d': 14})
1385 assert p.a == 14
1386 assert p.b == 0
1387 assert p.c == 14
1388 assert p.d == 14
1389 p = ffi.new("union nested_anon_u *", {'b': 12})
1390 assert p.a == 0
1391 assert p.b == 12
1392 assert p.c == 0
1393 assert p.d == 0
1394 # we cannot specify several items in the dict, even though
1395 # in theory in this particular case it would make sense
1396 # to give both 'a' and 'b'
1397
1398 def test_cast_to_array_type(self):
1399 p = ffi.new("int[4]", [-5])
1400 q = ffi.cast("int[3]", p)
1401 assert q[0] == -5
1402 assert repr(q).startswith("<cdata 'int[3]' 0x")
1403
1404 def test_gc(self):
1405 p = ffi.new("int *", 123)
1406 seen = []
1407 def destructor(p1):
1408 assert p1 is p
1409 assert p1[0] == 123
1410 seen.append(1)
1411 q = ffi.gc(p, destructor=destructor)
1412 import gc; gc.collect()
1413 assert seen == []
1414 del q
1415 import gc; gc.collect(); gc.collect(); gc.collect()
1416 assert seen == [1]
1417
1418 def test_gc_2(self):
1419 p = ffi.new("int *", 123)
1420 seen = []
1421 q1 = ffi.gc(p, lambda p: seen.append(1))
1422 q2 = ffi.gc(q1, lambda p: seen.append(2))
1423 import gc; gc.collect()
1424 assert seen == []
1425 del q1, q2
1426 import gc; gc.collect(); gc.collect(); gc.collect(); gc.collect()
1427 assert seen == [2, 1]
1428
1429 def test_gc_3(self):
1430 p = ffi.new("int *", 123)
1431 r = ffi.new("int *", 123)
1432 seen = []
1433 seen_r = []
1434 q1 = ffi.gc(p, lambda p: seen.append(1))
1435 s1 = ffi.gc(r, lambda r: seen_r.append(4))
1436 q2 = ffi.gc(q1, lambda p: seen.append(2))
1437 s2 = ffi.gc(s1, lambda r: seen_r.append(5))
1438 q3 = ffi.gc(q2, lambda p: seen.append(3))
1439 import gc; gc.collect()
1440 assert seen == []
1441 assert seen_r == []
1442 del q1, q2, q3, s2, s1
1443 import gc; gc.collect(); gc.collect(); gc.collect(); gc.collect()
1444 assert seen == [3, 2, 1]
1445 assert seen_r == [5, 4]
1446
1447 def test_gc_4(self):
1448 p = ffi.new("int *", 123)
1449 seen = []
1450 q1 = ffi.gc(p, lambda p: seen.append(1))
1451 q2 = ffi.gc(q1, lambda p: seen.append(2))
1452 q3 = ffi.gc(q2, lambda p: seen.append(3))
1453 import gc; gc.collect()
1454 assert seen == []
1455 del q1, q3 # q2 remains, and has a hard ref to q1
1456 import gc; gc.collect(); gc.collect(); gc.collect()
1457 assert seen == [3]
1458
1459 def test_release(self):
1460 p = ffi.new("int[]", 123)
1461 ffi.release(p)
1462 # here, reading p[0] might give garbage or segfault...
1463 ffi.release(p) # no effect
1464
1465 def test_release_new_allocator(self):
1466 seen = []
1467 def myalloc(size):
1468 seen.append(size)
1469 return ffi.new("char[]", b"X" * size)
1470 def myfree(raw):
1471 seen.append(raw)
1472 alloc2 = ffi.new_allocator(alloc=myalloc, free=myfree)
1473 p = alloc2("int[]", 15)
1474 assert seen == [15 * 4]
1475 ffi.release(p)
1476 assert seen == [15 * 4, p]
1477 ffi.release(p) # no effect
1478 assert seen == [15 * 4, p]
1479 #
1480 del seen[:]
1481 p = alloc2("struct ab *")
1482 assert seen == [2 * 4]
1483 ffi.release(p)
1484 assert seen == [2 * 4, p]
1485 ffi.release(p) # no effect
1486 assert seen == [2 * 4, p]
1487
1488 def test_CData_CType(self):
1489 assert isinstance(ffi.cast("int", 0), ffi.CData)
1490 assert isinstance(ffi.new("int *"), ffi.CData)
1491 assert not isinstance(ffi.typeof("int"), ffi.CData)
1492 assert not isinstance(ffi.cast("int", 0), ffi.CType)
1493 assert not isinstance(ffi.new("int *"), ffi.CType)
1494
1495 def test_CData_CType_2(self):
1496 assert isinstance(ffi.typeof("int"), ffi.CType)
1497
1498 def test_bool(self):
1499 assert int(ffi.cast("_Bool", 0.1)) == 1
1500 assert int(ffi.cast("_Bool", -0.0)) == 0
1501 assert int(ffi.cast("_Bool", b'\x02')) == 1
1502 assert int(ffi.cast("_Bool", b'\x00')) == 0
1503 assert int(ffi.cast("_Bool", b'\x80')) == 1
1504 assert ffi.new("_Bool *", False)[0] == 0
1505 assert ffi.new("_Bool *", 1)[0] == 1
1506 py.test.raises(OverflowError, ffi.new, "_Bool *", 2)
1507 py.test.raises(TypeError, ffi.string, ffi.cast("_Bool", 2))
1508
1509 def test_addressof(self):
1510 p = ffi.new("struct ab *")
1511 a = ffi.addressof(p[0])
1512 assert repr(a).startswith("<cdata 'struct ab *' 0x")
1513 assert a == p
1514 py.test.raises(TypeError, ffi.addressof, p)
1515 py.test.raises((AttributeError, TypeError), ffi.addressof, 5)
1516 py.test.raises(TypeError, ffi.addressof, ffi.cast("int", 5))
1517
1518 def test_addressof_field(self):
1519 p = ffi.new("struct ab *")
1520 b = ffi.addressof(p[0], 'b')
1521 assert repr(b).startswith("<cdata 'int *' 0x")
1522 assert int(ffi.cast("uintptr_t", b)) == (
1523 int(ffi.cast("uintptr_t", p)) + ffi.sizeof("int"))
1524 assert b == ffi.addressof(p, 'b')
1525 assert b != ffi.addressof(p, 'a')
1526
1527 def test_addressof_field_nested(self):
1528 # struct nesting { struct abc d, e; };
1529 p = ffi.new("struct nesting *")
1530 py.test.raises(KeyError, ffi.addressof, p[0], 'e.b')
1531 a = ffi.addressof(p[0], 'e', 'b')
1532 assert int(ffi.cast("uintptr_t", a)) == (
1533 int(ffi.cast("uintptr_t", p)) +
1534 ffi.sizeof("struct abc") + ffi.sizeof("int"))
1535
1536 def test_addressof_anonymous_struct(self):
1537 # typedef struct { int a; } anon_foo_t;
1538 p = ffi.new("anon_foo_t *")
1539 a = ffi.addressof(p[0])
1540 assert a == p
1541
1542 def test_addressof_array(self):
1543 p = ffi.new("int[52]")
1544 p0 = ffi.addressof(p)
1545 assert p0 == p
1546 assert ffi.typeof(p0) is ffi.typeof("int(*)[52]")
1547 py.test.raises(TypeError, ffi.addressof, p0)
1548 #
1549 p1 = ffi.addressof(p, 25)
1550 assert ffi.typeof(p1) is ffi.typeof("int *")
1551 assert (p1 - p) == 25
1552 assert ffi.addressof(p, 0) == p
1553
1554 def test_addressof_pointer(self):
1555 array = ffi.new("int[50]")
1556 p = ffi.cast("int *", array)
1557 py.test.raises(TypeError, ffi.addressof, p)
1558 assert ffi.addressof(p, 0) == p
1559 assert ffi.addressof(p, 25) == p + 25
1560 assert ffi.typeof(ffi.addressof(p, 25)) == ffi.typeof(p)
1561 #
1562 array = ffi.new("struct ab[50]")
1563 p = ffi.cast("int *", array)
1564 py.test.raises(TypeError, ffi.addressof, p)
1565 assert ffi.addressof(p, 0) == p
1566 assert ffi.addressof(p, 25) == p + 25
1567 assert ffi.typeof(ffi.addressof(p, 25)) == ffi.typeof(p)
1568
1569 def test_addressof_array_in_struct(self):
1570 # struct abc50 { int a, b; int c[50]; };
1571 p = ffi.new("struct abc50 *")
1572 p1 = ffi.addressof(p, "c", 25)
1573 assert ffi.typeof(p1) is ffi.typeof("int *")
1574 assert p1 == ffi.cast("int *", p) + 27
1575 assert ffi.addressof(p, "c") == ffi.cast("int *", p) + 2
1576 assert ffi.addressof(p, "c", 0) == ffi.cast("int *", p) + 2
1577 p2 = ffi.addressof(p, 1)
1578 assert ffi.typeof(p2) is ffi.typeof("struct abc50 *")
1579 assert p2 == p + 1
1580
1581 def test_multiple_independent_structs(self):
1582 CDEF2 = "struct ab { int x; };"
1583 ffi2 = cffi.FFI(); ffi2.cdef(CDEF2)
1584 outputfilename = recompile(ffi2, "test_multiple_independent_structs",
1585 CDEF2, tmpdir=str(udir))
1586 module = imp.load_dynamic("test_multiple_independent_structs",
1587 outputfilename)
1588 ffi1 = module.ffi
1589 foo1 = ffi1.new("struct ab *", [10])
1590 foo2 = ffi .new("struct ab *", [20, 30])
1591 assert foo1.x == 10
1592 assert foo2.a == 20
1593 assert foo2.b == 30
1594
1595 def test_include_struct_union_enum_typedef(self):
1596 ffi1, CCODE = construction_params
1597 ffi2 = cffi.FFI()
1598 ffi2.include(ffi1)
1599 outputfilename = recompile(ffi2,
1600 "test_include_struct_union_enum_typedef",
1601 CCODE, tmpdir=str(udir))
1602 module = imp.load_dynamic("test_include_struct_union_enum_typedef",
1603 outputfilename)
1604 ffi2 = module.ffi
1605 #
1606 p = ffi2.new("struct nonpacked *", [b'A', -43141])
1607 assert p.a == b'A'
1608 assert p.b == -43141
1609 #
1610 p = ffi.new("union simple_u *", [-52525])
1611 assert p.a == -52525
1612 #
1613 p = ffi.cast("enum foq", 2)
1614 assert ffi.string(p) == "cffiCC0"
1615 assert ffi2.sizeof("char[cffiCC0]") == 2
1616 #
1617 p = ffi.new("anon_foo_t *", [-52526])
1618 assert p.a == -52526
1619 p = ffi.new("named_foo_p", [-52527])
1620 assert p.a == -52527
1621
1622 def test_struct_packed(self):
1623 # struct nonpacked { char a; int b; };
1624 # struct is_packed { char a; int b; } __attribute__((packed));
1625 assert ffi.sizeof("struct nonpacked") == 8
1626 assert ffi.sizeof("struct is_packed") == 5
1627 assert ffi.alignof("struct nonpacked") == 4
1628 assert ffi.alignof("struct is_packed") == 1
1629 s = ffi.new("struct is_packed[2]")
1630 s[0].b = 42623381
1631 s[0].a = b'X'
1632 s[1].b = -4892220
1633 s[1].a = b'Y'
1634 assert s[0].b == 42623381
1635 assert s[0].a == b'X'
1636 assert s[1].b == -4892220
1637 assert s[1].a == b'Y'
1638
1639 def test_not_supported_bitfield_in_result(self):
1640 # struct ints_and_bitfield { int a,b,c,d,e; int x:1; };
1641 e = py.test.raises(NotImplementedError, ffi.callback,
1642 "struct ints_and_bitfield foo(void)", lambda: 42)
1643 assert str(e.value) == ("struct ints_and_bitfield(*)(): "
1644 "callback with unsupported argument or return type or with '...'")
1645
1646 def test_inspecttype(self):
1647 assert ffi.typeof("long").kind == "primitive"
1648 assert ffi.typeof("long(*)(long, long**, ...)").cname == (
1649 "long(*)(long, long * *, ...)")
1650 assert ffi.typeof("long(*)(long, long**, ...)").ellipsis is True
1651
1652 def test_new_handle(self):
1653 o = [2, 3, 4]
1654 p = ffi.new_handle(o)
1655 assert ffi.typeof(p) == ffi.typeof("void *")
1656 assert ffi.from_handle(p) is o
1657 assert ffi.from_handle(ffi.cast("char *", p)) is o
1658 py.test.raises(RuntimeError, ffi.from_handle, ffi.NULL)
1659
1660 def test_struct_array_no_length(self):
1661 # struct array_no_length { int x; int a[]; };
1662 p = ffi.new("struct array_no_length *", [100, [200, 300, 400]])
1663 assert p.x == 100
1664 assert ffi.typeof(p.a) is ffi.typeof("int[]") # length available
1665 assert p.a[0] == 200
1666 assert p.a[1] == 300
1667 assert p.a[2] == 400
1668 assert len(p.a) == 3
1669 assert list(p.a) == [200, 300, 400]
1670 q = ffi.cast("struct array_no_length *", p)
1671 assert ffi.typeof(q.a) is ffi.typeof("int *") # no length available
1672 assert q.a[0] == 200
1673 assert q.a[1] == 300
1674 assert q.a[2] == 400
1675 py.test.raises(TypeError, len, q.a)
1676 py.test.raises(TypeError, list, q.a)
1677
1678 def test_all_primitives(self):
1679 assert set(PRIMITIVE_TO_INDEX) == set([
1680 "char",
1681 "short",
1682 "int",
1683 "long",
1684 "long long",
1685 "signed char",
1686 "unsigned char",
1687 "unsigned short",
1688 "unsigned int",
1689 "unsigned long",
1690 "unsigned long long",
1691 "float",
1692 "double",
1693 "long double",
1694 "wchar_t",
1695 "char16_t",
1696 "char32_t",
1697 "_Bool",
1698 "int8_t",
1699 "uint8_t",
1700 "int16_t",
1701 "uint16_t",
1702 "int32_t",
1703 "uint32_t",
1704 "int64_t",
1705 "uint64_t",
1706 "int_least8_t",
1707 "uint_least8_t",
1708 "int_least16_t",
1709 "uint_least16_t",
1710 "int_least32_t",
1711 "uint_least32_t",
1712 "int_least64_t",
1713 "uint_least64_t",
1714 "int_fast8_t",
1715 "uint_fast8_t",
1716 "int_fast16_t",
1717 "uint_fast16_t",
1718 "int_fast32_t",
1719 "uint_fast32_t",
1720 "int_fast64_t",
1721 "uint_fast64_t",
1722 "intptr_t",
1723 "uintptr_t",
1724 "intmax_t",
1725 "uintmax_t",
1726 "ptrdiff_t",
1727 "size_t",
1728 "ssize_t",
1729 'float _Complex',
1730 'double _Complex',
1731 ])
1732 for name in PRIMITIVE_TO_INDEX:
1733 x = ffi.sizeof(name)
1734 assert 1 <= x <= 16
1735
1736 def test_emit_c_code(self):
1737 ffi = cffi.FFI()
1738 ffi.set_source("foobar", "??")
1739 c_file = str(udir.join('test_emit_c_code'))
1740 ffi.emit_c_code(c_file)
1741 assert os.path.isfile(c_file)
1742
1743 def test_import_from_lib(self):
1744 ffi2 = cffi.FFI()
1745 ffi2.cdef("int myfunc(int); int myvar;\n#define MYFOO ...\n")
1746 outputfilename = recompile(ffi2, "_test_import_from_lib",
1747 "int myfunc(int x) { return x + 1; }\n"
1748 "int myvar = -5;\n"
1749 "#define MYFOO 42", tmpdir=str(udir))
1750 imp.load_dynamic("_test_import_from_lib", outputfilename)
1751 from _test_import_from_lib.lib import myfunc, myvar, MYFOO
1752 assert MYFOO == 42
1753 assert myfunc(43) == 44
1754 assert myvar == -5 # but can't be changed, so not very useful
1755 py.test.raises(ImportError, "from _test_import_from_lib.lib import bar")
1756 d = {}
1757 exec("from _test_import_from_lib.lib import *", d)
1758 assert (set(key for key in d if not key.startswith('_')) ==
1759 set(['myfunc', 'MYFOO']))
1760 #
1761 # also test "import *" on the module itself, which should be
1762 # equivalent to "import ffi, lib"
1763 d = {}
1764 exec("from _test_import_from_lib import *", d)
1765 assert (sorted([x for x in d.keys() if not x.startswith('__')]) ==
1766 ['ffi', 'lib'])
1767
1768 def test_char16_t(self):
1769 x = ffi.new("char16_t[]", 5)
1770 assert len(x) == 5 and ffi.sizeof(x) == 10
1771 x[2] = u+'\u1324'
1772 assert x[2] == u+'\u1324'
1773 y = ffi.new("char16_t[]", u+'\u1234\u5678')
1774 assert len(y) == 3
1775 assert list(y) == [u+'\u1234', u+'\u5678', u+'\x00']
1776 assert ffi.string(y) == u+'\u1234\u5678'
1777 z = ffi.new("char16_t[]", u+'\U00012345')
1778 assert len(z) == 3
1779 assert list(z) == [u+'\ud808', u+'\udf45', u+'\x00']
1780 assert ffi.string(z) == u+'\U00012345'
1781
1782 def test_char32_t(self):
1783 x = ffi.new("char32_t[]", 5)
1784 assert len(x) == 5 and ffi.sizeof(x) == 20
1785 x[3] = u+'\U00013245'
1786 assert x[3] == u+'\U00013245'
1787 y = ffi.new("char32_t[]", u+'\u1234\u5678')
1788 assert len(y) == 3
1789 assert list(y) == [u+'\u1234', u+'\u5678', u+'\x00']
1790 z = ffi.new("char32_t[]", u+'\U00012345')
1791 assert len(z) == 2
1792 assert list(z) == [u+'\U00012345', u+'\x00'] # maybe a 2-unichars strin
1793 assert ffi.string(z) == u+'\U00012345'
0 # Generated by pypy/tool/import_cffi.py
1 import sys, re, os, py
2 import cffi
3 from cffi import cffi_opcode
4
5 if '__pypy__' in sys.builtin_module_names:
6 try:
7 # pytest >= 4.0
8 py.test.skip("not available on pypy", allow_module_level=True)
9 except TypeError:
10 # older pytest
11 py.test.skip("not available on pypy")
12
13 cffi_dir = os.path.dirname(cffi_opcode.__file__)
14
15 r_macro = re.compile(r"#define \w+[(][^\n]*|#include [^\n]*")
16 r_define = re.compile(r"(#define \w+) [^\n]*")
17 r_ifdefs = re.compile(r"(#ifdef |#endif)[^\n]*")
18 header = open(os.path.join(cffi_dir, 'parse_c_type.h')).read()
19 header = r_macro.sub(r"", header)
20 header = r_define.sub(r"\1 ...", header)
21 header = r_ifdefs.sub(r"", header)
22
23 ffi = cffi.FFI()
24 ffi.cdef(header)
25
26 lib = ffi.verify(
27 open(os.path.join(cffi_dir, '..', 'c', 'parse_c_type.c')).read() + """
28 static const char *get_common_type(const char *search, size_t search_len) {
29 return NULL;
30 }
31 """, include_dirs=[cffi_dir])
32
33 class ParseError(Exception):
34 pass
35
36 struct_names = ["bar_s", "foo", "foo_", "foo_s", "foo_s1", "foo_s12"]
37 assert struct_names == sorted(struct_names)
38
39 enum_names = ["ebar_s", "efoo", "efoo_", "efoo_s", "efoo_s1", "efoo_s12"]
40 assert enum_names == sorted(enum_names)
41
42 identifier_names = ["id", "id0", "id05", "id05b", "tail"]
43 assert identifier_names == sorted(identifier_names)
44
45 global_names = ["FIVE", "NEG", "ZERO"]
46 assert global_names == sorted(global_names)
47
48 ctx = ffi.new("struct _cffi_type_context_s *")
49 c_struct_names = [ffi.new("char[]", _n.encode('ascii')) for _n in struct_names]
50 ctx_structs = ffi.new("struct _cffi_struct_union_s[]", len(struct_names))
51 for _i in range(len(struct_names)):
52 ctx_structs[_i].name = c_struct_names[_i]
53 ctx_structs[3].flags = lib._CFFI_F_UNION
54 ctx.struct_unions = ctx_structs
55 ctx.num_struct_unions = len(struct_names)
56
57 c_enum_names = [ffi.new("char[]", _n.encode('ascii')) for _n in enum_names]
58 ctx_enums = ffi.new("struct _cffi_enum_s[]", len(enum_names))
59 for _i in range(len(enum_names)):
60 ctx_enums[_i].name = c_enum_names[_i]
61 ctx.enums = ctx_enums
62 ctx.num_enums = len(enum_names)
63
64 c_identifier_names = [ffi.new("char[]", _n.encode('ascii'))
65 for _n in identifier_names]
66 ctx_identifiers = ffi.new("struct _cffi_typename_s[]", len(identifier_names))
67 for _i in range(len(identifier_names)):
68 ctx_identifiers[_i].name = c_identifier_names[_i]
69 ctx_identifiers[_i].type_index = 100 + _i
70 ctx.typenames = ctx_identifiers
71 ctx.num_typenames = len(identifier_names)
72
73 @ffi.callback("int(unsigned long long *)")
74 def fetch_constant_five(p):
75 p[0] = 5
76 return 0
77 @ffi.callback("int(unsigned long long *)")
78 def fetch_constant_zero(p):
79 p[0] = 0
80 return 1
81 @ffi.callback("int(unsigned long long *)")
82 def fetch_constant_neg(p):
83 p[0] = 123321
84 return 1
85
86 ctx_globals = ffi.new("struct _cffi_global_s[]", len(global_names))
87 c_glob_names = [ffi.new("char[]", _n.encode('ascii')) for _n in global_names]
88 for _i, _fn in enumerate([fetch_constant_five,
89 fetch_constant_neg,
90 fetch_constant_zero]):
91 ctx_globals[_i].name = c_glob_names[_i]
92 ctx_globals[_i].address = _fn
93 ctx_globals[_i].type_op = ffi.cast("_cffi_opcode_t",
94 cffi_opcode.OP_CONSTANT_INT if _i != 1
95 else cffi_opcode.OP_ENUM)
96 ctx.globals = ctx_globals
97 ctx.num_globals = len(global_names)
98
99
100 def parse(input):
101 out = ffi.new("_cffi_opcode_t[]", 100)
102 info = ffi.new("struct _cffi_parse_info_s *")
103 info.ctx = ctx
104 info.output = out
105 info.output_size = len(out)
106 for j in range(len(out)):
107 out[j] = ffi.cast("void *", -424242)
108 res = lib.parse_c_type(info, input.encode('ascii'))
109 if res < 0:
110 raise ParseError(ffi.string(info.error_message).decode('ascii'),
111 info.error_location)
112 assert 0 <= res < len(out)
113 result = []
114 for j in range(len(out)):
115 if out[j] == ffi.cast("void *", -424242):
116 assert res < j
117 break
118 i = int(ffi.cast("intptr_t", out[j]))
119 if j == res:
120 result.append('->')
121 result.append(i)
122 return result
123
124 def parsex(input):
125 result = parse(input)
126 def str_if_int(x):
127 if isinstance(x, str):
128 return x
129 return '%d,%d' % (x & 255, x >> 8)
130 return ' '.join(map(str_if_int, result))
131
132 def parse_error(input, expected_msg, expected_location):
133 e = py.test.raises(ParseError, parse, input)
134 assert e.value.args[0] == expected_msg
135 assert e.value.args[1] == expected_location
136
137 def make_getter(name):
138 opcode = getattr(lib, '_CFFI_OP_' + name)
139 def getter(value):
140 return opcode | (value << 8)
141 return getter
142
143 Prim = make_getter('PRIMITIVE')
144 Pointer = make_getter('POINTER')
145 Array = make_getter('ARRAY')
146 OpenArray = make_getter('OPEN_ARRAY')
147 NoOp = make_getter('NOOP')
148 Func = make_getter('FUNCTION')
149 FuncEnd = make_getter('FUNCTION_END')
150 Struct = make_getter('STRUCT_UNION')
151 Enum = make_getter('ENUM')
152 Typename = make_getter('TYPENAME')
153
154
155 def test_simple():
156 for simple_type, expected in [
157 ("int", lib._CFFI_PRIM_INT),
158 ("signed int", lib._CFFI_PRIM_INT),
159 (" long ", lib._CFFI_PRIM_LONG),
160 ("long int", lib._CFFI_PRIM_LONG),
161 ("unsigned short", lib._CFFI_PRIM_USHORT),
162 ("long double", lib._CFFI_PRIM_LONGDOUBLE),
163 (" float _Complex", lib._CFFI_PRIM_FLOATCOMPLEX),
164 ("double _Complex ", lib._CFFI_PRIM_DOUBLECOMPLEX),
165 ]:
166 assert parse(simple_type) == ['->', Prim(expected)]
167
168 def test_array():
169 assert parse("int[5]") == [Prim(lib._CFFI_PRIM_INT), '->', Array(0), 5]
170 assert parse("int[]") == [Prim(lib._CFFI_PRIM_INT), '->', OpenArray(0)]
171 assert parse("int[5][8]") == [Prim(lib._CFFI_PRIM_INT),
172 '->', Array(3),
173 5,
174 Array(0),
175 8]
176 assert parse("int[][8]") == [Prim(lib._CFFI_PRIM_INT),
177 '->', OpenArray(2),
178 Array(0),
179 8]
180
181 def test_pointer():
182 assert parse("int*") == [Prim(lib._CFFI_PRIM_INT), '->', Pointer(0)]
183 assert parse("int***") == [Prim(lib._CFFI_PRIM_INT),
184 Pointer(0), Pointer(1), '->', Pointer(2)]
185
186 def test_grouping():
187 assert parse("int*[]") == [Prim(lib._CFFI_PRIM_INT),
188 Pointer(0), '->', OpenArray(1)]
189 assert parse("int**[][8]") == [Prim(lib._CFFI_PRIM_INT),
190 Pointer(0), Pointer(1),
191 '->', OpenArray(4), Array(2), 8]
192 assert parse("int(*)[]") == [Prim(lib._CFFI_PRIM_INT),
193 NoOp(3), '->', Pointer(1), OpenArray(0)]
194 assert parse("int(*)[][8]") == [Prim(lib._CFFI_PRIM_INT),
195 NoOp(3), '->', Pointer(1),
196 OpenArray(4), Array(0), 8]
197 assert parse("int**(**)") == [Prim(lib._CFFI_PRIM_INT),
198 Pointer(0), Pointer(1),
199 NoOp(2), Pointer(3), '->', Pointer(4)]
200 assert parse("int**(**)[]") == [Prim(lib._CFFI_PRIM_INT),
201 Pointer(0), Pointer(1),
202 NoOp(6), Pointer(3), '->', Pointer(4),
203 OpenArray(2)]
204
205 def test_simple_function():
206 assert parse("int()") == [Prim(lib._CFFI_PRIM_INT),
207 '->', Func(0), FuncEnd(0), 0]
208 assert parse("int(int)") == [Prim(lib._CFFI_PRIM_INT),
209 '->', Func(0), NoOp(4), FuncEnd(0),
210 Prim(lib._CFFI_PRIM_INT)]
211 assert parse("int(long, char)") == [
212 Prim(lib._CFFI_PRIM_INT),
213 '->', Func(0), NoOp(5), NoOp(6), FuncEnd(0),
214 Prim(lib._CFFI_PRIM_LONG),
215 Prim(lib._CFFI_PRIM_CHAR)]
216 assert parse("int(int*)") == [Prim(lib._CFFI_PRIM_INT),
217 '->', Func(0), NoOp(5), FuncEnd(0),
218 Prim(lib._CFFI_PRIM_INT),
219 Pointer(4)]
220 assert parse("int*(void)") == [Prim(lib._CFFI_PRIM_INT),
221 Pointer(0),
222 '->', Func(1), FuncEnd(0), 0]
223 assert parse("int(int, ...)") == [Prim(lib._CFFI_PRIM_INT),
224 '->', Func(0), NoOp(5), FuncEnd(1), 0,
225 Prim(lib._CFFI_PRIM_INT)]
226
227 def test_internal_function():
228 assert parse("int(*)()") == [Prim(lib._CFFI_PRIM_INT),
229 NoOp(3), '->', Pointer(1),
230 Func(0), FuncEnd(0), 0]
231 assert parse("int(*())[]") == [Prim(lib._CFFI_PRIM_INT),
232 NoOp(6), Pointer(1),
233 '->', Func(2), FuncEnd(0), 0,
234 OpenArray(0)]
235 assert parse("int(char(*)(long, short))") == [
236 Prim(lib._CFFI_PRIM_INT),
237 '->', Func(0), NoOp(6), FuncEnd(0),
238 Prim(lib._CFFI_PRIM_CHAR),
239 NoOp(7), Pointer(5),
240 Func(4), NoOp(11), NoOp(12), FuncEnd(0),
241 Prim(lib._CFFI_PRIM_LONG),
242 Prim(lib._CFFI_PRIM_SHORT)]
243
244 def test_fix_arg_types():
245 assert parse("int(char(long, short))") == [
246 Prim(lib._CFFI_PRIM_INT),
247 '->', Func(0), Pointer(5), FuncEnd(0),
248 Prim(lib._CFFI_PRIM_CHAR),
249 Func(4), NoOp(9), NoOp(10), FuncEnd(0),
250 Prim(lib._CFFI_PRIM_LONG),
251 Prim(lib._CFFI_PRIM_SHORT)]
252 assert parse("int(char[])") == [
253 Prim(lib._CFFI_PRIM_INT),
254 '->', Func(0), Pointer(4), FuncEnd(0),
255 Prim(lib._CFFI_PRIM_CHAR),
256 OpenArray(4)]
257
258 def test_enum():
259 for i in range(len(enum_names)):
260 assert parse("enum %s" % (enum_names[i],)) == ['->', Enum(i)]
261 assert parse("enum %s*" % (enum_names[i],)) == [Enum(i),
262 '->', Pointer(0)]
263
264 def test_error():
265 parse_error("short short int", "'short' after another 'short' or 'long'", 6)
266 parse_error("long long long", "'long long long' is too long", 10)
267 parse_error("short long", "'long' after 'short'", 6)
268 parse_error("signed unsigned int", "multiple 'signed' or 'unsigned'", 7)
269 parse_error("unsigned signed int", "multiple 'signed' or 'unsigned'", 9)
270 parse_error("long char", "invalid combination of types", 5)
271 parse_error("short char", "invalid combination of types", 6)
272 parse_error("signed void", "invalid combination of types", 7)
273 parse_error("unsigned struct", "invalid combination of types", 9)
274 #
275 parse_error("", "identifier expected", 0)
276 parse_error("]", "identifier expected", 0)
277 parse_error("*", "identifier expected", 0)
278 parse_error("int ]**", "unexpected symbol", 4)
279 parse_error("char char", "unexpected symbol", 5)
280 parse_error("int(int]", "expected ')'", 7)
281 parse_error("int(*]", "expected ')'", 5)
282 parse_error("int(]", "identifier expected", 4)
283 parse_error("int[?]", "expected a positive integer constant", 4)
284 parse_error("int[24)", "expected ']'", 6)
285 parse_error("struct", "struct or union name expected", 6)
286 parse_error("struct 24", "struct or union name expected", 7)
287 parse_error("int[5](*)", "unexpected symbol", 6)
288 parse_error("int a(*)", "identifier expected", 6)
289 parse_error("int[123456789012345678901234567890]", "number too large", 4)
290 #
291 parse_error("_Complex", "identifier expected", 0)
292 parse_error("int _Complex", "_Complex type combination unsupported", 4)
293 parse_error("long double _Complex", "_Complex type combination unsupported",
294 12)
295
296 def test_number_too_large():
297 num_max = sys.maxsize
298 assert parse("char[%d]" % num_max) == [Prim(lib._CFFI_PRIM_CHAR),
299 '->', Array(0), num_max]
300 parse_error("char[%d]" % (num_max + 1), "number too large", 5)
301
302 def test_complexity_limit():
303 parse_error("int" + "[]" * 2500, "internal type complexity limit reached",
304 202)
305
306 def test_struct():
307 for i in range(len(struct_names)):
308 if i == 3:
309 tag = "union"
310 else:
311 tag = "struct"
312 assert parse("%s %s" % (tag, struct_names[i])) == ['->', Struct(i)]
313 assert parse("%s %s*" % (tag, struct_names[i])) == [Struct(i),
314 '->', Pointer(0)]
315
316 def test_exchanging_struct_union():
317 parse_error("union %s" % (struct_names[0],),
318 "wrong kind of tag: struct vs union", 6)
319 parse_error("struct %s" % (struct_names[3],),
320 "wrong kind of tag: struct vs union", 7)
321
322 def test_identifier():
323 for i in range(len(identifier_names)):
324 assert parse("%s" % (identifier_names[i])) == ['->', Typename(i)]
325 assert parse("%s*" % (identifier_names[i])) == [Typename(i),
326 '->', Pointer(0)]
327
328 def test_cffi_opcode_sync():
329 import cffi.model
330 for name in dir(lib):
331 if name.startswith('_CFFI_'):
332 assert getattr(cffi_opcode, name[6:]) == getattr(lib, name)
333 assert sorted(cffi_opcode.PRIMITIVE_TO_INDEX.keys()) == (
334 sorted(cffi.model.PrimitiveType.ALL_PRIMITIVE_TYPES.keys()))
335
336 def test_array_length_from_constant():
337 parse_error("int[UNKNOWN]", "expected a positive integer constant", 4)
338 assert parse("int[FIVE]") == [Prim(lib._CFFI_PRIM_INT), '->', Array(0), 5]
339 assert parse("int[ZERO]") == [Prim(lib._CFFI_PRIM_INT), '->', Array(0), 0]
340 parse_error("int[NEG]", "expected a positive integer constant", 4)
341
342 def test_various_constant_exprs():
343 def array(n):
344 return [Prim(lib._CFFI_PRIM_CHAR), '->', Array(0), n]
345 assert parse("char[21]") == array(21)
346 assert parse("char[0x10]") == array(16)
347 assert parse("char[0X21]") == array(33)
348 assert parse("char[0Xb]") == array(11)
349 assert parse("char[0x1C]") == array(0x1C)
350 assert parse("char[0xc6]") == array(0xC6)
351 assert parse("char[010]") == array(8)
352 assert parse("char[021]") == array(17)
353 parse_error("char[08]", "invalid number", 5)
354 parse_error("char[1C]", "invalid number", 5)
355 parse_error("char[0C]", "invalid number", 5)
356 # not supported (really obscure):
357 # "char[+5]"
358 # "char['A']"
359
360 def test_stdcall_cdecl():
361 assert parse("int __stdcall(int)") == [Prim(lib._CFFI_PRIM_INT),
362 '->', Func(0), NoOp(4), FuncEnd(2),
363 Prim(lib._CFFI_PRIM_INT)]
364 assert parse("int __stdcall func(int)") == parse("int __stdcall(int)")
365 assert parse("int (__stdcall *)()") == [Prim(lib._CFFI_PRIM_INT),
366 NoOp(3), '->', Pointer(1),
367 Func(0), FuncEnd(2), 0]
368 assert parse("int (__stdcall *p)()") == parse("int (__stdcall*)()")
369 parse_error("__stdcall int", "identifier expected", 0)
370 parse_error("__cdecl int", "identifier expected", 0)
371 parse_error("int __stdcall", "expected '('", 13)
372 parse_error("int __cdecl", "expected '('", 11)
0 # Generated by pypy/tool/import_cffi.py
1 import sys
2 import subprocess
3 import py
4 import cffi.pkgconfig as pkgconfig
5 from cffi import PkgConfigError
6
7
8 def mock_call(libname, flag):
9 assert libname=="foobarbaz"
10 flags = {
11 "--cflags": "-I/usr/include/python3.6m -DABCD -DCFFI_TEST=1 -O42\n",
12 "--libs": "-L/usr/lib64 -lpython3.6 -shared\n",
13 }
14 return flags[flag]
15
16
17 def test_merge_flags():
18 d1 = {"ham": [1, 2, 3], "spam" : ["a", "b", "c"], "foo" : []}
19 d2 = {"spam" : ["spam", "spam", "spam"], "bar" : ["b", "a", "z"]}
20
21 pkgconfig.merge_flags(d1, d2)
22 assert d1 == {
23 "ham": [1, 2, 3],
24 "spam" : ["a", "b", "c", "spam", "spam", "spam"],
25 "bar" : ["b", "a", "z"],
26 "foo" : []}
27
28
29 def test_pkgconfig():
30 assert pkgconfig.flags_from_pkgconfig([]) == {}
31
32 saved = pkgconfig.call
33 try:
34 pkgconfig.call = mock_call
35 flags = pkgconfig.flags_from_pkgconfig(["foobarbaz"])
36 finally:
37 pkgconfig.call = saved
38 assert flags == {
39 'include_dirs': ['/usr/include/python3.6m'],
40 'library_dirs': ['/usr/lib64'],
41 'libraries': ['python3.6'],
42 'define_macros': [('ABCD', None), ('CFFI_TEST', '1')],
43 'extra_compile_args': ['-O42'],
44 'extra_link_args': ['-shared']
45 }
46
47 class mock_subprocess:
48 PIPE = Ellipsis
49 class Popen:
50 def __init__(self, cmd, stdout, stderr):
51 if mock_subprocess.RESULT is None:
52 raise OSError("oops can't run")
53 assert cmd == ['pkg-config', '--print-errors', '--cflags', 'libfoo']
54 def communicate(self):
55 bout, berr, rc = mock_subprocess.RESULT
56 self.returncode = rc
57 return bout, berr
58
59 def test_call():
60 saved = pkgconfig.subprocess
61 try:
62 pkgconfig.subprocess = mock_subprocess
63
64 mock_subprocess.RESULT = None
65 e = py.test.raises(PkgConfigError, pkgconfig.call, "libfoo", "--cflags")
66 assert str(e.value) == "cannot run pkg-config: oops can't run"
67
68 mock_subprocess.RESULT = b"", "Foo error!\n", 1
69 e = py.test.raises(PkgConfigError, pkgconfig.call, "libfoo", "--cflags")
70 assert str(e.value) == "Foo error!"
71
72 mock_subprocess.RESULT = b"abc\\def\n", "", 0
73 e = py.test.raises(PkgConfigError, pkgconfig.call, "libfoo", "--cflags")
74 assert str(e.value).startswith("pkg-config --cflags libfoo returned an "
75 "unsupported backslash-escaped output:")
76
77 mock_subprocess.RESULT = b"abc def\n", "", 0
78 result = pkgconfig.call("libfoo", "--cflags")
79 assert result == "abc def\n"
80
81 mock_subprocess.RESULT = b"abc def\n", "", 0
82 result = pkgconfig.call("libfoo", "--cflags")
83 assert result == "abc def\n"
84
85 if sys.version_info >= (3,):
86 mock_subprocess.RESULT = b"\xff\n", "", 0
87 e = py.test.raises(PkgConfigError, pkgconfig.call,
88 "libfoo", "--cflags", encoding="utf-8")
89 assert str(e.value) == (
90 "pkg-config --cflags libfoo returned bytes that cannot be "
91 "decoded with encoding 'utf-8':\nb'\\xff\\n'")
92
93 finally:
94 pkgconfig.subprocess = saved
0 # Generated by pypy/tool/import_cffi.py
1 import sys, os
2 import py
3 from cffi import FFI
4 from cffi import recompiler, ffiplatform, VerificationMissing
5 from extra_tests.cffi_tests.udir import udir
6 from extra_tests.cffi_tests.support import u
7
8
9 def setup_module(mod):
10 SRC = """
11 #include <string.h>
12 #define FOOBAR (-42)
13 static const int FOOBAZ = -43;
14 #define BIGPOS 420000000000L
15 #define BIGNEG -420000000000L
16 int add42(int x) { return x + 42; }
17 int add43(int x, ...) { return x; }
18 int globalvar42 = 1234;
19 const int globalconst42 = 4321;
20 const char *const globalconsthello = "hello";
21 struct foo_s;
22 typedef struct bar_s { int x; signed char a[]; } bar_t;
23 enum foo_e { AA, BB, CC };
24
25 void init_test_re_python(void) { } /* windows hack */
26 void PyInit__test_re_python(void) { } /* windows hack */
27 """
28 tmpdir = udir.join('test_re_python')
29 tmpdir.ensure(dir=1)
30 c_file = tmpdir.join('_test_re_python.c')
31 c_file.write(SRC)
32 ext = ffiplatform.get_extension(
33 str(c_file),
34 '_test_re_python',
35 export_symbols=['add42', 'add43', 'globalvar42',
36 'globalconst42', 'globalconsthello']
37 )
38 outputfilename = ffiplatform.compile(str(tmpdir), ext)
39
40 # test with a non-ascii char
41 ofn, oext = os.path.splitext(outputfilename)
42 if sys.platform == "win32":
43 unicode_name = ofn + (u+'\u03be') + oext
44 else:
45 unicode_name = ofn + (u+'\xe9') + oext
46 try:
47 unicode_name.encode(sys.getfilesystemencoding())
48 except UnicodeEncodeError:
49 unicode_name = None
50 if unicode_name is not None:
51 print(repr(outputfilename) + ' ==> ' + repr(unicode_name))
52 os.rename(outputfilename, unicode_name)
53 outputfilename = unicode_name
54
55 mod.extmod = outputfilename
56 mod.tmpdir = tmpdir
57 #
58 ffi = FFI()
59 ffi.cdef("""
60 #define FOOBAR -42
61 static const int FOOBAZ = -43;
62 #define BIGPOS 420000000000L
63 #define BIGNEG -420000000000L
64 int add42(int);
65 int add43(int, ...);
66 int globalvar42;
67 const int globalconst42;
68 const char *const globalconsthello = "hello";
69 int no_such_function(int);
70 int no_such_globalvar;
71 struct foo_s;
72 typedef struct bar_s { int x; signed char a[]; } bar_t;
73 enum foo_e { AA, BB, CC };
74 int strlen(const char *);
75 struct with_union { union { int a; char b; }; };
76 union with_struct { struct { int a; char b; }; };
77 struct NVGcolor { union { float rgba[4]; struct { float r,g,b,a; }; }; };
78 """)
79 ffi.set_source('re_python_pysrc', None)
80 ffi.emit_python_code(str(tmpdir.join('re_python_pysrc.py')))
81 mod.original_ffi = ffi
82 #
83 sys.path.insert(0, str(tmpdir))
84
85
86 def test_constant():
87 from re_python_pysrc import ffi
88 assert ffi.integer_const('FOOBAR') == -42
89 assert ffi.integer_const('FOOBAZ') == -43
90
91 def test_large_constant():
92 from re_python_pysrc import ffi
93 assert ffi.integer_const('BIGPOS') == 420000000000
94 assert ffi.integer_const('BIGNEG') == -420000000000
95
96 def test_function():
97 import _cffi_backend
98 from re_python_pysrc import ffi
99 lib = ffi.dlopen(extmod)
100 assert lib.add42(-10) == 32
101 assert type(lib.add42) is _cffi_backend.FFI.CData
102
103 def test_function_with_varargs():
104 import _cffi_backend
105 from re_python_pysrc import ffi
106 lib = ffi.dlopen(extmod, 0)
107 assert lib.add43(45, ffi.cast("int", -5)) == 45
108 assert type(lib.add43) is _cffi_backend.FFI.CData
109
110 def test_dlopen_none():
111 import _cffi_backend
112 from re_python_pysrc import ffi
113 name = None
114 if sys.platform == 'win32':
115 import ctypes.util
116 name = ctypes.util.find_msvcrt()
117 if name is None:
118 py.test.skip("dlopen(None) cannot work on Windows with Python 3")
119 lib = ffi.dlopen(name)
120 assert lib.strlen(b"hello") == 5
121
122 def test_dlclose():
123 import _cffi_backend
124 from re_python_pysrc import ffi
125 lib = ffi.dlopen(extmod)
126 ffi.dlclose(lib)
127 if type(extmod) is not str: # unicode, on python 2
128 str_extmod = extmod.encode('utf-8')
129 else:
130 str_extmod = extmod
131 e = py.test.raises(ffi.error, getattr, lib, 'add42')
132 assert str(e.value) == (
133 "library '%s' has been closed" % (str_extmod,))
134 ffi.dlclose(lib) # does not raise
135
136 def test_constant_via_lib():
137 from re_python_pysrc import ffi
138 lib = ffi.dlopen(extmod)
139 assert lib.FOOBAR == -42
140 assert lib.FOOBAZ == -43
141
142 def test_opaque_struct():
143 from re_python_pysrc import ffi
144 ffi.cast("struct foo_s *", 0)
145 py.test.raises(TypeError, ffi.new, "struct foo_s *")
146
147 def test_nonopaque_struct():
148 from re_python_pysrc import ffi
149 for p in [ffi.new("struct bar_s *", [5, b"foobar"]),
150 ffi.new("bar_t *", [5, b"foobar"])]:
151 assert p.x == 5
152 assert p.a[0] == ord('f')
153 assert p.a[5] == ord('r')
154
155 def test_enum():
156 from re_python_pysrc import ffi
157 assert ffi.integer_const("BB") == 1
158 e = ffi.cast("enum foo_e", 2)
159 assert ffi.string(e) == "CC"
160
161 def test_include_1():
162 sub_ffi = FFI()
163 sub_ffi.cdef("static const int k2 = 121212;")
164 sub_ffi.include(original_ffi)
165 assert 'macro FOOBAR' in original_ffi._parser._declarations
166 assert 'macro FOOBAZ' in original_ffi._parser._declarations
167 sub_ffi.set_source('re_python_pysrc', None)
168 sub_ffi.emit_python_code(str(tmpdir.join('_re_include_1.py')))
169 #
170 if sys.version_info[:2] >= (3, 3):
171 import importlib
172 importlib.invalidate_caches() # issue 197 (but can't reproduce myself)
173 #
174 from _re_include_1 import ffi
175 assert ffi.integer_const('FOOBAR') == -42
176 assert ffi.integer_const('FOOBAZ') == -43
177 assert ffi.integer_const('k2') == 121212
178 lib = ffi.dlopen(extmod) # <- a random unrelated library would be fine
179 assert lib.FOOBAR == -42
180 assert lib.FOOBAZ == -43
181 assert lib.k2 == 121212
182 #
183 p = ffi.new("bar_t *", [5, b"foobar"])
184 assert p.a[4] == ord('a')
185
186 def test_global_var():
187 from re_python_pysrc import ffi
188 lib = ffi.dlopen(extmod)
189 assert lib.globalvar42 == 1234
190 p = ffi.addressof(lib, 'globalvar42')
191 lib.globalvar42 += 5
192 assert p[0] == 1239
193 p[0] -= 1
194 assert lib.globalvar42 == 1238
195
196 def test_global_const_int():
197 from re_python_pysrc import ffi
198 lib = ffi.dlopen(extmod)
199 assert lib.globalconst42 == 4321
200 py.test.raises(AttributeError, ffi.addressof, lib, 'globalconst42')
201
202 def test_global_const_nonint():
203 from re_python_pysrc import ffi
204 lib = ffi.dlopen(extmod)
205 assert ffi.string(lib.globalconsthello, 8) == b"hello"
206 py.test.raises(AttributeError, ffi.addressof, lib, 'globalconsthello')
207
208 def test_rtld_constants():
209 from re_python_pysrc import ffi
210 ffi.RTLD_NOW # check that we have the attributes
211 ffi.RTLD_LAZY
212 ffi.RTLD_GLOBAL
213
214 def test_no_such_function_or_global_var():
215 from re_python_pysrc import ffi
216 lib = ffi.dlopen(extmod)
217 e = py.test.raises(ffi.error, getattr, lib, 'no_such_function')
218 assert str(e.value).startswith(
219 "symbol 'no_such_function' not found in library '")
220 e = py.test.raises(ffi.error, getattr, lib, 'no_such_globalvar')
221 assert str(e.value).startswith(
222 "symbol 'no_such_globalvar' not found in library '")
223
224 def test_check_version():
225 import _cffi_backend
226 e = py.test.raises(ImportError, _cffi_backend.FFI,
227 "foobar", _version=0x2594)
228 assert str(e.value).startswith(
229 "cffi out-of-line Python module 'foobar' has unknown version")
230
231 def test_partial_enum():
232 ffi = FFI()
233 ffi.cdef("enum foo { A, B, ... };")
234 ffi.set_source('test_partial_enum', None)
235 py.test.raises(VerificationMissing, ffi.emit_python_code,
236 str(tmpdir.join('test_partial_enum.py')))
237
238 def test_anonymous_union_inside_struct():
239 # based on issue #357
240 from re_python_pysrc import ffi
241 INT = ffi.sizeof("int")
242 assert ffi.offsetof("struct with_union", "a") == 0
243 assert ffi.offsetof("struct with_union", "b") == 0
244 assert ffi.sizeof("struct with_union") == INT
245 #
246 assert ffi.offsetof("union with_struct", "a") == 0
247 assert ffi.offsetof("union with_struct", "b") == INT
248 assert ffi.sizeof("union with_struct") >= INT + 1
249 #
250 FLOAT = ffi.sizeof("float")
251 assert ffi.sizeof("struct NVGcolor") == FLOAT * 4
252 assert ffi.offsetof("struct NVGcolor", "rgba") == 0
253 assert ffi.offsetof("struct NVGcolor", "r") == 0
254 assert ffi.offsetof("struct NVGcolor", "g") == FLOAT
255 assert ffi.offsetof("struct NVGcolor", "b") == FLOAT * 2
256 assert ffi.offsetof("struct NVGcolor", "a") == FLOAT * 3
0 # Generated by pypy/tool/import_cffi.py
1 import py, sys
2 from cffi import cffi_opcode
3
4
5 def check(input, expected_output=None, expected_ffi_error=False):
6 import _cffi_backend
7 ffi = _cffi_backend.FFI()
8 if not expected_ffi_error:
9 ct = ffi.typeof(input)
10 assert isinstance(ct, ffi.CType)
11 assert ct.cname == (expected_output or input)
12 else:
13 e = py.test.raises(ffi.error, ffi.typeof, input)
14 if isinstance(expected_ffi_error, str):
15 assert str(e.value) == expected_ffi_error
16
17 def test_void():
18 check("void", "void")
19 check(" void ", "void")
20
21 def test_int_star():
22 check("int")
23 check("int *")
24 check("int*", "int *")
25 check("long int", "long")
26 check("long")
27
28 def test_noop():
29 check("int(*)", "int *")
30
31 def test_array():
32 check("int[6]")
33
34 def test_funcptr():
35 check("int(*)(long)")
36 check("int(long)", expected_ffi_error="the type 'int(long)' is a"
37 " function type, not a pointer-to-function type")
38 check("int(void)", expected_ffi_error="the type 'int()' is a"
39 " function type, not a pointer-to-function type")
40
41 def test_funcptr_rewrite_args():
42 check("int(*)(int(int))", "int(*)(int(*)(int))")
43 check("int(*)(long[])", "int(*)(long *)")
44 check("int(*)(long[5])", "int(*)(long *)")
45
46 def test_all_primitives():
47 for name in cffi_opcode.PRIMITIVE_TO_INDEX:
48 check(name, name)
49
50 def check_func(input, expected_output=None):
51 import _cffi_backend
52 ffi = _cffi_backend.FFI()
53 ct = ffi.typeof(ffi.callback(input, lambda: None))
54 assert isinstance(ct, ffi.CType)
55 if sys.platform != 'win32' or sys.maxsize > 2**32:
56 expected_output = expected_output.replace('__stdcall *', '*')
57 assert ct.cname == expected_output
58
59 def test_funcptr_stdcall():
60 check_func("int(int)", "int(*)(int)")
61 check_func("int foobar(int)", "int(*)(int)")
62 check_func("int __stdcall(int)", "int(__stdcall *)(int)")
63 check_func("int __stdcall foobar(int)", "int(__stdcall *)(int)")
64 check_func("void __cdecl(void)", "void(*)()")
65 check_func("void __cdecl foobar(void)", "void(*)()")
66 check_func("void __stdcall(void)", "void(__stdcall *)()")
67 check_func("void __stdcall foobar(long, short)",
68 "void(__stdcall *)(long, short)")
69 check_func("void(void __cdecl(void), void __stdcall(void))",
70 "void(*)(void(*)(), void(__stdcall *)())")
71
72 def test_variadic_overrides_stdcall():
73 check("void (__stdcall*)(int, ...)", "void(*)(int, ...)")
0 # Generated by pypy/tool/import_cffi.py
1
2 import sys, os, py
3 from cffi import FFI, VerificationError, FFIError, CDefError
4 from cffi import recompiler
5 from extra_tests.cffi_tests.udir import udir
6 from extra_tests.cffi_tests.support import u, long
7 from extra_tests.cffi_tests.support import FdWriteCapture, StdErrCapture, _verify
8
9 try:
10 import importlib
11 except ImportError:
12 importlib = None
13
14
15 def check_type_table(input, expected_output, included=None):
16 ffi = FFI()
17 if included:
18 ffi1 = FFI()
19 ffi1.cdef(included)
20 ffi.include(ffi1)
21 ffi.cdef(input)
22 recomp = recompiler.Recompiler(ffi, 'testmod')
23 recomp.collect_type_table()
24 assert ''.join(map(str, recomp.cffi_types)) == expected_output
25
26 def verify(ffi, module_name, source, *args, **kwds):
27 no_cpp = kwds.pop('no_cpp', False)
28 kwds.setdefault('undef_macros', ['NDEBUG'])
29 module_name = '_CFFI_' + module_name
30 ffi.set_source(module_name, source)
31 if not os.environ.get('NO_CPP') and not no_cpp: # test the .cpp mode too
32 kwds.setdefault('source_extension', '.cpp')
33 source = 'extern "C" {\n%s\n}' % (source,)
34 elif sys.platform != 'win32':
35 # add '-Werror' to the existing 'extra_compile_args' flags
36 kwds['extra_compile_args'] = (kwds.get('extra_compile_args', []) +
37 ['-Werror'])
38 return _verify(ffi, module_name, source, *args, **kwds)
39
40 def test_set_source_no_slashes():
41 ffi = FFI()
42 py.test.raises(ValueError, ffi.set_source, "abc/def", None)
43 py.test.raises(ValueError, ffi.set_source, "abc/def", "C code")
44
45
46 def test_type_table_func():
47 check_type_table("double sin(double);",
48 "(FUNCTION 1)(PRIMITIVE 14)(FUNCTION_END 0)")
49 check_type_table("float sin(double);",
50 "(FUNCTION 3)(PRIMITIVE 14)(FUNCTION_END 0)(PRIMITIVE 13)")
51 check_type_table("float sin(void);",
52 "(FUNCTION 2)(FUNCTION_END 0)(PRIMITIVE 13)")
53 check_type_table("double sin(float); double cos(float);",
54 "(FUNCTION 3)(PRIMITIVE 13)(FUNCTION_END 0)(PRIMITIVE 14)")
55 check_type_table("double sin(float); double cos(double);",
56 "(FUNCTION 1)(PRIMITIVE 14)(FUNCTION_END 0)" # cos
57 "(FUNCTION 1)(PRIMITIVE 13)(FUNCTION_END 0)") # sin
58 check_type_table("float sin(double); float cos(float);",
59 "(FUNCTION 4)(PRIMITIVE 14)(FUNCTION_END 0)" # sin
60 "(FUNCTION 4)(PRIMITIVE 13)(FUNCTION_END 0)") # cos
61
62 def test_type_table_use_noop_for_repeated_args():
63 check_type_table("double sin(double *, double *);",
64 "(FUNCTION 4)(POINTER 4)(NOOP 1)(FUNCTION_END 0)"
65 "(PRIMITIVE 14)")
66 check_type_table("double sin(double *, double *, double);",
67 "(FUNCTION 3)(POINTER 3)(NOOP 1)(PRIMITIVE 14)"
68 "(FUNCTION_END 0)")
69
70 def test_type_table_dont_use_noop_for_primitives():
71 check_type_table("double sin(double, double);",
72 "(FUNCTION 1)(PRIMITIVE 14)(PRIMITIVE 14)(FUNCTION_END 0)")
73
74 def test_type_table_funcptr_as_argument():
75 check_type_table("int sin(double(float));",
76 "(FUNCTION 6)(PRIMITIVE 13)(FUNCTION_END 0)"
77 "(FUNCTION 7)(POINTER 0)(FUNCTION_END 0)"
78 "(PRIMITIVE 14)(PRIMITIVE 7)")
79
80 def test_type_table_variadic_function():
81 check_type_table("int sin(int, ...);",
82 "(FUNCTION 1)(PRIMITIVE 7)(FUNCTION_END 1)(POINTER 0)")
83
84 def test_type_table_array():
85 check_type_table("int a[100];",
86 "(PRIMITIVE 7)(ARRAY 0)(None 100)")
87
88 def test_type_table_typedef():
89 check_type_table("typedef int foo_t;",
90 "(PRIMITIVE 7)")
91
92 def test_type_table_prebuilt_type():
93 check_type_table("int32_t f(void);",
94 "(FUNCTION 2)(FUNCTION_END 0)(PRIMITIVE 21)")
95
96 def test_type_table_struct_opaque():
97 check_type_table("struct foo_s;",
98 "(STRUCT_UNION 0)")
99
100 def test_type_table_struct():
101 check_type_table("struct foo_s { int a; long b; };",
102 "(PRIMITIVE 7)(PRIMITIVE 9)(STRUCT_UNION 0)")
103
104 def test_type_table_union():
105 check_type_table("union foo_u { int a; long b; };",
106 "(PRIMITIVE 7)(PRIMITIVE 9)(STRUCT_UNION 0)")
107
108 def test_type_table_struct_used():
109 check_type_table("struct foo_s { int a; long b; }; int f(struct foo_s*);",
110 "(FUNCTION 3)(POINTER 5)(FUNCTION_END 0)"
111 "(PRIMITIVE 7)(PRIMITIVE 9)"
112 "(STRUCT_UNION 0)")
113
114 def test_type_table_anonymous_struct_with_typedef():
115 check_type_table("typedef struct { int a; long b; } foo_t;",
116 "(STRUCT_UNION 0)(PRIMITIVE 7)(PRIMITIVE 9)")
117
118 def test_type_table_enum():
119 check_type_table("enum foo_e { AA, BB, ... };",
120 "(ENUM 0)")
121
122 def test_type_table_include_1():
123 check_type_table("foo_t sin(foo_t);",
124 "(FUNCTION 1)(PRIMITIVE 14)(FUNCTION_END 0)",
125 included="typedef double foo_t;")
126
127 def test_type_table_include_2():
128 check_type_table("struct foo_s *sin(struct foo_s *);",
129 "(FUNCTION 1)(POINTER 3)(FUNCTION_END 0)(STRUCT_UNION 0)",
130 included="struct foo_s { int x, y; };")
131
132
133 def test_math_sin():
134 import math
135 ffi = FFI()
136 ffi.cdef("float sin(double); double cos(double);")
137 lib = verify(ffi, 'test_math_sin', '#include <math.h>')
138 assert lib.cos(1.43) == math.cos(1.43)
139
140 def test_repr_lib():
141 ffi = FFI()
142 lib = verify(ffi, 'test_repr_lib', '')
143 assert repr(lib) == "<Lib object for '_CFFI_test_repr_lib'>"
144
145 def test_funcarg_ptr():
146 ffi = FFI()
147 ffi.cdef("int foo(int *);")
148 lib = verify(ffi, 'test_funcarg_ptr', 'int foo(int *p) { return *p; }')
149 assert lib.foo([-12345]) == -12345
150
151 def test_funcres_ptr():
152 ffi = FFI()
153 ffi.cdef("int *foo(void);")
154 lib = verify(ffi, 'test_funcres_ptr',
155 'int *foo(void) { static int x=-12345; return &x; }')
156 assert lib.foo()[0] == -12345
157
158 def test_global_var_array():
159 ffi = FFI()
160 ffi.cdef("int a[100];")
161 lib = verify(ffi, 'test_global_var_array', 'int a[100] = { 9999 };')
162 lib.a[42] = 123456
163 assert lib.a[42] == 123456
164 assert lib.a[0] == 9999
165
166 def test_verify_typedef():
167 ffi = FFI()
168 ffi.cdef("typedef int **foo_t;")
169 lib = verify(ffi, 'test_verify_typedef', 'typedef int **foo_t;')
170 assert ffi.sizeof("foo_t") == ffi.sizeof("void *")
171
172 def test_verify_typedef_dotdotdot():
173 ffi = FFI()
174 ffi.cdef("typedef ... foo_t;")
175 verify(ffi, 'test_verify_typedef_dotdotdot', 'typedef int **foo_t;')
176
177 def test_verify_typedef_star_dotdotdot():
178 ffi = FFI()
179 ffi.cdef("typedef ... *foo_t;")
180 verify(ffi, 'test_verify_typedef_star_dotdotdot', 'typedef int **foo_t;')
181
182 def test_global_var_int():
183 ffi = FFI()
184 ffi.cdef("int a, b, c;")
185 lib = verify(ffi, 'test_global_var_int', 'int a = 999, b, c;')
186 assert lib.a == 999
187 lib.a -= 1001
188 assert lib.a == -2
189 lib.a = -2147483648
190 assert lib.a == -2147483648
191 py.test.raises(OverflowError, "lib.a = 2147483648")
192 py.test.raises(OverflowError, "lib.a = -2147483649")
193 lib.b = 525 # try with the first access being in setattr, too
194 assert lib.b == 525
195 py.test.raises(AttributeError, "del lib.a")
196 py.test.raises(AttributeError, "del lib.c")
197 py.test.raises(AttributeError, "del lib.foobarbaz")
198
199 def test_macro():
200 ffi = FFI()
201 ffi.cdef("#define FOOBAR ...")
202 lib = verify(ffi, 'test_macro', "#define FOOBAR (-6912)")
203 assert lib.FOOBAR == -6912
204 py.test.raises(AttributeError, "lib.FOOBAR = 2")
205
206 def test_macro_check_value():
207 # the value '-0x80000000' in C sources does not have a clear meaning
208 # to me; it appears to have a different effect than '-2147483648'...
209 # Moreover, on 32-bits, -2147483648 is actually equal to
210 # -2147483648U, which in turn is equal to 2147483648U and so positive.
211 vals = ['42', '-42', '0x80000000', '-2147483648',
212 '0', '9223372036854775809ULL',
213 '-9223372036854775807LL']
214 if sys.maxsize <= 2**32 or sys.platform == 'win32':
215 vals.remove('-2147483648')
216 ffi = FFI()
217 cdef_lines = ['#define FOO_%d_%d %s' % (i, j, vals[i])
218 for i in range(len(vals))
219 for j in range(len(vals))]
220 ffi.cdef('\n'.join(cdef_lines))
221
222 verify_lines = ['#define FOO_%d_%d %s' % (i, j, vals[j]) # [j], not [i]
223 for i in range(len(vals))
224 for j in range(len(vals))]
225 lib = verify(ffi, 'test_macro_check_value_ok',
226 '\n'.join(verify_lines))
227 #
228 for j in range(len(vals)):
229 c_got = int(vals[j].replace('U', '').replace('L', ''), 0)
230 c_compiler_msg = str(c_got)
231 if c_got > 0:
232 c_compiler_msg += ' (0x%x)' % (c_got,)
233 #
234 for i in range(len(vals)):
235 attrname = 'FOO_%d_%d' % (i, j)
236 if i == j:
237 x = getattr(lib, attrname)
238 assert x == c_got
239 else:
240 e = py.test.raises(ffi.error, getattr, lib, attrname)
241 assert str(e.value) == (
242 "the C compiler says '%s' is equal to "
243 "%s, but the cdef disagrees" % (attrname, c_compiler_msg))
244
245 def test_constant():
246 ffi = FFI()
247 ffi.cdef("static const int FOOBAR;")
248 lib = verify(ffi, 'test_constant', "#define FOOBAR (-6912)")
249 assert lib.FOOBAR == -6912
250 py.test.raises(AttributeError, "lib.FOOBAR = 2")
251
252 def test_check_value_of_static_const():
253 ffi = FFI()
254 ffi.cdef("static const int FOOBAR = 042;")
255 lib = verify(ffi, 'test_check_value_of_static_const',
256 "#define FOOBAR (-6912)")
257 e = py.test.raises(ffi.error, getattr, lib, 'FOOBAR')
258 assert str(e.value) == (
259 "the C compiler says 'FOOBAR' is equal to -6912, but the cdef disagrees")
260
261 def test_constant_nonint():
262 ffi = FFI()
263 ffi.cdef("static const double FOOBAR;")
264 lib = verify(ffi, 'test_constant_nonint', "#define FOOBAR (-6912.5)")
265 assert lib.FOOBAR == -6912.5
266 py.test.raises(AttributeError, "lib.FOOBAR = 2")
267
268 def test_constant_ptr():
269 ffi = FFI()
270 ffi.cdef("static double *const FOOBAR;")
271 lib = verify(ffi, 'test_constant_ptr', "#define FOOBAR NULL")
272 assert lib.FOOBAR == ffi.NULL
273 assert ffi.typeof(lib.FOOBAR) == ffi.typeof("double *")
274
275 def test_dir():
276 ffi = FFI()
277 ffi.cdef("int ff(int); int aa; static const int my_constant;")
278 lib = verify(ffi, 'test_dir', """
279 #define my_constant (-45)
280 int aa;
281 int ff(int x) { return x+aa; }
282 """)
283 lib.aa = 5
284 assert dir(lib) == ['aa', 'ff', 'my_constant']
285 #
286 aaobj = lib.__dict__['aa']
287 assert not isinstance(aaobj, int) # some internal object instead
288 assert lib.__dict__ == {
289 'ff': lib.ff,
290 'aa': aaobj,
291 'my_constant': -45}
292 lib.__dict__['ff'] = "??"
293 assert lib.ff(10) == 15
294
295 def test_verify_opaque_struct():
296 ffi = FFI()
297 ffi.cdef("struct foo_s;")
298 lib = verify(ffi, 'test_verify_opaque_struct', "struct foo_s;")
299 assert ffi.typeof("struct foo_s").cname == "struct foo_s"
300
301 def test_verify_opaque_union():
302 ffi = FFI()
303 ffi.cdef("union foo_s;")
304 lib = verify(ffi, 'test_verify_opaque_union', "union foo_s;")
305 assert ffi.typeof("union foo_s").cname == "union foo_s"
306
307 def test_verify_struct():
308 ffi = FFI()
309 ffi.cdef("""struct foo_s { int b; short a; ...; };
310 struct bar_s { struct foo_s *f; };""")
311 lib = verify(ffi, 'test_verify_struct',
312 """struct foo_s { short a; int b; };
313 struct bar_s { struct foo_s *f; };""")
314 ffi.typeof("struct bar_s *")
315 p = ffi.new("struct foo_s *", {'a': -32768, 'b': -2147483648})
316 assert p.a == -32768
317 assert p.b == -2147483648
318 py.test.raises(OverflowError, "p.a -= 1")
319 py.test.raises(OverflowError, "p.b -= 1")
320 q = ffi.new("struct bar_s *", {'f': p})
321 assert q.f == p
322 #
323 assert ffi.offsetof("struct foo_s", "a") == 0
324 assert ffi.offsetof("struct foo_s", "b") == 4
325 assert ffi.offsetof(u+"struct foo_s", u+"b") == 4
326 #
327 py.test.raises(TypeError, ffi.addressof, p)
328 assert ffi.addressof(p[0]) == p
329 assert ffi.typeof(ffi.addressof(p[0])) is ffi.typeof("struct foo_s *")
330 assert ffi.typeof(ffi.addressof(p, "b")) is ffi.typeof("int *")
331 assert ffi.addressof(p, "b")[0] == p.b
332
333 def test_verify_exact_field_offset():
334 ffi = FFI()
335 ffi.cdef("""struct foo_s { int b; short a; };""")
336 lib = verify(ffi, 'test_verify_exact_field_offset',
337 """struct foo_s { short a; int b; };""")
338 e = py.test.raises(ffi.error, ffi.new, "struct foo_s *", []) # lazily
339 assert str(e.value) == ("struct foo_s: wrong offset for field 'b' (cdef "
340 'says 0, but C compiler says 4). fix it or use "...;" '
341 "in the cdef for struct foo_s to make it flexible")
342
343 def test_type_caching():
344 ffi1 = FFI(); ffi1.cdef("struct foo_s;")
345 ffi2 = FFI(); ffi2.cdef("struct foo_s;") # different one!
346 lib1 = verify(ffi1, 'test_type_caching_1', 'struct foo_s;')
347 lib2 = verify(ffi2, 'test_type_caching_2', 'struct foo_s;')
348 # shared types
349 assert ffi1.typeof("long") is ffi2.typeof("long")
350 assert ffi1.typeof("long**") is ffi2.typeof("long * *")
351 assert ffi1.typeof("long(*)(int, ...)") is ffi2.typeof("long(*)(int, ...)")
352 # non-shared types
353 assert ffi1.typeof("struct foo_s") is not ffi2.typeof("struct foo_s")
354 assert ffi1.typeof("struct foo_s *") is not ffi2.typeof("struct foo_s *")
355 assert ffi1.typeof("struct foo_s*(*)()") is not (
356 ffi2.typeof("struct foo_s*(*)()"))
357 assert ffi1.typeof("void(*)(struct foo_s*)") is not (
358 ffi2.typeof("void(*)(struct foo_s*)"))
359
360 def test_verify_enum():
361 ffi = FFI()
362 ffi.cdef("""enum e1 { B1, A1, ... }; enum e2 { B2, A2, ... };""")
363 lib = verify(ffi, 'test_verify_enum',
364 "enum e1 { A1, B1, C1=%d };" % sys.maxsize +
365 "enum e2 { A2, B2, C2 };")
366 ffi.typeof("enum e1")
367 ffi.typeof("enum e2")
368 assert lib.A1 == 0
369 assert lib.B1 == 1
370 assert lib.A2 == 0
371 assert lib.B2 == 1
372 assert ffi.sizeof("enum e1") == ffi.sizeof("long")
373 assert ffi.sizeof("enum e2") == ffi.sizeof("int")
374 assert repr(ffi.cast("enum e1", 0)) == "<cdata 'enum e1' 0: A1>"
375
376 def test_duplicate_enum():
377 ffi = FFI()
378 ffi.cdef("enum e1 { A1, ... }; enum e2 { A1, ... };")
379 py.test.raises(VerificationError, verify, ffi, 'test_duplicate_enum',
380 "enum e1 { A1 }; enum e2 { B1 };")
381
382 def test_dotdotdot_length_of_array_field():
383 ffi = FFI()
384 ffi.cdef("struct foo_s { int a[...]; int b[...]; };")
385 verify(ffi, 'test_dotdotdot_length_of_array_field',
386 "struct foo_s { int a[42]; int b[11]; };")
387 assert ffi.sizeof("struct foo_s") == (42 + 11) * 4
388 p = ffi.new("struct foo_s *")
389 assert p.a[41] == p.b[10] == 0
390 py.test.raises(IndexError, "p.a[42]")
391 py.test.raises(IndexError, "p.b[11]")
392
393 def test_dotdotdot_global_array():
394 ffi = FFI()
395 ffi.cdef("int aa[...]; int bb[...];")
396 lib = verify(ffi, 'test_dotdotdot_global_array',
397 "int aa[41]; int bb[12];")
398 assert ffi.sizeof(lib.aa) == 41 * 4
399 assert ffi.sizeof(lib.bb) == 12 * 4
400 assert lib.aa[40] == lib.bb[11] == 0
401 py.test.raises(IndexError, "lib.aa[41]")
402 py.test.raises(IndexError, "lib.bb[12]")
403
404 def test_misdeclared_field_1():
405 ffi = FFI()
406 ffi.cdef("struct foo_s { int a[5]; };")
407 try:
408 verify(ffi, 'test_misdeclared_field_1',
409 "struct foo_s { int a[6]; };")
410 except VerificationError:
411 pass # ok, fail during compilation already (e.g. C++)
412 else:
413 assert ffi.sizeof("struct foo_s") == 24 # found by the actual C code
414 try:
415 # lazily build the fields and boom:
416 p = ffi.new("struct foo_s *")
417 p.a
418 assert False, "should have raised"
419 except ffi.error as e:
420 assert str(e).startswith("struct foo_s: wrong size for field 'a' "
421 "(cdef says 20, but C compiler says 24)")
422
423 def test_open_array_in_struct():
424 ffi = FFI()
425 ffi.cdef("struct foo_s { int b; int a[]; };")
426 verify(ffi, 'test_open_array_in_struct',
427 "struct foo_s { int b; int a[]; };")
428 assert ffi.sizeof("struct foo_s") == 4
429 p = ffi.new("struct foo_s *", [5, [10, 20, 30, 40]])
430 assert p.a[2] == 30
431 assert ffi.sizeof(p) == ffi.sizeof("void *")
432 assert ffi.sizeof(p[0]) == 5 * ffi.sizeof("int")
433
434 def test_math_sin_type():
435 ffi = FFI()
436 ffi.cdef("double sin(double); void *xxtestfunc();")
437 lib = verify(ffi, 'test_math_sin_type', """
438 #include <math.h>
439 void *xxtestfunc(void) { return 0; }
440 """)
441 # 'lib.sin' is typed as a <built-in method> object on lib
442 assert ffi.typeof(lib.sin).cname == "double(*)(double)"
443 # 'x' is another <built-in method> object on lib, made very indirectly
444 x = type(lib).__dir__.__get__(lib)
445 py.test.raises(TypeError, ffi.typeof, x)
446 #
447 # present on built-in functions on CPython; must be emulated on PyPy:
448 assert lib.sin.__name__ == 'sin'
449 assert lib.sin.__module__ == '_CFFI_test_math_sin_type'
450 assert lib.sin.__doc__ == (
451 "double sin(double);\n"
452 "\n"
453 "CFFI C function from _CFFI_test_math_sin_type.lib")
454
455 assert ffi.typeof(lib.xxtestfunc).cname == "void *(*)()"
456 assert lib.xxtestfunc.__doc__ == (
457 "void *xxtestfunc();\n"
458 "\n"
459 "CFFI C function from _CFFI_test_math_sin_type.lib")
460
461 def test_verify_anonymous_struct_with_typedef():
462 ffi = FFI()
463 ffi.cdef("typedef struct { int a; long b; ...; } foo_t;")
464 verify(ffi, 'test_verify_anonymous_struct_with_typedef',
465 "typedef struct { long b; int hidden, a; } foo_t;")
466 p = ffi.new("foo_t *", {'b': 42})
467 assert p.b == 42
468 assert repr(p).startswith("<cdata 'foo_t *' ")
469
470 def test_verify_anonymous_struct_with_star_typedef():
471 ffi = FFI()
472 ffi.cdef("typedef struct { int a; long b; } *foo_t;")
473 verify(ffi, 'test_verify_anonymous_struct_with_star_typedef',
474 "typedef struct { int a; long b; } *foo_t;")
475 p = ffi.new("foo_t", {'b': 42})
476 assert p.b == 42
477
478 def test_verify_anonymous_enum_with_typedef():
479 ffi = FFI()
480 ffi.cdef("typedef enum { AA, ... } e1;")
481 lib = verify(ffi, 'test_verify_anonymous_enum_with_typedef1',
482 "typedef enum { BB, CC, AA } e1;")
483 assert lib.AA == 2
484 assert ffi.sizeof("e1") == ffi.sizeof("int")
485 assert repr(ffi.cast("e1", 2)) == "<cdata 'e1' 2: AA>"
486 #
487 ffi = FFI()
488 ffi.cdef("typedef enum { AA=%d } e1;" % sys.maxsize)
489 lib = verify(ffi, 'test_verify_anonymous_enum_with_typedef2',
490 "typedef enum { AA=%d } e1;" % sys.maxsize)
491 assert lib.AA == int(ffi.cast("long", sys.maxsize))
492 assert ffi.sizeof("e1") == ffi.sizeof("long")
493
494 def test_unique_types():
495 CDEF = "struct foo_s; union foo_u; enum foo_e { AA };"
496 ffi1 = FFI(); ffi1.cdef(CDEF); verify(ffi1, "test_unique_types_1", CDEF)
497 ffi2 = FFI(); ffi2.cdef(CDEF); verify(ffi2, "test_unique_types_2", CDEF)
498 #
499 assert ffi1.typeof("char") is ffi2.typeof("char ")
500 assert ffi1.typeof("long") is ffi2.typeof("signed long int")
501 assert ffi1.typeof("double *") is ffi2.typeof("double*")
502 assert ffi1.typeof("int ***") is ffi2.typeof(" int * * *")
503 assert ffi1.typeof("int[]") is ffi2.typeof("signed int[]")
504 assert ffi1.typeof("signed int*[17]") is ffi2.typeof("int *[17]")
505 assert ffi1.typeof("void") is ffi2.typeof("void")
506 assert ffi1.typeof("int(*)(int,int)") is ffi2.typeof("int(*)(int,int)")
507 #
508 # these depend on user-defined data, so should not be shared
509 for name in ["struct foo_s",
510 "union foo_u *",
511 "enum foo_e",
512 "struct foo_s *(*)()",
513 "void(*)(struct foo_s *)",
514 "struct foo_s *(*[5])[8]",
515 ]:
516 assert ffi1.typeof(name) is not ffi2.typeof(name)
517 # sanity check: twice 'ffi1'
518 assert ffi1.typeof("struct foo_s*") is ffi1.typeof("struct foo_s *")
519
520 def test_module_name_in_package():
521 ffi = FFI()
522 ffi.cdef("int foo(int);")
523 recompiler.recompile(ffi, "test_module_name_in_package.mymod",
524 "int foo(int x) { return x + 32; }",
525 tmpdir=str(udir))
526 old_sys_path = sys.path[:]
527 try:
528 package_dir = udir.join('test_module_name_in_package')
529 for name in os.listdir(str(udir)):
530 assert not name.startswith('test_module_name_in_package.')
531 assert os.path.isdir(str(package_dir))
532 assert len(os.listdir(str(package_dir))) > 0
533 assert os.path.exists(str(package_dir.join('mymod.c')))
534 package_dir.join('__init__.py').write('')
535 #
536 getattr(importlib, 'invalidate_caches', object)()
537 #
538 sys.path.insert(0, str(udir))
539 import test_module_name_in_package.mymod
540 assert test_module_name_in_package.mymod.lib.foo(10) == 42
541 assert test_module_name_in_package.mymod.__name__ == (
542 'test_module_name_in_package.mymod')
543 finally:
544 sys.path[:] = old_sys_path
545
546 def test_bad_size_of_global_1():
547 ffi = FFI()
548 ffi.cdef("short glob;")
549 py.test.raises(VerificationError, verify, ffi,
550 "test_bad_size_of_global_1", "long glob;")
551
552 def test_bad_size_of_global_2():
553 ffi = FFI()
554 ffi.cdef("int glob[10];")
555 py.test.raises(VerificationError, verify, ffi,
556 "test_bad_size_of_global_2", "int glob[9];")
557
558 def test_unspecified_size_of_global_1():
559 ffi = FFI()
560 ffi.cdef("int glob[];")
561 lib = verify(ffi, "test_unspecified_size_of_global_1", "int glob[10];")
562 assert ffi.typeof(lib.glob) == ffi.typeof("int *")
563
564 def test_unspecified_size_of_global_2():
565 ffi = FFI()
566 ffi.cdef("int glob[][5];")
567 lib = verify(ffi, "test_unspecified_size_of_global_2", "int glob[10][5];")
568 assert ffi.typeof(lib.glob) == ffi.typeof("int(*)[5]")
569
570 def test_unspecified_size_of_global_3():
571 ffi = FFI()
572 ffi.cdef("int glob[][...];")
573 lib = verify(ffi, "test_unspecified_size_of_global_3", "int glob[10][5];")
574 assert ffi.typeof(lib.glob) == ffi.typeof("int(*)[5]")
575
576 def test_unspecified_size_of_global_4():
577 ffi = FFI()
578 ffi.cdef("int glob[...][...];")
579 lib = verify(ffi, "test_unspecified_size_of_global_4", "int glob[10][5];")
580 assert ffi.typeof(lib.glob) == ffi.typeof("int[10][5]")
581
582 def test_include_1():
583 ffi1 = FFI()
584 ffi1.cdef("typedef double foo_t;")
585 verify(ffi1, "test_include_1_parent", "typedef double foo_t;")
586 ffi = FFI()
587 ffi.include(ffi1)
588 ffi.cdef("foo_t ff1(foo_t);")
589 lib = verify(ffi, "test_include_1", "double ff1(double x) { return 42.5; }")
590 assert lib.ff1(0) == 42.5
591 assert ffi1.typeof("foo_t") is ffi.typeof("foo_t") is ffi.typeof("double")
592
593 def test_include_1b():
594 ffi1 = FFI()
595 ffi1.cdef("int foo1(int);")
596 lib1 = verify(ffi1, "test_include_1b_parent",
597 "int foo1(int x) { return x + 10; }")
598 ffi = FFI()
599 ffi.include(ffi1)
600 ffi.cdef("int foo2(int);")
601 lib = verify(ffi, "test_include_1b", "int foo2(int x) { return x - 5; }")
602 assert lib.foo2(42) == 37
603 assert lib.foo1(42) == 52
604 assert lib.foo1 is lib1.foo1
605
606 def test_include_2():
607 ffi1 = FFI()
608 ffi1.cdef("struct foo_s { int x, y; };")
609 verify(ffi1, "test_include_2_parent", "struct foo_s { int x, y; };")
610 ffi = FFI()
611 ffi.include(ffi1)
612 ffi.cdef("struct foo_s *ff2(struct foo_s *);")
613 lib = verify(ffi, "test_include_2",
614 "struct foo_s { int x, y; }; //usually from a #include\n"
615 "struct foo_s *ff2(struct foo_s *p) { p->y++; return p; }")
616 p = ffi.new("struct foo_s *")
617 p.y = 41
618 q = lib.ff2(p)
619 assert q == p
620 assert p.y == 42
621 assert ffi1.typeof("struct foo_s") is ffi.typeof("struct foo_s")
622
623 def test_include_3():
624 ffi1 = FFI()
625 ffi1.cdef("typedef short sshort_t;")
626 verify(ffi1, "test_include_3_parent", "typedef short sshort_t;")
627 ffi = FFI()
628 ffi.include(ffi1)
629 ffi.cdef("sshort_t ff3(sshort_t);")
630 lib = verify(ffi, "test_include_3",
631 "typedef short sshort_t; //usually from a #include\n"
632 "sshort_t ff3(sshort_t x) { return x + 42; }")
633 assert lib.ff3(10) == 52
634 assert ffi.typeof(ffi.cast("sshort_t", 42)) is ffi.typeof("short")
635 assert ffi1.typeof("sshort_t") is ffi.typeof("sshort_t")
636
637 def test_include_4():
638 ffi1 = FFI()
639 ffi1.cdef("typedef struct { int x; } mystruct_t;")
640 verify(ffi1, "test_include_4_parent",
641 "typedef struct { int x; } mystruct_t;")
642 ffi = FFI()
643 ffi.include(ffi1)
644 ffi.cdef("mystruct_t *ff4(mystruct_t *);")
645 lib = verify(ffi, "test_include_4",
646 "typedef struct {int x; } mystruct_t; //usually from a #include\n"
647 "mystruct_t *ff4(mystruct_t *p) { p->x += 42; return p; }")
648 p = ffi.new("mystruct_t *", [10])
649 q = lib.ff4(p)
650 assert q == p
651 assert p.x == 52
652 assert ffi1.typeof("mystruct_t") is ffi.typeof("mystruct_t")
653
654 def test_include_5():
655 ffi1 = FFI()
656 ffi1.cdef("typedef struct { int x[2]; int y; } *mystruct_p;")
657 verify(ffi1, "test_include_5_parent",
658 "typedef struct { int x[2]; int y; } *mystruct_p;")
659 ffi = FFI()
660 ffi.include(ffi1)
661 ffi.cdef("mystruct_p ff5(mystruct_p);")
662 lib = verify(ffi, "test_include_5",
663 "typedef struct {int x[2]; int y; } *mystruct_p; //usually #include\n"
664 "mystruct_p ff5(mystruct_p p) { p->x[1] += 42; return p; }")
665 assert ffi.alignof(ffi.typeof("mystruct_p").item) == 4
666 assert ffi1.typeof("mystruct_p") is ffi.typeof("mystruct_p")
667 p = ffi.new("mystruct_p", [[5, 10], -17])
668 q = lib.ff5(p)
669 assert q == p
670 assert p.x[0] == 5
671 assert p.x[1] == 52
672 assert p.y == -17
673 assert ffi.alignof(ffi.typeof(p[0])) == 4
674
675 def test_include_6():
676 ffi1 = FFI()
677 ffi1.cdef("typedef ... mystruct_t;")
678 verify(ffi1, "test_include_6_parent",
679 "typedef struct _mystruct_s mystruct_t;")
680 ffi = FFI()
681 ffi.include(ffi1)
682 ffi.cdef("mystruct_t *ff6(void); int ff6b(mystruct_t *);")
683 lib = verify(ffi, "test_include_6",
684 "typedef struct _mystruct_s mystruct_t; //usually from a #include\n"
685 "struct _mystruct_s { int x; };\n"
686 "static mystruct_t result_struct = { 42 };\n"
687 "mystruct_t *ff6(void) { return &result_struct; }\n"
688 "int ff6b(mystruct_t *p) { return p->x; }")
689 p = lib.ff6()
690 assert ffi.cast("int *", p)[0] == 42
691 assert lib.ff6b(p) == 42
692
693 def test_include_7():
694 ffi1 = FFI()
695 ffi1.cdef("typedef ... mystruct_t;\n"
696 "int ff7b(mystruct_t *);")
697 verify(ffi1, "test_include_7_parent",
698 "typedef struct { int x; } mystruct_t;\n"
699 "int ff7b(mystruct_t *p) { return p->x; }")
700 ffi = FFI()
701 ffi.include(ffi1)
702 ffi.cdef("mystruct_t *ff7(void);")
703 lib = verify(ffi, "test_include_7",
704 "typedef struct { int x; } mystruct_t; //usually from a #include\n"
705 "static mystruct_t result_struct = { 42 };"
706 "mystruct_t *ff7(void) { return &result_struct; }")
707 p = lib.ff7()
708 assert ffi.cast("int *", p)[0] == 42
709 assert lib.ff7b(p) == 42
710
711 def test_include_8():
712 ffi1 = FFI()
713 ffi1.cdef("struct foo_s;")
714 verify(ffi1, "test_include_8_parent", "struct foo_s;")
715 ffi = FFI()
716 ffi.include(ffi1)
717 ffi.cdef("struct foo_s { int x, y; };")
718 verify(ffi, "test_include_8", "struct foo_s { int x, y; };")
719 e = py.test.raises(NotImplementedError, ffi.new, "struct foo_s *")
720 assert str(e.value) == (
721 "'struct foo_s' is opaque in the ffi.include(), but no longer in "
722 "the ffi doing the include (workaround: don't use ffi.include() but"
723 " duplicate the declarations of everything using struct foo_s)")
724
725 def test_unicode_libraries():
726 try:
727 unicode
728 except NameError:
729 py.test.skip("for python 2.x")
730 #
731 import math
732 lib_m = "m"
733 if sys.platform == 'win32':
734 #there is a small chance this fails on Mingw via environ $CC
735 import distutils.ccompiler
736 if distutils.ccompiler.get_default_compiler() == 'msvc':
737 lib_m = 'msvcrt'
738 ffi = FFI()
739 ffi.cdef(unicode("float sin(double); double cos(double);"))
740 lib = verify(ffi, 'test_math_sin_unicode', unicode('#include <math.h>'),
741 libraries=[unicode(lib_m)])
742 assert lib.cos(1.43) == math.cos(1.43)
743
744 def test_incomplete_struct_as_arg():
745 ffi = FFI()
746 ffi.cdef("struct foo_s { int x; ...; }; int f(int, struct foo_s);")
747 lib = verify(ffi, "test_incomplete_struct_as_arg",
748 "struct foo_s { int a, x, z; };\n"
749 "int f(int b, struct foo_s s) { return s.x * b; }")
750 s = ffi.new("struct foo_s *", [21])
751 assert s.x == 21
752 assert ffi.sizeof(s[0]) == 12
753 assert ffi.offsetof(ffi.typeof(s), 'x') == 4
754 assert lib.f(2, s[0]) == 42
755 assert ffi.typeof(lib.f) == ffi.typeof("int(*)(int, struct foo_s)")
756
757 def test_incomplete_struct_as_result():
758 ffi = FFI()
759 ffi.cdef("struct foo_s { int x; ...; }; struct foo_s f(int);")
760 lib = verify(ffi, "test_incomplete_struct_as_result",
761 "struct foo_s { int a, x, z; };\n"
762 "struct foo_s f(int x) { struct foo_s r; r.x = x * 2; return r; }")
763 s = lib.f(21)
764 assert s.x == 42
765 assert ffi.typeof(lib.f) == ffi.typeof("struct foo_s(*)(int)")
766
767 def test_incomplete_struct_as_both():
768 ffi = FFI()
769 ffi.cdef("struct foo_s { int x; ...; }; struct bar_s { int y; ...; };\n"
770 "struct foo_s f(int, struct bar_s);")
771 lib = verify(ffi, "test_incomplete_struct_as_both",
772 "struct foo_s { int a, x, z; };\n"
773 "struct bar_s { int b, c, y, d; };\n"
774 "struct foo_s f(int x, struct bar_s b) {\n"
775 " struct foo_s r; r.x = x * b.y; return r;\n"
776 "}")
777 b = ffi.new("struct bar_s *", [7])
778 s = lib.f(6, b[0])
779 assert s.x == 42
780 assert ffi.typeof(lib.f) == ffi.typeof(
781 "struct foo_s(*)(int, struct bar_s)")
782 s = lib.f(14, {'y': -3})
783 assert s.x == -42
784
785 def test_name_of_unnamed_struct():
786 ffi = FFI()
787 ffi.cdef("typedef struct { int x; } foo_t;\n"
788 "typedef struct { int y; } *bar_p;\n"
789 "typedef struct { int y; } **baz_pp;\n")
790 verify(ffi, "test_name_of_unnamed_struct",
791 "typedef struct { int x; } foo_t;\n"
792 "typedef struct { int y; } *bar_p;\n"
793 "typedef struct { int y; } **baz_pp;\n")
794 assert repr(ffi.typeof("foo_t")) == "<ctype 'foo_t'>"
795 assert repr(ffi.typeof("bar_p")) == "<ctype 'struct $1 *'>"
796 assert repr(ffi.typeof("baz_pp")) == "<ctype 'struct $2 * *'>"
797
798 def test_address_of_global_var():
799 ffi = FFI()
800 ffi.cdef("""
801 long bottom, bottoms[2];
802 long FetchRectBottom(void);
803 long FetchRectBottoms1(void);
804 #define FOOBAR 42
805 """)
806 lib = verify(ffi, "test_address_of_global_var", """
807 long bottom, bottoms[2];
808 long FetchRectBottom(void) { return bottom; }
809 long FetchRectBottoms1(void) { return bottoms[1]; }
810 #define FOOBAR 42
811 """)
812 lib.bottom = 300
813 assert lib.FetchRectBottom() == 300
814 lib.bottom += 1
815 assert lib.FetchRectBottom() == 301
816 lib.bottoms[1] = 500
817 assert lib.FetchRectBottoms1() == 500
818 lib.bottoms[1] += 2
819 assert lib.FetchRectBottoms1() == 502
820 #
821 p = ffi.addressof(lib, 'bottom')
822 assert ffi.typeof(p) == ffi.typeof("long *")
823 assert p[0] == 301
824 p[0] += 1
825 assert lib.FetchRectBottom() == 302
826 p = ffi.addressof(lib, 'bottoms')
827 assert ffi.typeof(p) == ffi.typeof("long(*)[2]")
828 assert p[0] == lib.bottoms
829 #
830 py.test.raises(AttributeError, ffi.addressof, lib, 'unknown_var')
831 py.test.raises(AttributeError, ffi.addressof, lib, "FOOBAR")
832
833 def test_defines__CFFI_():
834 # Check that we define the macro _CFFI_ automatically.
835 # It should be done before including Python.h, so that PyPy's Python.h
836 # can check for it.
837 ffi = FFI()
838 ffi.cdef("""
839 #define CORRECT 1
840 """)
841 lib = verify(ffi, "test_defines__CFFI_", """
842 #ifdef _CFFI_
843 # define CORRECT 1
844 #endif
845 """)
846 assert lib.CORRECT == 1
847
848 def test_unpack_args():
849 ffi = FFI()
850 ffi.cdef("void foo0(void); void foo1(int); void foo2(int, int);")
851 lib = verify(ffi, "test_unpack_args", """
852 void foo0(void) { }
853 void foo1(int x) { }
854 void foo2(int x, int y) { }
855 """)
856 assert 'foo0' in repr(lib.foo0)
857 assert 'foo1' in repr(lib.foo1)
858 assert 'foo2' in repr(lib.foo2)
859 lib.foo0()
860 lib.foo1(42)
861 lib.foo2(43, 44)
862 e1 = py.test.raises(TypeError, lib.foo0, 42)
863 e2 = py.test.raises(TypeError, lib.foo0, 43, 44)
864 e3 = py.test.raises(TypeError, lib.foo1)
865 e4 = py.test.raises(TypeError, lib.foo1, 43, 44)
866 e5 = py.test.raises(TypeError, lib.foo2)
867 e6 = py.test.raises(TypeError, lib.foo2, 42)
868 e7 = py.test.raises(TypeError, lib.foo2, 45, 46, 47)
869 assert str(e1.value) == "foo0() takes no arguments (1 given)"
870 assert str(e2.value) == "foo0() takes no arguments (2 given)"
871 assert str(e3.value) == "foo1() takes exactly one argument (0 given)"
872 assert str(e4.value) == "foo1() takes exactly one argument (2 given)"
873 assert str(e5.value) in ["foo2 expected 2 arguments, got 0",
874 "foo2() takes exactly 2 arguments (0 given)"]
875 assert str(e6.value) in ["foo2 expected 2 arguments, got 1",
876 "foo2() takes exactly 2 arguments (1 given)"]
877 assert str(e7.value) in ["foo2 expected 2 arguments, got 3",
878 "foo2() takes exactly 2 arguments (3 given)"]
879
880 def test_address_of_function():
881 ffi = FFI()
882 ffi.cdef("long myfunc(long x);")
883 lib = verify(ffi, "test_addressof_function", """
884 char myfunc(char x) { return (char)(x + 42); }
885 """)
886 assert lib.myfunc(5) == 47
887 assert lib.myfunc(0xABC05) == 47
888 assert not isinstance(lib.myfunc, ffi.CData)
889 assert ffi.typeof(lib.myfunc) == ffi.typeof("long(*)(long)")
890 addr = ffi.addressof(lib, 'myfunc')
891 assert addr(5) == 47
892 assert addr(0xABC05) == 47
893 assert isinstance(addr, ffi.CData)
894 assert ffi.typeof(addr) == ffi.typeof("long(*)(long)")
895
896 def test_address_of_function_with_struct():
897 ffi = FFI()
898 ffi.cdef("struct foo_s { int x; }; long myfunc(struct foo_s);")
899 lib = verify(ffi, "test_addressof_function_with_struct", """
900 struct foo_s { int x; };
901 char myfunc(struct foo_s input) { return (char)(input.x + 42); }
902 """)
903 s = ffi.new("struct foo_s *", [5])[0]
904 assert lib.myfunc(s) == 47
905 assert not isinstance(lib.myfunc, ffi.CData)
906 assert ffi.typeof(lib.myfunc) == ffi.typeof("long(*)(struct foo_s)")
907 addr = ffi.addressof(lib, 'myfunc')
908 assert addr(s) == 47
909 assert isinstance(addr, ffi.CData)
910 assert ffi.typeof(addr) == ffi.typeof("long(*)(struct foo_s)")
911
912 def test_issue198():
913 ffi = FFI()
914 ffi.cdef("""
915 typedef struct{...;} opaque_t;
916 const opaque_t CONSTANT;
917 int toint(opaque_t);
918 """)
919 lib = verify(ffi, 'test_issue198', """
920 typedef int opaque_t;
921 #define CONSTANT ((opaque_t)42)
922 static int toint(opaque_t o) { return o; }
923 """)
924 def random_stuff():
925 pass
926 assert lib.toint(lib.CONSTANT) == 42
927 random_stuff()
928 assert lib.toint(lib.CONSTANT) == 42
929
930 def test_constant_is_not_a_compiler_constant():
931 ffi = FFI()
932 ffi.cdef("static const float almost_forty_two;")
933 lib = verify(ffi, 'test_constant_is_not_a_compiler_constant', """
934 static float f(void) { return 42.25; }
935 #define almost_forty_two (f())
936 """)
937 assert lib.almost_forty_two == 42.25
938
939 def test_constant_of_unknown_size():
940 ffi = FFI()
941 ffi.cdef("""
942 typedef ... opaque_t;
943 const opaque_t CONSTANT;
944 """)
945 lib = verify(ffi, 'test_constant_of_unknown_size',
946 "typedef int opaque_t;"
947 "const int CONSTANT = 42;")
948 e = py.test.raises(ffi.error, getattr, lib, 'CONSTANT')
949 assert str(e.value) == ("constant 'CONSTANT' is of "
950 "type 'opaque_t', whose size is not known")
951
952 def test_variable_of_unknown_size():
953 ffi = FFI()
954 ffi.cdef("""
955 typedef ... opaque_t;
956 opaque_t globvar;
957 """)
958 lib = verify(ffi, 'test_variable_of_unknown_size', """
959 typedef char opaque_t[6];
960 opaque_t globvar = "hello";
961 """)
962 # can't read or write it at all
963 e = py.test.raises(TypeError, getattr, lib, 'globvar')
964 assert str(e.value) in ["cdata 'opaque_t' is opaque",
965 "'opaque_t' is opaque or not completed yet"] #pypy
966 e = py.test.raises(TypeError, setattr, lib, 'globvar', [])
967 assert str(e.value) in ["'opaque_t' is opaque",
968 "'opaque_t' is opaque or not completed yet"] #pypy
969 # but we can get its address
970 p = ffi.addressof(lib, 'globvar')
971 assert ffi.typeof(p) == ffi.typeof('opaque_t *')
972 assert ffi.string(ffi.cast("char *", p), 8) == b"hello"
973
974 def test_constant_of_value_unknown_to_the_compiler():
975 extra_c_source = udir.join(
976 'extra_test_constant_of_value_unknown_to_the_compiler.c')
977 extra_c_source.write('const int external_foo = 42;\n')
978 ffi = FFI()
979 ffi.cdef("const int external_foo;")
980 lib = verify(ffi, 'test_constant_of_value_unknown_to_the_compiler', """
981 extern const int external_foo;
982 """, sources=[str(extra_c_source)])
983 assert lib.external_foo == 42
984
985 def test_dotdot_in_source_file_names():
986 extra_c_source = udir.join(
987 'extra_test_dotdot_in_source_file_names.c')
988 extra_c_source.write('const int external_foo = 42;\n')
989 ffi = FFI()
990 ffi.cdef("const int external_foo;")
991 lib = verify(ffi, 'test_dotdot_in_source_file_names', """
992 extern const int external_foo;
993 """, sources=[os.path.join(os.path.dirname(str(extra_c_source)),
994 'foobar', '..',
995 os.path.basename(str(extra_c_source)))])
996 assert lib.external_foo == 42
997
998 def test_call_with_incomplete_structs():
999 ffi = FFI()
1000 ffi.cdef("typedef struct {...;} foo_t; "
1001 "foo_t myglob; "
1002 "foo_t increment(foo_t s); "
1003 "double getx(foo_t s);")
1004 lib = verify(ffi, 'test_call_with_incomplete_structs', """
1005 typedef double foo_t;
1006 double myglob = 42.5;
1007 double getx(double x) { return x; }
1008 double increment(double x) { return x + 1; }
1009 """)
1010 assert lib.getx(lib.myglob) == 42.5
1011 assert lib.getx(lib.increment(lib.myglob)) == 43.5
1012
1013 def test_struct_array_guess_length_2():
1014 ffi = FFI()
1015 ffi.cdef("struct foo_s { int a[...][...]; };")
1016 lib = verify(ffi, 'test_struct_array_guess_length_2',
1017 "struct foo_s { int x; int a[5][8]; int y; };")
1018 assert ffi.sizeof('struct foo_s') == 42 * ffi.sizeof('int')
1019 s = ffi.new("struct foo_s *")
1020 assert ffi.typeof(s.a) == ffi.typeof("int[5][8]")
1021 assert ffi.sizeof(s.a) == 40 * ffi.sizeof('int')
1022 assert s.a[4][7] == 0
1023 py.test.raises(IndexError, 's.a[4][8]')
1024 py.test.raises(IndexError, 's.a[5][0]')
1025 assert ffi.typeof(s.a) == ffi.typeof("int[5][8]")
1026 assert ffi.typeof(s.a[0]) == ffi.typeof("int[8]")
1027
1028 def test_struct_array_guess_length_3():
1029 ffi = FFI()
1030 ffi.cdef("struct foo_s { int a[][...]; };")
1031 lib = verify(ffi, 'test_struct_array_guess_length_3',
1032 "struct foo_s { int x; int a[5][7]; int y; };")
1033 assert ffi.sizeof('struct foo_s') == 37 * ffi.sizeof('int')
1034 s = ffi.new("struct foo_s *")
1035 assert ffi.typeof(s.a) == ffi.typeof("int[][7]")
1036 assert s.a[4][6] == 0
1037 py.test.raises(IndexError, 's.a[4][7]')
1038 assert ffi.typeof(s.a[0]) == ffi.typeof("int[7]")
1039
1040 def test_global_var_array_2():
1041 ffi = FFI()
1042 ffi.cdef("int a[...][...];")
1043 lib = verify(ffi, 'test_global_var_array_2', 'int a[10][8];')
1044 lib.a[9][7] = 123456
1045 assert lib.a[9][7] == 123456
1046 py.test.raises(IndexError, 'lib.a[0][8]')
1047 py.test.raises(IndexError, 'lib.a[10][0]')
1048 assert ffi.typeof(lib.a) == ffi.typeof("int[10][8]")
1049 assert ffi.typeof(lib.a[0]) == ffi.typeof("int[8]")
1050
1051 def test_global_var_array_3():
1052 ffi = FFI()
1053 ffi.cdef("int a[][...];")
1054 lib = verify(ffi, 'test_global_var_array_3', 'int a[10][8];')
1055 lib.a[9][7] = 123456
1056 assert lib.a[9][7] == 123456
1057 py.test.raises(IndexError, 'lib.a[0][8]')
1058 assert ffi.typeof(lib.a) == ffi.typeof("int(*)[8]")
1059 assert ffi.typeof(lib.a[0]) == ffi.typeof("int[8]")
1060
1061 def test_global_var_array_4():
1062 ffi = FFI()
1063 ffi.cdef("int a[10][...];")
1064 lib = verify(ffi, 'test_global_var_array_4', 'int a[10][8];')
1065 lib.a[9][7] = 123456
1066 assert lib.a[9][7] == 123456
1067 py.test.raises(IndexError, 'lib.a[0][8]')
1068 py.test.raises(IndexError, 'lib.a[10][8]')
1069 assert ffi.typeof(lib.a) == ffi.typeof("int[10][8]")
1070 assert ffi.typeof(lib.a[0]) == ffi.typeof("int[8]")
1071
1072 def test_some_integer_type():
1073 ffi = FFI()
1074 ffi.cdef("""
1075 typedef int... foo_t;
1076 typedef unsigned long... bar_t;
1077 typedef struct { foo_t a, b; } mystruct_t;
1078 foo_t foobar(bar_t, mystruct_t);
1079 static const bar_t mu = -20;
1080 static const foo_t nu = 20;
1081 """)
1082 lib = verify(ffi, 'test_some_integer_type', """
1083 typedef unsigned long long foo_t;
1084 typedef short bar_t;
1085 typedef struct { foo_t a, b; } mystruct_t;
1086 static foo_t foobar(bar_t x, mystruct_t s) {
1087 return (foo_t)x + s.a + s.b;
1088 }
1089 static const bar_t mu = -20;
1090 static const foo_t nu = 20;
1091 """)
1092 assert ffi.sizeof("foo_t") == ffi.sizeof("unsigned long long")
1093 assert ffi.sizeof("bar_t") == ffi.sizeof("short")
1094 maxulonglong = 2 ** 64 - 1
1095 assert int(ffi.cast("foo_t", -1)) == maxulonglong
1096 assert int(ffi.cast("bar_t", -1)) == -1
1097 assert lib.foobar(-1, [0, 0]) == maxulonglong
1098 assert lib.foobar(2 ** 15 - 1, [0, 0]) == 2 ** 15 - 1
1099 assert lib.foobar(10, [20, 31]) == 61
1100 assert lib.foobar(0, [0, maxulonglong]) == maxulonglong
1101 py.test.raises(OverflowError, lib.foobar, 2 ** 15, [0, 0])
1102 py.test.raises(OverflowError, lib.foobar, -(2 ** 15) - 1, [0, 0])
1103 py.test.raises(OverflowError, ffi.new, "mystruct_t *", [0, -1])
1104 assert lib.mu == -20
1105 assert lib.nu == 20
1106
1107 def test_some_float_type():
1108 ffi = FFI()
1109 ffi.cdef("""
1110 typedef double... foo_t;
1111 typedef float... bar_t;
1112 foo_t sum(foo_t[]);
1113 bar_t neg(bar_t);
1114 """)
1115 lib = verify(ffi, 'test_some_float_type', """
1116 typedef float foo_t;
1117 static foo_t sum(foo_t x[]) { return x[0] + x[1]; }
1118 typedef double bar_t;
1119 static double neg(double x) { return -x; }
1120 """)
1121 assert lib.sum([40.0, 2.25]) == 42.25
1122 assert lib.sum([12.3, 45.6]) != 12.3 + 45.6 # precision loss
1123 assert lib.neg(12.3) == -12.3 # no precision loss
1124 assert ffi.sizeof("foo_t") == ffi.sizeof("float")
1125 assert ffi.sizeof("bar_t") == ffi.sizeof("double")
1126
1127 def test_some_float_invalid_1():
1128 ffi = FFI()
1129 py.test.raises((FFIError, # with pycparser <= 2.17
1130 CDefError), # with pycparser >= 2.18
1131 ffi.cdef, "typedef long double... foo_t;")
1132
1133 def test_some_float_invalid_2():
1134 ffi = FFI()
1135 ffi.cdef("typedef double... foo_t; foo_t neg(foo_t);")
1136 lib = verify(ffi, 'test_some_float_invalid_2', """
1137 typedef unsigned long foo_t;
1138 foo_t neg(foo_t x) { return -x; }
1139 """)
1140 e = py.test.raises(ffi.error, getattr, lib, 'neg')
1141 assert str(e.value) == ("primitive floating-point type with an unexpected "
1142 "size (or not a float type at all)")
1143
1144 def test_some_float_invalid_3():
1145 ffi = FFI()
1146 ffi.cdef("typedef double... foo_t; foo_t neg(foo_t);")
1147 lib = verify(ffi, 'test_some_float_invalid_3', """
1148 typedef long double foo_t;
1149 foo_t neg(foo_t x) { return -x; }
1150 """)
1151 if ffi.sizeof("long double") == ffi.sizeof("double"):
1152 assert lib.neg(12.3) == -12.3
1153 else:
1154 e = py.test.raises(ffi.error, getattr, lib, 'neg')
1155 assert str(e.value) == ("primitive floating-point type is "
1156 "'long double', not supported for now with "
1157 "the syntax 'typedef double... xxx;'")
1158
1159 def test_issue200():
1160 ffi = FFI()
1161 ffi.cdef("""
1162 typedef void (function_t)(void*);
1163 void function(void *);
1164 """)
1165 lib = verify(ffi, 'test_issue200', """
1166 static void function(void *p) { (void)p; }
1167 """)
1168 ffi.typeof('function_t*')
1169 lib.function(ffi.NULL)
1170 # assert did not crash
1171
1172 def test_alignment_of_longlong():
1173 ffi = FFI()
1174 x1 = ffi.alignof('unsigned long long')
1175 assert x1 in [4, 8]
1176 ffi.cdef("struct foo_s { unsigned long long x; };")
1177 lib = verify(ffi, 'test_alignment_of_longlong',
1178 "struct foo_s { unsigned long long x; };")
1179 assert ffi.alignof('unsigned long long') == x1
1180 assert ffi.alignof('struct foo_s') == x1
1181
1182 def test_import_from_lib():
1183 ffi = FFI()
1184 ffi.cdef("int mybar(int); int myvar;\n#define MYFOO ...")
1185 lib = verify(ffi, 'test_import_from_lib',
1186 "#define MYFOO 42\n"
1187 "static int mybar(int x) { return x + 1; }\n"
1188 "static int myvar = -5;")
1189 assert sys.modules['_CFFI_test_import_from_lib'].lib is lib
1190 assert sys.modules['_CFFI_test_import_from_lib.lib'] is lib
1191 from _CFFI_test_import_from_lib.lib import MYFOO
1192 assert MYFOO == 42
1193 assert hasattr(lib, '__dict__')
1194 assert lib.__all__ == ['MYFOO', 'mybar'] # but not 'myvar'
1195 assert lib.__name__ == '_CFFI_test_import_from_lib.lib'
1196 assert lib.__class__ is type(sys) # !! hack for help()
1197
1198 def test_macro_var_callback():
1199 ffi = FFI()
1200 ffi.cdef("int my_value; int *(*get_my_value)(void);")
1201 lib = verify(ffi, 'test_macro_var_callback',
1202 "int *(*get_my_value)(void);\n"
1203 "#define my_value (*get_my_value())")
1204 #
1205 values = ffi.new("int[50]")
1206 def it():
1207 for i in range(50):
1208 yield i
1209 it = it()
1210 #
1211 @ffi.callback("int *(*)(void)")
1212 def get_my_value():
1213 for nextvalue in it:
1214 return values + nextvalue
1215 lib.get_my_value = get_my_value
1216 #
1217 values[0] = 41
1218 assert lib.my_value == 41 # [0]
1219 p = ffi.addressof(lib, 'my_value') # [1]
1220 assert p == values + 1
1221 assert p[-1] == 41
1222 assert p[+1] == 0
1223 lib.my_value = 42 # [2]
1224 assert values[2] == 42
1225 assert p[-1] == 41
1226 assert p[+1] == 42
1227 #
1228 # if get_my_value raises or returns nonsense, the exception is printed
1229 # to stderr like with any callback, but then the C expression 'my_value'
1230 # expand to '*NULL'. We assume here that '&my_value' will return NULL
1231 # without segfaulting, and check for NULL when accessing the variable.
1232 @ffi.callback("int *(*)(void)")
1233 def get_my_value():
1234 raise LookupError
1235 lib.get_my_value = get_my_value
1236 py.test.raises(ffi.error, getattr, lib, 'my_value')
1237 py.test.raises(ffi.error, setattr, lib, 'my_value', 50)
1238 py.test.raises(ffi.error, ffi.addressof, lib, 'my_value')
1239 @ffi.callback("int *(*)(void)")
1240 def get_my_value():
1241 return "hello"
1242 lib.get_my_value = get_my_value
1243 py.test.raises(ffi.error, getattr, lib, 'my_value')
1244 e = py.test.raises(ffi.error, setattr, lib, 'my_value', 50)
1245 assert str(e.value) == "global variable 'my_value' is at address NULL"
1246
1247 def test_const_fields():
1248 ffi = FFI()
1249 ffi.cdef("""struct foo_s { const int a; void *const b; };""")
1250 lib = verify(ffi, 'test_const_fields', """
1251 struct foo_s { const int a; void *const b; };""")
1252 foo_s = ffi.typeof("struct foo_s")
1253 assert foo_s.fields[0][0] == 'a'
1254 assert foo_s.fields[0][1].type is ffi.typeof("int")
1255 assert foo_s.fields[1][0] == 'b'
1256 assert foo_s.fields[1][1].type is ffi.typeof("void *")
1257
1258 def test_restrict_fields():
1259 ffi = FFI()
1260 ffi.cdef("""struct foo_s { void * restrict b; };""")
1261 lib = verify(ffi, 'test_restrict_fields', """
1262 struct foo_s { void * __restrict b; };""")
1263 foo_s = ffi.typeof("struct foo_s")
1264 assert foo_s.fields[0][0] == 'b'
1265 assert foo_s.fields[0][1].type is ffi.typeof("void *")
1266
1267 def test_volatile_fields():
1268 ffi = FFI()
1269 ffi.cdef("""struct foo_s { void * volatile b; };""")
1270 lib = verify(ffi, 'test_volatile_fields', """
1271 struct foo_s { void * volatile b; };""")
1272 foo_s = ffi.typeof("struct foo_s")
1273 assert foo_s.fields[0][0] == 'b'
1274 assert foo_s.fields[0][1].type is ffi.typeof("void *")
1275
1276 def test_const_array_fields():
1277 ffi = FFI()
1278 ffi.cdef("""struct foo_s { const int a[4]; };""")
1279 lib = verify(ffi, 'test_const_array_fields', """
1280 struct foo_s { const int a[4]; };""")
1281 foo_s = ffi.typeof("struct foo_s")
1282 assert foo_s.fields[0][0] == 'a'
1283 assert foo_s.fields[0][1].type is ffi.typeof("int[4]")
1284
1285 def test_const_array_fields_varlength():
1286 ffi = FFI()
1287 ffi.cdef("""struct foo_s { const int a[]; ...; };""")
1288 lib = verify(ffi, 'test_const_array_fields_varlength', """
1289 struct foo_s { const int a[4]; };""")
1290 foo_s = ffi.typeof("struct foo_s")
1291 assert foo_s.fields[0][0] == 'a'
1292 assert foo_s.fields[0][1].type is ffi.typeof("int[]")
1293
1294 def test_const_array_fields_unknownlength():
1295 ffi = FFI()
1296 ffi.cdef("""struct foo_s { const int a[...]; ...; };""")
1297 lib = verify(ffi, 'test_const_array_fields_unknownlength', """
1298 struct foo_s { const int a[4]; };""")
1299 foo_s = ffi.typeof("struct foo_s")
1300 assert foo_s.fields[0][0] == 'a'
1301 assert foo_s.fields[0][1].type is ffi.typeof("int[4]")
1302
1303 def test_const_function_args():
1304 ffi = FFI()
1305 ffi.cdef("""int foobar(const int a, const int *b, const int c[]);""")
1306 lib = verify(ffi, 'test_const_function_args', """
1307 int foobar(const int a, const int *b, const int c[]) {
1308 return a + *b + *c;
1309 }
1310 """)
1311 assert lib.foobar(100, ffi.new("int *", 40), ffi.new("int *", 2)) == 142
1312
1313 def test_const_function_type_args():
1314 ffi = FFI()
1315 ffi.cdef("""int (*foobar)(const int a, const int *b, const int c[]);""")
1316 lib = verify(ffi, 'test_const_function_type_args', """
1317 int (*foobar)(const int a, const int *b, const int c[]);
1318 """)
1319 t = ffi.typeof(lib.foobar)
1320 assert t.args[0] is ffi.typeof("int")
1321 assert t.args[1] is ffi.typeof("int *")
1322 assert t.args[2] is ffi.typeof("int *")
1323
1324 def test_const_constant():
1325 ffi = FFI()
1326 ffi.cdef("""struct foo_s { int x,y; }; const struct foo_s myfoo;""")
1327 lib = verify(ffi, 'test_const_constant', """
1328 struct foo_s { int x,y; }; const struct foo_s myfoo = { 40, 2 };
1329 """)
1330 assert lib.myfoo.x == 40
1331 assert lib.myfoo.y == 2
1332
1333 def test_const_via_typedef():
1334 ffi = FFI()
1335 ffi.cdef("""typedef const int const_t; const_t aaa;""")
1336 lib = verify(ffi, 'test_const_via_typedef', """
1337 typedef const int const_t;
1338 #define aaa 42
1339 """)
1340 assert lib.aaa == 42
1341 py.test.raises(AttributeError, "lib.aaa = 43")
1342
1343 def test_win32_calling_convention_0():
1344 ffi = FFI()
1345 ffi.cdef("""
1346 int call1(int(__cdecl *cb)(int));
1347 int (*const call2)(int(__stdcall *cb)(int));
1348 """)
1349 lib = verify(ffi, 'test_win32_calling_convention_0', r"""
1350 #ifndef _MSC_VER
1351 # define __stdcall /* nothing */
1352 #endif
1353 int call1(int(*cb)(int)) {
1354 int i, result = 0;
1355 //printf("call1: cb = %p\n", cb);
1356 for (i = 0; i < 1000; i++)
1357 result += cb(i);
1358 //printf("result = %d\n", result);
1359 return result;
1360 }
1361 int call2(int(__stdcall *cb)(int)) {
1362 int i, result = 0;
1363 //printf("call2: cb = %p\n", cb);
1364 for (i = 0; i < 1000; i++)
1365 result += cb(-i);
1366 //printf("result = %d\n", result);
1367 return result;
1368 }
1369 """)
1370 @ffi.callback("int(int)")
1371 def cb1(x):
1372 return x * 2
1373 @ffi.callback("int __stdcall(int)")
1374 def cb2(x):
1375 return x * 3
1376 res = lib.call1(cb1)
1377 assert res == 500*999*2
1378 assert res == ffi.addressof(lib, 'call1')(cb1)
1379 res = lib.call2(cb2)
1380 assert res == -500*999*3
1381 assert res == ffi.addressof(lib, 'call2')(cb2)
1382 if sys.platform == 'win32' and not sys.maxsize > 2**32:
1383 assert '__stdcall' in str(ffi.typeof(cb2))
1384 assert '__stdcall' not in str(ffi.typeof(cb1))
1385 py.test.raises(TypeError, lib.call1, cb2)
1386 py.test.raises(TypeError, lib.call2, cb1)
1387 else:
1388 assert '__stdcall' not in str(ffi.typeof(cb2))
1389 assert ffi.typeof(cb2) is ffi.typeof(cb1)
1390
1391 def test_win32_calling_convention_1():
1392 ffi = FFI()
1393 ffi.cdef("""
1394 int __cdecl call1(int(__cdecl *cb)(int));
1395 int __stdcall call2(int(__stdcall *cb)(int));
1396 int (__cdecl *const cb1)(int);
1397 int (__stdcall *const cb2)(int);
1398 """)
1399 lib = verify(ffi, 'test_win32_calling_convention_1', r"""
1400 #ifndef _MSC_VER
1401 # define __cdecl
1402 # define __stdcall
1403 #endif
1404 int __cdecl cb1(int x) { return x * 2; }
1405 int __stdcall cb2(int x) { return x * 3; }
1406
1407 int __cdecl call1(int(__cdecl *cb)(int)) {
1408 int i, result = 0;
1409 //printf("here1\n");
1410 //printf("cb = %p, cb1 = %p\n", cb, (void *)cb1);
1411 for (i = 0; i < 1000; i++)
1412 result += cb(i);
1413 //printf("result = %d\n", result);
1414 return result;
1415 }
1416 int __stdcall call2(int(__stdcall *cb)(int)) {
1417 int i, result = 0;
1418 //printf("here1\n");
1419 //printf("cb = %p, cb2 = %p\n", cb, (void *)cb2);
1420 for (i = 0; i < 1000; i++)
1421 result += cb(-i);
1422 //printf("result = %d\n", result);
1423 return result;
1424 }
1425 """)
1426 #print '<<< cb1 =', ffi.addressof(lib, 'cb1')
1427 ptr_call1 = ffi.addressof(lib, 'call1')
1428 assert lib.call1(ffi.addressof(lib, 'cb1')) == 500*999*2
1429 assert ptr_call1(ffi.addressof(lib, 'cb1')) == 500*999*2
1430 #print '<<< cb2 =', ffi.addressof(lib, 'cb2')
1431 ptr_call2 = ffi.addressof(lib, 'call2')
1432 assert lib.call2(ffi.addressof(lib, 'cb2')) == -500*999*3
1433 assert ptr_call2(ffi.addressof(lib, 'cb2')) == -500*999*3
1434 #print '<<< done'
1435
1436 def test_win32_calling_convention_2():
1437 # any mistake in the declaration of plain function (including the
1438 # precise argument types and, here, the calling convention) are
1439 # automatically corrected. But this does not apply to the 'cb'
1440 # function pointer argument.
1441 ffi = FFI()
1442 ffi.cdef("""
1443 int __stdcall call1(int(__cdecl *cb)(int));
1444 int __cdecl call2(int(__stdcall *cb)(int));
1445 int (__cdecl *const cb1)(int);
1446 int (__stdcall *const cb2)(int);
1447 """)
1448 lib = verify(ffi, 'test_win32_calling_convention_2', """
1449 #ifndef _MSC_VER
1450 # define __cdecl
1451 # define __stdcall
1452 #endif
1453 int __cdecl call1(int(__cdecl *cb)(int)) {
1454 int i, result = 0;
1455 for (i = 0; i < 1000; i++)
1456 result += cb(i);
1457 return result;
1458 }
1459 int __stdcall call2(int(__stdcall *cb)(int)) {
1460 int i, result = 0;
1461 for (i = 0; i < 1000; i++)
1462 result += cb(-i);
1463 return result;
1464 }
1465 int __cdecl cb1(int x) { return x * 2; }
1466 int __stdcall cb2(int x) { return x * 3; }
1467 """)
1468 ptr_call1 = ffi.addressof(lib, 'call1')
1469 ptr_call2 = ffi.addressof(lib, 'call2')
1470 if sys.platform == 'win32' and not sys.maxsize > 2**32:
1471 py.test.raises(TypeError, lib.call1, ffi.addressof(lib, 'cb2'))
1472 py.test.raises(TypeError, ptr_call1, ffi.addressof(lib, 'cb2'))
1473 py.test.raises(TypeError, lib.call2, ffi.addressof(lib, 'cb1'))
1474 py.test.raises(TypeError, ptr_call2, ffi.addressof(lib, 'cb1'))
1475 assert lib.call1(ffi.addressof(lib, 'cb1')) == 500*999*2
1476 assert ptr_call1(ffi.addressof(lib, 'cb1')) == 500*999*2
1477 assert lib.call2(ffi.addressof(lib, 'cb2')) == -500*999*3
1478 assert ptr_call2(ffi.addressof(lib, 'cb2')) == -500*999*3
1479
1480 def test_win32_calling_convention_3():
1481 ffi = FFI()
1482 ffi.cdef("""
1483 struct point { int x, y; };
1484
1485 int (*const cb1)(struct point);
1486 int (__stdcall *const cb2)(struct point);
1487
1488 struct point __stdcall call1(int(*cb)(struct point));
1489 struct point call2(int(__stdcall *cb)(struct point));
1490 """)
1491 lib = verify(ffi, 'test_win32_calling_convention_3', r"""
1492 #ifndef _MSC_VER
1493 # define __cdecl
1494 # define __stdcall
1495 #endif
1496 struct point { int x, y; };
1497 int cb1(struct point pt) { return pt.x + 10 * pt.y; }
1498 int __stdcall cb2(struct point pt) { return pt.x + 100 * pt.y; }
1499 struct point __stdcall call1(int(__cdecl *cb)(struct point)) {
1500 int i;
1501 struct point result = { 0, 0 };
1502 //printf("here1\n");
1503 //printf("cb = %p, cb1 = %p\n", cb, (void *)cb1);
1504 for (i = 0; i < 1000; i++) {
1505 struct point p = { i, -i };
1506 int r = cb(p);
1507 result.x += r;
1508 result.y -= r;
1509 }
1510 return result;
1511 }
1512 struct point __cdecl call2(int(__stdcall *cb)(struct point)) {
1513 int i;
1514 struct point result = { 0, 0 };
1515 for (i = 0; i < 1000; i++) {
1516 struct point p = { -i, i };
1517 int r = cb(p);
1518 result.x += r;
1519 result.y -= r;
1520 }
1521 return result;
1522 }
1523 """)
1524 ptr_call1 = ffi.addressof(lib, 'call1')
1525 ptr_call2 = ffi.addressof(lib, 'call2')
1526 if sys.platform == 'win32' and not sys.maxsize > 2**32:
1527 py.test.raises(TypeError, lib.call1, ffi.addressof(lib, 'cb2'))
1528 py.test.raises(TypeError, ptr_call1, ffi.addressof(lib, 'cb2'))
1529 py.test.raises(TypeError, lib.call2, ffi.addressof(lib, 'cb1'))
1530 py.test.raises(TypeError, ptr_call2, ffi.addressof(lib, 'cb1'))
1531 pt = lib.call1(ffi.addressof(lib, 'cb1'))
1532 assert (pt.x, pt.y) == (-9*500*999, 9*500*999)
1533 pt = ptr_call1(ffi.addressof(lib, 'cb1'))
1534 assert (pt.x, pt.y) == (-9*500*999, 9*500*999)
1535 pt = lib.call2(ffi.addressof(lib, 'cb2'))
1536 assert (pt.x, pt.y) == (99*500*999, -99*500*999)
1537 pt = ptr_call2(ffi.addressof(lib, 'cb2'))
1538 assert (pt.x, pt.y) == (99*500*999, -99*500*999)
1539
1540 def test_extern_python_1():
1541 import warnings
1542 ffi = FFI()
1543 with warnings.catch_warnings(record=True) as log:
1544 ffi.cdef("""
1545 extern "Python" {
1546 int bar(int, int);
1547 void baz(int, int);
1548 int bok(void);
1549 void boz(void);
1550 }
1551 """)
1552 assert len(log) == 0, "got a warning: %r" % (log,)
1553 lib = verify(ffi, 'test_extern_python_1', """
1554 static void baz(int, int); /* forward */
1555 """)
1556 assert ffi.typeof(lib.bar) == ffi.typeof("int(*)(int, int)")
1557 with FdWriteCapture() as f:
1558 res = lib.bar(4, 5)
1559 assert res == 0
1560 assert f.getvalue() == (
1561 b"extern \"Python\": function _CFFI_test_extern_python_1.bar() called, "
1562 b"but no code was attached "
1563 b"to it yet with @ffi.def_extern(). Returning 0.\n")
1564
1565 @ffi.def_extern("bar")
1566 def my_bar(x, y):
1567 seen.append(("Bar", x, y))
1568 return x * y
1569 assert my_bar != lib.bar
1570 seen = []
1571 res = lib.bar(6, 7)
1572 assert seen == [("Bar", 6, 7)]
1573 assert res == 42
1574
1575 def baz(x, y):
1576 seen.append(("Baz", x, y))
1577 baz1 = ffi.def_extern()(baz)
1578 assert baz1 is baz
1579 seen = []
1580 baz(long(40), long(4))
1581 res = lib.baz(long(50), long(8))
1582 assert res is None
1583 assert seen == [("Baz", 40, 4), ("Baz", 50, 8)]
1584 assert type(seen[0][1]) is type(seen[0][2]) is long
1585 assert type(seen[1][1]) is type(seen[1][2]) is int
1586
1587 @ffi.def_extern(name="bok")
1588 def bokk():
1589 seen.append("Bok")
1590 return 42
1591 seen = []
1592 assert lib.bok() == 42
1593 assert seen == ["Bok"]
1594
1595 @ffi.def_extern()
1596 def boz():
1597 seen.append("Boz")
1598 seen = []
1599 assert lib.boz() is None
1600 assert seen == ["Boz"]
1601
1602 def test_extern_python_bogus_name():
1603 ffi = FFI()
1604 ffi.cdef("int abc;")
1605 lib = verify(ffi, 'test_extern_python_bogus_name', "int abc;")
1606 def fn():
1607 pass
1608 py.test.raises(ffi.error, ffi.def_extern("unknown_name"), fn)
1609 py.test.raises(ffi.error, ffi.def_extern("abc"), fn)
1610 assert lib.abc == 0
1611 e = py.test.raises(ffi.error, ffi.def_extern("abc"), fn)
1612 assert str(e.value) == ("ffi.def_extern('abc'): no 'extern \"Python\"' "
1613 "function with this name")
1614 e = py.test.raises(ffi.error, ffi.def_extern(), fn)
1615 assert str(e.value) == ("ffi.def_extern('fn'): no 'extern \"Python\"' "
1616 "function with this name")
1617 #
1618 py.test.raises(TypeError, ffi.def_extern(42), fn)
1619 py.test.raises((TypeError, AttributeError), ffi.def_extern(), "foo")
1620 class X:
1621 pass
1622 x = X()
1623 x.__name__ = x
1624 py.test.raises(TypeError, ffi.def_extern(), x)
1625
1626 def test_extern_python_bogus_result_type():
1627 ffi = FFI()
1628 ffi.cdef("""extern "Python" void bar(int);""")
1629 lib = verify(ffi, 'test_extern_python_bogus_result_type', "")
1630 #
1631 @ffi.def_extern()
1632 def bar(n):
1633 return n * 10
1634 with StdErrCapture() as f:
1635 res = lib.bar(321)
1636 assert res is None
1637 assert f.getvalue() == (
1638 "From cffi callback %r:\n" % (bar,) +
1639 "Trying to convert the result back to C:\n"
1640 "TypeError: callback with the return type 'void' must return None\n")
1641
1642 def test_extern_python_redefine():
1643 ffi = FFI()
1644 ffi.cdef("""extern "Python" int bar(int);""")
1645 lib = verify(ffi, 'test_extern_python_redefine', "")
1646 #
1647 @ffi.def_extern()
1648 def bar(n):
1649 return n * 10
1650 assert lib.bar(42) == 420
1651 #
1652 @ffi.def_extern()
1653 def bar(n):
1654 return -n
1655 assert lib.bar(42) == -42
1656
1657 def test_extern_python_struct():
1658 ffi = FFI()
1659 ffi.cdef("""
1660 struct foo_s { int a, b, c; };
1661 extern "Python" int bar(int, struct foo_s, int);
1662 extern "Python" { struct foo_s baz(int, int);
1663 struct foo_s bok(void); }
1664 """)
1665 lib = verify(ffi, 'test_extern_python_struct',
1666 "struct foo_s { int a, b, c; };")
1667 #
1668 @ffi.def_extern()
1669 def bar(x, s, z):
1670 return x + s.a + s.b + s.c + z
1671 res = lib.bar(1000, [1001, 1002, 1004], 1008)
1672 assert res == 5015
1673 #
1674 @ffi.def_extern()
1675 def baz(x, y):
1676 return [x + y, x - y, x * y]
1677 res = lib.baz(1000, 42)
1678 assert res.a == 1042
1679 assert res.b == 958
1680 assert res.c == 42000
1681 #
1682 @ffi.def_extern()
1683 def bok():
1684 return [10, 20, 30]
1685 res = lib.bok()
1686 assert [res.a, res.b, res.c] == [10, 20, 30]
1687
1688 def test_extern_python_long_double():
1689 ffi = FFI()
1690 ffi.cdef("""
1691 extern "Python" int bar(int, long double, int);
1692 extern "Python" long double baz(int, int);
1693 extern "Python" long double bok(void);
1694 """)
1695 lib = verify(ffi, 'test_extern_python_long_double', "")
1696 #
1697 @ffi.def_extern()
1698 def bar(x, l, z):
1699 seen.append((x, l, z))
1700 return 6
1701 seen = []
1702 lib.bar(10, 3.5, 20)
1703 expected = ffi.cast("long double", 3.5)
1704 assert repr(seen) == repr([(10, expected, 20)])
1705 #
1706 @ffi.def_extern()
1707 def baz(x, z):
1708 assert x == 10 and z == 20
1709 return expected
1710 res = lib.baz(10, 20)
1711 assert repr(res) == repr(expected)
1712 #
1713 @ffi.def_extern()
1714 def bok():
1715 return expected
1716 res = lib.bok()
1717 assert repr(res) == repr(expected)
1718
1719 def test_extern_python_signature():
1720 ffi = FFI()
1721 lib = verify(ffi, 'test_extern_python_signature', "")
1722 py.test.raises(TypeError, ffi.def_extern(425), None)
1723 py.test.raises(TypeError, ffi.def_extern, 'a', 'b', 'c', 'd')
1724
1725 def test_extern_python_errors():
1726 ffi = FFI()
1727 ffi.cdef("""
1728 extern "Python" int bar(int);
1729 """)
1730 lib = verify(ffi, 'test_extern_python_errors', "")
1731
1732 seen = []
1733 def oops(*args):
1734 seen.append(args)
1735
1736 @ffi.def_extern(onerror=oops)
1737 def bar(x):
1738 return x + ""
1739 assert lib.bar(10) == 0
1740
1741 @ffi.def_extern(name="bar", onerror=oops, error=-66)
1742 def bar2(x):
1743 return x + ""
1744 assert lib.bar(10) == -66
1745
1746 assert len(seen) == 2
1747 exc, val, tb = seen[0]
1748 assert exc is TypeError
1749 assert isinstance(val, TypeError)
1750 assert tb.tb_frame.f_code.co_name == "bar"
1751 exc, val, tb = seen[1]
1752 assert exc is TypeError
1753 assert isinstance(val, TypeError)
1754 assert tb.tb_frame.f_code.co_name == "bar2"
1755 #
1756 # a case where 'onerror' is not callable
1757 py.test.raises(TypeError, ffi.def_extern(name='bar', onerror=42),
1758 lambda x: x)
1759
1760 def test_extern_python_stdcall():
1761 ffi = FFI()
1762 ffi.cdef("""
1763 extern "Python" int __stdcall foo(int);
1764 extern "Python" int WINAPI bar(int);
1765 int (__stdcall * mycb1)(int);
1766 int indirect_call(int);
1767 """)
1768 lib = verify(ffi, 'test_extern_python_stdcall', """
1769 #ifndef _MSC_VER
1770 # define __stdcall
1771 #endif
1772 static int (__stdcall * mycb1)(int);
1773 static int indirect_call(int x) {
1774 return mycb1(x);
1775 }
1776 """)
1777 #
1778 @ffi.def_extern()
1779 def foo(x):
1780 return x + 42
1781 @ffi.def_extern()
1782 def bar(x):
1783 return x + 43
1784 assert lib.foo(100) == 142
1785 assert lib.bar(100) == 143
1786 lib.mycb1 = lib.foo
1787 assert lib.mycb1(200) == 242
1788 assert lib.indirect_call(300) == 342
1789
1790 def test_extern_python_plus_c():
1791 ffi = FFI()
1792 ffi.cdef("""
1793 extern "Python+C" int foo(int);
1794 extern "C +\tPython" int bar(int);
1795 int call_me(int);
1796 """)
1797 lib = verify(ffi, 'test_extern_python_plus_c', """
1798 int foo(int);
1799 #ifdef __GNUC__
1800 __attribute__((visibility("hidden")))
1801 #endif
1802 int bar(int);
1803
1804 static int call_me(int x) {
1805 return foo(x) - bar(x);
1806 }
1807 """)
1808 #
1809 @ffi.def_extern()
1810 def foo(x):
1811 return x * 42
1812 @ffi.def_extern()
1813 def bar(x):
1814 return x * 63
1815 assert lib.foo(100) == 4200
1816 assert lib.bar(100) == 6300
1817 assert lib.call_me(100) == -2100
1818
1819 def test_introspect_function():
1820 ffi = FFI()
1821 ffi.cdef("float f1(double);")
1822 lib = verify(ffi, 'test_introspect_function', """
1823 float f1(double x) { return x; }
1824 """)
1825 assert dir(lib) == ['f1']
1826 FUNC = ffi.typeof(lib.f1)
1827 assert FUNC.kind == 'function'
1828 assert FUNC.args[0].cname == 'double'
1829 assert FUNC.result.cname == 'float'
1830 assert ffi.typeof(ffi.addressof(lib, 'f1')) is FUNC
1831
1832 def test_introspect_global_var():
1833 ffi = FFI()
1834 ffi.cdef("float g1;")
1835 lib = verify(ffi, 'test_introspect_global_var', """
1836 float g1;
1837 """)
1838 assert dir(lib) == ['g1']
1839 FLOATPTR = ffi.typeof(ffi.addressof(lib, 'g1'))
1840 assert FLOATPTR.kind == 'pointer'
1841 assert FLOATPTR.item.cname == 'float'
1842
1843 def test_introspect_global_var_array():
1844 ffi = FFI()
1845 ffi.cdef("float g1[100];")
1846 lib = verify(ffi, 'test_introspect_global_var_array', """
1847 float g1[100];
1848 """)
1849 assert dir(lib) == ['g1']
1850 FLOATARRAYPTR = ffi.typeof(ffi.addressof(lib, 'g1'))
1851 assert FLOATARRAYPTR.kind == 'pointer'
1852 assert FLOATARRAYPTR.item.kind == 'array'
1853 assert FLOATARRAYPTR.item.length == 100
1854 assert ffi.typeof(lib.g1) is FLOATARRAYPTR.item
1855
1856 def test_introspect_integer_const():
1857 ffi = FFI()
1858 ffi.cdef("#define FOO 42")
1859 lib = verify(ffi, 'test_introspect_integer_const', """
1860 #define FOO 42
1861 """)
1862 assert dir(lib) == ['FOO']
1863 assert lib.FOO == ffi.integer_const('FOO') == 42
1864
1865 def test_introspect_typedef():
1866 ffi = FFI()
1867 ffi.cdef("typedef int foo_t;")
1868 lib = verify(ffi, 'test_introspect_typedef', """
1869 typedef int foo_t;
1870 """)
1871 assert ffi.list_types() == (['foo_t'], [], [])
1872 assert ffi.typeof('foo_t').kind == 'primitive'
1873 assert ffi.typeof('foo_t').cname == 'int'
1874
1875 def test_introspect_typedef_multiple():
1876 ffi = FFI()
1877 ffi.cdef("typedef signed char a_t, c_t, g_t, b_t;")
1878 lib = verify(ffi, 'test_introspect_typedef_multiple', """
1879 typedef signed char a_t, c_t, g_t, b_t;
1880 """)
1881 assert ffi.list_types() == (['a_t', 'b_t', 'c_t', 'g_t'], [], [])
1882
1883 def test_introspect_struct():
1884 ffi = FFI()
1885 ffi.cdef("struct foo_s { int a; };")
1886 lib = verify(ffi, 'test_introspect_struct', """
1887 struct foo_s { int a; };
1888 """)
1889 assert ffi.list_types() == ([], ['foo_s'], [])
1890 assert ffi.typeof('struct foo_s').kind == 'struct'
1891 assert ffi.typeof('struct foo_s').cname == 'struct foo_s'
1892
1893 def test_introspect_union():
1894 ffi = FFI()
1895 ffi.cdef("union foo_s { int a; };")
1896 lib = verify(ffi, 'test_introspect_union', """
1897 union foo_s { int a; };
1898 """)
1899 assert ffi.list_types() == ([], [], ['foo_s'])
1900 assert ffi.typeof('union foo_s').kind == 'union'
1901 assert ffi.typeof('union foo_s').cname == 'union foo_s'
1902
1903 def test_introspect_struct_and_typedef():
1904 ffi = FFI()
1905 ffi.cdef("typedef struct { int a; } foo_t;")
1906 lib = verify(ffi, 'test_introspect_struct_and_typedef', """
1907 typedef struct { int a; } foo_t;
1908 """)
1909 assert ffi.list_types() == (['foo_t'], [], [])
1910 assert ffi.typeof('foo_t').kind == 'struct'
1911 assert ffi.typeof('foo_t').cname == 'foo_t'
1912
1913 def test_introspect_included_type():
1914 SOURCE = """
1915 typedef signed char schar_t;
1916 struct sint_t { int x; };
1917 """
1918 ffi1 = FFI()
1919 ffi1.cdef(SOURCE)
1920 ffi2 = FFI()
1921 ffi2.include(ffi1)
1922 verify(ffi1, "test_introspect_included_type_parent", SOURCE)
1923 verify(ffi2, "test_introspect_included_type", SOURCE)
1924 assert ffi1.list_types() == ffi2.list_types() == (
1925 ['schar_t'], ['sint_t'], [])
1926
1927 def test_introspect_order():
1928 ffi = FFI()
1929 ffi.cdef("union CFFIaaa { int a; }; typedef struct CFFIccc { int a; } CFFIb;")
1930 ffi.cdef("union CFFIg { int a; }; typedef struct CFFIcc { int a; } CFFIbbb;")
1931 ffi.cdef("union CFFIaa { int a; }; typedef struct CFFIa { int a; } CFFIbb;")
1932 verify(ffi, "test_introspect_order", """
1933 union CFFIaaa { int a; }; typedef struct CFFIccc { int a; } CFFIb;
1934 union CFFIg { int a; }; typedef struct CFFIcc { int a; } CFFIbbb;
1935 union CFFIaa { int a; }; typedef struct CFFIa { int a; } CFFIbb;
1936 """)
1937 assert ffi.list_types() == (['CFFIb', 'CFFIbb', 'CFFIbbb'],
1938 ['CFFIa', 'CFFIcc', 'CFFIccc'],
1939 ['CFFIaa', 'CFFIaaa', 'CFFIg'])
1940
1941 def test_bool_in_cpp():
1942 # this works when compiled as C, but in cffi < 1.7 it fails as C++
1943 ffi = FFI()
1944 ffi.cdef("bool f(void);")
1945 lib = verify(ffi, "test_bool_in_cpp", "char f(void) { return 2; }")
1946 assert lib.f() is True
1947
1948 def test_bool_in_cpp_2():
1949 ffi = FFI()
1950 ffi.cdef('int add(int a, int b);')
1951 lib = verify(ffi, "test_bool_bug_cpp", '''
1952 typedef bool _Bool; /* there is a Windows header with this line */
1953 int add(int a, int b)
1954 {
1955 return a + b;
1956 }''', source_extension='.cpp')
1957 c = lib.add(2, 3)
1958 assert c == 5
1959
1960 def test_struct_field_opaque():
1961 ffi = FFI()
1962 ffi.cdef("struct a { struct b b; };")
1963 e = py.test.raises(TypeError, verify,
1964 ffi, "test_struct_field_opaque", "?")
1965 assert str(e.value) == ("struct a: field 'a.b' is of an opaque"
1966 " type (not declared in cdef())")
1967 ffi = FFI()
1968 ffi.cdef("struct a { struct b b[2]; };")
1969 e = py.test.raises(TypeError, verify,
1970 ffi, "test_struct_field_opaque", "?")
1971 assert str(e.value) == ("struct a: field 'a.b' is of an opaque"
1972 " type (not declared in cdef())")
1973 ffi = FFI()
1974 ffi.cdef("struct a { struct b b[]; };")
1975 e = py.test.raises(TypeError, verify,
1976 ffi, "test_struct_field_opaque", "?")
1977 assert str(e.value) == ("struct a: field 'a.b' is of an opaque"
1978 " type (not declared in cdef())")
1979
1980 def test_function_arg_opaque():
1981 py.test.skip("can currently declare a function with an opaque struct "
1982 "as argument, but AFAICT it's impossible to call it later")
1983
1984 def test_function_returns_opaque():
1985 ffi = FFI()
1986 ffi.cdef("struct a foo(int);")
1987 e = py.test.raises(TypeError, verify,
1988 ffi, "test_function_returns_opaque", "?")
1989 assert str(e.value) == ("function foo: 'struct a' is used as result type,"
1990 " but is opaque")
1991
1992 def test_function_returns_union():
1993 ffi = FFI()
1994 ffi.cdef("union u1 { int a, b; }; union u1 f1(int);")
1995 lib = verify(ffi, "test_function_returns_union", """
1996 union u1 { int a, b; };
1997 static union u1 f1(int x) { union u1 u; u.b = x; return u; }
1998 """)
1999 assert lib.f1(51).a == 51
2000
2001 def test_function_returns_partial_struct():
2002 ffi = FFI()
2003 ffi.cdef("struct aaa { int a; ...; }; struct aaa f1(int);")
2004 lib = verify(ffi, "test_function_returns_partial_struct", """
2005 struct aaa { int b, a, c; };
2006 static struct aaa f1(int x) { struct aaa s = {0}; s.a = x; return s; }
2007 """)
2008 assert lib.f1(52).a == 52
2009
2010 def test_function_returns_float_complex():
2011 if sys.platform == 'win32':
2012 py.test.skip("MSVC may not support _Complex")
2013 ffi = FFI()
2014 ffi.cdef("float _Complex f1(float a, float b);");
2015 lib = verify(ffi, "test_function_returns_float_complex", """
2016 #include <complex.h>
2017 static float _Complex f1(float a, float b) { return a + I*2.0*b; }
2018 """, no_cpp=True) # <complex.h> fails on some systems with C++
2019 result = lib.f1(1.25, 5.1)
2020 assert type(result) == complex
2021 assert result.real == 1.25 # exact
2022 assert (result.imag != 2*5.1) and (abs(result.imag - 2*5.1) < 1e-5) # inexact
2023
2024 def test_function_returns_double_complex():
2025 if sys.platform == 'win32':
2026 py.test.skip("MSVC may not support _Complex")
2027 ffi = FFI()
2028 ffi.cdef("double _Complex f1(double a, double b);");
2029 lib = verify(ffi, "test_function_returns_double_complex", """
2030 #include <complex.h>
2031 static double _Complex f1(double a, double b) { return a + I*2.0*b; }
2032 """, no_cpp=True) # <complex.h> fails on some systems with C++
2033 result = lib.f1(1.25, 5.1)
2034 assert type(result) == complex
2035 assert result.real == 1.25 # exact
2036 assert result.imag == 2*5.1 # exact
2037
2038 def test_function_argument_float_complex():
2039 if sys.platform == 'win32':
2040 py.test.skip("MSVC may not support _Complex")
2041 ffi = FFI()
2042 ffi.cdef("float f1(float _Complex x);");
2043 lib = verify(ffi, "test_function_argument_float_complex", """
2044 #include <complex.h>
2045 static float f1(float _Complex x) { return cabsf(x); }
2046 """, no_cpp=True) # <complex.h> fails on some systems with C++
2047 x = complex(12.34, 56.78)
2048 result = lib.f1(x)
2049 assert abs(result - abs(x)) < 1e-5
2050
2051 def test_function_argument_double_complex():
2052 if sys.platform == 'win32':
2053 py.test.skip("MSVC may not support _Complex")
2054 ffi = FFI()
2055 ffi.cdef("double f1(double _Complex);");
2056 lib = verify(ffi, "test_function_argument_double_complex", """
2057 #include <complex.h>
2058 static double f1(double _Complex x) { return cabs(x); }
2059 """, no_cpp=True) # <complex.h> fails on some systems with C++
2060 x = complex(12.34, 56.78)
2061 result = lib.f1(x)
2062 assert abs(result - abs(x)) < 1e-11
2063
2064 def test_typedef_array_dotdotdot():
2065 ffi = FFI()
2066 ffi.cdef("""
2067 typedef int foo_t[...], bar_t[...];
2068 int gv[...];
2069 typedef int mat_t[...][...];
2070 typedef int vmat_t[][...];
2071 """)
2072 lib = verify(ffi, "test_typedef_array_dotdotdot", """
2073 typedef int foo_t[50], bar_t[50];
2074 int gv[23];
2075 typedef int mat_t[6][7];
2076 typedef int vmat_t[][8];
2077 """)
2078 assert ffi.sizeof("foo_t") == 50 * ffi.sizeof("int")
2079 assert ffi.sizeof("bar_t") == 50 * ffi.sizeof("int")
2080 assert len(ffi.new("foo_t")) == 50
2081 assert len(ffi.new("bar_t")) == 50
2082 assert ffi.sizeof(lib.gv) == 23 * ffi.sizeof("int")
2083 assert ffi.sizeof("mat_t") == 6 * 7 * ffi.sizeof("int")
2084 assert len(ffi.new("mat_t")) == 6
2085 assert len(ffi.new("mat_t")[3]) == 7
2086 py.test.raises(ffi.error, ffi.sizeof, "vmat_t")
2087 p = ffi.new("vmat_t", 4)
2088 assert ffi.sizeof(p[3]) == 8 * ffi.sizeof("int")
2089
2090 def test_call_with_custom_field_pos():
2091 ffi = FFI()
2092 ffi.cdef("""
2093 struct foo { int x; ...; };
2094 struct foo f(void);
2095 struct foo g(int, ...);
2096 """)
2097 lib = verify(ffi, "test_call_with_custom_field_pos", """
2098 struct foo { int y, x; };
2099 struct foo f(void) {
2100 struct foo s = { 40, 200 };
2101 return s;
2102 }
2103 struct foo g(int a, ...) { return f(); }
2104 """)
2105 assert lib.f().x == 200
2106 e = py.test.raises(NotImplementedError, lib.g, 0)
2107 assert str(e.value) == (
2108 'ctype \'struct foo\' not supported as return value. It is a '
2109 'struct declared with "...;", but the C calling convention may '
2110 'depend on the missing fields; or, it contains anonymous '
2111 'struct/unions. Such structs are only supported '
2112 'as return value if the function is \'API mode\' and non-variadic '
2113 '(i.e. declared inside ffibuilder.cdef()+ffibuilder.set_source() '
2114 'and not taking a final \'...\' argument)')
2115
2116 def test_call_with_nested_anonymous_struct():
2117 if sys.platform == 'win32':
2118 py.test.skip("needs a GCC extension")
2119 ffi = FFI()
2120 ffi.cdef("""
2121 struct foo { int a; union { int b, c; }; };
2122 struct foo f(void);
2123 struct foo g(int, ...);
2124 """)
2125 lib = verify(ffi, "test_call_with_nested_anonymous_struct", """
2126 struct foo { int a; union { int b, c; }; };
2127 struct foo f(void) {
2128 struct foo s = { 40 };
2129 s.b = 200;
2130 return s;
2131 }
2132 struct foo g(int a, ...) { return f(); }
2133 """)
2134 assert lib.f().b == 200
2135 e = py.test.raises(NotImplementedError, lib.g, 0)
2136 assert str(e.value) == (
2137 'ctype \'struct foo\' not supported as return value. It is a '
2138 'struct declared with "...;", but the C calling convention may '
2139 'depend on the missing fields; or, it contains anonymous '
2140 'struct/unions. Such structs are only supported '
2141 'as return value if the function is \'API mode\' and non-variadic '
2142 '(i.e. declared inside ffibuilder.cdef()+ffibuilder.set_source() '
2143 'and not taking a final \'...\' argument)')
2144
2145 def test_call_with_bitfield():
2146 ffi = FFI()
2147 ffi.cdef("""
2148 struct foo { int x:5; };
2149 struct foo f(void);
2150 struct foo g(int, ...);
2151 """)
2152 lib = verify(ffi, "test_call_with_bitfield", """
2153 struct foo { int x:5; };
2154 struct foo f(void) {
2155 struct foo s = { 11 };
2156 return s;
2157 }
2158 struct foo g(int a, ...) { return f(); }
2159 """)
2160 assert lib.f().x == 11
2161 e = py.test.raises(NotImplementedError, lib.g, 0)
2162 assert str(e.value) == (
2163 "ctype 'struct foo' not supported as return value. It is a struct "
2164 "with bit fields, which libffi does not support. Such structs are "
2165 "only supported as return value if the function is 'API mode' and "
2166 "non-variadic (i.e. declared inside ffibuilder.cdef()+ffibuilder."
2167 "set_source() and not taking a final '...' argument)")
2168
2169 def test_call_with_zero_length_field():
2170 if sys.platform == 'win32':
2171 py.test.skip("zero-length field not supported by MSVC")
2172 ffi = FFI()
2173 ffi.cdef("""
2174 struct foo { int a; int x[0]; };
2175 struct foo f(void);
2176 struct foo g(int, ...);
2177 """)
2178 lib = verify(ffi, "test_call_with_zero_length_field", """
2179 struct foo { int a; int x[0]; };
2180 struct foo f(void) {
2181 struct foo s = { 42 };
2182 return s;
2183 }
2184 struct foo g(int a, ...) { return f(); }
2185 """)
2186 assert lib.f().a == 42
2187 e = py.test.raises(NotImplementedError, lib.g, 0)
2188 assert str(e.value) == (
2189 "ctype 'struct foo' not supported as return value. It is a "
2190 "struct with a zero-length array, which libffi does not support."
2191 " Such structs are only supported as return value if the function is "
2192 "'API mode' and non-variadic (i.e. declared inside ffibuilder.cdef()"
2193 "+ffibuilder.set_source() and not taking a final '...' argument)")
2194
2195 def test_call_with_union():
2196 ffi = FFI()
2197 ffi.cdef("""
2198 union foo { int a; char b; };
2199 union foo f(void);
2200 union foo g(int, ...);
2201 """)
2202 lib = verify(ffi, "test_call_with_union", """
2203 union foo { int a; char b; };
2204 union foo f(void) {
2205 union foo s = { 42 };
2206 return s;
2207 }
2208 union foo g(int a, ...) { return f(); }
2209 """)
2210 assert lib.f().a == 42
2211 e = py.test.raises(NotImplementedError, lib.g, 0)
2212 assert str(e.value) == (
2213 "ctype 'union foo' not supported as return value by libffi. "
2214 "Unions are only supported as return value if the function is "
2215 "'API mode' and non-variadic (i.e. declared inside ffibuilder.cdef()"
2216 "+ffibuilder.set_source() and not taking a final '...' argument)")
2217
2218 def test_call_with_packed_struct():
2219 if sys.platform == 'win32':
2220 py.test.skip("needs a GCC extension")
2221 ffi = FFI()
2222 ffi.cdef("""
2223 struct foo { char y; int x; };
2224 struct foo f(void);
2225 struct foo g(int, ...);
2226 """, packed=True)
2227 lib = verify(ffi, "test_call_with_packed_struct", """
2228 struct foo { char y; int x; } __attribute__((packed));
2229 struct foo f(void) {
2230 struct foo s = { 40, 200 };
2231 return s;
2232 }
2233 struct foo g(int a, ...) {
2234 struct foo s = { 41, 201 };
2235 return s;
2236 }
2237 """)
2238 assert ord(lib.f().y) == 40
2239 assert lib.f().x == 200
2240 e = py.test.raises(NotImplementedError, lib.g, 0)
2241 assert str(e.value) == (
2242 "ctype 'struct foo' not supported as return value. It is a "
2243 "'packed' structure, with a different layout than expected by libffi."
2244 " Such structs are only supported as return value if the function is "
2245 "'API mode' and non-variadic (i.e. declared inside ffibuilder.cdef()"
2246 "+ffibuilder.set_source() and not taking a final '...' argument)")
2247
2248 def test_pack_not_supported():
2249 ffi = FFI()
2250 ffi.cdef("""struct foo { char y; int x; };""", pack=2)
2251 py.test.raises(NotImplementedError, verify,
2252 ffi, "test_pack_not_supported", "")
2253
2254 def test_gcc_visibility_hidden():
2255 if sys.platform == 'win32':
2256 py.test.skip("test for gcc/clang")
2257 ffi = FFI()
2258 ffi.cdef("""
2259 int f(int);
2260 """)
2261 lib = verify(ffi, "test_gcc_visibility_hidden", """
2262 int f(int a) { return a + 40; }
2263 """, extra_compile_args=['-fvisibility=hidden'])
2264 assert lib.f(2) == 42
2265
2266 def test_override_default_definition():
2267 ffi = FFI()
2268 ffi.cdef("typedef long int16_t, char16_t;")
2269 lib = verify(ffi, "test_override_default_definition", "")
2270 assert ffi.typeof("int16_t") is ffi.typeof("char16_t") is ffi.typeof("long")
2271
2272 def test_char16_char32_type(no_cpp=False):
2273 if no_cpp is False and sys.platform == "win32":
2274 py.test.skip("aaaaaaa why do modern MSVC compilers still define "
2275 "a very old __cplusplus value")
2276 ffi = FFI()
2277 ffi.cdef("""
2278 char16_t foo_2bytes(char16_t);
2279 char32_t foo_4bytes(char32_t);
2280 """)
2281 lib = verify(ffi, "test_char16_char32_type" + no_cpp * "_nocpp", """
2282 #if !defined(__cplusplus) || (!defined(_LIBCPP_VERSION) && __cplusplus < 201103L)
2283 typedef uint_least16_t char16_t;
2284 typedef uint_least32_t char32_t;
2285 #endif
2286
2287 char16_t foo_2bytes(char16_t a) { return (char16_t)(a + 42); }
2288 char32_t foo_4bytes(char32_t a) { return (char32_t)(a + 42); }
2289 """, no_cpp=no_cpp)
2290 assert lib.foo_2bytes(u+'\u1234') == u+'\u125e'
2291 assert lib.foo_4bytes(u+'\u1234') == u+'\u125e'
2292 assert lib.foo_4bytes(u+'\U00012345') == u+'\U0001236f'
2293 py.test.raises(TypeError, lib.foo_2bytes, u+'\U00012345')
2294 py.test.raises(TypeError, lib.foo_2bytes, 1234)
2295 py.test.raises(TypeError, lib.foo_4bytes, 1234)
2296
2297 def test_char16_char32_plain_c():
2298 test_char16_char32_type(no_cpp=True)
2299
2300 def test_loader_spec():
2301 ffi = FFI()
2302 lib = verify(ffi, "test_loader_spec", "")
2303 if sys.version_info < (3,):
2304 assert not hasattr(lib, '__loader__')
2305 assert not hasattr(lib, '__spec__')
2306 else:
2307 assert lib.__loader__ is None
2308 assert lib.__spec__ is None
2309
2310 def test_realize_struct_error():
2311 ffi = FFI()
2312 ffi.cdef("""typedef ... foo_t; struct foo_s { void (*x)(foo_t); };""")
2313 lib = verify(ffi, "test_realize_struct_error", """
2314 typedef int foo_t; struct foo_s { void (*x)(foo_t); };
2315 """)
2316 py.test.raises(TypeError, ffi.new, "struct foo_s *")
0 # Generated by pypy/tool/import_cffi.py
1 #
2 # ----------------------------------------------
3 # WARNING, ALL LITERALS IN THIS FILE ARE UNICODE
4 # ----------------------------------------------
5 #
6 from __future__ import unicode_literals
7 #
8 #
9 #
10 from _cffi_backend import FFI
11
12
13 def test_cast():
14 ffi = FFI()
15 assert int(ffi.cast("int", 3.14)) == 3 # unicode literal
16
17 def test_new():
18 ffi = FFI()
19 assert ffi.new("int[]", [3, 4, 5])[2] == 5 # unicode literal
20
21 def test_typeof():
22 ffi = FFI()
23 tp = ffi.typeof("int[51]") # unicode literal
24 assert tp.length == 51
25
26 def test_sizeof():
27 ffi = FFI()
28 assert ffi.sizeof("int[51]") == 51 * 4 # unicode literal
29
30 def test_alignof():
31 ffi = FFI()
32 assert ffi.alignof("int[51]") == 4 # unicode literal
33
34 def test_getctype():
35 ffi = FFI()
36 assert ffi.getctype("int**") == "int * *" # unicode literal
37 assert type(ffi.getctype("int**")) is str
38
39 def test_callback():
40 ffi = FFI()
41 cb = ffi.callback("int(int)", # unicode literal
42 lambda x: x + 42)
43 assert cb(5) == 47
0 # Generated by pypy/tool/import_cffi.py
1 import os, sys, math, py
2 from cffi import FFI, FFIError, VerificationError, VerificationMissing, model
3 from cffi import CDefError
4 from cffi import recompiler
5 from extra_tests.cffi_tests.support import *
6 from extra_tests.cffi_tests.support import _verify
7 import _cffi_backend
8
9 lib_m = ['m']
10 if sys.platform == 'win32':
11 #there is a small chance this fails on Mingw via environ $CC
12 import distutils.ccompiler
13 if distutils.ccompiler.get_default_compiler() == 'msvc':
14 lib_m = ['msvcrt']
15 extra_compile_args = [] # no obvious -Werror equivalent on MSVC
16 else:
17 if (sys.platform == 'darwin' and
18 [int(x) for x in os.uname()[2].split('.')] >= [11, 0, 0]):
19 # assume a standard clang or gcc
20 extra_compile_args = ['-Werror', '-Wall', '-Wextra', '-Wconversion']
21 # special things for clang
22 extra_compile_args.append('-Qunused-arguments')
23 else:
24 # assume a standard gcc
25 extra_compile_args = ['-Werror', '-Wall', '-Wextra', '-Wconversion']
26
27 class FFI(FFI):
28 error = _cffi_backend.FFI.error
29 _extra_compile_args = extra_compile_args
30 _verify_counter = 0
31
32 def verify(self, preamble='', *args, **kwds):
33 # HACK to reuse the tests from ../cffi0/test_verify.py
34 FFI._verify_counter += 1
35 module_name = 'verify%d' % FFI._verify_counter
36 try:
37 del self._assigned_source
38 except AttributeError:
39 pass
40 self.set_source(module_name, preamble)
41 return _verify(self, module_name, preamble, *args,
42 extra_compile_args=self._extra_compile_args, **kwds)
43
44 class FFI_warnings_not_error(FFI):
45 _extra_compile_args = []
46
47
48 def test_missing_function(ffi=None):
49 # uses the FFI hacked above with '-Werror'
50 if ffi is None:
51 ffi = FFI()
52 ffi.cdef("void some_completely_unknown_function();")
53 try:
54 lib = ffi.verify()
55 except (VerificationError, OSError, ImportError):
56 pass # expected case: we get a VerificationError
57 else:
58 # but depending on compiler and loader details, maybe
59 # 'lib' could actually be imported but will fail if we
60 # actually try to call the unknown function... Hard
61 # to test anything more.
62 pass
63
64 def test_missing_function_import_error():
65 # uses the original FFI that just gives a warning during compilation
66 test_missing_function(ffi=FFI_warnings_not_error())
67
68 def test_simple_case():
69 ffi = FFI()
70 ffi.cdef("double sin(double x);")
71 lib = ffi.verify('#include <math.h>', libraries=lib_m)
72 assert lib.sin(1.23) == math.sin(1.23)
73
74 def _Wconversion(cdef, source, **kargs):
75 if sys.platform in ('win32', 'darwin'):
76 py.test.skip("needs GCC")
77 ffi = FFI()
78 ffi.cdef(cdef)
79 py.test.raises(VerificationError, ffi.verify, source, **kargs)
80 extra_compile_args_orig = extra_compile_args[:]
81 extra_compile_args.remove('-Wconversion')
82 try:
83 lib = ffi.verify(source, **kargs)
84 finally:
85 extra_compile_args[:] = extra_compile_args_orig
86 return lib
87
88 def test_Wconversion_unsigned():
89 _Wconversion("unsigned foo(void);",
90 "int foo(void) { return -1;}")
91
92 def test_Wconversion_integer():
93 _Wconversion("short foo(void);",
94 "long long foo(void) { return 1<<sizeof(short);}")
95
96 def test_Wconversion_floating():
97 lib = _Wconversion("float sin(double);",
98 "#include <math.h>", libraries=lib_m)
99 res = lib.sin(1.23)
100 assert res != math.sin(1.23) # not exact, because of double->float
101 assert abs(res - math.sin(1.23)) < 1E-5
102
103 def test_Wconversion_float2int():
104 _Wconversion("int sinf(float);",
105 "#include <math.h>", libraries=lib_m)
106
107 def test_Wconversion_double2int():
108 _Wconversion("int sin(double);",
109 "#include <math.h>", libraries=lib_m)
110
111 def test_rounding_1():
112 ffi = FFI()
113 ffi.cdef("double sinf(float x);")
114 lib = ffi.verify('#include <math.h>', libraries=lib_m)
115 res = lib.sinf(1.23)
116 assert res != math.sin(1.23) # not exact, because of double->float
117 assert abs(res - math.sin(1.23)) < 1E-5
118
119 def test_rounding_2():
120 ffi = FFI()
121 ffi.cdef("double sin(float x);")
122 lib = ffi.verify('#include <math.h>', libraries=lib_m)
123 res = lib.sin(1.23)
124 assert res != math.sin(1.23) # not exact, because of double->float
125 assert abs(res - math.sin(1.23)) < 1E-5
126
127 def test_strlen_exact():
128 ffi = FFI()
129 ffi.cdef("size_t strlen(const char *s);")
130 lib = ffi.verify("#include <string.h>")
131 assert lib.strlen(b"hi there!") == 9
132
133 def test_strlen_approximate():
134 lib = _Wconversion("int strlen(char *s);",
135 "#include <string.h>")
136 assert lib.strlen(b"hi there!") == 9
137
138 def test_return_approximate():
139 for typename in ['short', 'int', 'long', 'long long']:
140 ffi = FFI()
141 ffi.cdef("%s foo(signed char x);" % typename)
142 lib = ffi.verify("signed char foo(signed char x) { return x;}")
143 assert lib.foo(-128) == -128
144 assert lib.foo(+127) == +127
145
146 def test_strlen_array_of_char():
147 ffi = FFI()
148 ffi.cdef("size_t strlen(char[]);")
149 lib = ffi.verify("#include <string.h>")
150 assert lib.strlen(b"hello") == 5
151
152 def test_longdouble():
153 ffi = FFI()
154 ffi.cdef("long double sinl(long double x);")
155 lib = ffi.verify('#include <math.h>', libraries=lib_m)
156 for input in [1.23,
157 ffi.cast("double", 1.23),
158 ffi.cast("long double", 1.23)]:
159 x = lib.sinl(input)
160 assert repr(x).startswith("<cdata 'long double'")
161 assert (float(x) - math.sin(1.23)) < 1E-10
162
163 def test_longdouble_precision():
164 # Test that we don't loose any precision of 'long double' when
165 # passing through Python and CFFI.
166 ffi = FFI()
167 ffi.cdef("long double step1(long double x);")
168 SAME_SIZE = ffi.sizeof("long double") == ffi.sizeof("double")
169 lib = ffi.verify("""
170 long double step1(long double x)
171 {
172 return 4*x-x*x;
173 }
174 """)
175 def do(cast_to_double):
176 x = 0.9789
177 for i in range(10000):
178 x = lib.step1(x)
179 if cast_to_double:
180 x = float(x)
181 return float(x)
182
183 more_precise = do(False)
184 less_precise = do(True)
185 if SAME_SIZE:
186 assert more_precise == less_precise
187 else:
188 assert abs(more_precise - less_precise) > 0.1
189 # Check the particular results on Intel
190 import platform
191 if (platform.machine().startswith('i386') or
192 platform.machine().startswith('i486') or
193 platform.machine().startswith('i586') or
194 platform.machine().startswith('i686') or
195 platform.machine().startswith('x86')):
196 assert abs(more_precise - 0.656769) < 0.001
197 assert abs(less_precise - 3.99091) < 0.001
198 else:
199 py.test.skip("don't know the very exact precision of 'long double'")
200
201
202 all_primitive_types = model.PrimitiveType.ALL_PRIMITIVE_TYPES
203 if sys.platform == 'win32':
204 all_primitive_types = all_primitive_types.copy()
205 del all_primitive_types['ssize_t']
206 all_integer_types = sorted(tp for tp in all_primitive_types
207 if all_primitive_types[tp] == 'i')
208 all_float_types = sorted(tp for tp in all_primitive_types
209 if all_primitive_types[tp] == 'f')
210
211 def all_signed_integer_types(ffi):
212 return [x for x in all_integer_types if int(ffi.cast(x, -1)) < 0]
213
214 def all_unsigned_integer_types(ffi):
215 return [x for x in all_integer_types if int(ffi.cast(x, -1)) > 0]
216
217
218 def test_primitive_category():
219 for typename in all_primitive_types:
220 tp = model.PrimitiveType(typename)
221 C = tp.is_char_type()
222 F = tp.is_float_type()
223 X = tp.is_complex_type()
224 I = tp.is_integer_type()
225 assert C == (typename in ('char', 'wchar_t', 'char16_t', 'char32_t'))
226 assert F == (typename in ('float', 'double', 'long double'))
227 assert X == (typename in ('float _Complex', 'double _Complex'))
228 assert I + F + C + X == 1 # one and only one of them is true
229
230 def test_all_integer_and_float_types():
231 typenames = []
232 for typename in all_primitive_types:
233 if (all_primitive_types[typename] == 'c' or
234 all_primitive_types[typename] == 'j' or # complex
235 typename == '_Bool' or typename == 'long double'):
236 pass
237 else:
238 typenames.append(typename)
239 #
240 ffi = FFI()
241 ffi.cdef('\n'.join(["%s foo_%s(%s);" % (tp, tp.replace(' ', '_'), tp)
242 for tp in typenames]))
243 lib = ffi.verify('\n'.join(["%s foo_%s(%s x) { return (%s)(x+1); }" %
244 (tp, tp.replace(' ', '_'), tp, tp)
245 for tp in typenames]))
246 for typename in typenames:
247 foo = getattr(lib, 'foo_%s' % typename.replace(' ', '_'))
248 assert foo(42) == 43
249 if sys.version < '3':
250 assert foo(long(44)) == 45
251 assert foo(ffi.cast(typename, 46)) == 47
252 py.test.raises(TypeError, foo, ffi.NULL)
253 #
254 # check for overflow cases
255 if all_primitive_types[typename] == 'f':
256 continue
257 for value in [-2**80, -2**40, -2**20, -2**10, -2**5, -1,
258 2**5, 2**10, 2**20, 2**40, 2**80]:
259 overflows = int(ffi.cast(typename, value)) != value
260 if overflows:
261 py.test.raises(OverflowError, foo, value)
262 else:
263 assert foo(value) == value + 1
264
265 def test_var_signed_integer_types():
266 ffi = FFI()
267 lst = all_signed_integer_types(ffi)
268 csource = "\n".join(["%s somevar_%s;" % (tp, tp.replace(' ', '_'))
269 for tp in lst])
270 ffi.cdef(csource)
271 lib = ffi.verify(csource)
272 for tp in lst:
273 varname = 'somevar_%s' % tp.replace(' ', '_')
274 sz = ffi.sizeof(tp)
275 max = (1 << (8*sz-1)) - 1
276 min = -(1 << (8*sz-1))
277 setattr(lib, varname, max)
278 assert getattr(lib, varname) == max
279 setattr(lib, varname, min)
280 assert getattr(lib, varname) == min
281 py.test.raises(OverflowError, setattr, lib, varname, max+1)
282 py.test.raises(OverflowError, setattr, lib, varname, min-1)
283
284 def test_var_unsigned_integer_types():
285 ffi = FFI()
286 lst = all_unsigned_integer_types(ffi)
287 csource = "\n".join(["%s somevar_%s;" % (tp, tp.replace(' ', '_'))
288 for tp in lst])
289 ffi.cdef(csource)
290 lib = ffi.verify(csource)
291 for tp in lst:
292 varname = 'somevar_%s' % tp.replace(' ', '_')
293 sz = ffi.sizeof(tp)
294 if tp != '_Bool':
295 max = (1 << (8*sz)) - 1
296 else:
297 max = 1
298 setattr(lib, varname, max)
299 assert getattr(lib, varname) == max
300 setattr(lib, varname, 0)
301 assert getattr(lib, varname) == 0
302 py.test.raises(OverflowError, setattr, lib, varname, max+1)
303 py.test.raises(OverflowError, setattr, lib, varname, -1)
304
305 def test_fn_signed_integer_types():
306 ffi = FFI()
307 lst = all_signed_integer_types(ffi)
308 cdefsrc = "\n".join(["%s somefn_%s(%s);" % (tp, tp.replace(' ', '_'), tp)
309 for tp in lst])
310 ffi.cdef(cdefsrc)
311 verifysrc = "\n".join(["%s somefn_%s(%s x) { return x; }" %
312 (tp, tp.replace(' ', '_'), tp) for tp in lst])
313 lib = ffi.verify(verifysrc)
314 for tp in lst:
315 fnname = 'somefn_%s' % tp.replace(' ', '_')
316 sz = ffi.sizeof(tp)
317 max = (1 << (8*sz-1)) - 1
318 min = -(1 << (8*sz-1))
319 fn = getattr(lib, fnname)
320 assert fn(max) == max
321 assert fn(min) == min
322 py.test.raises(OverflowError, fn, max + 1)
323 py.test.raises(OverflowError, fn, min - 1)
324
325 def test_fn_unsigned_integer_types():
326 ffi = FFI()
327 lst = all_unsigned_integer_types(ffi)
328 cdefsrc = "\n".join(["%s somefn_%s(%s);" % (tp, tp.replace(' ', '_'), tp)
329 for tp in lst])
330 ffi.cdef(cdefsrc)
331 verifysrc = "\n".join(["%s somefn_%s(%s x) { return x; }" %
332 (tp, tp.replace(' ', '_'), tp) for tp in lst])
333 lib = ffi.verify(verifysrc)
334 for tp in lst:
335 fnname = 'somefn_%s' % tp.replace(' ', '_')
336 sz = ffi.sizeof(tp)
337 if tp != '_Bool':
338 max = (1 << (8*sz)) - 1
339 else:
340 max = 1
341 fn = getattr(lib, fnname)
342 assert fn(max) == max
343 assert fn(0) == 0
344 py.test.raises(OverflowError, fn, max + 1)
345 py.test.raises(OverflowError, fn, -1)
346
347 def test_char_type():
348 ffi = FFI()
349 ffi.cdef("char foo(char);")
350 lib = ffi.verify("char foo(char x) { return ++x; }")
351 assert lib.foo(b"A") == b"B"
352 py.test.raises(TypeError, lib.foo, b"bar")
353 py.test.raises(TypeError, lib.foo, "bar")
354
355 def test_wchar_type():
356 ffi = FFI()
357 if ffi.sizeof('wchar_t') == 2:
358 uniexample1 = u+'\u1234'
359 uniexample2 = u+'\u1235'
360 else:
361 uniexample1 = u+'\U00012345'
362 uniexample2 = u+'\U00012346'
363 #
364 ffi.cdef("wchar_t foo(wchar_t);")
365 lib = ffi.verify("wchar_t foo(wchar_t x) { return x+1; }")
366 assert lib.foo(uniexample1) == uniexample2
367
368 def test_no_argument():
369 ffi = FFI()
370 ffi.cdef("int foo(void);")
371 lib = ffi.verify("int foo(void) { return 42; }")
372 assert lib.foo() == 42
373
374 def test_two_arguments():
375 ffi = FFI()
376 ffi.cdef("int foo(int, int);")
377 lib = ffi.verify("int foo(int a, int b) { return a - b; }")
378 assert lib.foo(40, -2) == 42
379
380 def test_macro():
381 ffi = FFI()
382 ffi.cdef("int foo(int, int);")
383 lib = ffi.verify("#define foo(a, b) ((a) * (b))")
384 assert lib.foo(-6, -7) == 42
385
386 def test_ptr():
387 ffi = FFI()
388 ffi.cdef("int *foo(int *);")
389 lib = ffi.verify("int *foo(int *a) { return a; }")
390 assert lib.foo(ffi.NULL) == ffi.NULL
391 p = ffi.new("int *", 42)
392 q = ffi.new("int *", 42)
393 assert lib.foo(p) == p
394 assert lib.foo(q) != p
395
396 def test_bogus_ptr():
397 ffi = FFI()
398 ffi.cdef("int *foo(int *);")
399 lib = ffi.verify("int *foo(int *a) { return a; }")
400 py.test.raises(TypeError, lib.foo, ffi.new("short *", 42))
401
402
403 def test_verify_typedefs():
404 py.test.skip("ignored so far")
405 types = ['signed char', 'unsigned char', 'int', 'long']
406 for cdefed in types:
407 for real in types:
408 ffi = FFI()
409 ffi.cdef("typedef %s foo_t;" % cdefed)
410 if cdefed == real:
411 ffi.verify("typedef %s foo_t;" % real)
412 else:
413 py.test.raises(VerificationError, ffi.verify,
414 "typedef %s foo_t;" % real)
415
416 def test_nondecl_struct():
417 ffi = FFI()
418 ffi.cdef("typedef struct foo_s foo_t; int bar(foo_t *);")
419 lib = ffi.verify("typedef struct foo_s foo_t;\n"
420 "int bar(foo_t *f) { (void)f; return 42; }\n")
421 assert lib.bar(ffi.NULL) == 42
422
423 def test_ffi_full_struct():
424 def check(verified_code):
425 ffi = FFI()
426 ffi.cdef("struct foo_s { char x; int y; long *z; };")
427 ffi.verify(verified_code)
428 ffi.new("struct foo_s *", {})
429
430 check("struct foo_s { char x; int y; long *z; };")
431 #
432 if sys.platform != 'win32': # XXX fixme: only gives warnings
433 py.test.raises(VerificationError, check,
434 "struct foo_s { char x; int y; int *z; };")
435 #
436 py.test.raises(VerificationError, check,
437 "struct foo_s { int y; long *z; };") # cdef'ed field x is missing
438 #
439 e = py.test.raises(FFI.error, check,
440 "struct foo_s { int y; char x; long *z; };")
441 assert str(e.value).startswith(
442 "struct foo_s: wrong offset for field 'x'"
443 " (cdef says 0, but C compiler says 4)")
444 #
445 e = py.test.raises(FFI.error, check,
446 "struct foo_s { char x; int y; long *z; char extra; };")
447 assert str(e.value).startswith(
448 "struct foo_s: wrong total size"
449 " (cdef says %d, but C compiler says %d)" % (
450 8 + FFI().sizeof('long *'),
451 8 + FFI().sizeof('long *') * 2))
452 #
453 # a corner case that we cannot really detect, but where it has no
454 # bad consequences: the size is the same, but there is an extra field
455 # that replaces what is just padding in our declaration above
456 check("struct foo_s { char x, extra; int y; long *z; };")
457 #
458 e = py.test.raises(FFI.error, check,
459 "struct foo_s { char x; short pad; short y; long *z; };")
460 assert str(e.value).startswith(
461 "struct foo_s: wrong size for field 'y'"
462 " (cdef says 4, but C compiler says 2)")
463
464 def test_ffi_nonfull_struct():
465 ffi = FFI()
466 ffi.cdef("""
467 struct foo_s {
468 int x;
469 ...;
470 };
471 """)
472 py.test.raises(VerificationMissing, ffi.sizeof, 'struct foo_s')
473 py.test.raises(VerificationMissing, ffi.offsetof, 'struct foo_s', 'x')
474 py.test.raises(VerificationMissing, ffi.new, 'struct foo_s *')
475 ffi.verify("""
476 struct foo_s {
477 int a, b, x, c, d, e;
478 };
479 """)
480 assert ffi.sizeof('struct foo_s') == 6 * ffi.sizeof('int')
481 assert ffi.offsetof('struct foo_s', 'x') == 2 * ffi.sizeof('int')
482
483 def test_ffi_nonfull_alignment():
484 ffi = FFI()
485 ffi.cdef("struct foo_s { char x; ...; };")
486 ffi.verify("struct foo_s { int a, b; char x; };")
487 assert ffi.sizeof('struct foo_s') == 3 * ffi.sizeof('int')
488 assert ffi.alignof('struct foo_s') == ffi.sizeof('int')
489
490 def _check_field_match(typename, real, expect_mismatch):
491 ffi = FFI()
492 testing_by_size = (expect_mismatch == 'by_size')
493 if testing_by_size:
494 expect_mismatch = ffi.sizeof(typename) != ffi.sizeof(real)
495 ffi.cdef("struct foo_s { %s x; ...; };" % typename)
496 try:
497 ffi.verify("struct foo_s { %s x; };" % real)
498 ffi.new("struct foo_s *", []) # because some mismatches show up lazily
499 except (VerificationError, ffi.error):
500 if not expect_mismatch:
501 if testing_by_size and typename != real:
502 print("ignoring mismatch between %s* and %s* even though "
503 "they have the same size" % (typename, real))
504 return
505 raise AssertionError("unexpected mismatch: %s should be accepted "
506 "as equal to %s" % (typename, real))
507 else:
508 if expect_mismatch:
509 raise AssertionError("mismatch not detected: "
510 "%s != %s" % (typename, real))
511
512 def test_struct_bad_sized_integer():
513 for typename in ['int8_t', 'int16_t', 'int32_t', 'int64_t']:
514 for real in ['int8_t', 'int16_t', 'int32_t', 'int64_t']:
515 _check_field_match(typename, real, "by_size")
516
517 def test_struct_bad_sized_float():
518 for typename in all_float_types:
519 for real in all_float_types:
520 _check_field_match(typename, real, "by_size")
521
522 def test_struct_signedness_ignored():
523 _check_field_match("int", "unsigned int", expect_mismatch=False)
524 _check_field_match("unsigned short", "signed short", expect_mismatch=False)
525
526 def test_struct_float_vs_int():
527 if sys.platform == 'win32':
528 py.test.skip("XXX fixme: only gives warnings")
529 ffi = FFI()
530 for typename in all_signed_integer_types(ffi):
531 for real in all_float_types:
532 _check_field_match(typename, real, expect_mismatch=True)
533 for typename in all_float_types:
534 for real in all_signed_integer_types(ffi):
535 _check_field_match(typename, real, expect_mismatch=True)
536
537 def test_struct_array_field():
538 ffi = FFI()
539 ffi.cdef("struct foo_s { int a[17]; ...; };")
540 ffi.verify("struct foo_s { int x; int a[17]; int y; };")
541 assert ffi.sizeof('struct foo_s') == 19 * ffi.sizeof('int')
542 s = ffi.new("struct foo_s *")
543 assert ffi.sizeof(s.a) == 17 * ffi.sizeof('int')
544
545 def test_struct_array_no_length():
546 ffi = FFI()
547 ffi.cdef("struct foo_s { int a[]; int y; ...; };\n"
548 "int bar(struct foo_s *);\n")
549 lib = ffi.verify("struct foo_s { int x; int a[17]; int y; };\n"
550 "int bar(struct foo_s *f) { return f->a[14]; }\n")
551 assert ffi.sizeof('struct foo_s') == 19 * ffi.sizeof('int')
552 s = ffi.new("struct foo_s *")
553 assert ffi.typeof(s.a) is ffi.typeof('int[]') # implicit max length
554 assert len(s.a) == 18 # max length, computed from the size and start offset
555 s.a[14] = 4242
556 assert lib.bar(s) == 4242
557 # with no declared length, out-of-bound accesses are not detected
558 s.a[17] = -521
559 assert s.y == s.a[17] == -521
560 #
561 s = ffi.new("struct foo_s *", {'a': list(range(17))})
562 assert s.a[16] == 16
563 # overflows at construction time not detected either
564 s = ffi.new("struct foo_s *", {'a': list(range(18))})
565 assert s.y == s.a[17] == 17
566
567 def test_struct_array_guess_length():
568 ffi = FFI()
569 ffi.cdef("struct foo_s { int a[...]; };")
570 ffi.verify("struct foo_s { int x; int a[17]; int y; };")
571 assert ffi.sizeof('struct foo_s') == 19 * ffi.sizeof('int')
572 s = ffi.new("struct foo_s *")
573 assert ffi.sizeof(s.a) == 17 * ffi.sizeof('int')
574 py.test.raises(IndexError, 's.a[17]')
575
576 def test_struct_array_c99_1():
577 if sys.platform == 'win32':
578 py.test.skip("requires C99")
579 ffi = FFI()
580 ffi.cdef("struct foo_s { int x; int a[]; };")
581 ffi.verify("struct foo_s { int x; int a[]; };")
582 assert ffi.sizeof('struct foo_s') == 1 * ffi.sizeof('int')
583 s = ffi.new("struct foo_s *", [424242, 4])
584 assert ffi.sizeof(ffi.typeof(s[0])) == 1 * ffi.sizeof('int')
585 assert ffi.sizeof(s[0]) == 5 * ffi.sizeof('int')
586 # ^^^ explanation: if you write in C: "char x[5];", then
587 # "sizeof(x)" will evaluate to 5. The behavior above is
588 # a generalization of that to "struct foo_s[len(a)=5] x;"
589 # if you could do that in C.
590 assert s.a[3] == 0
591 s = ffi.new("struct foo_s *", [424242, [-40, -30, -20, -10]])
592 assert ffi.sizeof(s[0]) == 5 * ffi.sizeof('int')
593 assert s.a[3] == -10
594 s = ffi.new("struct foo_s *")
595 assert ffi.sizeof(s[0]) == 1 * ffi.sizeof('int')
596 s = ffi.new("struct foo_s *", [424242])
597 assert ffi.sizeof(s[0]) == 1 * ffi.sizeof('int')
598
599 def test_struct_array_c99_2():
600 if sys.platform == 'win32':
601 py.test.skip("requires C99")
602 ffi = FFI()
603 ffi.cdef("struct foo_s { int x; int a[]; ...; };")
604 ffi.verify("struct foo_s { int x, y; int a[]; };")
605 assert ffi.sizeof('struct foo_s') == 2 * ffi.sizeof('int')
606 s = ffi.new("struct foo_s *", [424242, 4])
607 assert ffi.sizeof(s[0]) == 6 * ffi.sizeof('int')
608 assert s.a[3] == 0
609 s = ffi.new("struct foo_s *", [424242, [-40, -30, -20, -10]])
610 assert ffi.sizeof(s[0]) == 6 * ffi.sizeof('int')
611 assert s.a[3] == -10
612 s = ffi.new("struct foo_s *")
613 assert ffi.sizeof(s[0]) == 2 * ffi.sizeof('int')
614 s = ffi.new("struct foo_s *", [424242])
615 assert ffi.sizeof(s[0]) == 2 * ffi.sizeof('int')
616
617 def test_struct_ptr_to_array_field():
618 ffi = FFI()
619 ffi.cdef("struct foo_s { int (*a)[17]; ...; }; struct bar_s { ...; };")
620 ffi.verify("struct foo_s { int x; int (*a)[17]; int y; };\n"
621 "struct bar_s { int x; int *a; int y; };")
622 assert ffi.sizeof('struct foo_s') == ffi.sizeof("struct bar_s")
623 s = ffi.new("struct foo_s *")
624 assert ffi.sizeof(s.a) == ffi.sizeof('int(*)[17]') == ffi.sizeof("int *")
625
626 def test_struct_with_bitfield_exact():
627 ffi = FFI()
628 ffi.cdef("struct foo_s { int a:2, b:3; };")
629 ffi.verify("struct foo_s { int a:2, b:3; };")
630 s = ffi.new("struct foo_s *")
631 s.b = 3
632 py.test.raises(OverflowError, "s.b = 4")
633 assert s.b == 3
634
635 def test_struct_with_bitfield_enum():
636 ffi = FFI()
637 code = """
638 typedef enum { AA, BB, CC } foo_e;
639 typedef struct { foo_e f:2; } foo_s;
640 """
641 ffi.cdef(code)
642 ffi.verify(code)
643 s = ffi.new("foo_s *")
644 s.f = 1
645 assert s.f == 1
646 if int(ffi.cast("foo_e", -1)) < 0:
647 two = -2
648 else:
649 two = 2
650 s.f = two
651 assert s.f == two
652
653 def test_unsupported_struct_with_bitfield_ellipsis():
654 ffi = FFI()
655 py.test.raises(NotImplementedError, ffi.cdef,
656 "struct foo_s { int a:2, b:3; ...; };")
657
658 def test_global_constants():
659 ffi = FFI()
660 # use 'static const int', as generally documented, although in this
661 # case the 'static' is completely ignored.
662 ffi.cdef("static const int AA, BB, CC, DD;")
663 lib = ffi.verify("#define AA 42\n"
664 "#define BB (-43) // blah\n"
665 "#define CC (22*2) /* foobar */\n"
666 "#define DD ((unsigned int)142) /* foo\nbar */\n")
667 assert lib.AA == 42
668 assert lib.BB == -43
669 assert lib.CC == 44
670 assert lib.DD == 142
671
672 def test_global_const_int_size():
673 # integer constants: ignore the declared type, always just use the value
674 for value in [-2**63, -2**31, -2**15,
675 2**15-1, 2**15, 2**31-1, 2**31, 2**32-1, 2**32,
676 2**63-1, 2**63, 2**64-1]:
677 ffi = FFI()
678 if value == int(ffi.cast("long long", value)):
679 if value < 0:
680 vstr = '(-%dLL-1)' % (~value,)
681 else:
682 vstr = '%dLL' % value
683 elif value == int(ffi.cast("unsigned long long", value)):
684 vstr = '%dULL' % value
685 else:
686 raise AssertionError(value)
687 ffi.cdef("static const unsigned short AA;")
688 lib = ffi.verify("#define AA %s\n" % vstr)
689 assert lib.AA == value
690 assert type(lib.AA) is type(int(lib.AA))
691
692 def test_global_constants_non_int():
693 ffi = FFI()
694 ffi.cdef("static char *const PP;")
695 lib = ffi.verify('static char *const PP = "testing!";\n')
696 assert ffi.typeof(lib.PP) == ffi.typeof("char *")
697 assert ffi.string(lib.PP) == b"testing!"
698
699 def test_nonfull_enum():
700 ffi = FFI()
701 ffi.cdef("enum ee { EE1, EE2, EE3, ... \n \t };")
702 py.test.raises(VerificationMissing, ffi.cast, 'enum ee', 'EE2')
703 ffi.verify("enum ee { EE1=10, EE2, EE3=-10, EE4 };")
704 assert ffi.string(ffi.cast('enum ee', 11)) == "EE2"
705 assert ffi.string(ffi.cast('enum ee', -10)) == "EE3"
706 #
707 assert ffi.typeof("enum ee").relements == {'EE1': 10, 'EE2': 11, 'EE3': -10}
708 assert ffi.typeof("enum ee").elements == {10: 'EE1', 11: 'EE2', -10: 'EE3'}
709
710 def test_full_enum():
711 ffi = FFI()
712 ffi.cdef("enum ee { EE1, EE2, EE3 };")
713 lib = ffi.verify("enum ee { EE1, EE2, EE3 };")
714 assert [lib.EE1, lib.EE2, lib.EE3] == [0, 1, 2]
715
716 def test_enum_usage():
717 ffi = FFI()
718 ffi.cdef("enum ee { EE1,EE2 }; typedef struct { enum ee x; } *sp;")
719 lib = ffi.verify("enum ee { EE1,EE2 }; typedef struct { enum ee x; } *sp;")
720 assert lib.EE2 == 1
721 s = ffi.new("sp", [lib.EE2])
722 assert s.x == 1
723 s.x = 17
724 assert s.x == 17
725
726 def test_anonymous_enum():
727 ffi = FFI()
728 ffi.cdef("enum { EE1 }; enum { EE2, EE3 };")
729 lib = ffi.verify("enum { EE1 }; enum { EE2, EE3 };")
730 assert lib.EE1 == 0
731 assert lib.EE2 == 0
732 assert lib.EE3 == 1
733
734 def test_nonfull_anonymous_enum():
735 ffi = FFI()
736 ffi.cdef("enum { EE1, ... }; enum { EE3, ... };")
737 lib = ffi.verify("enum { EE2, EE1 }; enum { EE3 };")
738 assert lib.EE1 == 1
739 assert lib.EE3 == 0
740
741 def test_nonfull_enum_syntax2():
742 ffi = FFI()
743 ffi.cdef("enum ee { EE1, EE2=\t..., EE3 };")
744 py.test.raises(VerificationMissing, ffi.cast, 'enum ee', 'EE1')
745 ffi.verify("enum ee { EE1=10, EE2, EE3=-10, EE4 };")
746 assert ffi.string(ffi.cast('enum ee', 11)) == 'EE2'
747 assert ffi.string(ffi.cast('enum ee', -10)) == 'EE3'
748 #
749 ffi = FFI()
750 ffi.cdef("enum ee { EE1, EE2=\t... };")
751 py.test.raises(VerificationMissing, ffi.cast, 'enum ee', 'EE1')
752 ffi.verify("enum ee { EE1=10, EE2, EE3=-10, EE4 };")
753 assert ffi.string(ffi.cast('enum ee', 11)) == 'EE2'
754 #
755 ffi = FFI()
756 ffi.cdef("enum ee2 { EE4=..., EE5=..., ... };")
757 ffi.verify("enum ee2 { EE4=-1234-5, EE5 }; ")
758 assert ffi.string(ffi.cast('enum ee2', -1239)) == 'EE4'
759 assert ffi.string(ffi.cast('enum ee2', -1238)) == 'EE5'
760
761 def test_get_set_errno():
762 ffi = FFI()
763 ffi.cdef("int foo(int);")
764 lib = ffi.verify("""
765 static int foo(int x)
766 {
767 errno += 1;
768 return x * 7;
769 }
770 """)
771 ffi.errno = 15
772 assert lib.foo(6) == 42
773 assert ffi.errno == 16
774
775 def test_define_int():
776 ffi = FFI()
777 ffi.cdef("#define FOO ...\n"
778 "\t#\tdefine\tBAR\t...\t\n"
779 "#define BAZ ...\n")
780 lib = ffi.verify("#define FOO 42\n"
781 "#define BAR (-44)\n"
782 "#define BAZ 0xffffffffffffffffULL\n")
783 assert lib.FOO == 42
784 assert lib.BAR == -44
785 assert lib.BAZ == 0xffffffffffffffff
786
787 def test_access_variable():
788 ffi = FFI()
789 ffi.cdef("int foo(void);\n"
790 "int somenumber;")
791 lib = ffi.verify("""
792 static int somenumber = 2;
793 static int foo(void) {
794 return somenumber * 7;
795 }
796 """)
797 assert lib.somenumber == 2
798 assert lib.foo() == 14
799 lib.somenumber = -6
800 assert lib.foo() == -42
801 assert lib.somenumber == -6
802 lib.somenumber = 2 # reset for the next run, if any
803
804 def test_access_address_of_variable():
805 # access the address of 'somenumber': need a trick
806 ffi = FFI()
807 ffi.cdef("int somenumber; static int *const somenumberptr;")
808 lib = ffi.verify("""
809 static int somenumber = 2;
810 #define somenumberptr (&somenumber)
811 """)
812 assert lib.somenumber == 2
813 lib.somenumberptr[0] = 42
814 assert lib.somenumber == 42
815 lib.somenumber = 2 # reset for the next run, if any
816
817 def test_access_array_variable(length=5):
818 ffi = FFI()
819 ffi.cdef("int foo(int);\n"
820 "int somenumber[%s];" % (length,))
821 lib = ffi.verify("""
822 static int somenumber[] = {2, 2, 3, 4, 5};
823 static int foo(int i) {
824 return somenumber[i] * 7;
825 }
826 """)
827 if length == '':
828 # a global variable of an unknown array length is implicitly
829 # transformed into a global pointer variable, because we can only
830 # work with array instances whose length we know. using a pointer
831 # instead of an array gives the correct effects.
832 assert repr(lib.somenumber).startswith("<cdata 'int *' 0x")
833 py.test.raises(TypeError, len, lib.somenumber)
834 else:
835 assert repr(lib.somenumber).startswith("<cdata 'int[%s]' 0x" % length)
836 assert len(lib.somenumber) == 5
837 assert lib.somenumber[3] == 4
838 assert lib.foo(3) == 28
839 lib.somenumber[3] = -6
840 assert lib.foo(3) == -42
841 assert lib.somenumber[3] == -6
842 assert lib.somenumber[4] == 5
843 lib.somenumber[3] = 4 # reset for the next run, if any
844
845 def test_access_array_variable_length_hidden():
846 test_access_array_variable(length='')
847
848 def test_access_struct_variable():
849 ffi = FFI()
850 ffi.cdef("struct foo { int x; ...; };\n"
851 "int foo(int);\n"
852 "struct foo stuff;")
853 lib = ffi.verify("""
854 struct foo { int x, y, z; };
855 static struct foo stuff = {2, 5, 8};
856 static int foo(int i) {
857 switch (i) {
858 case 0: return stuff.x * 7;
859 case 1: return stuff.y * 7;
860 case 2: return stuff.z * 7;
861 }
862 return -1;
863 }
864 """)
865 assert lib.stuff.x == 2
866 assert lib.foo(0) == 14
867 assert lib.foo(1) == 35
868 assert lib.foo(2) == 56
869 lib.stuff.x = -6
870 assert lib.foo(0) == -42
871 assert lib.foo(1) == 35
872 lib.stuff.x = 2 # reset for the next run, if any
873
874 def test_access_callback():
875 ffi = FFI()
876 ffi.cdef("int (*cb)(int);\n"
877 "int foo(int);\n"
878 "void reset_cb(void);")
879 lib = ffi.verify("""
880 static int g(int x) { return x * 7; }
881 static int (*cb)(int);
882 static int foo(int i) { return cb(i) - 1; }
883 static void reset_cb(void) { cb = g; }
884 """)
885 lib.reset_cb()
886 assert lib.foo(6) == 41
887 my_callback = ffi.callback("int(*)(int)", lambda n: n * 222)
888 lib.cb = my_callback
889 assert lib.foo(4) == 887
890
891 def test_access_callback_function_typedef():
892 ffi = FFI()
893 ffi.cdef("typedef int mycallback_t(int);\n"
894 "mycallback_t *cb;\n"
895 "int foo(int);\n"
896 "void reset_cb(void);")
897 lib = ffi.verify("""
898 static int g(int x) { return x * 7; }
899 static int (*cb)(int);
900 static int foo(int i) { return cb(i) - 1; }
901 static void reset_cb(void) { cb = g; }
902 """)
903 lib.reset_cb()
904 assert lib.foo(6) == 41
905 my_callback = ffi.callback("int(*)(int)", lambda n: n * 222)
906 lib.cb = my_callback
907 assert lib.foo(4) == 887
908
909 def test_call_with_struct_ptr():
910 ffi = FFI()
911 ffi.cdef("typedef struct { int x; ...; } foo_t; int foo(foo_t *);")
912 lib = ffi.verify("""
913 typedef struct { int y, x; } foo_t;
914 static int foo(foo_t *f) { return f->x * 7; }
915 """)
916 f = ffi.new("foo_t *")
917 f.x = 6
918 assert lib.foo(f) == 42
919
920 def test_unknown_type():
921 ffi = FFI()
922 ffi.cdef("""
923 typedef ... token_t;
924 int foo(token_t *);
925 #define TOKEN_SIZE ...
926 """)
927 lib = ffi.verify("""
928 typedef float token_t;
929 static int foo(token_t *tk) {
930 if (!tk)
931 return -42;
932 *tk += 1.601f;
933 return (int)*tk;
934 }
935 #define TOKEN_SIZE sizeof(token_t)
936 """)
937 # we cannot let ffi.new("token_t *") work, because we don't know ahead of
938 # time if it's ok to ask 'sizeof(token_t)' in the C code or not.
939 # See test_unknown_type_2. Workaround.
940 tkmem = ffi.new("char[]", lib.TOKEN_SIZE) # zero-initialized
941 tk = ffi.cast("token_t *", tkmem)
942 results = [lib.foo(tk) for i in range(6)]
943 assert results == [1, 3, 4, 6, 8, 9]
944 assert lib.foo(ffi.NULL) == -42
945
946 def test_unknown_type_2():
947 ffi = FFI()
948 ffi.cdef("typedef ... token_t;")
949 lib = ffi.verify("typedef struct token_s token_t;")
950 # assert did not crash, even though 'sizeof(token_t)' is not valid in C.
951
952 def test_unknown_type_3():
953 ffi = FFI()
954 ffi.cdef("""
955 typedef ... *token_p;
956 token_p foo(token_p);
957 """)
958 lib = ffi.verify("""
959 typedef struct _token_s *token_p;
960 token_p foo(token_p arg) {
961 if (arg)
962 return (token_p)0x12347;
963 else
964 return (token_p)0x12345;
965 }
966 """)
967 p = lib.foo(ffi.NULL)
968 assert int(ffi.cast("intptr_t", p)) == 0x12345
969 q = lib.foo(p)
970 assert int(ffi.cast("intptr_t", q)) == 0x12347
971
972 def test_varargs():
973 ffi = FFI()
974 ffi.cdef("int foo(int x, ...);")
975 lib = ffi.verify("""
976 int foo(int x, ...) {
977 va_list vargs;
978 va_start(vargs, x);
979 x -= va_arg(vargs, int);
980 x -= va_arg(vargs, int);
981 va_end(vargs);
982 return x;
983 }
984 """)
985 assert lib.foo(50, ffi.cast("int", 5), ffi.cast("int", 3)) == 42
986
987 def test_varargs_exact():
988 if sys.platform == 'win32':
989 py.test.skip("XXX fixme: only gives warnings")
990 ffi = FFI()
991 ffi.cdef("int foo(int x, ...);")
992 py.test.raises(VerificationError, ffi.verify, """
993 int foo(long long x, ...) {
994 return x;
995 }
996 """)
997
998 def test_varargs_struct():
999 ffi = FFI()
1000 ffi.cdef("struct foo_s { char a; int b; }; int foo(int x, ...);")
1001 lib = ffi.verify("""
1002 struct foo_s {
1003 char a; int b;
1004 };
1005 int foo(int x, ...) {
1006 va_list vargs;
1007 struct foo_s s;
1008 va_start(vargs, x);
1009 s = va_arg(vargs, struct foo_s);
1010 va_end(vargs);
1011 return s.a - s.b;
1012 }
1013 """)
1014 s = ffi.new("struct foo_s *", [b'B', 1])
1015 assert lib.foo(50, s[0]) == ord('A')
1016
1017 def test_autofilled_struct_as_argument():
1018 ffi = FFI()
1019 ffi.cdef("struct foo_s { long a; double b; ...; };\n"
1020 "int foo(struct foo_s);")
1021 lib = ffi.verify("""
1022 struct foo_s {
1023 double b;
1024 long a;
1025 };
1026 int foo(struct foo_s s) {
1027 return (int)s.a - (int)s.b;
1028 }
1029 """)
1030 s = ffi.new("struct foo_s *", [100, 1])
1031 assert lib.foo(s[0]) == 99
1032 assert lib.foo([100, 1]) == 99
1033
1034 def test_autofilled_struct_as_argument_dynamic():
1035 ffi = FFI()
1036 ffi.cdef("struct foo_s { long a; ...; };\n"
1037 "int (*foo)(struct foo_s);")
1038 lib = ffi.verify("""
1039 struct foo_s {
1040 double b;
1041 long a;
1042 };
1043 int foo1(struct foo_s s) {
1044 return (int)s.a - (int)s.b;
1045 }
1046 int (*foo)(struct foo_s s) = &foo1;
1047 """)
1048 e = py.test.raises(NotImplementedError, lib.foo, "?")
1049 msg = ("ctype 'struct foo_s' not supported as argument. It is a struct "
1050 'declared with "...;", but the C calling convention may depend on '
1051 "the missing fields; or, it contains anonymous struct/unions. "
1052 "Such structs are only supported as argument "
1053 "if the function is 'API mode' and non-variadic (i.e. declared "
1054 "inside ffibuilder.cdef()+ffibuilder.set_source() and not taking "
1055 "a final '...' argument)")
1056 assert str(e.value) == msg
1057
1058 def test_func_returns_struct():
1059 ffi = FFI()
1060 ffi.cdef("""
1061 struct foo_s { int aa, bb; };
1062 struct foo_s foo(int a, int b);
1063 """)
1064 lib = ffi.verify("""
1065 struct foo_s { int aa, bb; };
1066 struct foo_s foo(int a, int b) {
1067 struct foo_s r;
1068 r.aa = a*a;
1069 r.bb = b*b;
1070 return r;
1071 }
1072 """)
1073 s = lib.foo(6, 7)
1074 assert repr(s) == "<cdata 'struct foo_s' owning 8 bytes>"
1075 assert s.aa == 36
1076 assert s.bb == 49
1077
1078 def test_func_as_funcptr():
1079 ffi = FFI()
1080 ffi.cdef("int *(*const fooptr)(void);")
1081 lib = ffi.verify("""
1082 int *foo(void) {
1083 return (int*)"foobar";
1084 }
1085 int *(*fooptr)(void) = foo;
1086 """)
1087 foochar = ffi.cast("char *(*)(void)", lib.fooptr)
1088 s = foochar()
1089 assert ffi.string(s) == b"foobar"
1090
1091 def test_funcptr_as_argument():
1092 ffi = FFI()
1093 ffi.cdef("""
1094 void qsort(void *base, size_t nel, size_t width,
1095 int (*compar)(const void *, const void *));
1096 """)
1097 ffi.verify("#include <stdlib.h>")
1098
1099 def test_func_as_argument():
1100 ffi = FFI()
1101 ffi.cdef("""
1102 void qsort(void *base, size_t nel, size_t width,
1103 int compar(const void *, const void *));
1104 """)
1105 ffi.verify("#include <stdlib.h>")
1106
1107 def test_array_as_argument():
1108 ffi = FFI()
1109 ffi.cdef("""
1110 size_t strlen(char string[]);
1111 """)
1112 ffi.verify("#include <string.h>")
1113
1114 def test_enum_as_argument():
1115 ffi = FFI()
1116 ffi.cdef("""
1117 enum foo_e { AA, BB, ... };
1118 int foo_func(enum foo_e);
1119 """)
1120 lib = ffi.verify("""
1121 enum foo_e { AA, CC, BB };
1122 int foo_func(enum foo_e e) { return (int)e; }
1123 """)
1124 assert lib.foo_func(lib.BB) == 2
1125 py.test.raises(TypeError, lib.foo_func, "BB")
1126
1127 def test_enum_as_function_result():
1128 ffi = FFI()
1129 ffi.cdef("""
1130 enum foo_e { AA, BB, ... };
1131 enum foo_e foo_func(int x);
1132 """)
1133 lib = ffi.verify("""
1134 enum foo_e { AA, CC, BB };
1135 enum foo_e foo_func(int x) { return (enum foo_e)x; }
1136 """)
1137 assert lib.foo_func(lib.BB) == lib.BB == 2
1138
1139 def test_enum_values():
1140 ffi = FFI()
1141 ffi.cdef("enum enum1_e { AA, BB };")
1142 lib = ffi.verify("enum enum1_e { AA, BB };")
1143 assert lib.AA == 0
1144 assert lib.BB == 1
1145 assert ffi.string(ffi.cast("enum enum1_e", 1)) == 'BB'
1146
1147 def test_typedef_complete_enum():
1148 ffi = FFI()
1149 ffi.cdef("typedef enum { AA, BB } enum1_t;")
1150 lib = ffi.verify("typedef enum { AA, BB } enum1_t;")
1151 assert ffi.string(ffi.cast("enum1_t", 1)) == 'BB'
1152 assert lib.AA == 0
1153 assert lib.BB == 1
1154
1155 def test_typedef_broken_complete_enum():
1156 # xxx this is broken in old cffis, but works with recompiler.py
1157 ffi = FFI()
1158 ffi.cdef("typedef enum { AA, BB } enum1_t;")
1159 lib = ffi.verify("typedef enum { AA, CC, BB } enum1_t;")
1160 assert lib.AA == 0
1161 assert lib.BB == 2
1162
1163 def test_typedef_incomplete_enum():
1164 ffi = FFI()
1165 ffi.cdef("typedef enum { AA, BB, ... } enum1_t;")
1166 lib = ffi.verify("typedef enum { AA, CC, BB } enum1_t;")
1167 assert ffi.string(ffi.cast("enum1_t", 1)) == '1'
1168 assert ffi.string(ffi.cast("enum1_t", 2)) == 'BB'
1169 assert lib.AA == 0
1170 assert lib.BB == 2
1171
1172 def test_typedef_enum_as_argument():
1173 ffi = FFI()
1174 ffi.cdef("""
1175 typedef enum { AA, BB, ... } foo_t;
1176 int foo_func(foo_t);
1177 """)
1178 lib = ffi.verify("""
1179 typedef enum { AA, CC, BB } foo_t;
1180 int foo_func(foo_t e) { return (int)e; }
1181 """)
1182 assert lib.foo_func(lib.BB) == lib.BB == 2
1183 py.test.raises(TypeError, lib.foo_func, "BB")
1184
1185 def test_typedef_enum_as_function_result():
1186 ffi = FFI()
1187 ffi.cdef("""
1188 typedef enum { AA, BB, ... } foo_t;
1189 foo_t foo_func(int x);
1190 """)
1191 lib = ffi.verify("""
1192 typedef enum { AA, CC, BB } foo_t;
1193 foo_t foo_func(int x) { return (foo_t)x; }
1194 """)
1195 assert lib.foo_func(lib.BB) == lib.BB == 2
1196
1197 def test_function_typedef():
1198 ffi = FFI()
1199 ffi.cdef("""
1200 typedef double func_t(double);
1201 func_t sin;
1202 """)
1203 lib = ffi.verify('#include <math.h>', libraries=lib_m)
1204 assert lib.sin(1.23) == math.sin(1.23)
1205
1206 def test_opaque_integer_as_function_result():
1207 #import platform
1208 #if platform.machine().startswith('sparc'):
1209 # py.test.skip('Breaks horribly on sparc (SIGILL + corrupted stack)')
1210 #elif platform.machine() == 'mips64' and sys.maxsize > 2**32:
1211 # py.test.skip('Segfaults on mips64el')
1212 # XXX bad abuse of "struct { ...; }". It only works a bit by chance
1213 # anyway. XXX think about something better :-(
1214 ffi = FFI()
1215 ffi.cdef("""
1216 typedef struct { ...; } myhandle_t;
1217 myhandle_t foo(void);
1218 """)
1219 lib = ffi.verify("""
1220 typedef short myhandle_t;
1221 myhandle_t foo(void) { return 42; }
1222 """)
1223 h = lib.foo()
1224 assert ffi.sizeof(h) == ffi.sizeof("short")
1225
1226 def test_return_partial_struct():
1227 ffi = FFI()
1228 ffi.cdef("""
1229 typedef struct { int x; ...; } foo_t;
1230 foo_t foo(void);
1231 """)
1232 lib = ffi.verify("""
1233 typedef struct { int y, x; } foo_t;
1234 foo_t foo(void) { foo_t r = { 45, 81 }; return r; }
1235 """)
1236 h = lib.foo()
1237 assert ffi.sizeof(h) == 2 * ffi.sizeof("int")
1238 assert h.x == 81
1239
1240 def test_take_and_return_partial_structs():
1241 ffi = FFI()
1242 ffi.cdef("""
1243 typedef struct { int x; ...; } foo_t;
1244 foo_t foo(foo_t, foo_t);
1245 """)
1246 lib = ffi.verify("""
1247 typedef struct { int y, x; } foo_t;
1248 foo_t foo(foo_t a, foo_t b) {
1249 foo_t r = { 100, a.x * 5 + b.x * 7 };
1250 return r;
1251 }
1252 """)
1253 args = ffi.new("foo_t[3]")
1254 args[0].x = 1000
1255 args[2].x = -498
1256 h = lib.foo(args[0], args[2])
1257 assert ffi.sizeof(h) == 2 * ffi.sizeof("int")
1258 assert h.x == 1000 * 5 - 498 * 7
1259
1260 def test_cannot_name_struct_type():
1261 ffi = FFI()
1262 ffi.cdef("typedef struct { int x; } **sp; void foo(sp);")
1263 e = py.test.raises(VerificationError, ffi.verify,
1264 "typedef struct { int x; } **sp; void foo(sp x) { }")
1265 assert 'in argument of foo: unknown type name' in str(e.value)
1266
1267 def test_dont_check_unnamable_fields():
1268 ffi = FFI()
1269 ffi.cdef("struct foo_s { struct { int x; } someone; };")
1270 ffi.verify("struct foo_s { struct { int x; } someone; };")
1271 # assert did not crash
1272
1273 def test_nested_anonymous_struct_exact():
1274 if sys.platform == 'win32':
1275 py.test.skip("nested anonymous struct/union")
1276 ffi = FFI()
1277 ffi.cdef("""
1278 struct foo_s { struct { int a; char b; }; union { char c, d; }; };
1279 """)
1280 assert ffi.offsetof("struct foo_s", "c") == 2 * ffi.sizeof("int")
1281 assert ffi.sizeof("struct foo_s") == 3 * ffi.sizeof("int")
1282 ffi.verify("""
1283 struct foo_s { struct { int a; char b; }; union { char c, d; }; };
1284 """)
1285 p = ffi.new("struct foo_s *")
1286 assert ffi.sizeof(p[0]) == 3 * ffi.sizeof("int") # with alignment
1287 p.a = 1234567
1288 p.b = b'X'
1289 p.c = b'Y'
1290 assert p.a == 1234567
1291 assert p.b == b'X'
1292 assert p.c == b'Y'
1293 assert p.d == b'Y'
1294
1295 def test_nested_anonymous_struct_exact_error():
1296 if sys.platform == 'win32':
1297 py.test.skip("nested anonymous struct/union")
1298 ffi = FFI()
1299 ffi.cdef("""
1300 struct foo_s { struct { int a; char b; }; union { char c, d; }; };
1301 """)
1302 py.test.raises(VerificationError, ffi.verify, """
1303 struct foo_s { struct { int a; short b; }; union { char c, d; }; };
1304 """)
1305 # works fine now
1306 #py.test.raises(VerificationError, ffi.verify, """
1307 # struct foo_s { struct { int a; char e, b; }; union { char c, d; }; };
1308 #""")
1309
1310 def test_nested_anonymous_struct_inexact_1():
1311 ffi = FFI()
1312 ffi.cdef("""
1313 struct foo_s { struct { char b; ...; }; union { char c, d; }; };
1314 """)
1315 ffi.verify("""
1316 struct foo_s { int a, padding; char c, d, b; };
1317 """)
1318 assert ffi.sizeof("struct foo_s") == 3 * ffi.sizeof("int")
1319
1320 def test_nested_anonymous_struct_inexact_2():
1321 ffi = FFI()
1322 ffi.cdef("""
1323 struct foo_s { union { char c, d; }; struct { int a; char b; }; ...; };
1324 """)
1325 ffi.verify("""
1326 struct foo_s { int a, padding; char c, d, b; };
1327 """)
1328 assert ffi.sizeof("struct foo_s") == 3 * ffi.sizeof("int")
1329
1330 def test_ffi_union():
1331 ffi = FFI()
1332 ffi.cdef("union foo_u { char x; long *z; };")
1333 ffi.verify("union foo_u { char x; int y; long *z; };")
1334
1335 def test_ffi_union_partial():
1336 ffi = FFI()
1337 ffi.cdef("union foo_u { char x; ...; };")
1338 ffi.verify("union foo_u { char x; int y; };")
1339 assert ffi.sizeof("union foo_u") == 4
1340
1341 def test_ffi_union_with_partial_struct():
1342 ffi = FFI()
1343 ffi.cdef("struct foo_s { int x; ...; }; union foo_u { struct foo_s s; };")
1344 ffi.verify("struct foo_s { int a; int x; }; "
1345 "union foo_u { char b[32]; struct foo_s s; };")
1346 assert ffi.sizeof("struct foo_s") == 8
1347 assert ffi.sizeof("union foo_u") == 32
1348
1349 def test_ffi_union_partial_2():
1350 ffi = FFI()
1351 ffi.cdef("typedef union { char x; ...; } u1;")
1352 ffi.verify("typedef union { char x; int y; } u1;")
1353 assert ffi.sizeof("u1") == 4
1354
1355 def test_ffi_union_with_partial_struct_2():
1356 ffi = FFI()
1357 ffi.cdef("typedef struct { int x; ...; } s1;"
1358 "typedef union { s1 s; } u1;")
1359 ffi.verify("typedef struct { int a; int x; } s1; "
1360 "typedef union { char b[32]; s1 s; } u1;")
1361 assert ffi.sizeof("s1") == 8
1362 assert ffi.sizeof("u1") == 32
1363 assert ffi.offsetof("u1", "s") == 0
1364
1365 def test_ffi_struct_packed():
1366 if sys.platform == 'win32':
1367 py.test.skip("needs a GCC extension")
1368 ffi = FFI()
1369 ffi.cdef("struct foo_s { int b; ...; };")
1370 ffi.verify("""
1371 struct foo_s {
1372 char a;
1373 int b;
1374 } __attribute__((packed));
1375 """)
1376
1377 def test_tmpdir():
1378 import tempfile, os
1379 from extra_tests.cffi_tests.udir import udir
1380 tmpdir = tempfile.mkdtemp(dir=str(udir))
1381 ffi = FFI()
1382 ffi.cdef("int foo(int);")
1383 lib = ffi.verify("int foo(int a) { return a + 42; }", tmpdir=tmpdir)
1384 assert os.listdir(tmpdir)
1385 assert lib.foo(100) == 142
1386
1387 def test_relative_to():
1388 py.test.skip("not available")
1389 import tempfile, os
1390 from extra_tests.cffi_tests.udir import udir
1391 tmpdir = tempfile.mkdtemp(dir=str(udir))
1392 ffi = FFI()
1393 ffi.cdef("int foo(int);")
1394 f = open(os.path.join(tmpdir, 'foo.h'), 'w')
1395 f.write("int foo(int a) { return a + 42; }\n")
1396 f.close()
1397 lib = ffi.verify('#include "foo.h"',
1398 include_dirs=['.'],
1399 relative_to=os.path.join(tmpdir, 'x'))
1400 assert lib.foo(100) == 142
1401
1402 def test_bug1():
1403 ffi = FFI()
1404 ffi.cdef("""
1405 typedef struct tdlhandle_s { ...; } *tdl_handle_t;
1406 typedef struct my_error_code_ {
1407 tdl_handle_t *rh;
1408 } my_error_code_t;
1409 """)
1410 ffi.verify("""
1411 typedef struct tdlhandle_s { int foo; } *tdl_handle_t;
1412 typedef struct my_error_code_ {
1413 tdl_handle_t *rh;
1414 } my_error_code_t;
1415 """)
1416
1417 def test_bool():
1418 if sys.platform == 'win32':
1419 py.test.skip("_Bool not in MSVC")
1420 ffi = FFI()
1421 ffi.cdef("struct foo_s { _Bool x; };"
1422 "_Bool foo(_Bool); _Bool (*foop)(_Bool);")
1423 lib = ffi.verify("""
1424 struct foo_s { _Bool x; };
1425 int foo(int arg) {
1426 return !arg;
1427 }
1428 _Bool _foofunc(_Bool x) {
1429 return !x;
1430 }
1431 _Bool (*foop)(_Bool) = _foofunc;
1432 """)
1433 p = ffi.new("struct foo_s *")
1434 p.x = 1
1435 assert p.x is True
1436 py.test.raises(OverflowError, "p.x = -1")
1437 py.test.raises(TypeError, "p.x = 0.0")
1438 assert lib.foop(1) is False
1439 assert lib.foop(True) is False
1440 assert lib.foop(0) is True
1441 py.test.raises(OverflowError, lib.foop, 42)
1442 py.test.raises(TypeError, lib.foop, 0.0)
1443 assert lib.foo(1) is False
1444 assert lib.foo(True) is False
1445 assert lib.foo(0) is True
1446 py.test.raises(OverflowError, lib.foo, 42)
1447 py.test.raises(TypeError, lib.foo, 0.0)
1448 assert int(ffi.cast("_Bool", long(1))) == 1
1449 assert int(ffi.cast("_Bool", long(0))) == 0
1450 assert int(ffi.cast("_Bool", long(-1))) == 1
1451 assert int(ffi.cast("_Bool", 10**200)) == 1
1452 assert int(ffi.cast("_Bool", 10**40000)) == 1
1453 #
1454 class Foo(object):
1455 def __int__(self):
1456 self.seen = 1
1457 return result
1458 f = Foo()
1459 f.seen = 0
1460 result = 42
1461 assert int(ffi.cast("_Bool", f)) == 1
1462 assert f.seen
1463 f.seen = 0
1464 result = 0
1465 assert int(ffi.cast("_Bool", f)) == 0
1466 assert f.seen
1467 #
1468 py.test.raises(TypeError, ffi.cast, "_Bool", [])
1469
1470 def test_bool_on_long_double():
1471 if sys.platform == 'win32':
1472 py.test.skip("_Bool not in MSVC")
1473 f = 1E-250
1474 if f == 0.0 or f*f != 0.0:
1475 py.test.skip("unexpected precision")
1476 ffi = FFI()
1477 ffi.cdef("long double square(long double f); _Bool opposite(_Bool);")
1478 lib = ffi.verify("long double square(long double f) { return f*f; }\n"
1479 "_Bool opposite(_Bool x) { return !x; }")
1480 f0 = lib.square(0.0)
1481 f2 = lib.square(f)
1482 f3 = lib.square(f * 2.0)
1483 if repr(f2) == repr(f3):
1484 py.test.skip("long double doesn't have enough precision")
1485 assert float(f0) == float(f2) == float(f3) == 0.0 # too tiny for 'double'
1486 assert int(ffi.cast("_Bool", f2)) == 1
1487 assert int(ffi.cast("_Bool", f3)) == 1
1488 assert int(ffi.cast("_Bool", f0)) == 0
1489 py.test.raises(TypeError, lib.opposite, f2)
1490
1491 def test_cannot_pass_float():
1492 for basetype in ['char', 'short', 'int', 'long', 'long long']:
1493 for sign in ['signed', 'unsigned']:
1494 type = '%s %s' % (sign, basetype)
1495 ffi = FFI()
1496 ffi.cdef("struct foo_s { %s x; };\n"
1497 "int foo(%s);" % (type, type))
1498 lib = ffi.verify("""
1499 struct foo_s { %s x; };
1500 int foo(%s arg) {
1501 return !arg;
1502 }
1503 """ % (type, type))
1504 p = ffi.new("struct foo_s *")
1505 py.test.raises(TypeError, "p.x = 0.0")
1506 assert lib.foo(42) == 0
1507 assert lib.foo(0) == 1
1508 py.test.raises(TypeError, lib.foo, 0.0)
1509
1510 def test_addressof():
1511 ffi = FFI()
1512 ffi.cdef("""
1513 struct point_s { int x, y; };
1514 struct foo_s { int z; struct point_s point; };
1515 struct point_s sum_coord(struct point_s *);
1516 """)
1517 lib = ffi.verify("""
1518 struct point_s { int x, y; };
1519 struct foo_s { int z; struct point_s point; };
1520 struct point_s sum_coord(struct point_s *point) {
1521 struct point_s r;
1522 r.x = point->x + point->y;
1523 r.y = point->x - point->y;
1524 return r;
1525 }
1526 """)
1527 p = ffi.new("struct foo_s *")
1528 p.point.x = 16
1529 p.point.y = 9
1530 py.test.raises(TypeError, lib.sum_coord, p.point)
1531 res = lib.sum_coord(ffi.addressof(p.point))
1532 assert res.x == 25
1533 assert res.y == 7
1534 res2 = lib.sum_coord(ffi.addressof(res))
1535 assert res2.x == 32
1536 assert res2.y == 18
1537 py.test.raises(TypeError, lib.sum_coord, res2)
1538
1539 def test_callback_in_thread():
1540 py.test.xfail("adapt or remove")
1541 if sys.platform == 'win32':
1542 py.test.skip("pthread only")
1543 import os, subprocess, imp
1544 arg = os.path.join(os.path.dirname(__file__), 'callback_in_thread.py')
1545 g = subprocess.Popen([sys.executable, arg,
1546 os.path.dirname(imp.find_module('cffi')[1])])
1547 result = g.wait()
1548 assert result == 0
1549
1550 def test_keepalive_lib():
1551 py.test.xfail("adapt or remove")
1552 ffi = FFI()
1553 ffi.cdef("int foobar(void);")
1554 lib = ffi.verify("int foobar(void) { return 42; }")
1555 func = lib.foobar
1556 ffi_r = weakref.ref(ffi)
1557 lib_r = weakref.ref(lib)
1558 del ffi
1559 import gc; gc.collect() # lib stays alive
1560 assert lib_r() is not None
1561 assert ffi_r() is not None
1562 assert func() == 42
1563
1564 def test_keepalive_ffi():
1565 py.test.xfail("adapt or remove")
1566 ffi = FFI()
1567 ffi.cdef("int foobar(void);")
1568 lib = ffi.verify("int foobar(void) { return 42; }")
1569 func = lib.foobar
1570 ffi_r = weakref.ref(ffi)
1571 lib_r = weakref.ref(lib)
1572 del lib
1573 import gc; gc.collect() # ffi stays alive
1574 assert ffi_r() is not None
1575 assert lib_r() is not None
1576 assert func() == 42
1577
1578 def test_FILE_stored_in_stdout():
1579 if not sys.platform.startswith('linux'):
1580 py.test.skip("likely, we cannot assign to stdout")
1581 ffi = FFI()
1582 ffi.cdef("int printf(const char *, ...); FILE *setstdout(FILE *);")
1583 lib = ffi.verify("""
1584 #include <stdio.h>
1585 FILE *setstdout(FILE *f) {
1586 FILE *result = stdout;
1587 stdout = f;
1588 return result;
1589 }
1590 """)
1591 import os
1592 fdr, fdw = os.pipe()
1593 fw1 = os.fdopen(fdw, 'wb', 256)
1594 old_stdout = lib.setstdout(fw1)
1595 try:
1596 #
1597 fw1.write(b"X")
1598 r = lib.printf(b"hello, %d!\n", ffi.cast("int", 42))
1599 fw1.close()
1600 assert r == len("hello, 42!\n")
1601 #
1602 finally:
1603 lib.setstdout(old_stdout)
1604 #
1605 result = os.read(fdr, 256)
1606 os.close(fdr)
1607 # the 'X' might remain in the user-level buffer of 'fw1' and
1608 # end up showing up after the 'hello, 42!\n'
1609 assert result == b"Xhello, 42!\n" or result == b"hello, 42!\nX"
1610
1611 def test_FILE_stored_explicitly():
1612 ffi = FFI()
1613 ffi.cdef("int myprintf11(const char *, int); FILE *myfile;")
1614 lib = ffi.verify("""
1615 #include <stdio.h>
1616 FILE *myfile;
1617 int myprintf11(const char *out, int value) {
1618 return fprintf(myfile, out, value);
1619 }
1620 """)
1621 import os
1622 fdr, fdw = os.pipe()
1623 fw1 = os.fdopen(fdw, 'wb', 256)
1624 lib.myfile = ffi.cast("FILE *", fw1)
1625 #
1626 fw1.write(b"X")
1627 r = lib.myprintf11(b"hello, %d!\n", ffi.cast("int", 42))
1628 fw1.close()
1629 assert r == len("hello, 42!\n")
1630 #
1631 result = os.read(fdr, 256)
1632 os.close(fdr)
1633 # the 'X' might remain in the user-level buffer of 'fw1' and
1634 # end up showing up after the 'hello, 42!\n'
1635 assert result == b"Xhello, 42!\n" or result == b"hello, 42!\nX"
1636
1637 def test_global_array_with_missing_length():
1638 ffi = FFI()
1639 ffi.cdef("int fooarray[];")
1640 lib = ffi.verify("int fooarray[50];")
1641 assert repr(lib.fooarray).startswith("<cdata 'int *'")
1642
1643 def test_global_array_with_dotdotdot_length():
1644 ffi = FFI()
1645 ffi.cdef("int fooarray[...];")
1646 lib = ffi.verify("int fooarray[50];")
1647 assert repr(lib.fooarray).startswith("<cdata 'int[50]'")
1648
1649 def test_bad_global_array_with_dotdotdot_length():
1650 py.test.xfail("was detected only because 23 bytes cannot be divided by 4; "
1651 "redo more generally")
1652 ffi = FFI()
1653 ffi.cdef("int fooarray[...];")
1654 py.test.raises(VerificationError, ffi.verify, "char fooarray[23];")
1655
1656 def test_struct_containing_struct():
1657 ffi = FFI()
1658 ffi.cdef("struct foo_s { ...; }; struct bar_s { struct foo_s f; ...; };")
1659 ffi.verify("struct foo_s { int x; }; struct bar_s { struct foo_s f; };")
1660 #
1661 ffi = FFI()
1662 ffi.cdef("struct foo_s { struct bar_s f; ...; }; struct bar_s { ...; };")
1663 ffi.verify("struct bar_s { int x; }; struct foo_s { struct bar_s f; };")
1664
1665 def test_struct_returned_by_func():
1666 ffi = FFI()
1667 ffi.cdef("typedef ... foo_t; foo_t myfunc(void);")
1668 e = py.test.raises(TypeError, ffi.verify,
1669 "typedef struct { int x; } foo_t; "
1670 "foo_t myfunc(void) { foo_t x = { 42 }; return x; }")
1671 assert str(e.value) == (
1672 "function myfunc: 'foo_t' is used as result type, but is opaque")
1673
1674 def test_include():
1675 ffi1 = FFI()
1676 ffi1.cdef("typedef struct { int x; ...; } foo_t;")
1677 ffi1.verify("typedef struct { int y, x; } foo_t;")
1678 ffi2 = FFI()
1679 ffi2.include(ffi1)
1680 ffi2.cdef("int myfunc(foo_t *);")
1681 lib = ffi2.verify("typedef struct { int y, x; } foo_t;"
1682 "int myfunc(foo_t *p) { return 42 * p->x; }")
1683 res = lib.myfunc(ffi2.new("foo_t *", {'x': 10}))
1684 assert res == 420
1685 res = lib.myfunc(ffi1.new("foo_t *", {'x': -10}))
1686 assert res == -420
1687
1688 def test_include_enum():
1689 ffi1 = FFI()
1690 ffi1.cdef("enum foo_e { AA, ... };")
1691 lib1 = ffi1.verify("enum foo_e { CC, BB, AA };")
1692 ffi2 = FFI()
1693 ffi2.include(ffi1)
1694 ffi2.cdef("int myfunc(enum foo_e);")
1695 lib2 = ffi2.verify("enum foo_e { CC, BB, AA };"
1696 "int myfunc(enum foo_e x) { return (int)x; }")
1697 res = lib2.myfunc(lib2.AA)
1698 assert res == 2
1699
1700 def test_named_pointer_as_argument():
1701 ffi = FFI()
1702 ffi.cdef("typedef struct { int x; } *mystruct_p;\n"
1703 "mystruct_p ff5a(mystruct_p);")
1704 lib = ffi.verify("typedef struct { int x; } *mystruct_p;\n"
1705 "mystruct_p ff5a(mystruct_p p) { p->x += 40; return p; }")
1706 p = ffi.new("mystruct_p", [-2])
1707 q = lib.ff5a(p)
1708 assert q == p
1709 assert p.x == 38
1710
1711 def test_enum_size():
1712 cases = [('123', 4, 4294967295),
1713 ('4294967295U', 4, 4294967295),
1714 ('-123', 4, -1),
1715 ('-2147483647-1', 4, -1),
1716 ]
1717 if FFI().sizeof("long") == 8:
1718 cases += [('4294967296L', 8, 2**64-1),
1719 ('%dUL' % (2**64-1), 8, 2**64-1),
1720 ('-2147483649L', 8, -1),
1721 ('%dL-1L' % (1-2**63), 8, -1)]
1722 for hidden_value, expected_size, expected_minus1 in cases:
1723 if sys.platform == 'win32' and 'U' in hidden_value:
1724 continue # skipped on Windows
1725 ffi = FFI()
1726 ffi.cdef("enum foo_e { AA, BB, ... };")
1727 lib = ffi.verify("enum foo_e { AA, BB=%s };" % hidden_value)
1728 assert lib.AA == 0
1729 assert lib.BB == eval(hidden_value.replace('U', '').replace('L', ''))
1730 assert ffi.sizeof("enum foo_e") == expected_size
1731 if sys.platform != 'win32':
1732 assert int(ffi.cast("enum foo_e", -1)) == expected_minus1
1733 # test with the large value hidden:
1734 # disabled so far, doesn't work
1735 ## for hidden_value, expected_size, expected_minus1 in cases:
1736 ## ffi = FFI()
1737 ## ffi.cdef("enum foo_e { AA, BB, ... };")
1738 ## lib = ffi.verify("enum foo_e { AA, BB=%s };" % hidden_value)
1739 ## assert lib.AA == 0
1740 ## assert ffi.sizeof("enum foo_e") == expected_size
1741 ## assert int(ffi.cast("enum foo_e", -1)) == expected_minus1
1742
1743 def test_enum_bug118():
1744 maxulong = 256 ** FFI().sizeof("unsigned long") - 1
1745 for c2, c2c in [(-1, ''),
1746 (-1, ''),
1747 (0xffffffff, 'U'),
1748 (maxulong, 'UL'),
1749 (-int(maxulong / 3), 'L')]:
1750 if c2c and sys.platform == 'win32':
1751 continue # enums may always be signed with MSVC
1752 ffi = FFI()
1753 ffi.cdef("enum foo_e { AA };")
1754 lib = ffi.verify("enum foo_e { AA=%s%s };" % (c2, c2c))
1755 assert lib.AA == c2
1756
1757 def test_string_to_voidp_arg():
1758 ffi = FFI()
1759 ffi.cdef("int myfunc(void *);")
1760 lib = ffi.verify("int myfunc(void *p) { return ((signed char *)p)[0]; }")
1761 res = lib.myfunc(b"hi!")
1762 assert res == ord(b"h")
1763 p = ffi.new("char[]", b"gah")
1764 res = lib.myfunc(p)
1765 assert res == ord(b"g")
1766 res = lib.myfunc(ffi.cast("void *", p))
1767 assert res == ord(b"g")
1768 res = lib.myfunc(ffi.cast("int *", p))
1769 assert res == ord(b"g")
1770
1771 def test_callback_indirection():
1772 ffi = FFI()
1773 ffi.cdef("""
1774 int (*python_callback)(int how_many, int *values);
1775 int (*const c_callback)(int,...); /* pass this ptr to C routines */
1776 int some_c_function(int(*cb)(int,...));
1777 """)
1778 lib = ffi.verify("""
1779 #include <stdarg.h>
1780 #ifdef _WIN32
1781 #include <malloc.h>
1782 #define alloca _alloca
1783 #else
1784 # ifdef __FreeBSD__
1785 # include <stdlib.h>
1786 # else
1787 # include <alloca.h>
1788 # endif
1789 #endif
1790 static int (*python_callback)(int how_many, int *values);
1791 static int c_callback(int how_many, ...) {
1792 va_list ap;
1793 /* collect the "..." arguments into the values[] array */
1794 int i, *values = alloca((size_t)how_many * sizeof(int));
1795 va_start(ap, how_many);
1796 for (i=0; i<how_many; i++)
1797 values[i] = va_arg(ap, int);
1798 va_end(ap);
1799 return python_callback(how_many, values);
1800 }
1801 int some_c_function(int(*cb)(int,...)) {
1802 int result = cb(2, 10, 20);
1803 result += cb(3, 30, 40, 50);
1804 return result;
1805 }
1806 """)
1807 seen = []
1808 @ffi.callback("int(int, int*)")
1809 def python_callback(how_many, values):
1810 seen.append([values[i] for i in range(how_many)])
1811 return 42
1812 lib.python_callback = python_callback
1813
1814 res = lib.some_c_function(lib.c_callback)
1815 assert res == 84
1816 assert seen == [[10, 20], [30, 40, 50]]
1817
1818 def test_floatstar_argument():
1819 ffi = FFI()
1820 ffi.cdef("float sum3floats(float *);")
1821 lib = ffi.verify("""
1822 float sum3floats(float *f) {
1823 return f[0] + f[1] + f[2];
1824 }
1825 """)
1826 assert lib.sum3floats((1.5, 2.5, 3.5)) == 7.5
1827 p = ffi.new("float[]", (1.5, 2.5, 3.5))
1828 assert lib.sum3floats(p) == 7.5
1829
1830 def test_charstar_argument():
1831 ffi = FFI()
1832 ffi.cdef("char sum3chars(char *);")
1833 lib = ffi.verify("""
1834 char sum3chars(char *f) {
1835 return (char)(f[0] + f[1] + f[2]);
1836 }
1837 """)
1838 assert lib.sum3chars((b'\x10', b'\x20', b'\x30')) == b'\x60'
1839 p = ffi.new("char[]", b'\x10\x20\x30')
1840 assert lib.sum3chars(p) == b'\x60'
1841
1842 def test_passing_string_or_NULL():
1843 ffi = FFI()
1844 ffi.cdef("int seeme1(char *); int seeme2(int *);")
1845 lib = ffi.verify("""
1846 int seeme1(char *x) {
1847 return (x == NULL);
1848 }
1849 int seeme2(int *x) {
1850 return (x == NULL);
1851 }
1852 """)
1853 assert lib.seeme1(b"foo") == 0
1854 assert lib.seeme1(ffi.NULL) == 1
1855 assert lib.seeme2([42, 43]) == 0
1856 assert lib.seeme2(ffi.NULL) == 1
1857 py.test.raises(TypeError, lib.seeme1, None)
1858 py.test.raises(TypeError, lib.seeme2, None)
1859 py.test.raises(TypeError, lib.seeme1, 0.0)
1860 py.test.raises(TypeError, lib.seeme2, 0.0)
1861 py.test.raises(TypeError, lib.seeme1, 0)
1862 py.test.raises(TypeError, lib.seeme2, 0)
1863 zeroL = 99999999999999999999
1864 zeroL -= 99999999999999999999
1865 py.test.raises(TypeError, lib.seeme2, zeroL)
1866
1867 def test_typeof_function():
1868 ffi = FFI()
1869 ffi.cdef("int foo(int, char);")
1870 lib = ffi.verify("int foo(int x, char y) { (void)x; (void)y; return 42; }")
1871 ctype = ffi.typeof(lib.foo)
1872 assert len(ctype.args) == 2
1873 assert ctype.result == ffi.typeof("int")
1874
1875 def test_call_with_voidstar_arg():
1876 ffi = FFI()
1877 ffi.cdef("int f(void *);")
1878 lib = ffi.verify("int f(void *x) { return ((char*)x)[0]; }")
1879 assert lib.f(b"foobar") == ord(b"f")
1880
1881 def test_dir():
1882 ffi = FFI()
1883 ffi.cdef("""void somefunc(void);
1884 extern int somevar, somearray[2];
1885 static char *const sv2;
1886 enum my_e { AA, BB, ... };
1887 #define FOO ...""")
1888 lib = ffi.verify("""void somefunc(void) { }
1889 int somevar, somearray[2];
1890 #define sv2 "text"
1891 enum my_e { AA, BB };
1892 #define FOO 42""")
1893 assert dir(lib) == ['AA', 'BB', 'FOO', 'somearray',
1894 'somefunc', 'somevar', 'sv2']
1895
1896 def test_typeof_func_with_struct_argument():
1897 ffi = FFI()
1898 ffi.cdef("""struct s { int a; }; int foo(struct s);""")
1899 lib = ffi.verify("""struct s { int a; };
1900 int foo(struct s x) { return x.a; }""")
1901 s = ffi.new("struct s *", [-1234])
1902 m = lib.foo(s[0])
1903 assert m == -1234
1904 assert repr(ffi.typeof(lib.foo)) == "<ctype 'int(*)(struct s)'>"
1905
1906 def test_bug_const_char_ptr_array_1():
1907 ffi = FFI()
1908 ffi.cdef("""const char *a[...];""")
1909 lib = ffi.verify("""const char *a[5];""")
1910 assert repr(ffi.typeof(lib.a)) == "<ctype 'char *[5]'>"
1911
1912 def test_bug_const_char_ptr_array_2():
1913 ffi = FFI()
1914 ffi.cdef("""const int a[];""")
1915 lib = ffi.verify("""const int a[5];""")
1916 assert repr(ffi.typeof(lib.a)) == "<ctype 'int *'>"
1917
1918 def _test_various_calls(force_libffi):
1919 cdef_source = """
1920 int xvalue;
1921 long long ivalue, rvalue;
1922 float fvalue;
1923 double dvalue;
1924 long double Dvalue;
1925 signed char tf_bb(signed char x, signed char c);
1926 unsigned char tf_bB(signed char x, unsigned char c);
1927 short tf_bh(signed char x, short c);
1928 unsigned short tf_bH(signed char x, unsigned short c);
1929 int tf_bi(signed char x, int c);
1930 unsigned int tf_bI(signed char x, unsigned int c);
1931 long tf_bl(signed char x, long c);
1932 unsigned long tf_bL(signed char x, unsigned long c);
1933 long long tf_bq(signed char x, long long c);
1934 unsigned long long tf_bQ(signed char x, unsigned long long c);
1935 float tf_bf(signed char x, float c);
1936 double tf_bd(signed char x, double c);
1937 long double tf_bD(signed char x, long double c);
1938 """
1939 if force_libffi:
1940 cdef_source = (cdef_source
1941 .replace('tf_', '(*const tf_')
1942 .replace('(signed char x', ')(signed char x'))
1943 ffi = FFI()
1944 ffi.cdef(cdef_source)
1945 lib = ffi.verify("""
1946 int xvalue;
1947 long long ivalue, rvalue;
1948 float fvalue;
1949 double dvalue;
1950 long double Dvalue;
1951
1952 typedef signed char b_t;
1953 typedef unsigned char B_t;
1954 typedef short h_t;
1955 typedef unsigned short H_t;
1956 typedef int i_t;
1957 typedef unsigned int I_t;
1958 typedef long l_t;
1959 typedef unsigned long L_t;
1960 typedef long long q_t;
1961 typedef unsigned long long Q_t;
1962 typedef float f_t;
1963 typedef double d_t;
1964 typedef long double D_t;
1965 #define S(letter) xvalue = (int)x; letter##value = (letter##_t)c;
1966 #define R(letter) return (letter##_t)rvalue;
1967
1968 signed char tf_bb(signed char x, signed char c) { S(i) R(b) }
1969 unsigned char tf_bB(signed char x, unsigned char c) { S(i) R(B) }
1970 short tf_bh(signed char x, short c) { S(i) R(h) }
1971 unsigned short tf_bH(signed char x, unsigned short c) { S(i) R(H) }
1972 int tf_bi(signed char x, int c) { S(i) R(i) }
1973 unsigned int tf_bI(signed char x, unsigned int c) { S(i) R(I) }
1974 long tf_bl(signed char x, long c) { S(i) R(l) }
1975 unsigned long tf_bL(signed char x, unsigned long c) { S(i) R(L) }
1976 long long tf_bq(signed char x, long long c) { S(i) R(q) }
1977 unsigned long long tf_bQ(signed char x, unsigned long long c) { S(i) R(Q) }
1978 float tf_bf(signed char x, float c) { S(f) R(f) }
1979 double tf_bd(signed char x, double c) { S(d) R(d) }
1980 long double tf_bD(signed char x, long double c) { S(D) R(D) }
1981 """)
1982 lib.rvalue = 0x7182838485868788
1983 for kind, cname in [('b', 'signed char'),
1984 ('B', 'unsigned char'),
1985 ('h', 'short'),
1986 ('H', 'unsigned short'),
1987 ('i', 'int'),
1988 ('I', 'unsigned int'),
1989 ('l', 'long'),
1990 ('L', 'unsigned long'),
1991 ('q', 'long long'),
1992 ('Q', 'unsigned long long'),
1993 ('f', 'float'),
1994 ('d', 'double'),
1995 ('D', 'long double')]:
1996 sign = +1 if 'unsigned' in cname else -1
1997 lib.xvalue = 0
1998 lib.ivalue = 0
1999 lib.fvalue = 0
2000 lib.dvalue = 0
2001 lib.Dvalue = 0
2002 fun = getattr(lib, 'tf_b' + kind)
2003 res = fun(-42, sign * 99)
2004 if kind == 'D':
2005 res = float(res)
2006 assert res == int(ffi.cast(cname, 0x7182838485868788))
2007 assert lib.xvalue == -42
2008 if kind in 'fdD':
2009 assert float(getattr(lib, kind + 'value')) == -99.0
2010 else:
2011 assert lib.ivalue == sign * 99
2012
2013 def test_various_calls_direct():
2014 _test_various_calls(force_libffi=False)
2015
2016 def test_various_calls_libffi():
2017 _test_various_calls(force_libffi=True)
2018
2019 def test_ptr_to_opaque():
2020 ffi = FFI()
2021 ffi.cdef("typedef ... foo_t; int f1(foo_t*); foo_t *f2(int);")
2022 lib = ffi.verify("""
2023 #include <stdlib.h>
2024 typedef struct { int x; } foo_t;
2025 int f1(foo_t* p) {
2026 int x = p->x;
2027 free(p);
2028 return x;
2029 }
2030 foo_t *f2(int x) {
2031 foo_t *p = malloc(sizeof(foo_t));
2032 p->x = x;
2033 return p;
2034 }
2035 """)
2036 p = lib.f2(42)
2037 x = lib.f1(p)
2038 assert x == 42
2039
2040 def _run_in_multiple_threads(test1):
2041 test1()
2042 import sys
2043 try:
2044 import thread
2045 except ImportError:
2046 import _thread as thread
2047 errors = []
2048 def wrapper(lock):
2049 try:
2050 test1()
2051 except:
2052 errors.append(sys.exc_info())
2053 lock.release()
2054 locks = []
2055 for i in range(10):
2056 _lock = thread.allocate_lock()
2057 _lock.acquire()
2058 thread.start_new_thread(wrapper, (_lock,))
2059 locks.append(_lock)
2060 for _lock in locks:
2061 _lock.acquire()
2062 if errors:
2063 raise errors[0][1]
2064
2065 def test_errno_working_even_with_pypys_jit():
2066 ffi = FFI()
2067 ffi.cdef("int f(int);")
2068 lib = ffi.verify("""
2069 #include <errno.h>
2070 int f(int x) { return (errno = errno + x); }
2071 """)
2072 @_run_in_multiple_threads
2073 def test1():
2074 ffi.errno = 0
2075 for i in range(10000):
2076 e = lib.f(1)
2077 assert e == i + 1
2078 assert ffi.errno == e
2079 for i in range(10000):
2080 ffi.errno = i
2081 e = lib.f(42)
2082 assert e == i + 42
2083
2084 def test_getlasterror_working_even_with_pypys_jit():
2085 if sys.platform != 'win32':
2086 py.test.skip("win32-only test")
2087 ffi = FFI()
2088 ffi.cdef("void SetLastError(DWORD);")
2089 lib = ffi.dlopen("Kernel32.dll")
2090 @_run_in_multiple_threads
2091 def test1():
2092 for i in range(10000):
2093 n = (1 << 29) + i
2094 lib.SetLastError(n)
2095 assert ffi.getwinerror()[0] == n
2096
2097 def test_verify_dlopen_flags():
2098 if not hasattr(sys, 'setdlopenflags'):
2099 py.test.skip("requires sys.setdlopenflags()")
2100 # Careful with RTLD_GLOBAL. If by chance the FFI is not deleted
2101 # promptly, like on PyPy, then other tests may see the same
2102 # exported symbols as well. So we must not export a simple name
2103 # like 'foo'!
2104 old = sys.getdlopenflags()
2105 try:
2106 ffi1 = FFI()
2107 ffi1.cdef("int foo_verify_dlopen_flags_1;")
2108 sys.setdlopenflags(ffi1.RTLD_GLOBAL | ffi1.RTLD_NOW)
2109 lib1 = ffi1.verify("int foo_verify_dlopen_flags_1;")
2110 finally:
2111 sys.setdlopenflags(old)
2112
2113 ffi2 = FFI()
2114 ffi2.cdef("int *getptr(void);")
2115 lib2 = ffi2.verify("""
2116 extern int foo_verify_dlopen_flags_1;
2117 static int *getptr(void) { return &foo_verify_dlopen_flags_1; }
2118 """)
2119 p = lib2.getptr()
2120 assert ffi1.addressof(lib1, 'foo_verify_dlopen_flags_1') == p
2121
2122 def test_consider_not_implemented_function_type():
2123 ffi = FFI()
2124 ffi.cdef("typedef union { int a; float b; } Data;"
2125 "typedef struct { int a:2; } MyStr;"
2126 "typedef void (*foofunc_t)(Data);"
2127 "typedef Data (*bazfunc_t)(void);"
2128 "typedef MyStr (*barfunc_t)(void);")
2129 fooptr = ffi.cast("foofunc_t", 123)
2130 bazptr = ffi.cast("bazfunc_t", 123)
2131 barptr = ffi.cast("barfunc_t", 123)
2132 # assert did not crash so far
2133 e = py.test.raises(NotImplementedError, fooptr, ffi.new("Data *"))
2134 assert str(e.value) == (
2135 "ctype 'Data' not supported as argument by libffi. Unions are only "
2136 "supported as argument if the function is 'API mode' and "
2137 "non-variadic (i.e. declared inside ffibuilder.cdef()+"
2138 "ffibuilder.set_source() and not taking a final '...' argument)")
2139 e = py.test.raises(NotImplementedError, bazptr)
2140 assert str(e.value) == (
2141 "ctype 'Data' not supported as return value by libffi. Unions are "
2142 "only supported as return value if the function is 'API mode' and "
2143 "non-variadic (i.e. declared inside ffibuilder.cdef()+"
2144 "ffibuilder.set_source() and not taking a final '...' argument)")
2145 e = py.test.raises(NotImplementedError, barptr)
2146 assert str(e.value) == (
2147 "ctype 'MyStr' not supported as return value. It is a struct with "
2148 "bit fields, which libffi does not support. Such structs are only "
2149 "supported as return value if the function is 'API mode' and non-"
2150 "variadic (i.e. declared inside ffibuilder.cdef()+ffibuilder."
2151 "set_source() and not taking a final '...' argument)")
2152
2153 def test_verify_extra_arguments():
2154 ffi = FFI()
2155 ffi.cdef("#define ABA ...")
2156 lib = ffi.verify("", define_macros=[('ABA', '42')])
2157 assert lib.ABA == 42
2158
2159 def test_implicit_unicode_on_windows():
2160 from cffi import FFIError
2161 if sys.platform != 'win32':
2162 py.test.skip("win32-only test")
2163 ffi = FFI()
2164 e = py.test.raises(FFIError, ffi.cdef, "int foo(LPTSTR);")
2165 assert str(e.value) == ("The Windows type 'LPTSTR' is only available after"
2166 " you call ffi.set_unicode()")
2167 for with_unicode in [True, False]:
2168 ffi = FFI()
2169 ffi.set_unicode(with_unicode)
2170 ffi.cdef("""
2171 DWORD GetModuleFileName(HMODULE hModule, LPTSTR lpFilename,
2172 DWORD nSize);
2173 """)
2174 lib = ffi.verify("""
2175 #include <windows.h>
2176 """, libraries=['Kernel32'])
2177 outbuf = ffi.new("TCHAR[]", 200)
2178 n = lib.GetModuleFileName(ffi.NULL, outbuf, 500)
2179 assert 0 < n < 500
2180 for i in range(n):
2181 #print repr(outbuf[i])
2182 assert ord(outbuf[i]) != 0
2183 assert ord(outbuf[n]) == 0
2184 assert ord(outbuf[0]) < 128 # should be a letter, or '\'
2185
2186 def test_define_known_value():
2187 ffi = FFI()
2188 ffi.cdef("#define FOO 0x123")
2189 lib = ffi.verify("#define FOO 0x123")
2190 assert lib.FOO == 0x123
2191
2192 def test_define_wrong_value():
2193 ffi = FFI()
2194 ffi.cdef("#define FOO 123")
2195 lib = ffi.verify("#define FOO 124") # used to complain
2196 e = py.test.raises(ffi.error, "lib.FOO")
2197 assert str(e.value) == ("the C compiler says 'FOO' is equal to 124 (0x7c),"
2198 " but the cdef disagrees")
2199
2200 def test_some_integer_type_for_issue73():
2201 ffi = FFI()
2202 ffi.cdef("""
2203 typedef int... AnIntegerWith32Bits;
2204 typedef AnIntegerWith32Bits (*AFunctionReturningInteger) (void);
2205 AnIntegerWith32Bits InvokeFunction(AFunctionReturningInteger);
2206 """)
2207 lib = ffi.verify("""
2208 #ifdef __LP64__
2209 typedef int AnIntegerWith32Bits;
2210 #else
2211 typedef long AnIntegerWith32Bits;
2212 #endif
2213 typedef AnIntegerWith32Bits (*AFunctionReturningInteger) (void);
2214 AnIntegerWith32Bits InvokeFunction(AFunctionReturningInteger f) {
2215 return f();
2216 }
2217 """)
2218 @ffi.callback("AFunctionReturningInteger")
2219 def add():
2220 return 3 + 4
2221 x = lib.InvokeFunction(add)
2222 assert x == 7
2223
2224 def test_unsupported_some_primitive_types():
2225 ffi = FFI()
2226 py.test.raises((FFIError, # with pycparser <= 2.17
2227 CDefError), # with pycparser >= 2.18
2228 ffi.cdef, """typedef void... foo_t;""")
2229 #
2230 ffi.cdef("typedef int... foo_t;")
2231 py.test.raises(VerificationError, ffi.verify, "typedef float foo_t;")
2232
2233 def test_windows_dllimport_data():
2234 if sys.platform != 'win32':
2235 py.test.skip("Windows only")
2236 from extra_tests.cffi_tests.udir import udir
2237 tmpfile = udir.join('dllimport_data.c')
2238 tmpfile.write('int my_value = 42;\n')
2239 ffi = FFI()
2240 ffi.cdef("int my_value;")
2241 lib = ffi.verify("extern __declspec(dllimport) int my_value;",
2242 sources = [str(tmpfile)])
2243 assert lib.my_value == 42
2244
2245 def test_macro_var():
2246 ffi = FFI()
2247 ffi.cdef("int myarray[50], my_value;")
2248 lib = ffi.verify("""
2249 int myarray[50];
2250 int *get_my_value(void) {
2251 static int index = 0;
2252 return &myarray[index++];
2253 }
2254 #define my_value (*get_my_value())
2255 """)
2256 assert lib.my_value == 0 # [0]
2257 lib.my_value = 42 # [1]
2258 assert lib.myarray[1] == 42
2259 assert lib.my_value == 0 # [2]
2260 lib.myarray[3] = 63
2261 assert lib.my_value == 63 # [3]
2262 p = ffi.addressof(lib, 'my_value') # [4]
2263 assert p[-1] == 63
2264 assert p[0] == 0
2265 assert p == lib.myarray + 4
2266 p[1] = 82
2267 assert lib.my_value == 82 # [5]
2268
2269 def test_const_pointer_to_pointer():
2270 ffi = FFI()
2271 ffi.cdef("struct s { char *const *a; };")
2272 ffi.verify("struct s { char *const *a; };")
2273
2274 def test_share_FILE():
2275 ffi1 = FFI()
2276 ffi1.cdef("void do_stuff(FILE *);")
2277 lib1 = ffi1.verify("void do_stuff(FILE *f) { (void)f; }")
2278 ffi2 = FFI()
2279 ffi2.cdef("FILE *barize(void);")
2280 lib2 = ffi2.verify("FILE *barize(void) { return NULL; }")
2281 lib1.do_stuff(lib2.barize())
2282
2283 def test_win_common_types():
2284 if sys.platform != 'win32':
2285 py.test.skip("Windows only")
2286 ffi = FFI()
2287 ffi.set_unicode(True)
2288 ffi.verify("")
2289 assert ffi.typeof("PBYTE") is ffi.typeof("unsigned char *")
2290 if sys.maxsize > 2**32:
2291 expected = "unsigned long long"
2292 else:
2293 expected = "unsigned int"
2294 assert ffi.typeof("UINT_PTR") is ffi.typeof(expected)
2295 assert ffi.typeof("PTSTR") is ffi.typeof("wchar_t *")
2296
2297 def _only_test_on_linux_intel():
2298 if not sys.platform.startswith('linux'):
2299 py.test.skip('only running the memory-intensive test on Linux')
2300 import platform
2301 machine = platform.machine()
2302 if 'x86' not in machine and 'x64' not in machine:
2303 py.test.skip('only running the memory-intensive test on x86/x64')
2304
2305 def test_ffi_gc_size_arg():
2306 _only_test_on_linux_intel()
2307 ffi = FFI()
2308 ffi.cdef("void *malloc(size_t); void free(void *);")
2309 lib = ffi.verify(r"""
2310 #include <stdlib.h>
2311 """)
2312 for i in range(2000):
2313 p = lib.malloc(20*1024*1024) # 20 MB
2314 p1 = ffi.cast("char *", p)
2315 for j in range(0, 20*1024*1024, 4096):
2316 p1[j] = b'!'
2317 p = ffi.gc(p, lib.free, 20*1024*1024)
2318 del p
2319 # with PyPy's GC, the above would rapidly consume 40 GB of RAM
2320 # without the third argument to ffi.gc()
2321
2322 def test_ffi_gc_size_arg_2():
2323 # a variant of the above: this "attack" works on cpython's cyclic gc too
2324 # and I found no obvious way to prevent that. So for now, this test
2325 # is skipped on CPython, where it eats all the memory.
2326 if '__pypy__' not in sys.builtin_module_names:
2327 py.test.skip("find a way to tweak the cyclic GC of CPython")
2328 _only_test_on_linux_intel()
2329 ffi = FFI()
2330 ffi.cdef("void *malloc(size_t); void free(void *);")
2331 lib = ffi.verify(r"""
2332 #include <stdlib.h>
2333 """)
2334 class X(object):
2335 pass
2336 for i in range(2000):
2337 p = lib.malloc(50*1024*1024) # 50 MB
2338 p1 = ffi.cast("char *", p)
2339 for j in range(0, 50*1024*1024, 4096):
2340 p1[j] = b'!'
2341 p = ffi.gc(p, lib.free, 50*1024*1024)
2342 x = X()
2343 x.p = p
2344 x.cyclic = x
2345 del p, x
2346
2347 def test_ffi_new_with_cycles():
2348 # still another variant, with ffi.new()
2349 if '__pypy__' not in sys.builtin_module_names:
2350 py.test.skip("find a way to tweak the cyclic GC of CPython")
2351 ffi = FFI()
2352 ffi.cdef("")
2353 lib = ffi.verify("")
2354 class X(object):
2355 pass
2356 for i in range(2000):
2357 p = ffi.new("char[]", 50*1024*1024) # 50 MB
2358 for j in range(0, 50*1024*1024, 4096):
2359 p[j] = b'!'
2360 x = X()
2361 x.p = p
2362 x.cyclic = x
2363 del p, x
0 # Generated by pypy/tool/import_cffi.py
1 import sys, os, py
2 import subprocess
3 import cffi
4 from extra_tests.cffi_tests.udir import udir
5 from shutil import rmtree
6 from tempfile import mkdtemp
7
8
9 def chdir_to_tmp(f):
10 f.chdir_to_tmp = True
11 return f
12
13 def from_outside(f):
14 f.chdir_to_tmp = False
15 return f
16
17
18 class TestDist(object):
19
20 def setup_method(self, meth):
21 self.executable = os.path.abspath(sys.executable)
22 self.rootdir = os.path.abspath(os.path.dirname(os.path.dirname(
23 cffi.__file__)))
24 self.udir = udir.join(meth.__name__)
25 os.mkdir(str(self.udir))
26 if meth.chdir_to_tmp:
27 self.saved_cwd = os.getcwd()
28 os.chdir(str(self.udir))
29
30 def teardown_method(self, meth):
31 if hasattr(self, 'saved_cwd'):
32 os.chdir(self.saved_cwd)
33
34 def run(self, args, cwd=None):
35 env = os.environ.copy()
36 # a horrible hack to prevent distutils from finding ~/.pydistutils.cfg
37 # (there is the --no-user-cfg option, but not in Python 2.6...)
38 # NOTE: pointing $HOME to a nonexistent directory can break certain things
39 # that look there for configuration (like ccache).
40 tmp_home = mkdtemp()
41 assert tmp_home != None, "cannot create temporary homedir"
42 env['HOME'] = tmp_home
43 if cwd is None:
44 newpath = self.rootdir
45 if 'PYTHONPATH' in env:
46 newpath += os.pathsep + env['PYTHONPATH']
47 env['PYTHONPATH'] = newpath
48 try:
49 subprocess.check_call([self.executable] + args, cwd=cwd, env=env)
50 finally:
51 rmtree(tmp_home)
52
53 def _prepare_setuptools(self):
54 if hasattr(TestDist, '_setuptools_ready'):
55 return
56 try:
57 import setuptools
58 except ImportError:
59 py.test.skip("setuptools not found")
60 if os.path.exists(os.path.join(self.rootdir, 'setup.py')):
61 self.run(['setup.py', 'egg_info'], cwd=self.rootdir)
62 TestDist._setuptools_ready = True
63
64 def check_produced_files(self, content, curdir=None):
65 if curdir is None:
66 curdir = str(self.udir)
67 found_so = None
68 for name in os.listdir(curdir):
69 if (name.endswith('.so') or name.endswith('.pyd') or
70 name.endswith('.dylib') or name.endswith('.dll')):
71 found_so = os.path.join(curdir, name)
72 # foo.so => foo
73 parts = name.split('.')
74 del parts[-1]
75 if len(parts) > 1 and parts[-1] != 'bar':
76 # foo.cpython-34m.so => foo, but foo.bar.so => foo.bar
77 del parts[-1]
78 name = '.'.join(parts)
79 # foo_d => foo (Python 2 debug builds)
80 if name.endswith('_d') and hasattr(sys, 'gettotalrefcount'):
81 name = name[:-2]
82 name += '.SO'
83 if name.startswith('pycparser') and name.endswith('.egg'):
84 continue # no clue why this shows up sometimes and not others
85 if name == '.eggs':
86 continue # seems new in 3.5, ignore it
87 assert name in content, "found unexpected file %r" % (
88 os.path.join(curdir, name),)
89 value = content.pop(name)
90 if value is None:
91 assert name.endswith('.SO') or (
92 os.path.isfile(os.path.join(curdir, name)))
93 else:
94 subdir = os.path.join(curdir, name)
95 assert os.path.isdir(subdir)
96 if value == '?':
97 continue
98 found_so = self.check_produced_files(value, subdir) or found_so
99 assert content == {}, "files or dirs not produced in %r: %r" % (
100 curdir, content.keys())
101 return found_so
102
103 @chdir_to_tmp
104 def test_empty(self):
105 self.check_produced_files({})
106
107 @chdir_to_tmp
108 def test_abi_emit_python_code_1(self):
109 ffi = cffi.FFI()
110 ffi.set_source("package_name_1.mymod", None)
111 ffi.emit_python_code('xyz.py')
112 self.check_produced_files({'xyz.py': None})
113
114 @chdir_to_tmp
115 def test_abi_emit_python_code_2(self):
116 ffi = cffi.FFI()
117 ffi.set_source("package_name_1.mymod", None)
118 py.test.raises(IOError, ffi.emit_python_code, 'unexisting/xyz.py')
119
120 @from_outside
121 def test_abi_emit_python_code_3(self):
122 ffi = cffi.FFI()
123 ffi.set_source("package_name_1.mymod", None)
124 ffi.emit_python_code(str(self.udir.join('xyt.py')))
125 self.check_produced_files({'xyt.py': None})
126
127 @chdir_to_tmp
128 def test_abi_compile_1(self):
129 ffi = cffi.FFI()
130 ffi.set_source("mod_name_in_package.mymod", None)
131 x = ffi.compile()
132 self.check_produced_files({'mod_name_in_package': {'mymod.py': None}})
133 assert x == os.path.join('.', 'mod_name_in_package', 'mymod.py')
134
135 @chdir_to_tmp
136 def test_abi_compile_2(self):
137 ffi = cffi.FFI()
138 ffi.set_source("mod_name_in_package.mymod", None)
139 x = ffi.compile('build2')
140 self.check_produced_files({'build2': {
141 'mod_name_in_package': {'mymod.py': None}}})
142 assert x == os.path.join('build2', 'mod_name_in_package', 'mymod.py')
143
144 @from_outside
145 def test_abi_compile_3(self):
146 ffi = cffi.FFI()
147 ffi.set_source("mod_name_in_package.mymod", None)
148 tmpdir = str(self.udir.join('build3'))
149 x = ffi.compile(tmpdir)
150 self.check_produced_files({'build3': {
151 'mod_name_in_package': {'mymod.py': None}}})
152 assert x == os.path.join(tmpdir, 'mod_name_in_package', 'mymod.py')
153
154 @chdir_to_tmp
155 def test_api_emit_c_code_1(self):
156 ffi = cffi.FFI()
157 ffi.set_source("package_name_1.mymod", "/*code would be here*/")
158 ffi.emit_c_code('xyz.c')
159 self.check_produced_files({'xyz.c': None})
160
161 @chdir_to_tmp
162 def test_api_emit_c_code_2(self):
163 ffi = cffi.FFI()
164 ffi.set_source("package_name_1.mymod", "/*code would be here*/")
165 py.test.raises(IOError, ffi.emit_c_code, 'unexisting/xyz.c')
166
167 @from_outside
168 def test_api_emit_c_code_3(self):
169 ffi = cffi.FFI()
170 ffi.set_source("package_name_1.mymod", "/*code would be here*/")
171 ffi.emit_c_code(str(self.udir.join('xyu.c')))
172 self.check_produced_files({'xyu.c': None})
173
174 @chdir_to_tmp
175 def test_api_compile_1(self):
176 ffi = cffi.FFI()
177 ffi.set_source("mod_name_in_package.mymod", "/*code would be here*/")
178 x = ffi.compile()
179 if sys.platform != 'win32':
180 sofile = self.check_produced_files({
181 'mod_name_in_package': {'mymod.SO': None,
182 'mymod.c': None,
183 'mymod.o': None}})
184 assert os.path.isabs(x) and os.path.samefile(x, sofile)
185 else:
186 self.check_produced_files({
187 'mod_name_in_package': {'mymod.SO': None,
188 'mymod.c': None},
189 'Release': '?'})
190
191 @chdir_to_tmp
192 def test_api_compile_2(self):
193 ffi = cffi.FFI()
194 ffi.set_source("mod_name_in_package.mymod", "/*code would be here*/")
195 x = ffi.compile('output')
196 if sys.platform != 'win32':
197 sofile = self.check_produced_files({
198 'output': {'mod_name_in_package': {'mymod.SO': None,
199 'mymod.c': None,
200 'mymod.o': None}}})
201 assert os.path.isabs(x) and os.path.samefile(x, sofile)
202 else:
203 self.check_produced_files({
204 'output': {'mod_name_in_package': {'mymod.SO': None,
205 'mymod.c': None},
206 'Release': '?'}})
207
208 @from_outside
209 def test_api_compile_3(self):
210 ffi = cffi.FFI()
211 ffi.set_source("mod_name_in_package.mymod", "/*code would be here*/")
212 x = ffi.compile(str(self.udir.join('foo')))
213 if sys.platform != 'win32':
214 sofile = self.check_produced_files({
215 'foo': {'mod_name_in_package': {'mymod.SO': None,
216 'mymod.c': None,
217 'mymod.o': None}}})
218 assert os.path.isabs(x) and os.path.samefile(x, sofile)
219 else:
220 self.check_produced_files({
221 'foo': {'mod_name_in_package': {'mymod.SO': None,
222 'mymod.c': None},
223 'Release': '?'}})
224
225 @chdir_to_tmp
226 def test_api_compile_explicit_target_1(self):
227 ffi = cffi.FFI()
228 ffi.set_source("mod_name_in_package.mymod", "/*code would be here*/")
229 x = ffi.compile(target="foo.bar.*")
230 if sys.platform != 'win32':
231 sofile = self.check_produced_files({
232 'mod_name_in_package': {'foo.bar.SO': None,
233 'mymod.c': None,
234 'mymod.o': None}})
235 assert os.path.isabs(x) and os.path.samefile(x, sofile)
236 else:
237 self.check_produced_files({
238 'mod_name_in_package': {'foo.bar.SO': None,
239 'mymod.c': None},
240 'Release': '?'})
241
242 @chdir_to_tmp
243 def test_api_compile_explicit_target_3(self):
244 ffi = cffi.FFI()
245 ffi.set_source("mod_name_in_package.mymod", "/*code would be here*/")
246 x = ffi.compile(target="foo.bar.baz")
247 if sys.platform != 'win32':
248 self.check_produced_files({
249 'mod_name_in_package': {'foo.bar.baz': None,
250 'mymod.c': None,
251 'mymod.o': None}})
252 sofile = os.path.join(str(self.udir),
253 'mod_name_in_package', 'foo.bar.baz')
254 assert os.path.isabs(x) and os.path.samefile(x, sofile)
255 else:
256 self.check_produced_files({
257 'mod_name_in_package': {'foo.bar.baz': None,
258 'mymod.c': None},
259 'Release': '?'})
260
261 @chdir_to_tmp
262 def test_api_distutils_extension_1(self):
263 ffi = cffi.FFI()
264 ffi.set_source("mod_name_in_package.mymod", "/*code would be here*/")
265 ext = ffi.distutils_extension()
266 self.check_produced_files({'build': {
267 'mod_name_in_package': {'mymod.c': None}}})
268 if hasattr(os.path, 'samefile'):
269 assert os.path.samefile(ext.sources[0],
270 'build/mod_name_in_package/mymod.c')
271
272 @from_outside
273 def test_api_distutils_extension_2(self):
274 ffi = cffi.FFI()
275 ffi.set_source("mod_name_in_package.mymod", "/*code would be here*/")
276 ext = ffi.distutils_extension(str(self.udir.join('foo')))
277 self.check_produced_files({'foo': {
278 'mod_name_in_package': {'mymod.c': None}}})
279 if hasattr(os.path, 'samefile'):
280 assert os.path.samefile(ext.sources[0],
281 str(self.udir.join('foo/mod_name_in_package/mymod.c')))
282
283
284 def _make_distutils_api(self):
285 os.mkdir("src")
286 os.mkdir(os.path.join("src", "pack1"))
287 with open(os.path.join("src", "pack1", "__init__.py"), "w") as f:
288 pass
289 with open("setup.py", "w") as f:
290 f.write("""if 1:
291 # https://bugs.python.org/issue23246
292 import sys
293 if sys.platform == 'win32':
294 try:
295 import setuptools
296 except ImportError:
297 pass
298
299 import cffi
300 ffi = cffi.FFI()
301 ffi.set_source("pack1.mymod", "/*code would be here*/")
302
303 from distutils.core import setup
304 setup(name='example1',
305 version='0.1',
306 packages=['pack1'],
307 package_dir={'': 'src'},
308 ext_modules=[ffi.distutils_extension()])
309 """)
310
311 @chdir_to_tmp
312 def test_distutils_api_1(self):
313 self._make_distutils_api()
314 self.run(["setup.py", "build"])
315 self.check_produced_files({'setup.py': None,
316 'build': '?',
317 'src': {'pack1': {'__init__.py': None}}})
318
319 @chdir_to_tmp
320 def test_distutils_api_2(self):
321 self._make_distutils_api()
322 self.run(["setup.py", "build_ext", "-i"])
323 self.check_produced_files({'setup.py': None,
324 'build': '?',
325 'src': {'pack1': {'__init__.py': None,
326 'mymod.SO': None}}})
327
328 def _make_setuptools_abi(self):
329 self._prepare_setuptools()
330 os.mkdir("src0")
331 os.mkdir(os.path.join("src0", "pack2"))
332 with open(os.path.join("src0", "pack2", "__init__.py"), "w") as f:
333 pass
334 with open(os.path.join("src0", "pack2", "_build.py"), "w") as f:
335 f.write("""if 1:
336 import cffi
337 ffi = cffi.FFI()
338 ffi.set_source("pack2.mymod", None)
339 """)
340 with open("setup.py", "w") as f:
341 f.write("""if 1:
342 from setuptools import setup
343 setup(name='example1',
344 version='0.1',
345 packages=['pack2'],
346 package_dir={'': 'src0'},
347 cffi_modules=["src0/pack2/_build.py:ffi"])
348 """)
349
350 @chdir_to_tmp
351 def test_setuptools_abi_1(self):
352 self._make_setuptools_abi()
353 self.run(["setup.py", "build"])
354 self.check_produced_files({'setup.py': None,
355 'build': '?',
356 'src0': {'pack2': {'__init__.py': None,
357 '_build.py': None}}})
358
359 @chdir_to_tmp
360 def test_setuptools_abi_2(self):
361 self._make_setuptools_abi()
362 self.run(["setup.py", "build_ext", "-i"])
363 self.check_produced_files({'setup.py': None,
364 'src0': {'pack2': {'__init__.py': None,
365 '_build.py': None,
366 'mymod.py': None}}})
367
368 def _make_setuptools_api(self):
369 self._prepare_setuptools()
370 os.mkdir("src1")
371 os.mkdir(os.path.join("src1", "pack3"))
372 with open(os.path.join("src1", "pack3", "__init__.py"), "w") as f:
373 pass
374 with open(os.path.join("src1", "pack3", "_build.py"), "w") as f:
375 f.write("""if 1:
376 import cffi
377 ffi = cffi.FFI()
378 ffi.set_source("pack3.mymod", "/*code would be here*/")
379 ffi._hi_there = 42
380 """)
381 with open("setup.py", "w") as f:
382 f.write("from __future__ import print_function\n"
383 """if 1:
384 from setuptools import setup
385 from distutils.command.build_ext import build_ext
386 import os
387
388 class TestBuildExt(build_ext):
389 def pre_run(self, ext, ffi):
390 print('_make_setuptools_api: in pre_run:', end=" ")
391 assert ffi._hi_there == 42
392 assert ext.name == "pack3.mymod"
393 fn = os.path.join(os.path.dirname(self.build_lib),
394 '..', 'see_me')
395 print('creating %r' % (fn,))
396 open(fn, 'w').close()
397
398 setup(name='example1',
399 version='0.1',
400 packages=['pack3'],
401 package_dir={'': 'src1'},
402 cffi_modules=["src1/pack3/_build.py:ffi"],
403 cmdclass={'build_ext': TestBuildExt},
404 )
405 """)
406
407 @chdir_to_tmp
408 def test_setuptools_api_1(self):
409 self._make_setuptools_api()
410 self.run(["setup.py", "build"])
411 self.check_produced_files({'setup.py': None,
412 'build': '?',
413 'see_me': None,
414 'src1': {'pack3': {'__init__.py': None,
415 '_build.py': None}}})
416
417 @chdir_to_tmp
418 def test_setuptools_api_2(self):
419 self._make_setuptools_api()
420 self.run(["setup.py", "build_ext", "-i"])
421 self.check_produced_files({'setup.py': None,
422 'build': '?',
423 'see_me': None,
424 'src1': {'pack3': {'__init__.py': None,
425 '_build.py': None,
426 'mymod.SO': None}}})
0 import sys
1
2 def pytest_ignore_collect(path):
3 if '__pypy__' not in sys.builtin_module_names:
4 return True
0 # Generated by pypy/tool/import_cffi.py
0 /* Generated by pypy/tool/import_cffi.py */
1 #include <stdio.h>
2
3 #ifdef _MSC_VER
4 #include <windows.h>
5 #endif
6
7 extern int add1(int, int);
8
9
10 int main(void)
11 {
12 int x, y;
13 x = add1(40, 2);
14 y = add1(100, -5);
15 printf("got: %d %d\n", x, y);
16 #ifdef _MSC_VER
17 if (x == 0 && y == 0)
18 Sleep(2000);
19 #endif
20 return 0;
21 }
0 # Generated by pypy/tool/import_cffi.py
1 import cffi
2
3 ffi = cffi.FFI()
4
5 ffi.embedding_api("""
6 int add1(int, int);
7 """)
8
9 ffi.embedding_init_code(r"""
10 import sys, time
11 sys.stdout.write("preparing")
12 for i in range(3):
13 sys.stdout.flush()
14 time.sleep(0.2)
15 sys.stdout.write(".")
16 sys.stdout.write("\n")
17
18 from _add1_cffi import ffi
19
20 int(ord("A")) # check that built-ins are there
21
22 @ffi.def_extern()
23 def add1(x, y):
24 sys.stdout.write("adding %d and %d\n" % (x, y))
25 sys.stdout.flush()
26 return x + y
27 """)
28
29 ffi.set_source("_add1_cffi", """
30 """)
31
32 fn = ffi.compile(verbose=True)
33 print('FILENAME: %s' % (fn,))
0 /* Generated by pypy/tool/import_cffi.py */
1 #include <stdio.h>
2
3 extern int add1(int, int);
4 extern int add2(int, int, int);
5
6
7 int main(void)
8 {
9 int x, y;
10 x = add1(40, 2);
11 y = add2(100, -5, -20);
12 printf("got: %d %d\n", x, y);
13 return 0;
14 }
0 # Generated by pypy/tool/import_cffi.py
1 import cffi
2
3 ffi = cffi.FFI()
4
5 ffi.embedding_api("""
6 int add2(int, int, int);
7 """)
8
9 ffi.embedding_init_code(r"""
10 import sys
11 sys.stdout.write("prepADD2\n")
12
13 assert '_add2_cffi' in sys.modules
14 m = sys.modules['_add2_cffi']
15 import _add2_cffi
16 ffi = _add2_cffi.ffi
17
18 @ffi.def_extern()
19 def add2(x, y, z):
20 sys.stdout.write("adding %d and %d and %d\n" % (x, y, z))
21 sys.stdout.flush()
22 return x + y + z
23 """)
24
25 ffi.set_source("_add2_cffi", """
26 """)
27
28 fn = ffi.compile(verbose=True)
29 print('FILENAME: %s' % (fn,))
0 # Generated by pypy/tool/import_cffi.py
1 import cffi
2
3 ffi = cffi.FFI()
4
5 ffi.embedding_api("""
6 int add3(int, int, int, int);
7 """)
8
9 ffi.embedding_init_code(r"""
10 from _add3_cffi import ffi
11 import sys
12
13 @ffi.def_extern()
14 def add3(x, y, z, t):
15 sys.stdout.write("adding %d, %d, %d, %d\n" % (x, y, z, t))
16 sys.stdout.flush()
17 return x + y + z + t
18 """)
19
20 ffi.set_source("_add3_cffi", """
21 """)
22
23 fn = ffi.compile(verbose=True)
24 print('FILENAME: %s' % (fn,))
0 /* Generated by pypy/tool/import_cffi.py */
1 #include <stdio.h>
2
3 #ifdef _MSC_VER
4 # define DLLIMPORT __declspec(dllimport)
5 #else
6 # define DLLIMPORT extern
7 #endif
8
9 DLLIMPORT int add_rec(int, int);
10 DLLIMPORT int (*my_callback)(int);
11
12 static int some_callback(int x)
13 {
14 printf("some_callback(%d)\n", x);
15 fflush(stdout);
16 return add_rec(x, 9);
17 }
18
19 int main(void)
20 {
21 int x, y;
22 my_callback = some_callback;
23 x = add_rec(40, 2);
24 y = add_rec(100, -5);
25 printf("got: %d %d\n", x, y);
26 return 0;
27 }
0 # Generated by pypy/tool/import_cffi.py
1 import cffi
2
3 ffi = cffi.FFI()
4
5 ffi.embedding_api("""
6 int (*my_callback)(int);
7 int add_rec(int, int);
8 """)
9
10 ffi.embedding_init_code(r"""
11 from _add_recursive_cffi import ffi, lib
12 import sys
13 print("preparing REC")
14 sys.stdout.flush()
15
16 @ffi.def_extern()
17 def add_rec(x, y):
18 print("adding %d and %d" % (x, y))
19 sys.stdout.flush()
20 return x + y
21
22 x = lib.my_callback(400)
23 print('<<< %d >>>' % (x,))
24 """)
25
26 ffi.set_source("_add_recursive_cffi", """
27 /* use CFFI_DLLEXPORT: on windows, it expands to __declspec(dllexport),
28 which is needed to export a variable from a dll */
29 CFFI_DLLEXPORT int (*my_callback)(int);
30 """)
31
32 fn = ffi.compile(verbose=True)
33 print('FILENAME: %s' % (fn,))
0 # Generated by pypy/tool/import_cffi.py
1 import cffi
2
3 ffi = cffi.FFI()
4
5 ffi.embedding_api("")
6
7 ffi.set_source("_empty_cffi", "")
8
9 fn = ffi.compile(verbose=True)
10 print('FILENAME: %s' % (fn,))
0 # Generated by pypy/tool/import_cffi.py
1 import cffi
2
3 ffi = cffi.FFI()
4
5 ffi.embedding_api("""
6 int add1(int, int);
7 """)
8
9 ffi.embedding_init_code(r"""
10 raise KeyError
11 """)
12
13 ffi.set_source("_initerror_cffi", """
14 """)
15
16 fn = ffi.compile(verbose=True)
17 print('FILENAME: %s' % (fn,))
18
0 /* Generated by pypy/tool/import_cffi.py */
1 #include <stdio.h>
2 #include <assert.h>
3 #include <sys/time.h>
4 #ifdef PTEST_USE_THREAD
5 # include <pthread.h>
6 static pthread_mutex_t mutex1 = PTHREAD_MUTEX_INITIALIZER;
7 static pthread_cond_t cond1 = PTHREAD_COND_INITIALIZER;
8 static int remaining;
9 #endif
10
11
12 extern int add1(int, int);
13
14
15 static double time_delta(struct timeval *stop, struct timeval *start)
16 {
17 return (stop->tv_sec - start->tv_sec) +
18 1e-6 * (stop->tv_usec - start->tv_usec);
19 }
20
21 static double measure(void)
22 {
23 long long i, iterations;
24 int result;
25 struct timeval start, stop;
26 double elapsed;
27
28 add1(0, 0); /* prepare off-line */
29
30 i = 0;
31 iterations = 1000;
32 result = gettimeofday(&start, NULL);
33 assert(result == 0);
34
35 while (1) {
36 for (; i < iterations; i++) {
37 add1(((int)i) & 0xaaaaaa, ((int)i) & 0x555555);
38 }
39 result = gettimeofday(&stop, NULL);
40 assert(result == 0);
41
42 elapsed = time_delta(&stop, &start);
43 assert(elapsed >= 0.0);
44 if (elapsed > 2.5)
45 break;
46 iterations = iterations * 3 / 2;
47 }
48
49 return elapsed / (double)iterations;
50 }
51
52 static void *start_routine(void *arg)
53 {
54 double t = measure();
55 printf("time per call: %.3g\n", t);
56
57 #ifdef PTEST_USE_THREAD
58 pthread_mutex_lock(&mutex1);
59 remaining -= 1;
60 if (!remaining)
61 pthread_cond_signal(&cond1);
62 pthread_mutex_unlock(&mutex1);
63 #endif
64
65 return arg;
66 }
67
68
69 int main(void)
70 {
71 #ifndef PTEST_USE_THREAD
72 start_routine(0);
73 #else
74 pthread_t th;
75 int i, status;
76
77 add1(0, 0); /* this is the main thread */
78
79 remaining = PTEST_USE_THREAD;
80 for (i = 0; i < PTEST_USE_THREAD; i++) {
81 status = pthread_create(&th, NULL, start_routine, NULL);
82 assert(status == 0);
83 }
84 pthread_mutex_lock(&mutex1);
85 while (remaining)
86 pthread_cond_wait(&cond1, &mutex1);
87 pthread_mutex_unlock(&mutex1);
88 #endif
89 return 0;
90 }
0 # Generated by pypy/tool/import_cffi.py
1 import cffi
2
3 ffi = cffi.FFI()
4
5 ffi.embedding_api("""
6 int add1(int, int);
7 """)
8
9 ffi.embedding_init_code(r"""
10 from _perf_cffi import ffi
11
12 @ffi.def_extern()
13 def add1(x, y):
14 return x + y
15 """)
16
17 ffi.set_source("_perf_cffi", """
18 """)
19
20 fn = ffi.compile(verbose=True)
21 print('FILENAME: %s' % (fn,))
0 # Generated by pypy/tool/import_cffi.py
1 import py
2 import sys, os, re
3 import shutil, subprocess, time
4 from extra_tests.cffi_tests.udir import udir
5 import cffi
6
7
8 local_dir = os.path.dirname(os.path.abspath(__file__))
9 _link_error = '?'
10
11 def check_lib_python_found(tmpdir):
12 global _link_error
13 if _link_error == '?':
14 ffi = cffi.FFI()
15 kwds = {}
16 ffi._apply_embedding_fix(kwds)
17 ffi.set_source("_test_lib_python_found", "", **kwds)
18 try:
19 ffi.compile(tmpdir=tmpdir, verbose=True)
20 except cffi.VerificationError as e:
21 _link_error = e
22 else:
23 _link_error = None
24 if _link_error:
25 py.test.skip(str(_link_error))
26
27
28 def prefix_pythonpath():
29 cffi_base = os.path.dirname(os.path.dirname(local_dir))
30 pythonpath = org_env.get('PYTHONPATH', '').split(os.pathsep)
31 if cffi_base not in pythonpath:
32 pythonpath.insert(0, cffi_base)
33 return os.pathsep.join(pythonpath)
34
35 def copy_away_env():
36 global org_env
37 try:
38 org_env
39 except NameError:
40 org_env = os.environ.copy()
41
42
43 class EmbeddingTests:
44 _compiled_modules = {}
45
46 def setup_method(self, meth):
47 check_lib_python_found(str(udir.ensure('embedding', dir=1)))
48 self._path = udir.join('embedding', meth.__name__)
49 if sys.platform == "win32" or sys.platform == "darwin":
50 self._compiled_modules.clear() # workaround
51
52 def get_path(self):
53 return str(self._path.ensure(dir=1))
54
55 def _run_base(self, args, **kwds):
56 print('RUNNING:', args, kwds)
57 return subprocess.Popen(args, **kwds)
58
59 def _run(self, args):
60 popen = self._run_base(args, cwd=self.get_path(),
61 stdout=subprocess.PIPE,
62 universal_newlines=True)
63 output = popen.stdout.read()
64 err = popen.wait()
65 if err:
66 raise OSError("popen failed with exit code %r: %r" % (
67 err, args))
68 print(output.rstrip())
69 return output
70
71 def prepare_module(self, name):
72 self.patch_environment()
73 if name not in self._compiled_modules:
74 path = self.get_path()
75 filename = '%s.py' % name
76 # NOTE: if you have an .egg globally installed with an older
77 # version of cffi, this will not work, because sys.path ends
78 # up with the .egg before the PYTHONPATH entries. I didn't
79 # find a solution to that: we could hack sys.path inside the
80 # script run here, but we can't hack it in the same way in
81 # execute().
82 pathname = os.path.join(path, filename)
83 with open(pathname, 'w') as g:
84 g.write('''
85 # https://bugs.python.org/issue23246
86 import sys
87 if sys.platform == 'win32':
88 try:
89 import setuptools
90 except ImportError:
91 pass
92 ''')
93 with open(os.path.join(local_dir, filename), 'r') as f:
94 g.write(f.read())
95
96 output = self._run([sys.executable, pathname])
97 match = re.compile(r"\bFILENAME: (.+)").search(output)
98 assert match
99 dynamic_lib_name = match.group(1)
100 if sys.platform == 'win32':
101 assert dynamic_lib_name.endswith('_cffi.dll')
102 elif sys.platform == 'darwin':
103 assert dynamic_lib_name.endswith('_cffi.dylib')
104 else:
105 assert dynamic_lib_name.endswith('_cffi.so')
106 self._compiled_modules[name] = dynamic_lib_name
107 return self._compiled_modules[name]
108
109 def compile(self, name, modules, opt=False, threads=False, defines={}):
110 path = self.get_path()
111 filename = '%s.c' % name
112 shutil.copy(os.path.join(local_dir, filename), path)
113 shutil.copy(os.path.join(local_dir, 'thread-test.h'), path)
114 import distutils.ccompiler
115 curdir = os.getcwd()
116 try:
117 os.chdir(self.get_path())
118 c = distutils.ccompiler.new_compiler()
119 print('compiling %s with %r' % (name, modules))
120 extra_preargs = []
121 debug = True
122 if sys.platform == 'win32':
123 libfiles = []
124 for m in modules:
125 m = os.path.basename(m)
126 assert m.endswith('.dll')
127 libfiles.append('Release\\%s.lib' % m[:-4])
128 modules = libfiles
129 extra_preargs.append('/MANIFEST')
130 debug = False # you need to install extra stuff
131 # for this to work
132 elif threads:
133 extra_preargs.append('-pthread')
134 objects = c.compile([filename], macros=sorted(defines.items()),
135 debug=debug)
136 c.link_executable(objects + modules, name, extra_preargs=extra_preargs)
137 finally:
138 os.chdir(curdir)
139
140 def patch_environment(self):
141 copy_away_env()
142 path = self.get_path()
143 # for libpypy-c.dll or Python27.dll
144 path = os.path.split(sys.executable)[0] + os.path.pathsep + path
145 env_extra = {'PYTHONPATH': prefix_pythonpath()}
146 if sys.platform == 'win32':
147 envname = 'PATH'
148 else:
149 envname = 'LD_LIBRARY_PATH'
150 libpath = org_env.get(envname)
151 if libpath:
152 libpath = path + os.path.pathsep + libpath
153 else:
154 libpath = path
155 env_extra[envname] = libpath
156 for key, value in sorted(env_extra.items()):
157 if os.environ.get(key) != value:
158 print('* setting env var %r to %r' % (key, value))
159 os.environ[key] = value
160
161 def execute(self, name):
162 path = self.get_path()
163 print('running %r in %r' % (name, path))
164 executable_name = name
165 if sys.platform == 'win32':
166 executable_name = os.path.join(path, executable_name + '.exe')
167 else:
168 executable_name = os.path.join('.', executable_name)
169 popen = self._run_base([executable_name], cwd=path,
170 stdout=subprocess.PIPE,
171 universal_newlines=True)
172 result = popen.stdout.read()
173 err = popen.wait()
174 if err:
175 raise OSError("%r failed with exit code %r" % (name, err))
176 return result
177
178
179 class TestBasic(EmbeddingTests):
180 def test_empty(self):
181 empty_cffi = self.prepare_module('empty')
182
183 def test_basic(self):
184 add1_cffi = self.prepare_module('add1')
185 self.compile('add1-test', [add1_cffi])
186 output = self.execute('add1-test')
187 assert output == ("preparing...\n"
188 "adding 40 and 2\n"
189 "adding 100 and -5\n"
190 "got: 42 95\n")
191
192 def test_two_modules(self):
193 add1_cffi = self.prepare_module('add1')
194 add2_cffi = self.prepare_module('add2')
195 self.compile('add2-test', [add1_cffi, add2_cffi])
196 output = self.execute('add2-test')
197 assert output == ("preparing...\n"
198 "adding 40 and 2\n"
199 "prepADD2\n"
200 "adding 100 and -5 and -20\n"
201 "got: 42 75\n")
202
203 def test_init_time_error(self):
204 initerror_cffi = self.prepare_module('initerror')
205 self.compile('add1-test', [initerror_cffi])
206 output = self.execute('add1-test')
207 assert output == "got: 0 0\n" # plus lots of info to stderr
0 # Generated by pypy/tool/import_cffi.py
1 import sys
2 from extra_tests.cffi_tests.embedding.test_basic import EmbeddingTests
3
4 if sys.platform == 'win32':
5 import py
6 py.test.skip("written with POSIX functions")
7
8
9 class TestPerformance(EmbeddingTests):
10 def test_perf_single_threaded(self):
11 perf_cffi = self.prepare_module('perf')
12 self.compile('perf-test', [perf_cffi], opt=True)
13 output = self.execute('perf-test')
14 print('='*79)
15 print(output.rstrip())
16 print('='*79)
17
18 def test_perf_in_1_thread(self):
19 perf_cffi = self.prepare_module('perf')
20 self.compile('perf-test', [perf_cffi], opt=True, threads=True,
21 defines={'PTEST_USE_THREAD': '1'})
22 output = self.execute('perf-test')
23 print('='*79)
24 print(output.rstrip())
25 print('='*79)
26
27 def test_perf_in_2_threads(self):
28 perf_cffi = self.prepare_module('perf')
29 self.compile('perf-test', [perf_cffi], opt=True, threads=True,
30 defines={'PTEST_USE_THREAD': '2'})
31 output = self.execute('perf-test')
32 print('='*79)
33 print(output.rstrip())
34 print('='*79)
35
36 def test_perf_in_4_threads(self):
37 perf_cffi = self.prepare_module('perf')
38 self.compile('perf-test', [perf_cffi], opt=True, threads=True,
39 defines={'PTEST_USE_THREAD': '4'})
40 output = self.execute('perf-test')
41 print('='*79)
42 print(output.rstrip())
43 print('='*79)
44
45 def test_perf_in_8_threads(self):
46 perf_cffi = self.prepare_module('perf')
47 self.compile('perf-test', [perf_cffi], opt=True, threads=True,
48 defines={'PTEST_USE_THREAD': '8'})
49 output = self.execute('perf-test')
50 print('='*79)
51 print(output.rstrip())
52 print('='*79)
0 # Generated by pypy/tool/import_cffi.py
1 from extra_tests.cffi_tests.embedding.test_basic import EmbeddingTests
2
3
4 class TestRecursive(EmbeddingTests):
5 def test_recursive(self):
6 add_recursive_cffi = self.prepare_module('add_recursive')
7 self.compile('add_recursive-test', [add_recursive_cffi])
8 output = self.execute('add_recursive-test')
9 assert output == ("preparing REC\n"
10 "some_callback(400)\n"
11 "adding 400 and 9\n"
12 "<<< 409 >>>\n"
13 "adding 40 and 2\n"
14 "adding 100 and -5\n"
15 "got: 42 95\n")
0 # Generated by pypy/tool/import_cffi.py
1 from extra_tests.cffi_tests.embedding.test_basic import EmbeddingTests
2
3
4 class TestThread(EmbeddingTests):
5 def test_first_calls_in_parallel(self):
6 add1_cffi = self.prepare_module('add1')
7 self.compile('thread1-test', [add1_cffi], threads=True)
8 for i in range(20):
9 output = self.execute('thread1-test')
10 assert output == ("starting\n"
11 "preparing...\n" +
12 "adding 40 and 2\n" * 10 +
13 "done\n")
14
15 def _take_out(self, text, content):
16 assert content in text
17 i = text.index(content)
18 return text[:i] + text[i+len(content):]
19
20 def test_init_different_modules_in_different_threads(self):
21 add1_cffi = self.prepare_module('add1')
22 add2_cffi = self.prepare_module('add2')
23 self.compile('thread2-test', [add1_cffi, add2_cffi], threads=True)
24 output = self.execute('thread2-test')
25 output = self._take_out(output, "preparing")
26 output = self._take_out(output, ".")
27 output = self._take_out(output, ".")
28 # at least the 3rd dot should be after everything from ADD2
29 assert output == ("starting\n"
30 "prepADD2\n"
31 "adding 1000 and 200 and 30\n"
32 ".\n"
33 "adding 40 and 2\n"
34 "done\n")
35
36 def test_alt_issue(self):
37 add1_cffi = self.prepare_module('add1')
38 add2_cffi = self.prepare_module('add2')
39 self.compile('thread2-test', [add1_cffi, add2_cffi],
40 threads=True, defines={'T2TEST_AGAIN_ADD1': '1'})
41 output = self.execute('thread2-test')
42 output = self._take_out(output, "adding 40 and 2\n")
43 assert output == ("starting\n"
44 "preparing...\n"
45 "adding -1 and -1\n"
46 "prepADD2\n"
47 "adding 1000 and 200 and 30\n"
48 "done\n")
49
50 def test_load_in_parallel_more(self):
51 add2_cffi = self.prepare_module('add2')
52 add3_cffi = self.prepare_module('add3')
53 self.compile('thread3-test', [add2_cffi, add3_cffi], threads=True)
54 for i in range(150):
55 output = self.execute('thread3-test')
56 for j in range(10):
57 output = self._take_out(output, "adding 40 and 2 and 100\n")
58 output = self._take_out(output, "adding 1000, 200, 30, 4\n")
59 assert output == ("starting\n"
60 "prepADD2\n"
61 "done\n")
0 # Generated by pypy/tool/import_cffi.py
1 from extra_tests.cffi_tests.embedding.test_basic import EmbeddingTests
2
3
4 class TestThreadLocal(EmbeddingTests):
5 def test_thread_local(self):
6 tlocal_cffi = self.prepare_module('tlocal')
7 self.compile('tlocal-test', [tlocal_cffi], threads=True)
8 for i in range(10):
9 output = self.execute('tlocal-test')
10 assert output == "done\n"
0 /* Generated by pypy/tool/import_cffi.py */
1 /************************************************************/
2 #ifndef _MSC_VER
3 /************************************************************/
4
5
6 #include <pthread.h>
7
8 /* don't include <semaphore.h>, it is not available on OS/X */
9
10 typedef struct {
11 pthread_mutex_t mutex1;
12 pthread_cond_t cond1;
13 unsigned int value;
14 } sem_t;
15
16 static int sem_init(sem_t *sem, int pshared, unsigned int value)
17 {
18 assert(pshared == 0);
19 sem->value = value;
20 return (pthread_mutex_init(&sem->mutex1, NULL) ||
21 pthread_cond_init(&sem->cond1, NULL));
22 }
23
24 static int sem_post(sem_t *sem)
25 {
26 pthread_mutex_lock(&sem->mutex1);
27 sem->value += 1;
28 pthread_cond_signal(&sem->cond1);
29 pthread_mutex_unlock(&sem->mutex1);
30 return 0;
31 }
32
33 static int sem_wait(sem_t *sem)
34 {
35 pthread_mutex_lock(&sem->mutex1);
36 while (sem->value == 0)
37 pthread_cond_wait(&sem->cond1, &sem->mutex1);
38 sem->value -= 1;
39 pthread_mutex_unlock(&sem->mutex1);
40 return 0;
41 }
42
43
44 /************************************************************/
45 #else
46 /************************************************************/
47
48
49 /* Very quick and dirty, just what I need for these tests.
50 Don't use directly in any real code!
51 */
52
53 #include <Windows.h>
54 #include <assert.h>
55
56 typedef HANDLE sem_t;
57 typedef HANDLE pthread_t;
58
59 static int sem_init(sem_t *sem, int pshared, unsigned int value)
60 {
61 assert(pshared == 0);
62 assert(value == 0);
63 *sem = CreateSemaphore(NULL, 0, 999, NULL);
64 return *sem ? 0 : -1;
65 }
66
67 static int sem_post(sem_t *sem)
68 {
69 return ReleaseSemaphore(*sem, 1, NULL) ? 0 : -1;
70 }
71
72 static int sem_wait(sem_t *sem)
73 {
74 WaitForSingleObject(*sem, INFINITE);
75 return 0;
76 }
77
78 static DWORD WINAPI myThreadProc(LPVOID lpParameter)
79 {
80 void *(* start_routine)(void *) = (void *(*)(void *))lpParameter;
81 start_routine(NULL);
82 return 0;
83 }
84
85 static int pthread_create(pthread_t *thread, void *attr,
86 void *start_routine(void *), void *arg)
87 {
88 assert(arg == NULL);
89 *thread = CreateThread(NULL, 0, myThreadProc, start_routine, 0, NULL);
90 return *thread ? 0 : -1;
91 }
92
93
94 /************************************************************/
95 #endif
96 /************************************************************/
0 /* Generated by pypy/tool/import_cffi.py */
1 #include <stdio.h>
2 #include <assert.h>
3 #include "thread-test.h"
4
5 #define NTHREADS 10
6
7
8 extern int add1(int, int);
9
10 static sem_t done;
11
12
13 static void *start_routine(void *arg)
14 {
15 int x, status;
16 x = add1(40, 2);
17 assert(x == 42);
18
19 status = sem_post(&done);
20 assert(status == 0);
21
22 return arg;
23 }
24
25 int main(void)
26 {
27 pthread_t th;
28 int i, status = sem_init(&done, 0, 0);
29 assert(status == 0);
30
31 printf("starting\n");
32 fflush(stdout);
33 for (i = 0; i < NTHREADS; i++) {
34 status = pthread_create(&th, NULL, start_routine, NULL);
35 assert(status == 0);
36 }
37 for (i = 0; i < NTHREADS; i++) {
38 status = sem_wait(&done);
39 assert(status == 0);
40 }
41 printf("done\n");
42 return 0;
43 }
0 /* Generated by pypy/tool/import_cffi.py */
1 #include <stdio.h>
2 #include <assert.h>
3 #include "thread-test.h"
4
5 extern int add1(int, int);
6 extern int add2(int, int, int);
7
8 static sem_t done;
9
10
11 static void *start_routine_1(void *arg)
12 {
13 int x, status;
14 x = add1(40, 2);
15 assert(x == 42);
16
17 status = sem_post(&done);
18 assert(status == 0);
19
20 return arg;
21 }
22
23 static void *start_routine_2(void *arg)
24 {
25 int x, status;
26 #ifdef T2TEST_AGAIN_ADD1
27 add1(-1, -1);
28 #endif
29 x = add2(1000, 200, 30);
30 assert(x == 1230);
31
32 status = sem_post(&done);
33 assert(status == 0);
34
35 return arg;
36 }
37
38 int main(void)
39 {
40 pthread_t th;
41 int i, status = sem_init(&done, 0, 0);
42 assert(status == 0);
43
44 printf("starting\n");
45 fflush(stdout);
46 status = pthread_create(&th, NULL, start_routine_1, NULL);
47 assert(status == 0);
48 status = pthread_create(&th, NULL, start_routine_2, NULL);
49 assert(status == 0);
50
51 for (i = 0; i < 2; i++) {
52 status = sem_wait(&done);
53 assert(status == 0);
54 }
55 printf("done\n");
56 return 0;
57 }
0 /* Generated by pypy/tool/import_cffi.py */
1 #include <stdio.h>
2 #include <assert.h>
3 #include "thread-test.h"
4
5 extern int add2(int, int, int);
6 extern int add3(int, int, int, int);
7
8 static sem_t done;
9
10
11 static void *start_routine_2(void *arg)
12 {
13 int x, status;
14 x = add2(40, 2, 100);
15 assert(x == 142);
16
17 status = sem_post(&done);
18 assert(status == 0);
19
20 return arg;
21 }
22
23 static void *start_routine_3(void *arg)
24 {
25 int x, status;
26 x = add3(1000, 200, 30, 4);
27 assert(x == 1234);
28
29 status = sem_post(&done);
30 assert(status == 0);
31
32 return arg;
33 }
34
35 int main(void)
36 {
37 pthread_t th;
38 int i, status = sem_init(&done, 0, 0);
39 assert(status == 0);
40
41 printf("starting\n");
42 fflush(stdout);
43 for (i = 0; i < 10; i++) {
44 status = pthread_create(&th, NULL, start_routine_2, NULL);
45 assert(status == 0);
46 status = pthread_create(&th, NULL, start_routine_3, NULL);
47 assert(status == 0);
48 }
49 for (i = 0; i < 20; i++) {
50 status = sem_wait(&done);
51 assert(status == 0);
52 }
53 printf("done\n");
54 return 0;
55 }
0 /* Generated by pypy/tool/import_cffi.py */
1 #include <stdio.h>
2 #include <assert.h>
3 #include "thread-test.h"
4
5 #define NTHREADS 10
6
7
8 extern int add1(int, int);
9
10 static sem_t done;
11
12
13 static void *start_routine(void *arg)
14 {
15 int i, x, expected, status;
16
17 expected = add1(40, 2);
18 assert((expected % 1000) == 42);
19
20 for (i=0; i<10; i++) {
21 x = add1(50, i);
22 assert(x == expected + 8 + i);
23 }
24
25 status = sem_post(&done);
26 assert(status == 0);
27
28 return arg;
29 }
30
31 int main(void)
32 {
33 pthread_t th;
34 int i, status = sem_init(&done, 0, 0);
35 assert(status == 0);
36
37 for (i = 0; i < NTHREADS; i++) {
38 status = pthread_create(&th, NULL, start_routine, NULL);
39 assert(status == 0);
40 }
41 for (i = 0; i < NTHREADS; i++) {
42 status = sem_wait(&done);
43 assert(status == 0);
44 }
45 printf("done\n");
46 return 0;
47 }
0 # Generated by pypy/tool/import_cffi.py
1 import cffi
2
3 ffi = cffi.FFI()
4
5 ffi.embedding_api("""
6 int add1(int, int);
7 """)
8
9 ffi.embedding_init_code(r"""
10 from _tlocal_cffi import ffi
11 import itertools
12 try:
13 import thread
14 g_seen = itertools.count().next
15 except ImportError:
16 import _thread as thread # py3
17 g_seen = itertools.count().__next__
18 tloc = thread._local()
19
20 @ffi.def_extern()
21 def add1(x, y):
22 try:
23 num = tloc.num
24 except AttributeError:
25 num = tloc.num = g_seen() * 1000
26 return x + y + num
27 """)
28
29 ffi.set_source("_tlocal_cffi", """
30 """)
31
32 fn = ffi.compile(verbose=True)
33 print('FILENAME: %s' % (fn,))
0 # Generated by pypy/tool/import_cffi.py
1 import sys
2
3 if sys.version_info < (3,):
4 __all__ = ['u']
5
6 class U(object):
7 def __add__(self, other):
8 return eval('u'+repr(other).replace(r'\\u', r'\u')
9 .replace(r'\\U', r'\U'))
10 u = U()
11 long = long # for further "from extra_tests.cffi_tests.support import long"
12 assert u+'a\x00b' == eval(r"u'a\x00b'")
13 assert u+'a\u1234b' == eval(r"u'a\u1234b'")
14 assert u+'a\U00012345b' == eval(r"u'a\U00012345b'")
15
16 else:
17 __all__ = ['u', 'unicode', 'long']
18 u = ""
19 unicode = str
20 long = int
21
22
23 class StdErrCapture(object):
24 """Capture writes to sys.stderr (not to the underlying file descriptor)."""
25 def __enter__(self):
26 try:
27 from StringIO import StringIO
28 except ImportError:
29 from io import StringIO
30 self.old_stderr = sys.stderr
31 sys.stderr = f = StringIO()
32 return f
33 def __exit__(self, *args):
34 sys.stderr = self.old_stderr
35
36
37 class FdWriteCapture(object):
38 """xxx limited to capture at most 512 bytes of output, according
39 to the Posix manual."""
40
41 def __init__(self, capture_fd=2): # stderr by default
42 if sys.platform == 'win32':
43 import py
44 py.test.skip("seems not to work, too bad")
45 self.capture_fd = capture_fd
46
47 def __enter__(self):
48 import os
49 self.read_fd, self.write_fd = os.pipe()
50 self.copy_fd = os.dup(self.capture_fd)
51 os.dup2(self.write_fd, self.capture_fd)
52 return self
53
54 def __exit__(self, *args):
55 import os
56 os.dup2(self.copy_fd, self.capture_fd)
57 os.close(self.copy_fd)
58 os.close(self.write_fd)
59 self._value = os.read(self.read_fd, 512)
60 os.close(self.read_fd)
61
62 def getvalue(self):
63 return self._value
64
65 def _verify(ffi, module_name, preamble, *args, **kwds):
66 import imp
67 from cffi.recompiler import recompile
68 from .udir import udir
69 assert module_name not in sys.modules, "module name conflict: %r" % (
70 module_name,)
71 kwds.setdefault('tmpdir', str(udir))
72 outputfilename = recompile(ffi, module_name, preamble, *args, **kwds)
73 module = imp.load_dynamic(module_name, outputfilename)
74 #
75 # hack hack hack: copy all *bound methods* from module.ffi back to the
76 # ffi instance. Then calls like ffi.new() will invoke module.ffi.new().
77 for name in dir(module.ffi):
78 if not name.startswith('_'):
79 attr = getattr(module.ffi, name)
80 if attr is not getattr(ffi, name, object()):
81 setattr(ffi, name, attr)
82 def typeof_disabled(*args, **kwds):
83 raise NotImplementedError
84 ffi._typeof = typeof_disabled
85 for name in dir(ffi):
86 if not name.startswith('_') and not hasattr(module.ffi, name):
87 setattr(ffi, name, NotImplemented)
88 return module.lib
0 from email.parser import Parser
1
2 import py
3
4 import cffi
5 import pypy
6
7 egg_info = py.path.local(pypy.__file__)/'../../lib_pypy/cffi.egg-info/PKG-INFO'
8
9 def test_egg_version():
10 info = Parser().parsestr(egg_info.read())
11 assert info['version'] == cffi.__version__
0 # Generated by pypy/tool/import_cffi.py
1 import py
2 import sys
3
4 udir = py.path.local.make_numbered_dir(prefix = 'ffi-')
5
6
7 # Windows-only workaround for some configurations: see
8 # https://bugs.python.org/issue23246 (Python 2.7.9)
9 if sys.platform == 'win32':
10 try:
11 import setuptools
12 except ImportError:
13 pass
0 #if defined(_MSC_VER) || defined(__CYGWIN__)
1 #include <windows.h>
2 #define MS_WIN32
3 #endif
4
5 #ifdef _WIN32
6 #define EXPORT(x) __declspec(dllexport) x
7 #else
8 #define EXPORT(x) extern x
9 #endif
10
11 #include <stdlib.h>
12 #include <math.h>
13 #include <string.h>
14 #include <wchar.h>
15 #include <stdio.h>
16 #include <errno.h>
17
18 #define HAVE_LONG_LONG
19 #define LONG_LONG long long
20 #define HAVE_WCHAR_H
21
22
23 /* some functions handy for testing */
24
25 EXPORT(char *)my_strtok(char *token, const char *delim)
26 {
27 return strtok(token, delim);
28 }
29
30 EXPORT(char *)my_strchr(const char *s, int c)
31 {
32 return strchr(s, c);
33 }
34
35
36 EXPORT(double) my_sqrt(double a)
37 {
38 return sqrt(a);
39 }
40
41 EXPORT(void) my_qsort(void *base, size_t num, size_t width, int(*compare)(const void*, const void*))
42 {
43 qsort(base, num, width, compare);
44 }
45
46 EXPORT(char) deref_LP_c_char_p(char** argv)
47 {
48 char* s = *argv;
49 return s[0];
50 }
51
52 EXPORT(int *) _testfunc_ai8(int a[8])
53 {
54 return a;
55 }
56
57 EXPORT(void) _testfunc_v(int a, int b, int *presult)
58 {
59 *presult = a + b;
60 }
61
62 EXPORT(int) _testfunc_i_bhilfd(signed char b, short h, int i, long l, float f, double d)
63 {
64 /* printf("_testfunc_i_bhilfd got %d %d %d %ld %f %f\n",
65 b, h, i, l, f, d);
66 */
67 return (int)(b + h + i + l + f + d);
68 }
69
70 EXPORT(float) _testfunc_f_bhilfd(signed char b, short h, int i, long l, float f, double d)
71 {
72 /* printf("_testfunc_f_bhilfd got %d %d %d %ld %f %f\n",
73 b, h, i, l, f, d);
74 */
75 return (float)(b + h + i + l + f + d);
76 }
77
78 EXPORT(double) _testfunc_d_bhilfd(signed char b, short h, int i, long l, float f, double d)
79 {
80 /* printf("_testfunc_d_bhilfd got %d %d %d %ld %f %f\n",
81 b, h, i, l, f, d);
82 */
83 return (double)(b + h + i + l + f + d);
84 }
85
86 EXPORT(char *) _testfunc_p_p(void *s)
87 {
88 return (char *)s;
89 }
90
91 EXPORT(void *) _testfunc_c_p_p(int *argcp, char **argv)
92 {
93 return argv[(*argcp)-1];
94 }
95
96 EXPORT(void *) get_strchr(void)
97 {
98 return (void *)strchr;
99 }
100
101 EXPORT(char *) my_strdup(char *src)
102 {
103 char *dst = (char *)malloc(strlen(src)+1);
104 if (!dst)
105 return NULL;
106 strcpy(dst, src);
107 return dst;
108 }
109
110 EXPORT(void)my_free(void *ptr)
111 {
112 free(ptr);
113 }
114
115 #ifdef HAVE_WCHAR_H
116 EXPORT(wchar_t *) my_wcsdup(wchar_t *src)
117 {
118 size_t len = wcslen(src);
119 wchar_t *ptr = (wchar_t *)malloc((len + 1) * sizeof(wchar_t));
120 if (ptr == NULL)
121 return NULL;
122 memcpy(ptr, src, (len+1) * sizeof(wchar_t));
123 return ptr;
124 }
125
126 EXPORT(size_t) my_wcslen(wchar_t *src)
127 {
128 return wcslen(src);
129 }
130 #endif
131
132 #ifndef MS_WIN32
133 # ifndef __stdcall
134 # define __stdcall /* */
135 # endif
136 #endif
137
138 typedef struct {
139 int (*c)(int, int);
140 int (__stdcall *s)(int, int);
141 } FUNCS;
142
143 EXPORT(int) _testfunc_callfuncp(FUNCS *fp)
144 {
145 fp->c(1, 2);
146 fp->s(3, 4);
147 return 0;
148 }
149
150 EXPORT(int) _testfunc_deref_pointer(int *pi)
151 {
152 return *pi;
153 }
154
155 #ifdef MS_WIN32
156 EXPORT(int) _testfunc_piunk(IUnknown FAR *piunk)
157 {
158 piunk->lpVtbl->AddRef(piunk);
159 return piunk->lpVtbl->Release(piunk);
160 }
161 #endif
162
163 EXPORT(int) _testfunc_callback_with_pointer(int (*func)(int *))
164 {
165 int table[] = {1, 2, 3, 4, 5, 6, 7, 8, 9, 10};
166
167 return (*func)(table);
168 }
169
170 EXPORT(int) _testfunc_callback_opaque(int (*func)(void*), void* arg)
171 {
172 return (*func)(arg);
173 }
174
175 EXPORT(int) _testfunc_callback_void(void (*func)(void))
176 {
177 func();
178 return 0;
179 }
180
181 #ifdef HAVE_LONG_LONG
182 EXPORT(LONG_LONG) _testfunc_q_bhilfdq(signed char b, short h, int i, long l, float f,
183 double d, LONG_LONG q)
184 {
185 return (LONG_LONG)(b + h + i + l + f + d + q);
186 }
187
188 EXPORT(LONG_LONG) _testfunc_q_bhilfd(signed char b, short h, int i, long l, float f, double d)
189 {
190 return (LONG_LONG)(b + h + i + l + f + d);
191 }
192
193 EXPORT(int) _testfunc_callback_i_if(int value, int (*func)(int))
194 {
195 int sum = 0;
196 while (value != 0) {
197 sum += func(value);
198 value /= 2;
199 }
200 return sum;
201 }
202
203 EXPORT(LONG_LONG) _testfunc_callback_q_qf(LONG_LONG value,
204 LONG_LONG (*func)(LONG_LONG))
205 {
206 LONG_LONG sum = 0;
207
208 while (value != 0) {
209 sum += func(value);
210 value /= 2;
211 }
212 return sum;
213 }
214
215 #endif
216
217 typedef struct {
218 char *name;
219 char *value;
220 } SPAM;
221
222 typedef struct {
223 char *name;
224 int num_spams;
225 SPAM *spams;
226 } EGG;
227
228 SPAM my_spams[2] = {
229 { "name1", "value1" },
230 { "name2", "value2" },
231 };
232
233 EGG my_eggs[1] = {
234 { "first egg", 1, my_spams }
235 };
236
237 EXPORT(int) getSPAMANDEGGS(EGG **eggs)
238 {
239 *eggs = my_eggs;
240 return 1;
241 }
242
243 typedef struct tagpoint {
244 int x;
245 int y;
246 } point;
247
248 EXPORT(int) _testfunc_byval(point in, point *pout)
249 {
250 if (pout) {
251 pout->x = in.x;
252 pout->y = in.y;
253 }
254 return in.x + in.y;
255 }
256
257 EXPORT (int) an_integer = 42;
258
259 EXPORT(int) get_an_integer(void)
260 {
261 return an_integer;
262 }
263
264 EXPORT(char) a_string[16] = "0123456789abcdef";
265
266 EXPORT(int) get_a_string_char(int index)
267 {
268 return a_string[index];
269 }
270
271 EXPORT(double)
272 integrate(double a, double b, double (*f)(double), long nstep)
273 {
274 double x, sum=0.0, dx=(b-a)/(double)nstep;
275 for(x=a+0.5*dx; (b-x)*(x-a)>0.0; x+=dx)
276 {
277 double y = f(x);
278 printf("f(x)=%.1f\n", y);
279 sum += f(x);
280 }
281 return sum/(double)nstep;
282 }
283
284 typedef struct {
285 void (*initialize)(void *(*)(int), void(*)(void *));
286 } xxx_library;
287
288 static void _xxx_init(void *(*Xalloc)(int), void (*Xfree)(void *))
289 {
290 void *ptr;
291
292 printf("_xxx_init got %p %p\n", Xalloc, Xfree);
293 printf("calling\n");
294 ptr = Xalloc(32);
295 Xfree(ptr);
296 printf("calls done, ptr was %p\n", ptr);
297 }
298
299 xxx_library _xxx_lib = {
300 _xxx_init
301 };
302
303 EXPORT(xxx_library) *library_get(void)
304 {
305 return &_xxx_lib;
306 }
307
308 #ifdef MS_WIN32
309 /* See Don Box (german), pp 79ff. */
310 EXPORT(void) GetString(BSTR *pbstr)
311 {
312 *pbstr = SysAllocString(L"Goodbye!");
313 }
314 #endif
315
316 EXPORT(void) _py_func_si(char *s, int i)
317 {
318 }
319
320 EXPORT(void) _py_func(void)
321 {
322 }
323
324 EXPORT(LONG_LONG) last_tf_arg_s = 0;
325 EXPORT(unsigned LONG_LONG) last_tf_arg_u = 0;
326
327 struct BITS {
328 int A: 1, B:2, C:3, D:4, E: 5, F: 6, G: 7, H: 8, I: 9;
329 short M: 1, N: 2, O: 3, P: 4, Q: 5, R: 6, S: 7;
330 };
331
332 EXPORT(void) set_bitfields(struct BITS *bits, char name, int value)
333 {
334 switch (name) {
335 case 'A': bits->A = value; break;
336 case 'B': bits->B = value; break;
337 case 'C': bits->C = value; break;
338 case 'D': bits->D = value; break;
339 case 'E': bits->E = value; break;
340 case 'F': bits->F = value; break;
341 case 'G': bits->G = value; break;
342 case 'H': bits->H = value; break;
343 case 'I': bits->I = value; break;
344
345 case 'M': bits->M = value; break;
346 case 'N': bits->N = value; break;
347 case 'O': bits->O = value; break;
348 case 'P': bits->P = value; break;
349 case 'Q': bits->Q = value; break;
350 case 'R': bits->R = value; break;
351 case 'S': bits->S = value; break;
352 }
353 }
354
355 EXPORT(int) unpack_bitfields(struct BITS *bits, char name)
356 {
357 switch (name) {
358 case 'A': return bits->A;
359 case 'B': return bits->B;
360 case 'C': return bits->C;
361 case 'D': return bits->D;
362 case 'E': return bits->E;
363 case 'F': return bits->F;
364 case 'G': return bits->G;
365 case 'H': return bits->H;
366 case 'I': return bits->I;
367
368 case 'M': return bits->M;
369 case 'N': return bits->N;
370 case 'O': return bits->O;
371 case 'P': return bits->P;
372 case 'Q': return bits->Q;
373 case 'R': return bits->R;
374 case 'S': return bits->S;
375 }
376 return 0;
377 }
378
379 #define S last_tf_arg_s = (LONG_LONG)c
380 #define U last_tf_arg_u = (unsigned LONG_LONG)c
381
382 EXPORT(signed char) tf_b(signed char c) { S; return c/3; }
383 EXPORT(unsigned char) tf_B(unsigned char c) { U; return c/3; }
384 EXPORT(short) tf_h(short c) { S; return c/3; }
385 EXPORT(unsigned short) tf_H(unsigned short c) { U; return c/3; }
386 EXPORT(int) tf_i(int c) { S; return c/3; }
387 EXPORT(unsigned int) tf_I(unsigned int c) { U; return c/3; }
388 EXPORT(long) tf_l(long c) { S; return c/3; }
389 EXPORT(unsigned long) tf_L(unsigned long c) { U; return c/3; }
390 EXPORT(LONG_LONG) tf_q(LONG_LONG c) { S; return c/3; }
391 EXPORT(unsigned LONG_LONG) tf_Q(unsigned LONG_LONG c) { U; return c/3; }
392 EXPORT(float) tf_f(float c) { S; return c/3; }
393 EXPORT(double) tf_d(double c) { S; return c/3; }
394
395 #ifdef MS_WIN32
396 EXPORT(signed char) __stdcall s_tf_b(signed char c) { S; return c/3; }
397 EXPORT(unsigned char) __stdcall s_tf_B(unsigned char c) { U; return c/3; }
398 EXPORT(short) __stdcall s_tf_h(short c) { S; return c/3; }
399 EXPORT(unsigned short) __stdcall s_tf_H(unsigned short c) { U; return c/3; }
400 EXPORT(int) __stdcall s_tf_i(int c) { S; return c/3; }
401 EXPORT(unsigned int) __stdcall s_tf_I(unsigned int c) { U; return c/3; }
402 EXPORT(long) __stdcall s_tf_l(long c) { S; return c/3; }
403 EXPORT(unsigned long) __stdcall s_tf_L(unsigned long c) { U; return c/3; }
404 EXPORT(LONG_LONG) __stdcall s_tf_q(LONG_LONG c) { S; return c/3; }
405 EXPORT(unsigned LONG_LONG) __stdcall s_tf_Q(unsigned LONG_LONG c) { U; return c/3; }
406 EXPORT(float) __stdcall s_tf_f(float c) { S; return c/3; }
407 EXPORT(double) __stdcall s_tf_d(double c) { S; return c/3; }
408 #endif
409 /*******/
410
411 EXPORT(signed char) tf_bb(signed char x, signed char c) { S; return c/3; }
412 EXPORT(unsigned char) tf_bB(signed char x, unsigned char c) { U; return c/3; }
413 EXPORT(short) tf_bh(signed char x, short c) { S; return c/3; }
414 EXPORT(unsigned short) tf_bH(signed char x, unsigned short c) { U; return c/3; }
415 EXPORT(int) tf_bi(signed char x, int c) { S; return c/3; }
416 EXPORT(unsigned int) tf_bI(signed char x, unsigned int c) { U; return c/3; }
417 EXPORT(long) tf_bl(signed char x, long c) { S; return c/3; }
418 EXPORT(unsigned long) tf_bL(signed char x, unsigned long c) { U; return c/3; }
419 EXPORT(LONG_LONG) tf_bq(signed char x, LONG_LONG c) { S; return c/3; }
420 EXPORT(unsigned LONG_LONG) tf_bQ(signed char x, unsigned LONG_LONG c) { U; return c/3; }
421 EXPORT(float) tf_bf(signed char x, float c) { S; return c/3; }
422 EXPORT(double) tf_bd(signed char x, double c) { S; return c/3; }
423 EXPORT(void) tv_i(int c) { S; return; }
424
425 #ifdef MS_WIN32
426 EXPORT(signed char) __stdcall s_tf_bb(signed char x, signed char c) { S; return c/3; }
427 EXPORT(unsigned char) __stdcall s_tf_bB(signed char x, unsigned char c) { U; return c/3; }
428 EXPORT(short) __stdcall s_tf_bh(signed char x, short c) { S; return c/3; }
429 EXPORT(unsigned short) __stdcall s_tf_bH(signed char x, unsigned short c) { U; return c/3; }
430 EXPORT(int) __stdcall s_tf_bi(signed char x, int c) { S; return c/3; }
431 EXPORT(unsigned int) __stdcall s_tf_bI(signed char x, unsigned int c) { U; return c/3; }
432 EXPORT(long) __stdcall s_tf_bl(signed char x, long c) { S; return c/3; }
433 EXPORT(unsigned long) __stdcall s_tf_bL(signed char x, unsigned long c) { U; return c/3; }
434 EXPORT(LONG_LONG) __stdcall s_tf_bq(signed char x, LONG_LONG c) { S; return c/3; }
435 EXPORT(unsigned LONG_LONG) __stdcall s_tf_bQ(signed char x, unsigned LONG_LONG c) { U; return c/3; }
436 EXPORT(float) __stdcall s_tf_bf(signed char x, float c) { S; return c/3; }
437 EXPORT(double) __stdcall s_tf_bd(signed char x, double c) { S; return c/3; }
438 EXPORT(void) __stdcall s_tv_i(int c) { S; return; }
439 #endif
440
441 /********/
442
443 #ifndef MS_WIN32
444
445 typedef struct {
446 long x;
447 long y;
448 } POINT;
449
450 typedef struct {
451 long left;
452 long top;
453 long right;
454 long bottom;
455 } RECT;
456
457 #endif
458
459 EXPORT(int) PointInRect(RECT *prc, POINT pt)
460 {
461 if (pt.x < prc->left)
462 return 0;
463 if (pt.x > prc->right)
464 return 0;
465 if (pt.y < prc->top)
466 return 0;
467 if (pt.y > prc->bottom)
468 return 0;
469 return 1;
470 }
471
472 typedef struct {
473 short x;
474 short y;
475 } S2H;
476
477 EXPORT(S2H) ret_2h_func(S2H inp)
478 {
479 inp.x *= 2;
480 inp.y *= 3;
481 return inp;
482 }
483
484 typedef struct {
485 int a, b, c, d, e, f, g, h;
486 } S8I;
487
488
489
490 typedef int (*CALLBACK_RECT)(RECT rect);
491
492 EXPORT(int) call_callback_with_rect(CALLBACK_RECT cb, RECT rect)
493 {
494 return cb(rect);
495 }
496
497
498 EXPORT(S8I) ret_8i_func(S8I inp)
499 {
500 inp.a *= 2;
501 inp.b *= 3;
502 inp.c *= 4;
503 inp.d *= 5;
504 inp.e *= 6;
505 inp.f *= 7;
506 inp.g *= 8;
507 inp.h *= 9;
508 return inp;
509 }
510
511 EXPORT(int) GetRectangle(int flag, RECT *prect)
512 {
513 if (flag == 0)
514 return 0;
515 prect->left = (int)flag;
516 prect->top = (int)flag + 1;
517 prect->right = (int)flag + 2;
518 prect->bottom = (int)flag + 3;
519 return 1;
520 }
521
522 EXPORT(void) TwoOutArgs(int a, int *pi, int b, int *pj)
523 {
524 *pi += a;
525 *pj += b;
526 }
527
528 #ifdef MS_WIN32
529 EXPORT(S2H) __stdcall s_ret_2h_func(S2H inp) { return ret_2h_func(inp); }
530 EXPORT(S8I) __stdcall s_ret_8i_func(S8I inp) { return ret_8i_func(inp); }
531 #endif
532
533 #ifdef MS_WIN32
534 /* Should port this */
535 #include <stdlib.h>
536 #include <search.h>
537
538 EXPORT (HRESULT) KeepObject(IUnknown *punk)
539 {
540 static IUnknown *pobj;
541 if (punk)
542 punk->lpVtbl->AddRef(punk);
543 if (pobj)
544 pobj->lpVtbl->Release(pobj);
545 pobj = punk;
546 return S_OK;
547 }
548
549 #endif
550
551 typedef union {
552 short x;
553 long y;
554 } UN;
555
556 EXPORT(UN) ret_un_func(UN inp)
557 {
558 inp.y = inp.x * 10000;
559 return inp;
560 }
561
562 EXPORT(int) my_unused_function(void)
563 {
564 return 42;
565 }
566
567 EXPORT(int) test_errno(void)
568 {
569 int result = errno;
570 errno = result + 1;
571 return result;
572 }
573
574 EXPORT(int *) test_issue1655(char const *tag, int *len)
575 {
576 static int data[] = { -1, -2, -3, -4 };
577 *len = -42;
578 if (strcmp(tag, "testing!") != 0)
579 return NULL;
580 *len = sizeof(data) / sizeof(data[0]);
581 return data;
582 }
0 import py
1 import pytest
2 import sys
3 import os
4
5 # XXX: copied from pypy/tool/cpyext/extbuild.py
6 if os.name != 'nt':
7 so_ext = 'so'
8 else:
9 so_ext = 'dll'
10
11 def _build(cfilenames, outputfilename, compile_extra, link_extra,
12 include_dirs, libraries, library_dirs):
13 try:
14 # monkeypatch distutils for some versions of msvc compiler
15 import setuptools
16 except ImportError:
17 # XXX if this fails and is required,
18 # we must call pypy -mensurepip after translation
19 pass
20 from distutils.ccompiler import new_compiler
21 from distutils import sysconfig
22
23 # XXX for Darwin running old versions of CPython 2.7.x
24 sysconfig.get_config_vars()
25
26 compiler = new_compiler(force=1)
27 sysconfig.customize_compiler(compiler) # XXX
28 objects = []
29 for cfile in cfilenames:
30 cfile = py.path.local(cfile)
31 old = cfile.dirpath().chdir()
32 try:
33 res = compiler.compile([cfile.basename],
34 include_dirs=include_dirs, extra_preargs=compile_extra)
35 assert len(res) == 1
36 cobjfile = py.path.local(res[0])
37 assert cobjfile.check()
38 objects.append(str(cobjfile))
39 finally:
40 old.chdir()
41
42 compiler.link_shared_object(
43 objects, str(outputfilename),
44 libraries=libraries,
45 extra_preargs=link_extra,
46 library_dirs=library_dirs)
47
48 def c_compile(cfilenames, outputfilename,
49 compile_extra=None, link_extra=None,
50 include_dirs=None, libraries=None, library_dirs=None):
51 compile_extra = compile_extra or []
52 link_extra = link_extra or []
53 include_dirs = include_dirs or []
54 libraries = libraries or []
55 library_dirs = library_dirs or []
56 if sys.platform == 'win32':
57 link_extra = link_extra + ['/DEBUG'] # generate .pdb file
58 if sys.platform == 'darwin':
59 # support Fink & Darwinports
60 for s in ('/sw/', '/opt/local/'):
61 if (s + 'include' not in include_dirs
62 and os.path.exists(s + 'include')):
63 include_dirs.append(s + 'include')
64 if s + 'lib' not in library_dirs and os.path.exists(s + 'lib'):
65 library_dirs.append(s + 'lib')
66
67 outputfilename = py.path.local(outputfilename).new(ext=so_ext)
68 saved_environ = os.environ.copy()
69 try:
70 _build(
71 cfilenames, outputfilename,
72 compile_extra, link_extra,
73 include_dirs, libraries, library_dirs)
74 finally:
75 # workaround for a distutils bugs where some env vars can
76 # become longer and longer every time it is used
77 for key, value in saved_environ.items():
78 if os.environ.get(key) != value:
79 os.environ[key] = value
80 return outputfilename
81 # end copy
82
83 def compile_so_file(udir):
84 cfile = py.path.local(__file__).dirpath().join("_ctypes_test.c")
85
86 if sys.platform == 'win32':
87 libraries = ['oleaut32']
88 else:
89 libraries = []
90
91 return c_compile([cfile], str(udir / '_ctypes_test'), libraries=libraries)
92
93 @pytest.fixture(scope='session')
94 def sofile(tmpdir_factory):
95 udir = tmpdir_factory.mktemp('_ctypes_test')
96 return str(compile_so_file(udir))
97
98 @pytest.fixture
99 def dll(sofile):
100 from ctypes import CDLL
101 return CDLL(str(sofile))
0 import py
1 import sys
2 import ctypes
3
4 try:
5 import _rawffi
6 except ImportError:
7 _rawffi = None
8
9 class WhiteBoxTests:
10
11 def setup_class(cls):
12 if _rawffi:
13 py.test.skip("white-box tests for pypy _rawffi based ctypes impl")
14
15 def del_funcptr_refs_maybe(obj, attrname):
16 dll = getattr(obj, attrname, None)
17 if not dll:
18 return
19 _FuncPtr = dll._FuncPtr
20 for name in dir(dll):
21 obj = getattr(dll, name, None)
22 if isinstance(obj, _FuncPtr):
23 delattr(dll, name)
24
25 class BaseCTypesTestChecker:
26 def setup_class(cls):
27 if _rawffi:
28 import gc
29 for _ in range(4):
30 gc.collect()
31 try:
32 cls.old_num = _rawffi._num_of_allocated_objects()
33 except RuntimeError:
34 pass
35
36 def teardown_class(cls):
37 if not hasattr(sys, 'pypy_translation_info'):
38 return
39 if sys.pypy_translation_info['translation.gc'] == 'boehm':
40 return # it seems that boehm has problems with __del__, so not
41 # everything is freed
42 #
43 mod = sys.modules[cls.__module__]
44 del_funcptr_refs_maybe(mod, 'dll')
45 del_funcptr_refs_maybe(mod, 'dll2')
46 del_funcptr_refs_maybe(mod, 'lib')
47 del_funcptr_refs_maybe(mod, 'testdll')
48 del_funcptr_refs_maybe(mod, 'ctdll')
49 del_funcptr_refs_maybe(cls, '_dll')
50 #
51 if hasattr(cls, 'old_num'):
52 import gc
53 for _ in range(4):
54 gc.collect()
55 # there is one reference coming from the byref() above
56 assert _rawffi._num_of_allocated_objects() == cls.old_num
0 import pytest
1 from ctypes import *
2
3 @pytest.mark.pypy_only
4 def test_nested():
5 class ANON_S(Structure):
6 _fields_ = [("a", c_int)]
7
8 class ANON_U(Union):
9 _fields_ = [("_", ANON_S),
10 ("b", c_int)]
11 _anonymous_ = ["_"]
12
13 class Y(Structure):
14 _fields_ = [("x", c_int),
15 ("_", ANON_U),
16 ("y", c_int)]
17 _anonymous_ = ["_"]
18
19 assert Y.x.offset == 0
20 assert Y.a.offset == sizeof(c_int)
21 assert Y.b.offset == sizeof(c_int)
22 assert Y._.offset == sizeof(c_int)
23 assert Y.y.offset == sizeof(c_int) * 2
24
25 assert Y._names_ == ['x', 'a', 'b', 'y']
26
27 def test_anonymous_fields_on_instance():
28 # this is about the *instance-level* access of anonymous fields,
29 # which you'd guess is the most common, but used not to work
30 # (issue #2230)
31
32 class B(Structure):
33 _fields_ = [("x", c_int), ("y", c_int), ("z", c_int)]
34 class A(Structure):
35 _anonymous_ = ["b"]
36 _fields_ = [("b", B)]
37
38 a = A()
39 a.x = 5
40 assert a.x == 5
41 assert a.b.x == 5
42 a.b.x += 1
43 assert a.x == 6
44
45 class C(Structure):
46 _anonymous_ = ["a"]
47 _fields_ = [("v", c_int), ("a", A)]
48
49 c = C()
50 c.v = 3
51 c.y = -8
52 assert c.v == 3
53 assert c.y == c.a.y == c.a.b.y == -8
54 assert not hasattr(c, 'b')
0 import pytest
1 from ctypes import *
2
3 def test_slice():
4 values = list(range(5))
5 numarray = c_int * 5
6
7 na = numarray(*(c_int(x) for x in values))
8
9 assert list(na[0:0]) == []
10 assert list(na[:]) == values
11 assert list(na[:10]) == values
12
13 def test_init_again():
14 sz = (c_char * 3)()
15 addr1 = addressof(sz)
16 sz.__init__(*b"foo")
17 addr2 = addressof(sz)
18 assert addr1 == addr2
19
20 def test_array_of_structures():
21 class X(Structure):
22 _fields_ = [('x', c_int), ('y', c_int)]
23
24 Y = X * 2
25 y = Y()
26 x = X()
27 x.y = 3
28 y[1] = x
29 assert y[1].y == 3
30
31 def test_output_simple():
32 A = c_char * 10
33 TP = POINTER(A)
34 x = TP(A())
35 assert x[0] != b''
36
37 A = c_wchar * 10
38 TP = POINTER(A)
39 x = TP(A())
40 assert x[0] != b''
41
42 def test_output_simple_array():
43 A = c_char * 10
44 AA = A * 10
45 aa = AA()
46 assert aa[0] != b''
47
48 def test_output_complex_test():
49 class Car(Structure):
50 _fields_ = [("brand", c_char * 10),
51 ("speed", c_float),
52 ("owner", c_char * 10)]
53
54 assert isinstance(Car(b"abcdefghi", 42.0, b"12345").brand, bytes)
55 assert Car(b"abcdefghi", 42.0, b"12345").brand == b"abcdefghi"
56 assert Car(b"abcdefghio", 42.0, b"12345").brand == b"abcdefghio"
57 with pytest.raises(ValueError):
58 Car(b"abcdefghiop", 42.0, b"12345")
59
60 A = Car._fields_[2][1]
61 TP = POINTER(A)
62 x = TP(A())
63 assert x[0] != b''
0 import pytest
1 from ctypes import *
2
3 pytestmark = pytest.mark.pypy_only
4
5 def test_pointer():
6 p = pointer(pointer(c_int(2)))
7 x = p[0]
8 assert x._base is p
9
10 def test_structure():
11 class X(Structure):
12 _fields_ = [('x', POINTER(c_int)),
13 ('y', POINTER(c_int))]
14
15 x = X()
16 assert x.y._base is x
17 assert x.y._index == 1
18
19 def test_array():
20 X = POINTER(c_int) * 24
21 x = X()
22 assert x[16]._base is x
23 assert x[16]._index == 16
0 import pytest
1 from ctypes import *
2
3
4 def test_set_fields_attr():
5 class A(Structure):
6 pass
7 A._fields_ = [("a", c_byte), ("b", c_ubyte)]
8
9 def test_set_fields_attr_bitfields():
10 class A(Structure):
11 pass
12 A._fields_ = [("a", POINTER(A)), ("b", c_ubyte, 4)]
13
14 def test_set_fields_cycle_fails():
15 class A(Structure):
16 pass
17 with pytest.raises(AttributeError):
18 A._fields_ = [("a", A)]
0 from ctypes import *
1
2 def test_buffer():
3 b = create_string_buffer(32)
4 assert len(b) == 32
5 assert sizeof(b) == 32 * sizeof(c_char)
6 assert type(b[0]) is bytes
7
8 b = create_string_buffer(b"abc")
9 assert len(b) == 4 # trailing nul char
10 assert sizeof(b) == 4 * sizeof(c_char)
11 assert type(b[0]) is bytes
12 assert b[0] == b"a"
13 assert b[:] == b"abc\0"
14
15 def test_from_buffer():
16 b1 = bytearray(b"abcde")
17 b = (c_char * 5).from_buffer(b1)
18 assert b[2] == b"c"
19 #
20 b1 = bytearray(b"abcd")
21 b = c_int.from_buffer(b1)
22 assert b.value in (1684234849, # little endian
23 1633837924) # big endian
24
25 def test_from_buffer_keepalive():
26 # Issue #2878
27 b1 = bytearray(b"ab")
28 array = (c_uint16 * 32)()
29 array[6] = c_uint16.from_buffer(b1)
30 # this is also what we get on CPython. I don't think it makes
31 # sense because the array contains just a copy of the number.
32 assert array._objects == {'6': b1}
0 # derived from test_random_things.py
1 import pytest
2
3 from ctypes import *
4
5 _rawffi = pytest.importorskip('_rawffi')
6
7 #
8 # This test makes sure the exception types *and* the exception
9 # value is printed correctly.
10
11 @pytest.mark.skipif("sys.flags.inspect")
12 def test_SystemExit(monkeypatch, capsys):
13 """
14 When an exception is raised in a ctypes callback function, the C
15 code prints a traceback. When SystemExit is raised, the interpreter
16 normally exits immediately.
17 """
18 def callback_func(arg):
19 raise SystemExit(42)
20 def custom_exit(value):
21 raise Exception("<<<exit(%r)>>>" % (value,))
22 monkeypatch.setattr(_rawffi, 'exit', custom_exit)
23 cb = CFUNCTYPE(c_int, c_int)(callback_func)
24 cb2 = cast(cast(cb, c_void_p), CFUNCTYPE(c_int, c_int))
25 out, err = capsys.readouterr()
26 assert not err
27 cb2(0)
28 out, err = capsys.readouterr()
29 assert err.splitlines()[-1] == "Exception: <<<exit(42)>>>"
30 #
31 cb = CFUNCTYPE(c_int, c_int)(callback_func)
32 cb(0)
33 out, err = capsys.readouterr()
34 assert err.splitlines()[-1] == "Exception: <<<exit(42)>>>"
0 import pytest
1
2 import math
3 from ctypes import *
4 from .support import BaseCTypesTestChecker
5
6 functypes = [CFUNCTYPE]
7 try:
8 functypes.append(WINFUNCTYPE)
9 except NameError:
10 pass
11
12
13 def callback(*args):
14 callback.got_args = args
15 return args[-1]
16
17 unwrapped_types = {
18 c_float: (float,),
19 c_double: (float,),
20 c_char: (bytes,),
21 c_char_p: (bytes,),
22 c_uint: (int,),
23 c_ulong: (int,),
24 }
25
26 @pytest.mark.parametrize("typ, arg", [
27 (c_byte, 42),
28 (c_byte, -42),
29 (c_ubyte, 42),
30 (c_short, 42),
31 (c_short, -42),
32 (c_ushort, 42),
33 (c_int, 42),
34 (c_int, -42),
35 (c_uint, 42),
36 (c_long, 42),
37 (c_long, -42),
38 (c_ulong, 42),
39 (c_longlong, 42),
40 (c_longlong, -42),
41 (c_ulonglong, 42),
42 (c_float, math.e), # only almost equal: double -> float -> double
43 (c_float, -math.e),
44 (c_double, 3.14),
45 (c_double, -3.14),
46 (c_char, b"x"),
47 (c_char, b"a"),
48 ])
49 @pytest.mark.parametrize('functype', functypes)
50 def test_types(typ, arg, functype):
51 PROTO = functype(typ, typ)
52 cfunc = PROTO(callback)
53 result = cfunc(arg)
54 if typ == c_float:
55 assert abs(result - arg) < 0.000001
56 else:
57 assert callback.got_args == (arg,)
58 assert result == arg
59
60 result2 = cfunc(typ(arg))
61 assert type(result2) in unwrapped_types.get(typ, (int,))
62
63 PROTO = functype(typ, c_byte, typ)
64 result = PROTO(callback)(-3, arg)
65 if typ == c_float:
66 assert abs(result - arg) < 0.000001
67 else:
68 assert callback.got_args == (-3, arg)
69 assert result == arg
70
71 @pytest.mark.parametrize('functype', functypes)
72 def test_unsupported_restype_1(functype):
73 # Only "fundamental" result types are supported for callback
74 # functions, the type must have a non-NULL stgdict->setfunc.
75 # POINTER(c_double), for example, is not supported.
76
77 prototype = functype(POINTER(c_double))
78 # The type is checked when the prototype is called
79 with pytest.raises(TypeError):
80 prototype(lambda: None)
81
82
83 def test_callback_with_struct_argument():
84 class RECT(Structure):
85 _fields_ = [("left", c_int), ("top", c_int),
86 ("right", c_int), ("bottom", c_int)]
87
88 proto = CFUNCTYPE(c_int, RECT)
89
90 def callback(point):
91 point.left *= -1
92 return point.left + point.top + point.right + point.bottom
93
94 cbp = proto(callback)
95 rect = RECT(-1000, 100, 10, 1)
96 res = cbp(rect)
97 assert res == 1111
98 assert rect.left == -1000 # must not have been changed!
99
100 def test_callback_from_c_with_struct_argument(dll):
101 class RECT(Structure):
102 _fields_ = [("left", c_long), ("top", c_long),
103 ("right", c_long), ("bottom", c_long)]
104
105 proto = CFUNCTYPE(c_int, RECT)
106
107 def callback(point):
108 return point.left + point.top + point.right + point.bottom
109
110 cbp = proto(callback)
111 rect = RECT(1000, 100, 10, 1)
112
113 call_callback_with_rect = dll.call_callback_with_rect
114 call_callback_with_rect.restype = c_int
115 call_callback_with_rect.argtypes = [proto, RECT]
116 res = call_callback_with_rect(cbp, rect)
117 assert res == 1111
118
119 def test_callback_unsupported_return_struct():
120 class RECT(Structure):
121 _fields_ = [("left", c_int), ("top", c_int),
122 ("right", c_int), ("bottom", c_int)]
123
124 proto = CFUNCTYPE(RECT, c_int)
125 with pytest.raises(TypeError):
126 proto(lambda r: 0)
127
128
129 def test_qsort(dll):
130 PI = POINTER(c_int)
131 A = c_int*5
132 a = A()
133 for i in range(5):
134 a[i] = 5-i
135
136 assert a[0] == 5 # sanity
137
138 def comp(a, b):
139 a = a.contents.value
140 b = b.contents.value
141 if a < b:
142 return -1
143 elif a > b:
144 return 1
145 else:
146 return 0
147 qs = dll.my_qsort
148 qs.restype = None
149 CMP = CFUNCTYPE(c_int, PI, PI)
150 qs.argtypes = (PI, c_size_t, c_size_t, CMP)
151
152 qs(cast(a, PI), 5, sizeof(c_int), CMP(comp))
153
154 res = list(a)
155
156 assert res == [1,2,3,4,5]
157
158 def test_pyobject_as_opaque(dll):
159 def callback(arg):
160 return arg()
161
162 CTP = CFUNCTYPE(c_int, py_object)
163 cfunc = dll._testfunc_callback_opaque
164 cfunc.argtypes = [CTP, py_object]
165 cfunc.restype = c_int
166 res = cfunc(CTP(callback), lambda : 3)
167 assert res == 3
168
169 def test_callback_void(capsys, dll):
170 def callback():
171 pass
172
173 CTP = CFUNCTYPE(None)
174 cfunc = dll._testfunc_callback_void
175 cfunc.argtypes = [CTP]
176 cfunc.restype = int
177 cfunc(CTP(callback))
178 out, err = capsys.readouterr()
179 assert (out, err) == ("", "")
180
181
182 def test_callback_pyobject():
183 def callback(obj):
184 return obj
185
186 FUNC = CFUNCTYPE(py_object, py_object)
187 cfunc = FUNC(callback)
188 param = c_int(42)
189 assert cfunc(param) is param
190
191 def test_raise_argumenterror():
192 def callback(x):
193 pass
194 FUNC = CFUNCTYPE(None, c_void_p)
195 cfunc = FUNC(callback)
196 param = c_uint(42)
197 with pytest.raises(ArgumentError):
198 cfunc(param)
0 import pytest
1
2 from ctypes import *
3
4 def test_cast_functype(dll):
5 # make sure we can cast function type
6 my_sqrt = dll.my_sqrt
7 saved_objects = my_sqrt._objects.copy()
8 sqrt = cast(cast(my_sqrt, c_void_p), CFUNCTYPE(c_double, c_double))
9 assert sqrt(4.0) == 2.0
10 assert not cast(0, CFUNCTYPE(c_int))
11 #
12 assert sqrt._objects is my_sqrt._objects # on CPython too
13 my_sqrt._objects.clear()
14 my_sqrt._objects.update(saved_objects)
15
16 def test_cast_argumenterror():
17 param = c_uint(42)
18 with pytest.raises(ArgumentError):
19 cast(param, c_void_p)
20
21 def test_c_bool():
22 x = c_bool(42)
23 assert x.value is True
24 x = c_bool(0.0)
25 assert x.value is False
26 x = c_bool("")
27 assert x.value is False
28 x = c_bool(['yadda'])
29 assert x.value is True
0 # unittest for SOME ctypes com function calls.
1 # Can't resist from implementing some kind of mini-comtypes
2 # theller ;-)
3
4 import pytest
5 import sys
6 if sys.platform != "win32":
7 pytest.importorskip('skip_the_whole_module') # hack!
8
9 import ctypes, new, unittest
10 from ctypes.wintypes import HRESULT
11 from _ctypes import COMError
12
13 oleaut32 = ctypes.OleDLL("oleaut32")
14
15 class UnboundMethod(object):
16 def __init__(self, func, index, name):
17 self.func = func
18 self.index = index
19 self.name = name
20 self.__doc__ = func.__doc__
21
22 def __repr__(self):
23 return "<Unbound COM method index %d: %s at %x>" % (self.index, self.name, id(self))
24
25 def __get__(self, instance, owner):
26 if instance is None:
27 return self
28 return new.instancemethod(self.func, instance, owner)
29
30 def commethod(index, restype, *argtypes):
31 """A decorator that generates COM methods. The decorated function
32 itself is not used except for it's name."""
33 def make_commethod(func):
34 comfunc = ctypes.WINFUNCTYPE(restype, *argtypes)(index, func.__name__)
35 comfunc.__name__ = func.__name__
36 comfunc.__doc__ = func.__doc__
37 return UnboundMethod(comfunc, index, func.__name__)
38 return make_commethod
39
40 class ICreateTypeLib2(ctypes.c_void_p):
41
42 @commethod(1, ctypes.c_long)
43 def AddRef(self):
44 pass
45
46 @commethod(2, ctypes.c_long)
47 def Release(self):
48 pass
49
50 @commethod(4, HRESULT, ctypes.c_wchar_p)
51 def SetName(self):
52 """Set the name of the library."""
53
54 @commethod(12, HRESULT)
55 def SaveAllChanges(self):
56 pass
57
58
59 CreateTypeLib2 = oleaut32.CreateTypeLib2
60 CreateTypeLib2.argtypes = (ctypes.c_int, ctypes.c_wchar_p, ctypes.POINTER(ICreateTypeLib2))
61
62 ################################################################
63
64 def test_basic_comtypes():
65 punk = ICreateTypeLib2()
66 hr = CreateTypeLib2(0, "foobar.tlb", punk)
67 assert hr == 0
68
69 assert 2 == punk.AddRef()
70 assert 3 == punk.AddRef()
71 assert 4 == punk.AddRef()
72
73 punk.SetName("TypeLib_ByPYPY")
74 with pytest.raises(COMError):
75 punk.SetName(None)
76
77 # This would save the typelib to disk.
78 ## punk.SaveAllChanges()
79
80 assert 3 == punk.Release()
81 assert 2 == punk.Release()
82 assert 1 == punk.Release()
0 import pytest
1
2 import ctypes
3 _rawffi = pytest.importorskip('_rawffi') # PyPy-only
4
5 def test_errno_saved_and_restored():
6 def check():
7 assert _rawffi.get_errno() == 42
8 assert ctypes.get_errno() == old
9 check.free_temp_buffers = lambda *args: None
10 f = ctypes._CFuncPtr()
11 old = _rawffi.get_errno()
12 f._flags_ = _rawffi.FUNCFLAG_USE_ERRNO
13 ctypes.set_errno(42)
14 f._call_funcptr(check)
15 assert _rawffi.get_errno() == old
16 ctypes.set_errno(0)
17
18 # see also test_functions.test_errno
0 """
1 The purpose of this test file is to check how ctypes really work,
2 down to what aliases what and what exact types operations return.
3 """
4
5 import py
6 from ctypes import *
7
8 def test_primitive_pointer():
9 x = c_int(5)
10 assert x.value == 5
11 x.value = 6
12 assert x.value == 6
13
14 p = pointer(x) # p ---> x = 6
15 assert isinstance(p.contents, c_int)
16 p.contents.value += 1
17 assert x.value == 7 # p ---> x = 7
18
19 y = c_int(12)
20 p.contents = y # p ---> y = 12
21 p.contents.value += 2 # p ---> y = 14
22 assert y.value == 14
23 assert x.value == 7
24
25 pp = pointer(p) # pp ---> p ---> y = 14
26 pp.contents.contents = x # pp ---> p ---> x = 7
27 p.contents.value += 2 # pp ---> p ---> x = 9
28 assert x.value == 9
29
30 assert isinstance(p[0], int)
31 p[0] += 1 # pp ---> p ---> x = 10
32 assert x.value == 10
33 z = c_int(86)
34 p[0] = z # pp ---> p ---> x = 86 (not z!)
35 assert x.value == 86
36 z.value = 84
37 assert x.value == 86
38
39 assert isinstance(pp[0], POINTER(c_int))
40 assert pp[0].contents.value == x.value == 86
41 pp[0].contents = z # pp ---> p ---> z = 84
42 assert p.contents.value == z.value == 84
43
44 ## *** the rest is commented out because it should work but occasionally
45 ## *** trigger a ctypes bug (SourceForge bug #1467852). ***
46 ## q = pointer(y)
47 ## pp[0] = q # pp ---> p ---> y = 14
48 ## assert y.value == 14 # (^^^ not q! )
49 ## assert p.contents.value == 14
50 ## assert pp.contents.contents.value == 14
51 ## q.contents = x
52 ## assert pp.contents.contents.value == 14
53
54
55 def test_char_p():
56 x = c_char_p(b"hello\x00world")
57 assert x.value == b"hello"
58 x.value = b"world"
59 assert x.value == b"world"
60
61 p = pointer(x)
62 assert p[0] == x.value == b"world"
63 p[0] = b"other"
64 assert x.value == p.contents.value == p[0] == b"other"
65
66 myarray = (c_char_p * 10)()
67 myarray[7] = b"hello"
68 assert isinstance(myarray[7], bytes)
69 assert myarray[7] == b"hello"
70
71 def test_struct():
72 class tagpoint(Structure):
73 _fields_ = [('x', c_int),
74 ('p', POINTER(c_short))]
75
76 y = c_short(123)
77 z = c_short(-33)
78 s = tagpoint()
79 s.p.contents = z
80 assert s.p.contents.value == -33
81 s.p = pointer(y)
82 assert s.p.contents.value == 123
83 s.p.contents.value = 124
84 assert y.value == 124
85
86 s = tagpoint(x=12)
87 assert s.x == 12
88 s = tagpoint(17, p=pointer(z))
89 assert s.x == 17
90 assert s.p.contents.value == -33
91
92 def test_ptr_array():
93 a = (POINTER(c_ushort) * 5)()
94 x = c_ushort(52)
95 y = c_ushort(1000)
96
97 a[2] = pointer(x)
98 assert a[2].contents.value == 52
99 a[2].contents.value += 1
100 assert x.value == 53
101
102 a[3].contents = y
103 assert a[3].contents.value == 1000
104 a[3].contents.value += 1
105 assert y.value == 1001
106
107 def test_void_p():
108 x = c_int(12)
109 p1 = cast(pointer(x), c_void_p)
110 p2 = cast(p1, POINTER(c_int))
111 assert p2.contents.value == 12
112
113 def test_char_array():
114 a = (c_char * 3)()
115 a[0] = b'x'
116 a[1] = b'y'
117 assert a.value == b'xy'
118 a[2] = b'z'
119 assert a.value == b'xyz'
120
121 b = create_string_buffer(3)
122 assert type(b) is type(a)
123 assert len(b) == 3
124
125 b.value = b"nxw"
126 assert b[0] == b'n'
127 assert b[1] == b'x'
128 assert b[2] == b'w'
129
130 b.value = b"?"
131 assert b[0] == b'?'
132 assert b[1] == b'\x00'
133 assert b[2] == b'w'
134
135 class S(Structure):
136 _fields_ = [('p', POINTER(c_char))]
137
138 s = S()
139 s.p = b
140 s.p.contents.value = b'!'
141 assert b.value == b'!'
142
143 assert len(create_string_buffer(0)) == 0
144
145 def test_array():
146 a = (c_int * 10)()
147
148 class S(Structure):
149 _fields_ = [('p', POINTER(c_int))]
150
151 s = S()
152 s.p = a
153 s.p.contents.value = 42
154 assert a[0] == 42
155
156 a = (c_int * 5)(5, 6, 7)
157 assert list(a) == [5, 6, 7, 0, 0]
158
159 def test_truth_value():
160 p = POINTER(c_int)()
161 assert not p
162 p.contents = c_int(12)
163 assert p
164 # I can't figure out how to reset p to NULL...
165
166 assert c_int(12)
167 assert not c_int(0) # a bit strange, if you ask me
168 assert c_int(-1)
169 assert not c_byte(0)
170 assert not c_char(b'\x00') # hum
171 assert not c_float(0.0)
172 assert not c_double(0.0)
173 assert not c_ulonglong(0)
174 assert c_ulonglong(2**42)
175
176 assert c_char_p(b"hello")
177 assert c_char_p(b"")
178 assert not c_char_p(None)
179
180 assert not c_void_p()
181
182 def test_sizeof():
183 x = create_string_buffer(117)
184 assert sizeof(x) == 117 # assumes that chars are one byte each
185 x = (c_int * 42)()
186 assert sizeof(x) == 42 * sizeof(c_int)
187
188 def test_convert_pointers(dll):
189 func = dll._testfunc_p_p
190 func.restype = c_char_p
191
192 # automatic conversions to c_char_p
193 func.argtypes = [c_char_p]
194 assert func(b"hello") == b"hello"
195 assert func(c_char_p(b"hello")) == b"hello"
196 assert func((c_char * 6)(*b"hello")) == b"hello"
197 assert func(create_string_buffer(b"hello")) == b"hello"
198
199 # automatic conversions to c_void_p
200 func.argtypes = [c_void_p]
201 assert func(b"hello") == b"hello"
202 assert func(c_char_p(b"hello")) == b"hello"
203 assert func((c_char * 6)(*b"hello")) == b"hello"
204 assert func((c_byte * 6)(104,101,108,108,111)) ==b"hello"
205 assert func(create_string_buffer(b"hello")) == b"hello"
206
207 def test_varsize_cast():
208 import struct
209 N = struct.calcsize("l")
210 x = c_long()
211 p = cast(pointer(x), POINTER(c_ubyte*N))
212 for i, c in enumerate(struct.pack("l", 12345678)):
213 p.contents[i] = c
214 assert x.value == 12345678
215
216 def test_cfunctype_inspection():
217 T = CFUNCTYPE(c_int, c_ubyte)
218 # T.argtypes and T.restype don't work, must use a dummy instance
219 assert list(T().argtypes) == [c_ubyte]
220 assert T().restype == c_int
221
222 def test_from_param():
223 # other working cases of from_param
224 assert isinstance(c_void_p.from_param((c_int * 4)()), c_int * 4)
225
226 def test_array_mul():
227 assert c_int * 10 == 10 * c_int
228 py.test.raises(TypeError, 'c_int * c_int')
229 py.test.raises(TypeError, 'c_int * (-1.5)')
230 py.test.raises(TypeError, 'c_int * "foo"')
231 py.test.raises(TypeError, '(-1.5) * c_int')
232 py.test.raises(TypeError, '"foo" * c_int')
233
234 def test_cast_none():
235 def check(P):
236 x = cast(None, P)
237 assert isinstance(x, P)
238 assert not x
239 check(c_void_p)
240 check(c_char_p)
241 check(POINTER(c_int))
242 check(POINTER(c_int * 10))
0 from ctypes import *
1
2 def test_restype(dll):
3 foo = dll.my_unused_function
4 assert foo.restype is c_int # by default
0 from ctypes import *
1 import sys
2 import pytest
3
4 @pytest.fixture
5 def dll(sofile):
6 return CDLL(str(sofile), use_errno=True)
7
8
9 def test_char_result(dll):
10 f = dll._testfunc_i_bhilfd
11 f.argtypes = [c_byte, c_short, c_int, c_long, c_float, c_double]
12 f.restype = c_char
13 result = f(0, 0, 0, 0, 0, 0)
14 assert result == b'\x00'
15
16 def test_boolresult(dll):
17 f = dll._testfunc_i_bhilfd
18 f.argtypes = [c_byte, c_short, c_int, c_long, c_float, c_double]
19 f.restype = c_bool
20 false_result = f(0, 0, 0, 0, 0, 0)
21 assert false_result is False
22 true_result = f(1, 0, 0, 0, 0, 0)
23 assert true_result is True
24
25 def test_unicode_function_name(dll):
26 f = dll[u'_testfunc_i_bhilfd']
27 f.argtypes = [c_byte, c_short, c_int, c_long, c_float, c_double]
28 f.restype = c_int
29 result = f(1, 2, 3, 4, 5.0, 6.0)
30 assert result == 21
31
32 def test_truncate_python_longs(dll):
33 f = dll._testfunc_i_bhilfd
34 f.argtypes = [c_byte, c_short, c_int, c_long, c_float, c_double]
35 f.restype = c_int
36 x = sys.maxsize * 2
37 result = f(x, x, x, x, 0, 0)
38 assert result == -8
39
40 def test_convert_pointers(dll):
41 f = dll.deref_LP_c_char_p
42 f.restype = c_char
43 f.argtypes = [POINTER(c_char_p)]
44 #
45 s = c_char_p(b'hello world')
46 ps = pointer(s)
47 assert f(ps) == b'h'
48 assert f(s) == b'h' # automatic conversion from char** to char*
49
50 ################################################################
51
52 def test_call_some_args(dll):
53 f = dll.my_strchr
54 f.argtypes = [c_char_p]
55 f.restype = c_char_p
56 result = f(b"abcd", ord("b"))
57 assert result == b"bcd"
58
59 @pytest.mark.pypy_only
60 def test_keepalive_buffers(monkeypatch, dll):
61 import gc
62 f = dll.my_strchr
63 f.argtypes = [c_char_p]
64 f.restype = c_char_p
65 #
66 orig__call_funcptr = f._call_funcptr
67 def _call_funcptr(funcptr, *newargs):
68 gc.collect()
69 gc.collect()
70 gc.collect()
71 return orig__call_funcptr(funcptr, *newargs)
72 monkeypatch.setattr(f, '_call_funcptr', _call_funcptr)
73 #
74 result = f(b"abcd", ord("b"))
75 assert result == b"bcd"
76
77 def test_caching_bug_1(dll):
78 # the same test as test_call_some_args, with two extra lines
79 # in the middle that trigger caching in f._ptr, which then
80 # makes the last two lines fail
81 f = dll.my_strchr
82 f.argtypes = [c_char_p, c_int]
83 f.restype = c_char_p
84 result = f(b"abcd", ord("b"))
85 assert result == b"bcd"
86 result = f(b"abcd", ord("b"), 42)
87 assert result == b"bcd"
88
89 def test_argument_conversion_and_checks(dll):
90 #This test is designed to check for segfaults if the wrong type of argument is passed as parameter
91 strlen = dll.my_strchr
92 strlen.argtypes = [c_char_p, c_int]
93 strlen.restype = c_char_p
94 assert strlen(b"eggs", ord("g")) == b"ggs"
95
96 # Should raise ArgumentError, not segfault
97 with pytest.raises(ArgumentError):
98 strlen(0, 0)
99 with pytest.raises(ArgumentError):
100 strlen(False, 0)
101
102 def test_union_as_passed_value(dll):
103 class UN(Union):
104 _fields_ = [("x", c_short),
105 ("y", c_long)]
106 dll.ret_un_func.restype = UN
107 dll.ret_un_func.argtypes = [UN]
108 A = UN * 2
109 a = A()
110 a[1].x = 33
111 u = dll.ret_un_func(a[1])
112 assert u.y == 33 * 10000
113
114 @pytest.mark.pypy_only
115 def test_cache_funcptr(dll):
116 tf_b = dll.tf_b
117 tf_b.restype = c_byte
118 tf_b.argtypes = (c_byte,)
119 assert tf_b(-126) == -42
120 ptr = tf_b._ptr
121 assert ptr is not None
122 assert tf_b(-126) == -42
123 assert tf_b._ptr is ptr
124
125 def test_custom_from_param(dll):
126 class A(c_byte):
127 @classmethod
128 def from_param(cls, obj):
129 seen.append(obj)
130 return -126
131 tf_b = dll.tf_b
132 tf_b.restype = c_byte
133 tf_b.argtypes = (c_byte,)
134 tf_b.argtypes = [A]
135 seen = []
136 assert tf_b("yadda") == -42
137 assert seen == ["yadda"]
138
139 @pytest.mark.xfail(reason="warnings are disabled")
140 def test_warnings(dll):
141 import warnings
142 warnings.simplefilter("always")
143 with warnings.catch_warnings(record=True) as w:
144 dll.get_an_integer()
145 assert len(w) == 1
146 assert issubclass(w[0].category, RuntimeWarning)
147 assert "C function without declared arguments called" in str(w[0].message)
148
149 @pytest.mark.xfail
150 def test_errcheck(dll):
151 import warnings
152 def errcheck(result, func, args):
153 assert result == -42
154 assert type(result) is int
155 arg, = args
156 assert arg == -126
157 assert type(arg) is int
158 return result
159 #
160 tf_b = dll.tf_b
161 tf_b.restype = c_byte
162 tf_b.argtypes = (c_byte,)
163 tf_b.errcheck = errcheck
164 assert tf_b(-126) == -42
165 del tf_b.errcheck
166 with warnings.catch_warnings(record=True) as w:
167 dll.get_an_integer.argtypes = []
168 dll.get_an_integer()
169 assert len(w) == 1
170 assert issubclass(w[0].category, RuntimeWarning)
171 assert "C function without declared return type called" in str(w[0].message)
172
173 with warnings.catch_warnings(record=True) as w:
174 dll.get_an_integer.restype = None
175 dll.get_an_integer()
176 assert len(w) == 0
177
178 warnings.resetwarnings()
179
180 def test_errno(dll):
181 test_errno = dll.test_errno
182 test_errno.restype = c_int
183 set_errno(42)
184 res = test_errno()
185 n = get_errno()
186 assert (res, n) == (42, 43)
187 set_errno(0)
188 assert get_errno() == 0
189
190 def test_issue1655(dll):
191 def ret_list_p(icount):
192 def sz_array_p(obj, func, args):
193 assert ('.LP_c_int object' in repr(obj) or
194 '.LP_c_long object' in repr(obj))
195 assert repr(args) =="(b'testing!', c_int(4))"
196 assert args[icount].value == 4
197 return [obj[i] for i in range(args[icount].value)]
198 return sz_array_p
199
200 get_data_prototype = CFUNCTYPE(POINTER(c_int),
201 c_char_p, POINTER(c_int))
202 get_data_paramflag = ((1,), (2,))
203 get_data_signature = ('test_issue1655', dll)
204
205 get_data = get_data_prototype(get_data_signature, get_data_paramflag)
206 assert get_data(b'testing!') == 4
207
208 get_data.errcheck = ret_list_p(1)
209 assert get_data(b'testing!') == [-1, -2, -3, -4]
210
211 def test_issue2533(tmpdir):
212 import cffi
213 ffi = cffi.FFI()
214 ffi.cdef("int **fetchme(void);")
215 ffi.set_source("_x_cffi", """
216 int **fetchme(void)
217 {
218 static int a = 42;
219 static int *pa = &a;
220 return &pa;
221 }
222 """)
223 ffi.compile(verbose=True, tmpdir=str(tmpdir))
224
225 import sys
226 sys.path.insert(0, str(tmpdir))
227 try:
228 from _x_cffi import ffi, lib
229 finally:
230 sys.path.pop(0)
231 fetchme = ffi.addressof(lib, 'fetchme')
232 fetchme = int(ffi.cast("intptr_t", fetchme))
233
234 FN = CFUNCTYPE(POINTER(POINTER(c_int)))
235 ff = cast(fetchme, FN)
236
237 g = ff()
238 assert g.contents.contents.value == 42
239
240 h = c_int(43)
241 g[0] = pointer(h) # used to crash here
242 assert g.contents.contents.value == 43
0
1 """ This test checks whether args wrapping behavior is correct
2 """
3 import pytest
4 import sys
5
6 from ctypes import *
7
8 @pytest.mark.pypy_only
9 def test_wrap_args():
10 from _ctypes import CFuncPtr
11
12 def guess(value):
13 _, cobj, ctype = CFuncPtr._conv_param(None, value)
14 return ctype
15 ## cobj = CFuncPtr._conv_param(None, value)
16 ## return type(cobj)
17
18 assert guess(13) == c_int
19 assert guess(0) == c_int
20 assert guess(b'xca') == c_char_p
21 assert guess(None) == c_void_p
22 assert guess(c_int(3)) == c_int
23 assert guess(u'xca') == c_wchar_p
24
25 class Stuff:
26 pass
27 s = Stuff()
28 s._as_parameter_ = None
29
30 assert guess(s) == c_void_p
31
32 def test_guess_unicode(dll):
33 if not hasattr(sys, 'pypy_translation_info') and sys.platform != 'win32':
34 pytest.skip("CPython segfaults: see http://bugs.python.org/issue5203")
35 wcslen = dll.my_wcslen
36 text = u"Some long unicode string"
37 assert wcslen(text) == len(text)
0 """ Tests whether various objects land in _objects
1 or not
2 """
3 import pytest
4
5 from ctypes import *
6 import sys
7
8 def test_array_of_pointers():
9 # tests array item assignements & pointer.contents = ...
10 A = POINTER(c_long) * 24
11 a = A()
12 l = c_long(2)
13 p = pointer(l)
14 a[3] = p
15 assert l._objects is None
16 assert p._objects == {'1':l}
17 assert a._objects == {'3':{'1':l}}
18
19 def test_simple_structure_and_pointer():
20 class X(Structure):
21 _fields_ = [('x', POINTER(c_int))]
22
23 x = X()
24 p = POINTER(c_int)()
25 assert x._objects is None
26 assert p._objects is None
27 x.x = p
28 assert p._objects == {}
29 assert len(x._objects) == 1
30 assert x._objects['0'] is p._objects
31
32 def test_simple_structure_and_pointer_with_array():
33 class X(Structure):
34 _fields_ = [('array', POINTER(c_int))]
35
36 x = X()
37 a = (c_int * 3)(1, 2, 3)
38 assert x._objects is None
39 x.array = a
40 assert x._objects['0'] is a
41
42 def test_structure_with_pointers():
43 class X(Structure):
44 _fields_ = [('x', POINTER(c_int)),
45 ('y', POINTER(c_int))]
46
47 x = X()
48 u = c_int(3)
49 p = pointer(u)
50 x.x = p
51 assert x.x._objects is None
52 assert p._objects == {'1': u}
53 assert x._objects == {'0': p._objects}
54
55 w = c_int(4)
56 q = pointer(w)
57 x.y = q
58 assert p._objects == {'1': u}
59 assert q._objects == {'1': w}
60 assert x._objects == {'0': p._objects, '1': q._objects}
61
62 n = POINTER(c_int)()
63 x.x = n
64 x.y = n
65 assert x._objects == {'0': n._objects, '1': n._objects}
66 assert x._objects['0'] is n._objects
67 assert n._objects is not None
68
69 def test_union_with_pointers():
70 class X(Union):
71 _fields_ = [('x', POINTER(c_int)),
72 ('y', POINTER(c_int))]
73
74 x = X()
75 u = c_int(3)
76 p = pointer(u)
77 x.x = p
78 assert x.x._objects is None
79 assert p._objects == {'1': u}
80 assert x._objects == {'0': p._objects}
81
82 # unions works just like structures it seems
83 w = c_int(4)
84 q = pointer(w)
85 x.y = q
86 assert p._objects == {'1': u}
87 assert q._objects == {'1': w}
88 assert x._objects == {'0': p._objects, '1': q._objects}
89
90 n = POINTER(c_int)()
91 x.x = n
92 x.y = n
93 assert x._objects == {'0': n._objects, '1': n._objects}
94 assert x._objects['0'] is n._objects
95 assert n._objects is not None
96
97 def test_pointer_setitem():
98 x = c_int(2)
99 y = c_int(3)
100 p = pointer(x)
101 assert p._objects == {'1':x}
102 p[0] = y
103 assert list(p._objects.keys()) == ['1']
104 assert p._objects['1'].value == 3
105
106 @pytest.mark.pypy_only
107 def test_primitive():
108 assert c_char_p(b"abc")._objects._buffer[0] == b"a"
109 assert c_int(3)._objects is None
110
111 def test_pointer_to_pointer():
112 l = c_long(2)
113 assert l._objects is None
114
115 p1 = pointer(l)
116 assert p1._objects == {'1':l}
117
118 p2 = pointer(p1)
119 assert p2._objects == {'1':p1, '0':{'1':l}}
120
121 def test_cfunc():
122 def f():
123 pass
124 cf = CFUNCTYPE(c_int, c_int)(f)
125 assert cf._objects == {'0':cf}
126
127 def test_cfunc_cast():
128 def f():
129 pass
130 cf = CFUNCTYPE(c_int, c_int)(f)
131 p1 = cast(cf, c_void_p)
132 assert p1._objects == {id(cf): cf, '0': cf}
133
134 def test_array_of_struct_with_pointer():
135 class S(Structure):
136 _fields_ = [('x', c_int)]
137 PS = POINTER(S)
138
139 class Q(Structure):
140 _fields_ = [('p', PS)]
141
142 A = Q*10
143 a=A()
144 s=S()
145 s.x=3
146 a[3].p = pointer(s)
147
148 assert a._objects['0:3']['1'] is s
149
150 def test_array_of_union_with_pointer():
151 class S(Structure):
152 _fields_ = [('x', c_int)]
153 PS = POINTER(S)
154
155 class Q(Union):
156 _fields_ = [('p', PS), ('x', c_int)]
157
158 A = Q*10
159 a=A()
160 s=S()
161 s.x=3
162 a[3].p = pointer(s)
163
164 assert a._objects['0:3']['1'] is s
165
166 def test_struct_with_inlined_array():
167 class S(Structure):
168 _fields_ = [('b', c_int),
169 ('a', POINTER(c_int) * 2)]
170
171 s = S()
172 stuff = c_int(2)
173 s.a[1] = pointer(stuff)
174 assert s._objects == {'1:1': {'1': stuff}}
175
176 def test_union_with_inlined_array():
177 class S(Union):
178 _fields_ = [('b', c_int),
179 ('a', POINTER(c_int) * 2)]
180
181 s = S()
182 stuff = c_int(2)
183 s.a[1] = pointer(stuff)
184 assert s._objects == {'1:1': {'1': stuff}}
185
186 def test_struct_within_struct():
187 class R(Structure):
188 _fields_ = [('p', POINTER(c_int))]
189
190 class S(Structure):
191 _fields_ = [('b', c_int),
192 ('r', R)]
193
194 s = S()
195 stuff = c_int(2)
196 s.r.p = pointer(stuff)
197 assert s._objects == {'0:1': {'1': stuff}}
198
199 r = R()
200 s.r = r
201 # obscure
202 assert s._objects == {'1': {}, '0:1': {'1': stuff}}
203
204 def test_union_within_union():
205 class R(Union):
206 _fields_ = [('p', POINTER(c_int))]
207
208 class S(Union):
209 _fields_ = [('b', c_int),
210 ('r', R)]
211
212 s = S()
213 stuff = c_int(2)
214 s.r.p = pointer(stuff)
215 assert s._objects == {'0:1': {'1': stuff}}
216
217 r = R()
218 s.r = r
219 # obscure
220 assert s._objects == {'1': {}, '0:1': {'1': stuff}}
221
222 def test_c_char_p():
223 n = 2
224 xs = b"hello" * n
225 x = c_char_p(xs)
226 del xs
227 import gc; gc.collect()
228 assert x.value == b'hellohello'
229 assert x._objects == b'hellohello'
230 #
231 class datum(Structure):
232 _fields_ = [
233 ('dptr', c_char_p),
234 ('dsize', c_int),
235 ]
236 class union(Union):
237 _fields_ = [
238 ('dptr', c_char_p),
239 ('dsize', c_int),
240 ]
241 for wrap in [False, True]:
242 n = 2
243 xs = b"hello" * n
244 if wrap:
245 xs = c_char_p(xs)
246 dat = datum()
247 dat.dptr = xs
248 dat.dsize = 15
249 del xs
250 import gc; gc.collect()
251 assert dat.dptr == b"hellohello"
252 assert list(dat._objects.keys()) == ['0']
253
254 xs = b"hello" * n
255 if wrap:
256 xs = c_char_p(xs)
257 dat = union()
258 dat.dptr = xs
259 del xs
260 import gc; gc.collect()
261 assert dat.dptr == b"hellohello"
262 assert list(dat._objects.keys()) == ['0']
0 from ctypes import CDLL
1 from ctypes.util import find_library
2
3 def test__handle():
4 lib = find_library("c")
5 if lib:
6 cdll = CDLL(lib)
7 assert type(cdll._handle) is int
0 import pytest
1 from ctypes import *
2
3 unsigned_types = [c_ubyte, c_ushort, c_uint, c_ulong]
4 signed_types = [c_byte, c_short, c_int, c_long, c_longlong]
5
6 float_types = [c_double, c_float, c_longdouble]
7
8 try:
9 c_ulonglong
10 c_longlong
11 except NameError:
12 pass
13 else:
14 unsigned_types.append(c_ulonglong)
15 signed_types.append(c_longlong)
16
17 ################################################################
18
19 @pytest.mark.parametrize('t', signed_types + unsigned_types + float_types)
20 def test_init_again(t):
21 parm = t()
22 addr1 = addressof(parm)
23 parm.__init__(0)
24 addr2 = addressof(parm)
25 assert addr1 == addr2
26
27 def test_subclass():
28 class enum(c_int):
29 def __new__(cls, value):
30 dont_call_me
31 class S(Structure):
32 _fields_ = [('t', enum)]
33 assert isinstance(S().t, enum)
34
35 #@pytest.mark.xfail("'__pypy__' not in sys.builtin_module_names")
36 @pytest.mark.xfail
37 def test_no_missing_shape_to_ffi_type():
38 # whitebox test
39 "re-enable after adding 'g' to _shape_to_ffi_type.typemap, "
40 "which I think needs fighting all the way up from "
41 "rpython.rlib.libffi"
42 from _ctypes.basics import _shape_to_ffi_type
43 from _rawffi import Array
44 for i in range(1, 256):
45 try:
46 Array(chr(i))
47 except ValueError:
48 pass
49 else:
50 assert chr(i) in _shape_to_ffi_type.typemap
51
52 @pytest.mark.xfail
53 def test_pointer_to_long_double():
54 import ctypes
55 ctypes.POINTER(ctypes.c_longdouble)
0 from ctypes import POINTER, c_void_p
1
2 def test_pointer_subclasses():
3 Void_pp = POINTER(c_void_p)
4 class My_void_p(c_void_p):
5 pass
6
7 My_void_pp = POINTER(My_void_p)
8 o = My_void_pp()
9
10 assert Void_pp.from_param(o) is o
11
12
13 def test_multiple_signature(dll):
14 # when .argtypes is not set, calling a function with a certain
15 # set of parameters should not prevent another call with
16 # another set.
17 func = dll._testfunc_p_p
18
19 # This is call has too many arguments
20 assert func(None, 1) == 0
21
22 # This one is normal
23 assert func(None) == 0
0 import pytest
1 from ctypes import *
2
3 @pytest.mark.pypy_only
4 def test_get_ffi_argtype():
5 P = POINTER(c_int)
6 ffitype = P.get_ffi_argtype()
7 assert P.get_ffi_argtype() is ffitype
8 assert ffitype.deref_pointer() is c_int.get_ffi_argtype()
9
10 @pytest.mark.parametrize("c_type, py_type", [
11 (c_byte, int),
12 (c_ubyte, int),
13 (c_short, int),
14 (c_ushort, int),
15 (c_int, int),
16 (c_uint, int),
17 (c_long, int),
18 (c_ulong, int),
19 (c_longlong, int),
20 (c_ulonglong, int),
21 (c_double, float),
22 (c_float, float),
23 ])
24 def test_byref(c_type, py_type):
25 i = c_type(42)
26 p = byref(i)
27 assert type(p._obj) is c_type
28 assert p._obj.value == 42
29
30 def test_pointer_to_pointer():
31 x = c_int(32)
32 y = c_int(42)
33 p1 = pointer(x)
34 p2 = pointer(p1)
35 assert p2.contents.contents.value == 32
36 p2.contents.contents = y
37 assert p2.contents.contents.value == 42
38 assert p1.contents.value == 42
39
40 def test_c_char_p_byref(dll):
41 TwoOutArgs = dll.TwoOutArgs
42 TwoOutArgs.restype = None
43 TwoOutArgs.argtypes = [c_int, c_void_p, c_int, c_void_p]
44 a = c_int(3)
45 b = c_int(4)
46 c = c_int(5)
47 d = c_int(6)
48 TwoOutArgs(a, byref(b), c, byref(d))
49 assert b.value == 7
50 assert d.value == 11
51
52 def test_byref_cannot_be_bound():
53 class A(object):
54 _byref = byref
55 A._byref(c_int(5))
56
57 def test_byref_with_offset():
58 c = c_int()
59 d = byref(c)
60 base = cast(d, c_void_p).value
61 for i in [0, 1, 4, 1444, -10293]:
62 assert cast(byref(c, i), c_void_p).value == base + i
63
64 @pytest.mark.pypy_only
65 def test_issue2813_fix():
66 class C(Structure):
67 pass
68 POINTER(C)
69 C._fields_ = [('x', c_int)]
70 ffitype = C.get_ffi_argtype()
71 assert C.get_ffi_argtype() is ffitype
72 assert ffitype.sizeof() == sizeof(c_int)
73
74 @pytest.mark.pypy_only
75 def test_issue2813_cant_change_fields_after_get_ffi_argtype():
76 class C(Structure):
77 pass
78 ffitype = C.get_ffi_argtype()
79 with pytest.raises(NotImplementedError):
80 C._fields_ = [('x', c_int)]
0 import pytest
1 from ctypes import *
2
3
4 def test_restype_setattr(dll):
5 func = dll._testfunc_p_p
6 with pytest.raises(TypeError):
7 setattr(func, 'restype', 20)
8
9 def test_argtypes_setattr(dll):
10 func = dll._testfunc_p_p
11 with pytest.raises(TypeError):
12 setattr(func, 'argtypes', 20)
13 with pytest.raises(TypeError):
14 setattr(func, 'argtypes', [20])
15
16 func = CFUNCTYPE(c_long, c_void_p, c_long)(lambda: None)
17 assert func.argtypes == (c_void_p, c_long)
18
19 def test_paramflags_setattr():
20 func = CFUNCTYPE(c_long, c_void_p, c_long)(lambda: None)
21 with pytest.raises(TypeError):
22 setattr(func, 'paramflags', 'spam')
23 with pytest.raises(ValueError):
24 setattr(func, 'paramflags', (1, 2, 3, 4))
25 with pytest.raises(TypeError):
26 setattr(func, 'paramflags', ((1,), ('a',)))
27 func.paramflags = (1,), (1|4,)
28
29 def test_kwargs(dll):
30 proto = CFUNCTYPE(c_char_p, c_char_p, c_int)
31 paramflags = (1, 'text', b"tavino"), (1, 'letter', ord('v'))
32 func = proto(('my_strchr', dll), paramflags)
33 assert func.argtypes == (c_char_p, c_int)
34 assert func.restype == c_char_p
35
36 result = func(b"abcd", ord('b'))
37 assert result == b"bcd"
38
39 result = func()
40 assert result == b"vino"
41
42 result = func(b"grapevine")
43 assert result == b"vine"
44
45 result = func(text=b"grapevine")
46 assert result == b"vine"
47
48 result = func(letter=ord('i'))
49 assert result == b"ino"
50
51 result = func(letter=ord('p'), text=b"impossible")
52 assert result == b"possible"
53
54 result = func(text=b"impossible", letter=ord('p'))
55 assert result == b"possible"
56
57 def test_array_to_ptr_wrongtype(dll):
58 ARRAY = c_byte * 8
59 func = dll._testfunc_ai8
60 func.restype = POINTER(c_int)
61 func.argtypes = [c_int * 8]
62 array = ARRAY(1, 2, 3, 4, 5, 6, 7, 8)
63 with pytest.raises(ArgumentError):
64 func(array)
0 from ctypes import *
1
2 import pytest
3
4
5 def test_subclass_initializer():
6 class POINT(Structure):
7 _fields_ = [("x", c_int), ("y", c_int)]
8
9 class POSITION(POINT):
10 # A subclass without _fields_
11 pass
12 pos = POSITION(1, 2)
13 assert (pos.x, pos.y) == (1, 2)
14 # Try a second time, result may be different (cf. issue1498)
15 pos = POSITION(1, 2)
16 assert (pos.x, pos.y) == (1, 2)
17
18 def test_fields_is_a_tuple():
19 class Person(Structure):
20 _fields_ = (("name", c_char*6),
21 ("age", c_int))
22
23 # short enough
24 p = Person(b"123456", 6)
25 assert p.name == b"123456"
26 assert p.age == 6
27
28 def test___init__():
29 class Person(Structure):
30 _fields_ = (("name", c_char*10),
31 ("age", c_int))
32
33 def __init__(self, name, surname, age):
34 self.name = name + b' ' + surname
35 self.age = age
36
37 p = Person(b"John", b"Doe", 25)
38 assert p.name == b"John Doe"
39 assert p.age == 25
40
41 def test_setattr():
42 class X(Structure):
43 _fields_ = [("a", c_int)]
44
45 x = X()
46 x.other = 42
47 assert x.other == 42
48
49 def test_withslots():
50 class X(Structure):
51 _fields_ = [("a", c_int * 2)]
52 __slots__ = ['a']
53
54 x = X()
55 x.a = (42, 43)
56 assert tuple(x.a) == (42, 43)
57
58 def test_getattr_recursion():
59 # Structure.__getattr__ used to call itself recursively
60 # and hit the recursion limit.
61 import sys
62 events = []
63
64 def tracefunc(frame, event, arg):
65 funcname = frame.f_code.co_name
66 if 'getattr' in funcname:
67 events.append(funcname)
68
69 oldtrace = sys.settrace(tracefunc)
70 try:
71 class X(Structure):
72 _fields_ = [("a", c_int)]
73
74 assert len(events) < 20
75 finally:
76 sys.settrace(oldtrace)
77 events = None
78
79 def test_large_fields():
80 # make sure that large fields are not "confused" with bitfields
81 # (because the bitfields use the higher bits of the "size" attribute)
82 Array = c_long * 8192
83 class X(Structure):
84 _fields_ = [('items', Array)]
85 obj = X()
86 assert isinstance(obj.items, Array)
87
88 def test_b_base():
89 # _b_base_ used to be None here in PyPy
90 class X(Structure):
91 _fields_ = [('x', c_int)]
92 obj = X()
93 p = pointer(obj)
94 assert p.contents._b_base_ is p
95
96 def test_swapped_bytes():
97 import sys
98
99 for i in [c_short, c_int, c_long, c_longlong,
100 c_float, c_double, c_ushort, c_uint,
101 c_ulong, c_ulonglong]:
102 FIELDS = [
103 ('n', i)
104 ]
105
106 class Native(Structure):
107 _fields_ = FIELDS
108
109 class Big(BigEndianStructure):
110 _fields_ = FIELDS
111
112 class Little(LittleEndianStructure):
113 _fields_ = FIELDS
114
115 def dostruct(c):
116 ba = create_string_buffer(sizeof(c))
117 ms = c.from_buffer(ba)
118 ms.n = 0xff00
119 return repr(ba[:])
120
121 if sys.byteorder == 'little':
122 assert dostruct(Native) == dostruct(Little)
123 assert dostruct(Native) != dostruct(Big)
124 else:
125 assert dostruct(Native) == dostruct(Big)
126 assert dostruct(Native) != dostruct(Little)
127
128 def test_from_buffer_copy():
129 from array import array
130
131 class S(Structure):
132 _fields_ = [('i', c_int)]
133 def __init__(self, some, unused, arguments):
134 pass
135 a = array('i', [1234567])
136 s1 = S.from_buffer(a)
137 s2 = S.from_buffer_copy(a)
138 assert s1.i == 1234567
139 assert s2.i == 1234567
140 a[0] = -7654321
141 assert s1.i == -7654321
142 assert s2.i == 1234567
143
144
145 def test_nonfinal_struct():
146 class X(Structure):
147 pass
148 assert sizeof(X) == 0
149 X._fields_ = [("a", c_int),]
150 with pytest.raises(AttributeError):
151 X._fields_ = []
152
153 class X(Structure):
154 pass
155 X()
156 with pytest.raises(AttributeError):
157 X._fields_ = []
158
159 class X(Structure):
160 pass
161 class Y(X):
162 pass
163 with pytest.raises(AttributeError):
164 X._fields_ = []
165 Y.__fields__ = []
166
167
168 def test_structure_overloading_getattr():
169 class X(Structure):
170 _fields_ = [('x', c_int)]
171
172 def __getattr__(self, name):
173 raise AttributeError(name)
174
175 x = X()
176 assert x.x == 0
177
178 def test_duplicate_names():
179 class S(Structure):
180 _fields_ = [('a', c_int),
181 ('b', c_int),
182 ('a', c_byte)]
183 s = S(260, -123)
184 assert sizeof(s) == 3 * sizeof(c_int)
185 assert s.a == 4 # 256 + 4
186 assert s.b == -123
0 import sys
1 from ctypes import *
2
3 def test_getattr():
4 class Stuff(Union):
5 _fields_ = [('x', c_char), ('y', c_int)]
6
7 stuff = Stuff()
8 stuff.y = ord('x') | (ord('z') << 24)
9 if sys.byteorder == 'little':
10 assert stuff.x == b'x'
11 else:
12 assert stuff.x == b'z'
13
14 def test_union_of_structures():
15 class Stuff(Structure):
16 _fields_ = [('x', c_int)]
17
18 class Stuff2(Structure):
19 _fields_ = [('x', c_int)]
20
21 class UnionofStuff(Union):
22 _fields_ = [('one', Stuff),
23 ('two', Stuff2)]
24
25 u = UnionofStuff()
26 u.one.x = 3
27 assert u.two.x == 3
0 from ctypes import *
1
2 def test_a_string(dll):
3 """
4 A testcase which accesses *values* in a dll.
5 """
6 a_string = (c_char * 16).in_dll(dll, "a_string")
7 assert a_string.raw == b"0123456789abcdef"
8 a_string[15:16] = b'$'
9 assert dll.get_a_string_char(15) == ord('$')
0 # Windows specific tests
1
2 from ctypes import *
3
4 import pytest
5
6 @pytest.mark.skipif("sys.platform != 'win32'")
7 def test_VARIANT(self):
8 from ctypes import wintypes
9 a = wintypes.VARIANT_BOOL()
10 assert a.value is False
11 b = wintypes.VARIANT_BOOL(3)
12 assert b.value is True
8787 assert self.stream.readline(80) == expected
8888
8989 @pytest.mark.parametrize('StreamCls', [Stream, StreamCFFI])
90 @settings(max_examples=50)
90 @settings(max_examples=50, deadline=None)
9191 @given(params=data_and_sizes(), chunk_size=st.integers(MIN_READ_SIZE, 8192))
9292 def test_stateful(params, chunk_size, StreamCls):
9393 data, sizes = params
0 import sys
1 from io import StringIO
2 import code
3
4
5 def test_flush_stdout_on_error():
6 runner = code.InteractiveInterpreter()
7 old_stdout = sys.stdout
8 try:
9 mystdout = StringIO()
10 sys.stdout = mystdout
11 runner.runcode(compile("print(5);0/0", "<interactive>", "exec"))
12 finally:
13 sys.stdout = old_stdout
14
15 assert mystdout.getvalue() == "5\n"
0 """Additional tests for datetime."""
1 import pytest
2
3 import datetime
4
5
6 class date_safe(datetime.date):
7 pass
8
9 class datetime_safe(datetime.datetime):
10 pass
11
12 class time_safe(datetime.time):
13 pass
14
15 class timedelta_safe(datetime.timedelta):
16 pass
17
18 @pytest.mark.parametrize("obj, expected", [
19 (datetime.date(2015, 6, 8), "datetime.date(2015, 6, 8)"),
20 (datetime.datetime(2015, 6, 8, 12, 34, 56),
21 "datetime.datetime(2015, 6, 8, 12, 34, 56)"),
22 (datetime.time(12, 34, 56), "datetime.time(12, 34, 56)"),
23 (datetime.timedelta(1), "datetime.timedelta(1)"),
24 (datetime.timedelta(1, 2), "datetime.timedelta(1, 2)"),
25 (datetime.timedelta(1, 2, 3), "datetime.timedelta(1, 2, 3)"),
26 (date_safe(2015, 6, 8), "date_safe(2015, 6, 8)"),
27 (datetime_safe(2015, 6, 8, 12, 34, 56),
28 "datetime_safe(2015, 6, 8, 12, 34, 56)"),
29 (time_safe(12, 34, 56), "time_safe(12, 34, 56)"),
30 (timedelta_safe(1), "timedelta_safe(1)"),
31 (timedelta_safe(1, 2), "timedelta_safe(1, 2)"),
32 (timedelta_safe(1, 2, 3), "timedelta_safe(1, 2, 3)"),
33 ])
34 def test_repr(obj, expected):
35 # XXX: there's a discrepancy between datetime.py and CPython's _datetime
36 # for the repr() of Python-defined subclasses of datetime classes.
37 assert repr(obj).endswith(expected)
38
39 @pytest.mark.parametrize("obj", [
40 datetime.date.today(),
41 datetime.time(),
42 datetime.datetime.utcnow(),
43 datetime.timedelta(),
44 datetime.tzinfo(),
45 ])
46 def test_attributes(obj):
47 with pytest.raises(AttributeError):
48 obj.abc = 1
49
50 def test_timedelta_init_long():
51 td = datetime.timedelta(microseconds=20000000000000000000)
52 assert td.days == 231481481
53 assert td.seconds == 41600
54 td = datetime.timedelta(microseconds=20000000000000000000.)
55 assert td.days == 231481481
56 assert td.seconds == 41600
57
58 def test_unpickle():
59 with pytest.raises(TypeError) as e:
60 datetime.date('123')
61 assert e.value.args[0].startswith('an integer is required')
62 with pytest.raises(TypeError) as e:
63 datetime.time('123')
64 assert e.value.args[0].startswith('an integer is required')
65 with pytest.raises(TypeError) as e:
66 datetime.datetime('123')
67 assert e.value.args[0].startswith('an integer is required')
68
69 datetime.time(b'\x01' * 6, None)
70 with pytest.raises(TypeError) as exc:
71 datetime.time(b'\x01' * 6, 123)
72 assert str(exc.value) == "bad tzinfo state arg"
73
74 datetime.datetime(b'\x01' * 10, None)
75 with pytest.raises(TypeError) as exc:
76 datetime.datetime(b'\x01' * 10, 123)
77 assert str(exc.value) == "bad tzinfo state arg"
78
79 def test_strptime():
80 import time, sys
81 string = '2004-12-01 13:02:47'
82 format = '%Y-%m-%d %H:%M:%S'
83 expected = datetime.datetime(*(time.strptime(string, format)[0:6]))
84 got = datetime.datetime.strptime(string, format)
85 assert expected == got
86
87 def test_datetime_rounding():
88 b = 0.0000001
89 a = 0.9999994
90
91 assert datetime.datetime.utcfromtimestamp(a).microsecond == 999999
92 assert datetime.datetime.utcfromtimestamp(a).second == 0
93 a += b
94 assert datetime.datetime.utcfromtimestamp(a).microsecond == 999999
95 assert datetime.datetime.utcfromtimestamp(a).second == 0
96 a += b
97 assert datetime.datetime.utcfromtimestamp(a).microsecond == 0
98 assert datetime.datetime.utcfromtimestamp(a).second == 1
99
100 def test_more_datetime_rounding():
101 expected_results = {
102 -1000.0: 'datetime.datetime(1969, 12, 31, 23, 43, 20)',
103 -999.9999996: 'datetime.datetime(1969, 12, 31, 23, 43, 20)',
104 -999.4: 'datetime.datetime(1969, 12, 31, 23, 43, 20, 600000)',
105 -999.0000004: 'datetime.datetime(1969, 12, 31, 23, 43, 21)',
106 -1.0: 'datetime.datetime(1969, 12, 31, 23, 59, 59)',
107 -0.9999996: 'datetime.datetime(1969, 12, 31, 23, 59, 59)',
108 -0.4: 'datetime.datetime(1969, 12, 31, 23, 59, 59, 600000)',
109 -0.0000004: 'datetime.datetime(1970, 1, 1, 0, 0)',
110 0.0: 'datetime.datetime(1970, 1, 1, 0, 0)',
111 0.0000004: 'datetime.datetime(1970, 1, 1, 0, 0)',
112 0.4: 'datetime.datetime(1970, 1, 1, 0, 0, 0, 400000)',
113 0.9999996: 'datetime.datetime(1970, 1, 1, 0, 0, 1)',
114 1000.0: 'datetime.datetime(1970, 1, 1, 0, 16, 40)',
115 1000.0000004: 'datetime.datetime(1970, 1, 1, 0, 16, 40)',
116 1000.4: 'datetime.datetime(1970, 1, 1, 0, 16, 40, 400000)',
117 1000.9999996: 'datetime.datetime(1970, 1, 1, 0, 16, 41)',
118 1293843661.191: 'datetime.datetime(2011, 1, 1, 1, 1, 1, 191000)',
119 }
120 for t in sorted(expected_results):
121 dt = datetime.datetime.utcfromtimestamp(t)
122 assert repr(dt) == expected_results[t]
123
124 def test_utcfromtimestamp():
125 """Confirm that utcfromtimestamp and fromtimestamp give consistent results.
126
127 Based on danchr's test script in https://bugs.pypy.org/issue986
128 """
129 import os
130 import time
131 if os.name == 'nt':
132 skip("setting os.environ['TZ'] ineffective on windows")
133 try:
134 prev_tz = os.environ.get("TZ")
135 os.environ["TZ"] = "GMT"
136 time.tzset()
137 for unused in range(100):
138 now = time.time()
139 delta = (datetime.datetime.utcfromtimestamp(now) -
140 datetime.datetime.fromtimestamp(now))
141 assert delta.days * 86400 + delta.seconds == 0
142 finally:
143 if prev_tz is None:
144 del os.environ["TZ"]
145 else:
146 os.environ["TZ"] = prev_tz
147 time.tzset()
148
149 def test_utcfromtimestamp_microsecond():
150 dt = datetime.datetime.utcfromtimestamp(0)
151 assert isinstance(dt.microsecond, int)
152
153 def test_default_args():
154 with pytest.raises(TypeError):
155 datetime.datetime()
156 with pytest.raises(TypeError):
157 datetime.datetime(10)
158 with pytest.raises(TypeError):
159 datetime.datetime(10, 10)
160 datetime.datetime(10, 10, 10)
161
162 def test_check_arg_types():
163 import decimal
164 class Number:
165 def __init__(self, value):
166 self.value = value
167 def __int__(self):
168 return self.value
169 class SubInt(int): pass
170
171 dt10 = datetime.datetime(10, 10, 10, 10, 10, 10, 10)
172 for xx in [
173 decimal.Decimal(10),
174 decimal.Decimal('10.9'),
175 Number(10),
176 SubInt(10),
177 Number(SubInt(10)),
178 ]:
179 dtxx = datetime.datetime(xx, xx, xx, xx, xx, xx, xx)
180 assert dt10 == dtxx
181 assert type(dtxx.month) is int
182 assert type(dtxx.second) is int
183
184 with pytest.raises(TypeError) as exc:
185 datetime.datetime(0, 10, '10')
186 assert str(exc.value).startswith('an integer is required')
187
188 f10 = Number(10.9)
189 with pytest.raises(TypeError) as exc:
190 datetime.datetime(10, 10, f10)
191 assert str(exc.value) == '__int__ returned non-int (type float)'
192
193 class Float(float):
194 pass
195 s10 = Float(10.9)
196 with pytest.raises(TypeError) as exc:
197 datetime.datetime(10, 10, s10)
198 assert str(exc.value) == 'integer argument expected, got float'
199
200 with pytest.raises(TypeError):
201 datetime.datetime(10., 10, 10)
202 with pytest.raises(TypeError):
203 datetime.datetime(10, 10., 10)
204 with pytest.raises(TypeError):
205 datetime.datetime(10, 10, 10.)
206 with pytest.raises(TypeError):
207 datetime.datetime(10, 10, 10, 10.)
208 with pytest.raises(TypeError):
209 datetime.datetime(10, 10, 10, 10, 10.)
210 with pytest.raises(TypeError):
211 datetime.datetime(10, 10, 10, 10, 10, 10.)
212 with pytest.raises(TypeError):
213 datetime.datetime(10, 10, 10, 10, 10, 10, 10.)
214
215 def test_utcnow_microsecond():
216 import copy
217
218 dt = datetime.datetime.utcnow()
219 assert type(dt.microsecond) is int
220
221 copy.copy(dt)
222
223 def test_radd():
224 class X(object):
225 def __radd__(self, other):
226 return "radd"
227 assert datetime.date(10, 10, 10) + X() == "radd"
228
229 def test_raises_if_passed_naive_datetime_and_start_or_end_time_defined():
230 class Foo(datetime.tzinfo):
231 def utcoffset(self, dt):
232 return datetime.timedelta(0.1)
233 naive = datetime.datetime(2014, 9, 22)
234 aware = datetime.datetime(2014, 9, 22, tzinfo=Foo())
235 assert naive != aware
236 with pytest.raises(TypeError) as exc:
237 naive.__sub__(aware)
238 assert str(exc.value) == "can't subtract offset-naive and offset-aware datetimes"
239
240 naive = datetime.time(7, 32, 12)
241 aware = datetime.time(7, 32, 12, tzinfo=Foo())
242 assert naive != aware
243
244 def test_future_types_newint():
245 # Issue 2193
246 class newint(int):
247 def __int__(self):
248 return self
249
250 dt_from_ints = datetime.datetime(2015, 12, 31, 12, 34, 56)
251 dt_from_newints = datetime.datetime(newint(2015), newint(12), newint(31), newint(12), newint(34), newint(56))
252 dt_from_mixed = datetime.datetime(2015, newint(12), 31, newint(12), 34, newint(56))
253 assert dt_from_ints == dt_from_newints
254 assert dt_from_newints == dt_from_mixed
255 assert dt_from_mixed == dt_from_ints
256
257 d_from_int = datetime.date.fromtimestamp(1431216000)
258 d_from_newint = datetime.date.fromtimestamp(newint(1431216000))
259 assert d_from_int == d_from_newint
260
261 dt_from_int = datetime.datetime.fromtimestamp(1431216000)
262 dt_from_newint = datetime.datetime.fromtimestamp(newint(1431216000))
263 assert dt_from_int == dt_from_newint
264
265 dtu_from_int = datetime.datetime.utcfromtimestamp(1431216000)
266 dtu_from_newint = datetime.datetime.utcfromtimestamp(newint(1431216000))
267 assert dtu_from_int == dtu_from_newint
268
269 td_from_int = datetime.timedelta(16565)
270 tds_from_int = datetime.timedelta(seconds=1431216000)
271 td_from_newint = datetime.timedelta(newint(16565))
272 tds_from_newint = datetime.timedelta(seconds=newint(1431216000))
273 assert td_from_int == tds_from_int
274 assert td_from_int == td_from_newint
275 assert td_from_int == tds_from_newint
276 assert tds_from_int == td_from_newint
277 assert tds_from_int == tds_from_newint
278 assert td_from_newint == tds_from_newint
279
280 td_mul_int_int = td_from_int * 2
281 td_mul_int_newint = td_from_int * newint(2)
282 td_mul_newint_int = td_from_newint * 2
283 td_mul_newint_newint = td_from_newint * newint(2)
284 assert td_mul_int_int == td_mul_int_newint
285 assert td_mul_int_int == td_mul_newint_int
286 assert td_mul_int_int == td_mul_newint_newint
287 assert td_mul_int_newint == td_mul_newint_int
288 assert td_mul_int_newint == td_mul_newint_newint
289 assert td_mul_newint_int == td_mul_newint_newint
290
291 td_div_int_int = td_from_int / 3600
292 td_div_int_newint = td_from_int / newint(3600)
293 td_div_newint_int = td_from_newint / 3600
294 td_div_newint_newint = td_from_newint / newint(3600)
295 assert td_div_int_int == td_div_int_newint
296 assert td_div_int_int == td_div_newint_int
297 assert td_div_int_int == td_div_newint_newint
298 assert td_div_int_newint == td_div_newint_int
299 assert td_div_int_newint == td_div_newint_newint
300 assert td_div_newint_int == td_div_newint_newint
301
302 def test_return_types():
303 td = datetime.timedelta(5)
304 assert type(td.total_seconds()) is float
305 class sub(datetime.timedelta): pass
306 assert type(+sub()) is datetime.timedelta
307
308 def test_subclass_date():
309 # replace() should return a subclass but not call __new__ or __init__.
310 class MyDate(datetime.date):
311 forbidden = False
312 def __new__(cls):
313 if cls.forbidden: FAIL
314 return datetime.date.__new__(cls, 2016, 2, 3)
315 def __init__(self, *args):
316 if self.forbidden: FAIL
317 d = MyDate()
318 d.forbidden = True
319 d2 = d.replace(day=5)
320 assert type(d2) is MyDate
321 assert d2 == datetime.date(2016, 2, 5)
322
323 def test_subclass_time():
324 # replace() should return a subclass but not call __new__ or __init__.
325 class MyTime(datetime.time):
326 forbidden = False
327 def __new__(cls):
328 if cls.forbidden: FAIL
329 return datetime.time.__new__(cls, 1, 2, 3)
330 def __init__(self, *args):
331 if self.forbidden: FAIL
332 d = MyTime()
333 d.forbidden = True
334 d2 = d.replace(hour=5)
335 assert type(d2) is MyTime
336 assert d2 == datetime.time(5, 2, 3)
337
338 def test_subclass_datetime():
339 # replace() should return a subclass but not call __new__ or __init__.
340 class MyDatetime(datetime.datetime):
341 forbidden = False
342 def __new__(cls):
343 if cls.forbidden: FAIL
344 return datetime.datetime.__new__(cls, 2016, 4, 5, 1, 2, 3)
345 def __init__(self, *args):
346 if self.forbidden: FAIL
347 d = MyDatetime()
348 d.forbidden = True
349 d2 = d.replace(hour=7)
350 assert type(d2) is MyDatetime
351 assert d2 == datetime.datetime(2016, 4, 5, 7, 2, 3)
0 import pytest
1
2 import os
3
4 dbm = pytest.importorskip('dbm')
5
6
7 def test_get(tmpdir):
8 path = str(tmpdir.join('test_dbm_extra.test_get'))
9 d = dbm.open(path, 'c')
10 x = d.get("42")
11 assert x is None
12 d.close()
13
14 def test_delitem(tmpdir):
15 path = str(tmpdir.join('test_dbm_extra.test_delitem'))
16 d = dbm.open(path, 'c')
17 with pytest.raises(KeyError):
18 del d['xyz']
19
20 def test_nonstring(tmpdir):
21 path = str(tmpdir.join('test_dbm_extra.test_nonstring'))
22 d = dbm.open(path, 'c')
23 with pytest.raises(TypeError):
24 d[123] = 'xyz'
25 with pytest.raises(TypeError):
26 d['xyz'] = 123
27 with pytest.raises(TypeError):
28 d['xyz'] = None
29 with pytest.raises(TypeError):
30 del d[123]
31 with pytest.raises(TypeError):
32 d[123]
33 with pytest.raises(TypeError):
34 123 in d
35 with pytest.raises(AttributeError):
36 d.has_key(123)
37 with pytest.raises(TypeError):
38 d.setdefault(123, 'xyz')
39 with pytest.raises(TypeError):
40 d.setdefault('xyz', 123)
41 with pytest.raises(TypeError):
42 d.get(123)
43 assert dict(d) == {}
44 d.setdefault('xyz', '123')
45 assert dict(d) == {b'xyz': b'123'}
46 d.close()
47
48 def test_multiple_sets(tmpdir):
49 path = str(tmpdir.join('test_dbm_extra.test_multiple_sets'))
50 d = dbm.open(path, 'c')
51 d['xyz'] = '12'
52 d['xyz'] = '3'
53 d['xyz'] = '546'
54 assert dict(d) == {b'xyz': b'546'}
55 assert d['xyz'] == b'546'
56
57 @pytest.mark.skipif("'__pypy__' not in sys.modules")
58 def test_extra():
59 import _dbm
60 with pytest.raises(TypeError):
61 _dbm.datum(123)
62 with pytest.raises(TypeError):
63 _dbm.datum(False)
64
65 def test_null():
66 db = dbm.open('test', 'c')
67 db['1'] = 'a\x00b'
68 db.close()
69
70 db = dbm.open('test', 'r')
71 assert db['1'] == b'a\x00b'
72 db.close()
73
74 def test_key_with_empty_value(tmpdir):
75 # this test fails on CPython too (at least on tannit), and the
76 # case shows up when gdbm is not installed and test_anydbm.py
77 # falls back dbm.
78 path = str(tmpdir.join('test_dbm_extra.test_key_with_empty_value'))
79 d = dbm.open(path, 'c')
80 assert 'key_with_empty_value' not in d
81 d['key_with_empty_value'] = ''
82 assert 'key_with_empty_value' in d
83 assert d['key_with_empty_value'] == b''
84 d.close()
85
86 def test_unicode_filename(tmpdir):
87 path = str(tmpdir) + os.sep + u'test_dbm_extra.test_unicode_filename'
88 d = dbm.open(path, 'c')
89 d.close()
33 import pickle
44 import sys
55
6 from support import import_fresh_module
6 from .support import import_fresh_module
77
88 C = import_fresh_module('decimal', fresh=['_decimal'])
99 P = import_fresh_module('decimal', blocked=['_decimal'])
0 import pytest
1
2 import _functools
3
4
5 def test_partial_reduce():
6 partial = _functools.partial(test_partial_reduce)
7 state = partial.__reduce__()
8 d = state[2][2]
9 assert state == (type(partial), (test_partial_reduce,),
10 (test_partial_reduce, (), d, None))
11 assert d is None or d == {} # both are acceptable
12
13 def test_partial_setstate():
14 partial = _functools.partial(object)
15 partial.__setstate__((test_partial_setstate, (), None, None))
16 assert partial.func == test_partial_setstate
17
18 def test_partial_pickle():
19 pytest.skip("can't run this test: _functools.partial now has "
20 "__module__=='functools', in this case confusing pickle")
21 import pickle
22 partial1 = _functools.partial(test_partial_pickle)
23 string = pickle.dumps(partial1)
24 partial2 = pickle.loads(string)
25 assert partial1.func == partial2.func
26
27 def test_immutable_attributes():
28 partial = _functools.partial(object)
29 with pytest.raises((TypeError, AttributeError)):
30 partial.func = sum
31 with pytest.raises(TypeError) as exc:
32 del partial.__dict__
33 assert str(exc.value) == "a partial object's dictionary may not be deleted"
34 with pytest.raises(AttributeError):
35 del partial.zzz
36
37 def test_self_keyword():
38 partial = _functools.partial(dict, self=42)
39 assert partial(other=43) == {'self': 42, 'other': 43}
40
41 def test_no_keywords():
42 kw1 = _functools.partial(dict).keywords
43 kw2 = _functools.partial(dict, **{}).keywords
44 # CPython gives different results for these two cases, which is not
45 # possible to emulate in pure Python; see issue #2043
46 assert kw1 == {} or kw1 is None
47 assert kw2 == {}
0 import pytest
1 gdbm = pytest.importorskip('gdbm')
2
3 def test_len(tmpdir):
4 path = str(tmpdir.join('test_gdbm_extra'))
5 g = gdbm.open(path, 'c')
6 g['abc'] = 'def'
7 assert len(g) == 1
8 g['bcd'] = 'efg'
9 assert len(g) == 2
10 del g['abc']
11 assert len(g) == 1
12
13 def test_unicode(tmpdir):
14 path = unicode(tmpdir.join('test_gdm_unicode'))
15 g = gdbm.open(path, 'c') # does not crash
0 import pytest
1
2 grp = pytest.importorskip('grp')
3
4
5 def test_basic():
6 with pytest.raises(KeyError) as e:
7 grp.getgrnam("dEkLofcG")
8 assert e.value.args[0] == 'getgrnam(): name not found: dEkLofcG'
9 for name in ["root", "wheel"]:
10 try:
11 g = grp.getgrnam(name)
12 except KeyError:
13 continue
14 assert g.gr_gid == 0
15 assert 'root' in g.gr_mem or g.gr_mem == []
16 assert g.gr_name == name
17 assert isinstance(g.gr_passwd, str) # usually just 'x', don't hope :-)
18 break
19 else:
20 raise
21
22 def test_extra():
23 with pytest.raises(TypeError):
24 grp.getgrnam(False)
25 with pytest.raises(TypeError):
26 grp.getgrnam(None)
27
28 def test_struct_group():
29 g = grp.struct_group((10, 20, 30, 40))
30 assert len(g) == 4
31 assert list(g) == [10, 20, 30, 40]
32 assert g.gr_name == 10
33 assert g.gr_passwd == 20
34 assert g.gr_gid == 30
35 assert g.gr_mem == 40
0 from __future__ import print_function
1 import pytest
2
3 @pytest.fixture
4 def testfile(tmpdir):
5 tmpfile = tmpdir.join('test_execution_context')
6 tmpfile.write("""
7 from __future__ import print_function
8 import gc
9 class X(object):
10 def __del__(self):
11 print("Called", self.num)
12 def f():
13 x1 = X(); x1.num = 1
14 x2 = X(); x2.num = 2
15 x1.next = x2
16 f()
17 gc.collect()
18 gc.collect()
19 """)
20 return tmpfile
21
22
23 def test_del_not_blocked(testfile):
24 # test the behavior fixed in r71420: before, only one __del__
25 # would be called
26 import os, sys
27 if sys.platform == "win32":
28 cmdformat = '"%s" "%s"'
29 else:
30 cmdformat = "'%s' '%s'"
31 g = os.popen(cmdformat % (sys.executable, testfile), 'r')
32 data = g.read()
33 g.close()
34 assert 'Called 1' in data
35 assert 'Called 2' in data
0 import sys
1 import itertools
2
3 def test_chain():
4 it = itertools.chain([], [1, 2, 3])
5 lst = list(it)
6 assert lst == [1, 2, 3]
7
8 def test_islice_maxint():
9 slic = itertools.islice(itertools.count(), 1, 10, sys.maxsize)
10 assert len(list(slic)) == 1
11
12 def test_islice_largeint():
13 slic = itertools.islice(itertools.count(), 1, 10, sys.maxsize - 20)
14 assert len(list(slic)) == 1
0 import sys
1
2 def pytest_ignore_collect(path):
3 if '__pypy__' not in sys.builtin_module_names:
4 try:
5 import pyrepl
6 except ImportError:
7 return True
0 # -*- coding: utf-8 -*-
1 """Tests for _sqlite3.py"""
2
3 from __future__ import absolute_import
4 import pytest
5 import sys
6
7 _sqlite3 = pytest.importorskip('_sqlite3')
8
9 pypy_only = pytest.mark.skipif('__pypy__' not in sys.builtin_module_names,
10 reason="PyPy-only test")
11
12
13 @pytest.yield_fixture
14 def con():
15 con = _sqlite3.connect(':memory:')
16 yield con
17 con.close()
18
19
20 def test_list_ddl(con):
21 """From issue996. Mostly just looking for lack of exceptions."""
22 cursor = con.cursor()
23 cursor.execute('CREATE TABLE foo (bar INTEGER)')
24 result = list(cursor)
25 assert result == []
26 cursor.execute('INSERT INTO foo (bar) VALUES (42)')
27 result = list(cursor)
28 assert result == []
29 cursor.execute('SELECT * FROM foo')
30 result = list(cursor)
31 assert result == [(42,)]
32
33 @pypy_only
34 def test_connect_takes_same_positional_args_as_Connection(con):
35 from inspect import getargspec
36 clsargs = getargspec(_sqlite3.Connection.__init__).args[1:] # ignore self
37 conargs = getargspec(_sqlite3.connect).args
38 assert clsargs == conargs
39
40 def test_total_changes_after_close(con):
41 con.close()
42 with pytest.raises(_sqlite3.ProgrammingError):
43 con.total_changes
44
45 def test_connection_check_init():
46 class Connection(_sqlite3.Connection):
47 def __init__(self, name):
48 pass
49
50 con = Connection(":memory:")
51 with pytest.raises(_sqlite3.ProgrammingError) as excinfo:
52 con.cursor()
53 assert '__init__' in str(excinfo.value)
54
55
56 def test_cursor_check_init(con):
57 class Cursor(_sqlite3.Cursor):
58 def __init__(self, name):
59 pass
60
61 cur = Cursor(con)
62 with pytest.raises(_sqlite3.ProgrammingError) as excinfo:
63 cur.execute('select 1')
64 assert '__init__' in str(excinfo.value)
65
66 def test_connection_after_close(con):
67 with pytest.raises(TypeError):
68 con()
69 con.close()
70 # raises ProgrammingError because should check closed before check args
71 with pytest.raises(_sqlite3.ProgrammingError):
72 con()
73
74 def test_cursor_iter(con):
75 cur = con.cursor()
76 with pytest.raises(StopIteration):
77 next(cur)
78
79 cur.execute('select 1')
80 next(cur)
81 with pytest.raises(StopIteration):
82 next(cur)
83
84 cur.execute('select 1')
85 con.commit()
86 next(cur)
87 with pytest.raises(StopIteration):
88 next(cur)
89
90 with pytest.raises(_sqlite3.ProgrammingError):
91 cur.executemany('select 1', [])
92 with pytest.raises(StopIteration):
93 next(cur)
94
95 cur.execute('select 1')
96 cur.execute('create table test(ing)')
97 with pytest.raises(StopIteration):
98 next(cur)
99
100 cur.execute('select 1')
101 cur.execute('insert into test values(1)')
102 con.commit()
103 with pytest.raises(StopIteration):
104 next(cur)
105
106 def test_cursor_after_close(con):
107 cur = con.execute('select 1')
108 cur.close()
109 con.close()
110 with pytest.raises(_sqlite3.ProgrammingError):
111 cur.close()
112 # raises ProgrammingError because should check closed before check args
113 with pytest.raises(_sqlite3.ProgrammingError):
114 cur.execute(1,2,3,4,5)
115 with pytest.raises(_sqlite3.ProgrammingError):
116 cur.executemany(1,2,3,4,5)
117
118 def test_connection_del(tmpdir):
119 """For issue1325."""
120 import os
121 import gc
122 resource = pytest.importorskip('resource')
123
124 limit = resource.getrlimit(resource.RLIMIT_NOFILE)
125 try:
126 fds = 0
127 while True:
128 fds += 1
129 resource.setrlimit(resource.RLIMIT_NOFILE, (fds, limit[1]))
130 try:
131 for p in os.pipe(): os.close(p)
132 except OSError:
133 assert fds < 100
134 else:
135 break
136
137 def open_many(cleanup):
138 con = []
139 for i in range(3):
140 con.append(_sqlite3.connect(str(tmpdir.join('test.db'))))
141 if cleanup:
142 con[i] = None
143 gc.collect(); gc.collect()
144
145 with pytest.raises(_sqlite3.OperationalError):
146 open_many(False)
147 gc.collect(); gc.collect()
148 open_many(True)
149 finally:
150 resource.setrlimit(resource.RLIMIT_NOFILE, limit)
151
152 def test_on_conflict_rollback_executemany(con):
153 major, minor, micro = _sqlite3.sqlite_version.split('.')[:3]
154 if (int(major), int(minor), int(micro)) < (3, 2, 2):
155 pytest.skip("requires sqlite3 version >= 3.2.2")
156 con.execute("create table foo(x, unique(x) on conflict rollback)")
157 con.execute("insert into foo(x) values (1)")
158 try:
159 con.executemany("insert into foo(x) values (?)", [[1]])
160 except _sqlite3.DatabaseError:
161 pass
162 con.execute("insert into foo(x) values (2)")
163 try:
164 con.commit()
165 except _sqlite3.OperationalError:
166 pytest.fail("_sqlite3 knew nothing about the implicit ROLLBACK")
167
168 def test_statement_arg_checking(con):
169 with pytest.raises(_sqlite3.Warning) as e:
170 con(123)
171 assert str(e.value).startswith('SQL is of wrong type. Must be string')
172 with pytest.raises(ValueError) as e:
173 con.execute(123)
174 assert str(e.value).startswith('operation parameter must be str')
175 with pytest.raises(ValueError) as e:
176 con.executemany(123, 123)
177 assert str(e.value).startswith('operation parameter must be str')
178 with pytest.raises(ValueError) as e:
179 con.executescript(123)
180 assert str(e.value).startswith('script argument must be unicode')
181
182 def test_statement_param_checking(con):
183 con.execute('create table foo(x)')
184 con.execute('insert into foo(x) values (?)', [2])
185 con.execute('insert into foo(x) values (?)', (2,))
186 class seq(object):
187 def __len__(self):
188 return 1
189 def __getitem__(self, key):
190 return 2
191 con.execute('insert into foo(x) values (?)', seq())
192 del seq.__len__
193 with pytest.raises(_sqlite3.ProgrammingError):
194 con.execute('insert into foo(x) values (?)', seq())
195 with pytest.raises(_sqlite3.ProgrammingError):
196 con.execute('insert into foo(x) values (?)', {2:2})
197 with pytest.raises(ValueError) as e:
198 con.execute('insert into foo(x) values (?)', 2)
199 assert str(e.value) == 'parameters are of unsupported type'
200
201 def test_explicit_begin(con):
202 con.execute('BEGIN')
203 con.execute('BEGIN ')
204 con.execute('BEGIN')
205 con.commit()
206 con.execute('BEGIN')
207 con.commit()
208
209 def test_row_factory_use(con):
210 con.row_factory = 42
211 con.execute('select 1')
212
213 def test_returning_blob_must_own_memory(con):
214 import gc
215 con.create_function("returnblob", 0, lambda: memoryview(b"blob"))
216 cur = con.execute("select returnblob()")
217 val = cur.fetchone()[0]
218 assert isinstance(val, bytes)
219
220 def test_description_after_fetchall(con):
221 cur = con.cursor()
222 assert cur.description is None
223 cur.execute("select 42").fetchall()
224 assert cur.description is not None
225
226 def test_executemany_lastrowid(con):
227 cur = con.cursor()
228 cur.execute("create table test(a)")
229 cur.executemany("insert into test values (?)", [[1], [2], [3]])
230 assert cur.lastrowid is None
231 # issue 2682
232 cur.execute('''insert
233 into test
234 values (?)
235 ''', (1, ))
236 assert cur.lastrowid is not None
237 cur.execute('''insert\t into test values (?) ''', (1, ))
238 assert cur.lastrowid is not None
239
240 def test_authorizer_bad_value(con):
241 def authorizer_cb(action, arg1, arg2, dbname, source):
242 return 42
243 con.set_authorizer(authorizer_cb)
244 with pytest.raises(_sqlite3.OperationalError) as e:
245 con.execute('select 123')
246 major, minor, micro = _sqlite3.sqlite_version.split('.')[:3]
247 if (int(major), int(minor), int(micro)) >= (3, 6, 14):
248 assert str(e.value) == 'authorizer malfunction'
249 else:
250 assert str(e.value) == \
251 ("illegal return value (1) from the authorization function - "
252 "should be SQLITE_OK, SQLITE_IGNORE, or SQLITE_DENY")
253
254 def test_issue1573(con):
255 cur = con.cursor()
256 cur.execute(u'SELECT 1 as méil')
257 assert cur.description[0][0] == u"méil"
258
259 def test_adapter_exception(con):
260 def cast(obj):
261 raise ZeroDivisionError
262
263 _sqlite3.register_adapter(int, cast)
264 try:
265 cur = con.cursor()
266 cur.execute("select ?", (4,))
267 val = cur.fetchone()[0]
268 # Adapter error is ignored, and parameter is passed as is.
269 assert val == 4
270 assert type(val) is int
271 finally:
272 del _sqlite3.adapters[(int, _sqlite3.PrepareProtocol)]
273
274 def test_null_character(con):
275 if not hasattr(_sqlite3, '_ffi') and sys.version_info < (2, 7, 9):
276 pytest.skip("_sqlite3 too old")
277 with pytest.raises(ValueError) as excinfo:
278 con("\0select 1")
279 assert str(excinfo.value) == "the query contains a null character"
280 with pytest.raises(ValueError) as excinfo:
281 con("select 1\0")
282 assert str(excinfo.value) == "the query contains a null character"
283 cur = con.cursor()
284 with pytest.raises(ValueError) as excinfo:
285 cur.execute("\0select 2")
286 assert str(excinfo.value) == "the query contains a null character"
287 with pytest.raises(ValueError) as excinfo:
288 cur.execute("select 2\0")
289 assert str(excinfo.value) == "the query contains a null character"
290
291 def test_close_in_del_ordering():
292 import gc
293 class SQLiteBackend(object):
294 success = False
295 def __init__(self):
296 self.connection = _sqlite3.connect(":memory:")
297 def close(self):
298 self.connection.close()
299 def __del__(self):
300 self.close()
301 SQLiteBackend.success = True
302 def create_db_if_needed(self):
303 conn = self.connection
304 cursor = conn.cursor()
305 cursor.execute("""
306 create table if not exists nameoftable(value text)
307 """)
308 cursor.close()
309 conn.commit()
310 SQLiteBackend().create_db_if_needed()
311 gc.collect()
312 gc.collect()
313 assert SQLiteBackend.success
0 import pytest
1 syslog = pytest.importorskip('syslog')
2
3 # XXX very minimal test
4
5 def test_syslog():
6 assert hasattr(syslog, 'LOG_ALERT')
00 import time
11 import pytest
2 import greenlet
32 vmprof = pytest.importorskip('vmprof')
3 greenlet = pytest.importorskip('greenlet')
44
55 def count_samples(filename):
66 stats = vmprof.read_profile(filename)
2121 vmprof.enable(f.fileno(), 1/250.0)
2222 G.switch(0.1)
2323 vmprof.disable()
24
24
2525 samples = count_samples(str(fname))
2626 # 0.1 seconds at 250Hz should be 25 samples
2727 assert 23 < samples < 27
520520 -self._microseconds)
521521
522522 def __pos__(self):
523 return self
523 # for CPython compatibility, we cannot use
524 # our __class__ here, but need a real timedelta
525 return timedelta(self._days,
526 self._seconds,
527 self._microseconds)
524528
525529 def __abs__(self):
526530 if self._days < 0:
812816 month = self._month
813817 if day is None:
814818 day = self._day
815 # PyPy fix: returns type(self)() instead of date()
816 return type(self)(year, month, day)
819 return date.__new__(type(self), year, month, day)
817820
818821 # Comparisons of date objects with other.
819822
12881291 microsecond = self.microsecond
12891292 if tzinfo is True:
12901293 tzinfo = self.tzinfo
1291 # PyPy fix: returns type(self)() instead of time()
1292 return type(self)(hour, minute, second, microsecond, tzinfo)
1294 return time.__new__(type(self),
1295 hour, minute, second, microsecond, tzinfo)
12931296
12941297 # Pickle support.
12951298
13401343 hour, minute, second, microsecond)
13411344 _check_tzinfo_arg(tzinfo)
13421345 self = dateinterop.__new__(cls)
1343 self._year = year
1344 self._month = month
1345 self._day = day
1346 self._hour = hour
1347 self._minute = minute
1348 self._second = second
1349 self._microsecond = microsecond
1346 self._year = int(year)
1347 self._month = int(month)
1348 self._day = int(day)
1349 self._hour = int(hour)
1350 self._minute = int(minute)
1351 self._second = int(second)
1352 self._microsecond = int(microsecond)
13501353 self._tzinfo = tzinfo
13511354 self._hashcode = -1
13521355 return self
15021505 if tzinfo is True:
15031506 tzinfo = self.tzinfo
15041507 # PyPy fix: returns type(self)() instead of datetime()
1505 return type(self)(year, month, day, hour, minute, second, microsecond,
1506 tzinfo)
1508 return datetime.__new__(type(self), year, month, day, hour, minute,
1509 second, microsecond, tzinfo)
15071510
15081511 def astimezone(self, tz=None):
15091512 if tz is None:
17671770 if myoff == otoff:
17681771 return base
17691772 if myoff is None or otoff is None:
1770 raise TypeError("cannot mix naive and timezone-aware time")
1773 # The CPython _datetimemodule.c error message and the
1774 # datetime.py one are different
1775 raise TypeError("can't subtract offset-naive and "
1776 "offset-aware datetimes")
17711777 return base + otoff - myoff
17721778
17731779 def __hash__(self):
77 available.
88 """
99
10 __revision__ = "$Id: sysconfig.py 85358 2010-10-10 09:54:59Z antoine.pitrou $"
11
1210 import sys
1311 import os
14 import imp
12 import _imp
1513
1614 from distutils.errors import DistutilsPlatformError
1715
6260
6361 def _init_posix():
6462 """Initialize the module as appropriate for POSIX systems."""
65 so_ext = [s[0] for s in imp.get_suffixes() if s[2] == imp.C_EXTENSION][0]
66
67 g = {}
68 g['CC'] = "cc -pthread"
69 g['CXX'] = "c++ -pthread"
70 g['OPT'] = "-DNDEBUG -O2"
71 g['CFLAGS'] = "-DNDEBUG -O2"
72 g['CCSHARED'] = "-fPIC"
73 g['LDSHARED'] = "cc -pthread -shared"
74 g['EXT_SUFFIX'] = so_ext
75 g['SHLIB_SUFFIX'] = ".so"
76 g['SO'] = so_ext # deprecated in Python 3, for backward compatibility
77 g['AR'] = "ar"
78 g['ARFLAGS'] = "rc"
79 g['EXE'] = ""
80 g['LIBDIR'] = os.path.join(sys.prefix, 'lib')
81 g['VERSION'] = get_python_version()
82
83 if sys.platform[:6] == "darwin":
84 import platform
85 if platform.machine() == 'i386':
86 if platform.architecture()[0] == '32bit':
87 arch = 'i386'
88 else:
89 arch = 'x86_64'
90 else:
91 # just a guess
92 arch = platform.machine()
93 g['LDSHARED'] += ' -undefined dynamic_lookup'
94 g['CC'] += ' -arch %s' % (arch,)
95
63 from _sysconfigdata import build_time_vars
9664 global _config_vars
97 _config_vars = g
65 _config_vars = build_time_vars
9866
9967
10068 def _init_nt():
10169 """Initialize the module as appropriate for NT"""
10270 g = {}
71 # set basic install directories
72 g['LIBDEST'] = get_python_lib(plat_specific=0, standard_lib=1)
73 g['BINLIBDEST'] = get_python_lib(plat_specific=1, standard_lib=1)
74
75 # XXX hmmm.. a normal install puts include files here
76 g['INCLUDEPY'] = get_python_inc(plat_specific=0)
77
78 g['EXT_SUFFIX'] = _imp.extension_suffixes()[0]
10379 g['EXE'] = ".exe"
104 g['SO'] = ".pyd"
105 g['SOABI'] = g['SO'].rsplit('.')[0] # xxx?
80 g['VERSION'] = get_python_version().replace(".", "")
81 g['BINDIR'] = os.path.dirname(os.path.abspath(sys.executable))
10682
10783 global _config_vars
10884 _config_vars = g
220196
221197 from .sysconfig_cpython import (
222198 parse_makefile, _variable_rx, expand_makefile_vars)
223
565565 else:
566566 return Fraction(round(self / shift) * shift)
567567
568 def __hash__(self):
568 def __hash__(self, CACHE=[-1] * 1001):
569569 """hash(self)"""
570570
571571 # XXX since this method is expensive, consider caching the result
579579 # dinv is the inverse of self._denominator modulo the prime
580580 # _PyHASH_MODULUS, or 0 if self._denominator is divisible by
581581 # _PyHASH_MODULUS.
582 dinv = pow(self._denominator, _PyHASH_MODULUS - 2, _PyHASH_MODULUS)
582
583 # PyPy3: added caching of pow() results for denominators up to 1000
584 denom = self._denominator
585 assert denom >= 0
586 if denom < len(CACHE):
587 dinv = CACHE[denom]
588 if dinv == -1:
589 dinv = pow(denom, _PyHASH_MODULUS - 2, _PyHASH_MODULUS)
590 CACHE[denom] = dinv
591 else:
592 dinv = pow(denom, _PyHASH_MODULUS - 2, _PyHASH_MODULUS)
593
583594 if not dinv:
584595 hash_ = _PyHASH_INF
585596 else:
586597 hash_ = abs(self._numerator) * dinv % _PyHASH_MODULUS
587 result = hash_ if self >= 0 else -hash_
598 result = hash_ if self._numerator >= 0 else -hash_
588599 return -2 if result == -1 else result
589600
590601 def __eq__(a, b):
133133 __get_hash = __get_openssl_constructor
134134 algorithms_available = algorithms_available.union(
135135 _hashlib.openssl_md_meth_names)
136 except ImportError:
136 except ImportError as e:
137137 new = __py_new
138138 __get_hash = __get_builtin_constructor
139 # added by PyPy
140 import warnings
141 warnings.warn("The _hashlib module is not available, falling back "
142 "to a much slower implementation (%s)" % str(e),
143 RuntimeWarning)
139144
140145 try:
141146 # OpenSSL's PKCS5_PBKDF2_HMAC requires OpenSSL 1.0+ with HMAC and SHA
222222 def_op('CALL_METHOD', 202) # #args not including 'self'
223223 def_op('BUILD_LIST_FROM_ARG', 203)
224224 jrel_op('JUMP_IF_NOT_DEBUG', 204) # jump over assert statements
225 def_op('LOAD_REVDB_VAR', 205) # reverse debugger (syntax example: $5)
225226
226227 del def_op, name_op, jrel_op, jabs_op
1919
2020 _INSTALL_SCHEMES = {
2121 'posix_prefix': {
22 'stdlib': '{installed_base}/lib/python{py_version_short}',
23 'platstdlib': '{platbase}/lib/python{py_version_short}',
24 'purelib': '{base}/lib/python{py_version_short}/site-packages',
25 'platlib': '{platbase}/lib/python{py_version_short}/site-packages',
22 'stdlib': '{installed_base}/lib/{implementation_lower}{py_version_short}',
23 'platstdlib': '{platbase}/lib/{implementation_lower}{py_version_short}',
24 'purelib': '{base}/lib/{implementation_lower}{py_version_short}/site-packages',
25 'platlib': '{platbase}/lib/{implementation_lower}{py_version_short}/site-packages',
2626 'include':
27 '{installed_base}/include/python{py_version_short}{abiflags}',
27 '{installed_base}/include/{implementation_lower}{py_version_short}{abiflags}',
2828 'platinclude':
29 '{installed_platbase}/include/python{py_version_short}{abiflags}',
29 '{installed_platbase}/include/{implementation_lower}{py_version_short}{abiflags}',
3030 'scripts': '{base}/bin',
3131 'data': '{base}',
3232 },
3333 'posix_home': {
34 'stdlib': '{installed_base}/lib/python',
35 'platstdlib': '{base}/lib/python',
36 'purelib': '{base}/lib/python',
37 'platlib': '{base}/lib/python',
38 'include': '{installed_base}/include/python',
39 'platinclude': '{installed_base}/include/python',
34 'stdlib': '{installed_base}/lib/{implementation_lower}',
35 'platstdlib': '{base}/lib/{implementation_lower}',
36 'purelib': '{base}/lib/{implementation_lower}',
37 'platlib': '{base}/lib/{implementation_lower}',
38 'include': '{installed_base}/include/{implementation_lower}',
39 'platinclude': '{installed_base}/include/{implementation_lower}',
4040 'scripts': '{base}/bin',
4141 'data': '{base}',
4242 },
4343 'pypy': {
44 'stdlib': '{installed_base}/lib-python',
45 'platstdlib': '{base}/lib-python',
44 'stdlib': '{installed_base}/lib-{implementation_lower}',
45 'platstdlib': '{base}/lib-{implementation_lower}',
4646 'purelib': '{base}/site-packages',
4747 'platlib': '{base}/site-packages',
4848 'include': '{installed_base}/include',
6161 'data': '{base}',
6262 },
6363 'nt_user': {
64 'stdlib': '{userbase}/Python{py_version_nodot}',
65 'platstdlib': '{userbase}/Python{py_version_nodot}',
66 'purelib': '{userbase}/Python{py_version_nodot}/site-packages',
67 'platlib': '{userbase}/Python{py_version_nodot}/site-packages',
68 'include': '{userbase}/Python{py_version_nodot}/Include',
69 'scripts': '{userbase}/Python{py_version_nodot}/Scripts',
64 'stdlib': '{userbase}/{implementation}{py_version_nodot}',
65 'platstdlib': '{userbase}/{implementation}{py_version_nodot}',
66 'purelib': '{userbase}/{implementation}{py_version_nodot}/site-packages',
67 'platlib': '{userbase}/{implementation}{py_version_nodot}/site-packages',
68 'include': '{userbase}/{implementation}{py_version_nodot}/Include',
69 'scripts': '{userbase}/{implementation}{py_version_nodot}/Scripts',
7070 'data': '{userbase}',
7171 },
7272 'posix_user': {
73 'stdlib': '{userbase}/lib/python{py_version_short}',
74 'platstdlib': '{userbase}/lib/python{py_version_short}',
75 'purelib': '{userbase}/lib/python{py_version_short}/site-packages',
76 'platlib': '{userbase}/lib/python{py_version_short}/site-packages',
77 'include': '{userbase}/include/python{py_version_short}',
73 'stdlib': '{userbase}/lib/{implementation_lower}{py_version_short}',
74 'platstdlib': '{userbase}/lib/{implementation_lower}{py_version_short}',
75 'purelib': '{userbase}/lib/{implementation_lower}{py_version_short}/site-packages',
76 'platlib': '{userbase}/lib/{implementation_lower}{py_version_short}/site-packages',
77 'include': '{userbase}/include/{implementation_lower}{py_version_short}',
7878 'scripts': '{userbase}/bin',
7979 'data': '{userbase}',
8080 },
8181 'osx_framework_user': {
82 'stdlib': '{userbase}/lib/python',
83 'platstdlib': '{userbase}/lib/python',
84 'purelib': '{userbase}/lib/python/site-packages',
85 'platlib': '{userbase}/lib/python/site-packages',
82 'stdlib': '{userbase}/lib/{implementation_lower}',
83 'platstdlib': '{userbase}/lib/{implementation_lower}',
84 'purelib': '{userbase}/lib/{implementation_lower}/site-packages',
85 'platlib': '{userbase}/lib/{implementation_lower}/site-packages',
8686 'include': '{userbase}/include',
8787 'scripts': '{userbase}/bin',
8888 'data': '{userbase}',
104104 _CONFIG_VARS = None
105105 _USER_BASE = None
106106
107
108 def _get_implementation():
109 if '__pypy__' in sys.builtin_module_names:
110 return 'PyPy'
111 return 'Python'
107112
108113 def _safe_realpath(path):
109114 try:
539544 except AttributeError:
540545 # sys.abiflags may not be defined on all platforms.
541546 _CONFIG_VARS['abiflags'] = ''
547 _CONFIG_VARS['implementation'] = _get_implementation()
548 _CONFIG_VARS['implementation_lower'] = _get_implementation().lower()
542549
543550 if os.name == 'nt':
544551 _init_non_posix(_CONFIG_VARS)
714721 _print_dict('Paths', get_paths())
715722 print()
716723 _print_dict('Variables', get_config_vars())
724 print
725 _print_dict('User', get_paths('%s_user' % os.name))
717726
718727
719728 if __name__ == '__main__':
0 from test import support
01 import copy
12 import pickle
23 import unittest
34
45 class DictSetTest(unittest.TestCase):
56
7 @support.cpython_only
68 def test_constructors_not_callable(self):
79 kt = type({}.keys())
810 self.assertRaises(TypeError, kt, {})
5959 import builtins
6060
6161 git = mod.StupidGit()
62
63 class ExampleClassWithSlot(object):
64 __slots__ = 'myslot'
6265
6366 class IsTestBase(unittest.TestCase):
6467 predicates = set([inspect.isbuiltin, inspect.isclass, inspect.iscode,
130133 self.istest(inspect.iscoroutinefunction, 'coroutine_function_example')
131134
132135 if hasattr(types, 'MemberDescriptorType'):
133 self.istest(inspect.ismemberdescriptor,
134 'type(lambda: None).__globals__')
136 # App-level slots are member descriptors on both PyPy and
137 # CPython, but the various built-in attributes are all
138 # getsetdescriptors on PyPy. So check ismemberdescriptor()
139 # with an app-level slot.
140 self.istest(inspect.ismemberdescriptor, 'ExampleClassWithSlot.myslot')
135141 else:
136142 self.assertFalse(inspect.ismemberdescriptor(datetime.timedelta.days))
137143
33 import subprocess
44 import shutil
55 from copy import copy
6 from distutils.spawn import find_executable
67
78 from test.support import (run_unittest, TESTFN, unlink, check_warnings,
89 captured_stdout, impl_detail, import_module,
296297
297298 self.assertIn(ldflags, ldshared)
298299
300 @unittest.skipIf(sys.platform == "win32", "Does not apply to Windows")
301 def test_cc_values(self):
302 """ CC and CXX should be set for pypy """
303 for var in ["CC", "CXX"]:
304 assert sysconfig.get_config_var(var) is not None
305
306 @unittest.skipIf(not find_executable("gcc"),
307 "Does not apply to machines without gcc installed"
308 )
309 def test_gcc_values(self):
310 """ if gcc is installed on the box, gcc values should be set. """
311 assert "gcc" in sysconfig.get_config_var("CC")
312 assert sysconfig.get_config_var("GNULD") == "yes"
313 assert "gcc" in sysconfig.get_config_var("LDSHARED")
314
315
316 @unittest.skipIf(not find_executable("g++"),
317 "Does not apply to machines without g++ installed"
318 )
319 def test_gplusplus_values(self):
320 """ if g++ is installed on the box, g++ values should be set. """
321 assert "g++" in sysconfig.get_config_var("CXX")
322
323
299324 @unittest.skipUnless(sys.platform == "darwin", "test only relevant on MacOSX")
300325 def test_platform_in_subprocess(self):
301326 my_platform = sysconfig.get_platform()
0 import os
1 import sys
2 import unittest
3 import site
4
5
6 class TestSysConfigPypy(unittest.TestCase):
7 def test_install_schemes(self):
8 # User-site etc. paths should have "pypy" and not "python"
9 # inside them.
10 if site.ENABLE_USER_SITE:
11 parts = site.USER_SITE.lower().split(os.path.sep)
12 assert any(x.startswith('pypy') for x in parts[-2:]), parts
13
14
15 if __name__ == "__main__":
16 unittest.main()
4040 FrameType = type(tb.tb_frame)
4141 tb = None; del tb
4242
43 # For Jython, the following two types are identical
43 #
44 # On CPython, FunctionType.__code__ is a 'getset_descriptor', but
45 # FunctionType.__globals__ is a 'member_descriptor', just like app-level
46 # slots. On PyPy, all descriptors of built-in types are
47 # 'getset_descriptor', but the app-level slots are 'member_descriptor'
48 # as well. (On Jython the situation might still be different.)
49 #
50 # Note that MemberDescriptorType was equal to GetSetDescriptorType in
51 # PyPy <= 6.0.
52 #
4453 GetSetDescriptorType = type(FunctionType.__code__)
45 MemberDescriptorType = type(FunctionType.__globals__)
54 class _C: __slots__ = 's'
55 MemberDescriptorType = type(_C.s)
4656
4757 del sys, _f, _g, _C, _c, # Not for export
4858
421421 RegrTest('test_sys_setprofile.py', core=True),
422422 RegrTest('test_sys_settrace.py', core=True),
423423 RegrTest('test_sysconfig.py'),
424 RegrTest('test_sysconfig_pypy.py'),
424425 RegrTest('test_syslog.py'),
425426 RegrTest('test_tarfile.py'),
426427 RegrTest('test_tcl.py'),
185185 # Prefer poll, if available, since you can poll() any fd
186186 # which can't be done with select().
187187 if HAVE_POLL:
188 p.register(sock.fileno(), POLLOUT | POLLIN)
188 p.register(sock.fileno(), POLLOUT if writing else POLLIN)
189189
190190 rc = len(p.poll(timeout * 1000.0))
191191 else:
219219 if server_hostname:
220220 self.server_hostname = server_hostname.decode('idna', 'strict')
221221
222 lib.ERR_get_state()
223222 lib.ERR_clear_error()
224223 self.ssl = ssl = ffi.gc(lib.SSL_new(ctx), lib.SSL_free)
225224
389389
390390 class defaultdict(dict):
391391 __slots__ = ["default_factory"]
392
392
393393 def __init__(self, *args, **kwds):
394394 if len(args) > 0:
395395 default_factory = args[0]
400400 default_factory = None
401401 self.default_factory = default_factory
402402 super(defaultdict, self).__init__(*args, **kwds)
403
403
404404 def __missing__(self, key):
405405 # from defaultdict docs
406 if self.default_factory is None:
406 if self.default_factory is None:
407407 raise KeyError(key)
408408 self[key] = value = self.default_factory()
409409 return value
419419
420420 def copy(self):
421421 return type(self)(self.default_factory, self)
422
422
423423 def __copy__(self):
424424 return self.copy()
425425
437437 """
438438 return (type(self), (self.default_factory,), None, None,
439439 iter(self.items()))
440
441
442 try:
443 from _pypy_collections import OrderedDict
444 except ImportError:
445 pass
8080 def _CData_output(self, resarray, base=None, index=-1):
8181 from _rawffi.alt import types
8282 # If a char_p or unichar_p is received, skip the string interpretation
83 if base._ffiargtype != types.Pointer(types.char_p) and \
84 base._ffiargtype != types.Pointer(types.unichar_p):
83 try:
84 deref = type(base)._deref_ffiargtype()
85 except AttributeError:
86 deref = None
87 if deref != types.char_p and deref != types.unichar_p:
8588 # this seems to be a string if we're array of char, surprise!
8689 from ctypes import c_char, c_wchar
8790 if self._type_ is c_char:
126129 value = self(*value)
127130 return _CDataMeta.from_param(self, value)
128131
132 def _build_ffiargtype(self):
133 return _ffi.types.Pointer(self._type_.get_ffi_argtype())
134
135 def _deref_ffiargtype(self):
136 return self._type_.get_ffi_argtype()
137
129138 def array_get_slice_params(self, index):
130139 if hasattr(self, '_length_'):
131140 start, stop, step = index.indices(self._length_)
179188 self._buffer = self._ffiarray(self._length_, autofree=True)
180189 for i, arg in enumerate(args):
181190 self[i] = arg
191 _init_no_arg_ = __init__
182192
183193 def _fix_index(self, index):
184194 if index < 0:
253263 _type_ = base
254264 )
255265 cls = ArrayMeta(name, (Array,), tpdict)
256 cls._ffiargtype = _ffi.types.Pointer(base.get_ffi_argtype())
257266 ARRAY_CACHE[key] = cls
258267 return cls
4848 else:
4949 return self.from_param(as_parameter)
5050
51 def _build_ffiargtype(self):
52 return _shape_to_ffi_type(self._ffiargshape_)
53
5154 def get_ffi_argtype(self):
5255 if self._ffiargtype:
5356 return self._ffiargtype
54 self._ffiargtype = _shape_to_ffi_type(self._ffiargshape_)
57 self._ffiargtype = self._build_ffiargtype()
5558 return self._ffiargtype
5659
5760 def _CData_output(self, resbuffer, base=None, index=-1):
106109 raise ValueError(
107110 "Buffer size too small (%d instead of at least %d bytes)"
108111 % (buf.nbytes, offset + size))
109 result = self()
112 result = self._newowninstance_()
110113 dest = result._buffer.buffer
111114 try:
112115 raw_addr = buf._pypy_raw_address() + offset
115118 else:
116119 from ctypes import memmove
117120 memmove(dest, raw_addr, size)
121 return result
122
123 def _newowninstance_(self):
124 result = self.__new__(self)
125 result._init_no_arg_()
118126 return result
119127
120128
147155
148156 def __init__(self, *args, **kwds):
149157 raise TypeError("%s has no type" % (type(self),))
158 _init_no_arg_ = __init__
150159
151160 def _ensure_objects(self):
152161 if '_objects' not in self.__dict__:
266266 return
267267
268268 raise TypeError("Unknown constructor %s" % (args,))
269 _init_no_arg_ = __init__
269270
270271 def _wrap_callable(self, to_call, argtypes):
271272 def f(*args):
484485 return cobj, cobj._to_ffi_param(), type(cobj)
485486
486487 def _convert_args_for_callback(self, argtypes, args):
488 from _ctypes.structure import StructOrUnion
489 #
487490 assert len(argtypes) == len(args)
488491 newargs = []
489492 for argtype, arg in zip(argtypes, args):
493496 param = param._get_buffer_value()
494497 elif self._is_primitive(argtype):
495498 param = param.value
499 elif isinstance(param, StructOrUnion): # not a *pointer* to struct
500 newparam = StructOrUnion.__new__(type(param))
501 param._copy_to(newparam._buffer.buffer)
502 param = newparam
496503 newargs.append(param)
497504 return newargs
498505
556563 keepalive, newarg, newargtype = self._conv_param(argtype, defval)
557564 else:
558565 import ctypes
559 val = argtype._type_()
566 val = argtype._type_._newowninstance_()
560567 keepalive = None
561568 newarg = ctypes.byref(val)
562569 newargtype = type(newarg)
6666 self._buffer = ffiarray(1, autofree=True)
6767 if value is not None:
6868 self.contents = value
69 def _init_no_arg_(self):
70 self._buffer = ffiarray(1, autofree=True)
6971 self._ffiarray = ffiarray
7072 self.__init__ = __init__
73 self._init_no_arg_ = _init_no_arg_
7174 self._type_ = TP
72 self._ffiargtype = _ffi.types.Pointer(TP.get_ffi_argtype())
75
76 def _build_ffiargtype(self):
77 return _ffi.types.Pointer(self._type_.get_ffi_argtype())
78
79 def _deref_ffiargtype(self):
80 return self._type_.get_ffi_argtype()
7381
7482 from_address = cdata_from_address
7583
130138 if not (isinstance(tp, _CDataMeta) and tp._is_pointer_like()):
131139 raise TypeError("cast() argument 2 must be a pointer type, not %s"
132140 % (tp,))
141 result = tp._newowninstance_()
133142 if isinstance(obj, int):
134 result = tp()
135143 result._buffer[0] = obj
136144 return result
137145 elif obj is None:
138 result = tp()
139146 return result
140147 elif isinstance(obj, Array):
141 ptr = tp.__new__(tp)
142 ptr._buffer = tp._ffiarray(1, autofree=True)
143 ptr._buffer[0] = obj._buffer
144 result = ptr
148 result._buffer[0] = obj._buffer
145149 elif isinstance(obj, bytes):
146 result = tp()
147150 result._buffer[0] = memoryview(obj)._pypy_raw_address()
148151 return result
149152 elif not (isinstance(obj, _CData) and type(obj)._is_pointer_like()):
150153 raise TypeError("cast() argument 1 must be a pointer, not %s"
151154 % (type(obj),))
152155 else:
153 result = tp()
154156 result._buffer[0] = obj._buffer[0]
155157
156158 # The casted objects '_objects' member:
377377 self._buffer = self._ffiarray(1, autofree=True)
378378 if value is not DEFAULT_VALUE:
379379 self.value = value
380 _init_no_arg_ = __init__
380381
381382 def _ensure_objects(self):
382 if self._type_ not in 'zZP':
383 assert self._objects is None
384 return self._objects
383 # No '_objects' is the common case for primitives. Examples
384 # where there is an _objects is if _type in 'zZP', or if
385 # self comes from 'from_buffer(buf)'. See module/test_lib_pypy/
386 # ctypes_test/test_buffers.py: test_from_buffer_keepalive.
387 return getattr(self, '_objects', None)
385388
386389 def _getvalue(self):
387390 return self._buffer[0]
406409 id(self))
407410
408411 def __bool__(self):
409 return self._buffer[0] not in (0, '\x00')
412 return self._buffer[0] not in (0, b'\x00')
410413
411414 from _ctypes.function import CFuncPtr
159159 raise AttributeError("_fields_ is final")
160160 if self in [f[1] for f in value]:
161161 raise AttributeError("Structure or union cannot contain itself")
162 if self._ffiargtype is not None:
163 raise NotImplementedError("Too late to set _fields_: we already "
164 "said to libffi that the structure type %s is opaque"
165 % (self,))
162166 names_and_fields(
163167 self,
164168 value, self.__bases__[0],
275279 self.__setattr__(name, arg)
276280 for name, arg in kwds.items():
277281 self.__setattr__(name, arg)
282 _init_no_arg_ = __init__
278283
279284 def _subarray(self, fieldtype, name):
280285 """Return a _rawffi array of length 1 whose address is the same as
7373 self.__check_closed()
7474 key = _checkstr(key)
7575 return lib.pygdbm_exists(self.__ll_dbm, key, len(key))
76 has_key = __contains__
7776
7877 def get(self, key, default=None):
7978 with _lock:
8079 self.__check_closed()
81 key = _checkstr(key)
80 key = _checkstr(key)
8281 drec = lib.pygdbm_fetch(self.__ll_dbm, key, len(key))
8382 if not drec.dptr:
8483 return default
+0
-122
lib_pypy/_pypy_collections.py less more
0 from __pypy__ import reversed_dict, move_to_end, objects_in_repr
1 from _operator import eq as _eq
2 import _collections_abc
3
4
5 class OrderedDict(dict):
6 '''Dictionary that remembers insertion order.
7
8 In PyPy all dicts are ordered anyway. This is mostly useful as a
9 placeholder to mean "this dict must be ordered even on CPython".
10
11 Known difference: iterating over an OrderedDict which is being
12 concurrently modified raises RuntimeError in PyPy. In CPython
13 instead we get some behavior that appears reasonable in some
14 cases but is nonsensical in other cases. This is officially
15 forbidden by the CPython docs, so we forbid it explicitly for now.
16 '''
17 def __init__(*args, **kwds):
18 '''Initialize an ordered dictionary. The signature is the same as
19 regular dictionaries, but keyword arguments are not recommended because
20 their insertion order is arbitrary.
21
22 '''
23 if not args:
24 raise TypeError("descriptor '__init__' of 'OrderedDict' object "
25 "needs an argument")
26 self, *args = args
27 if len(args) > 1:
28 raise TypeError('expected at most 1 arguments, got %d' % len(args))
29 self.__update(*args, **kwds)
30
31 update = __update = _collections_abc.MutableMapping.update
32
33 def __reversed__(self):
34 return reversed_dict(self)
35
36 def popitem(self, last=True):
37 '''od.popitem() -> (k, v), return and remove a (key, value) pair.
38 Pairs are returned in LIFO order if last is true or FIFO order if false.
39
40 '''
41 if last:
42 return dict.popitem(self)
43 else:
44 it = dict.__iter__(self)
45 try:
46 k = next(it)
47 except StopIteration:
48 raise KeyError('dictionary is empty')
49 return (k, self.pop(k))
50
51 def move_to_end(self, key, last=True):
52 '''Move an existing element to the end (or beginning if last==False).
53
54 Raises KeyError if the element does not exist.
55 When last=True, acts like a fast version of self[key]=self.pop(key).
56
57 '''
58 return move_to_end(self, key, last)
59
60 def __repr__(self):
61 'od.__repr__() <==> repr(od)'
62 if not self:
63 return '%s()' % (self.__class__.__name__,)
64 currently_in_repr = objects_in_repr()
65 if self in currently_in_repr:
66 return '...'
67 currently_in_repr[self] = 1
68 try:
69 return '%s(%r)' % (self.__class__.__name__, list(self.items()))
70 finally:
71 try:
72 del currently_in_repr[self]
73 except:
74 pass
75
76 def __reduce__(self):
77 'Return state information for pickling'
78 inst_dict = vars(self).copy()
79 return self.__class__, (), inst_dict or None, None, iter(self.items())
80
81 def copy(self):
82 'od.copy() -> a shallow copy of od'
83 return self.__class__(self)
84
85 def __eq__(self, other):
86 '''od.__eq__(y) <==> od==y. Comparison to another OD is order-sensitive
87 while comparison to a regular mapping is order-insensitive.
88
89 '''
90 if isinstance(other, OrderedDict):
91 return dict.__eq__(self, other) and all(map(_eq, self, other))
92 return dict.__eq__(self, other)
93
94 __ne__ = object.__ne__
95
96 def keys(self):
97 "D.keys() -> a set-like object providing a view on D's keys"
98 return _OrderedDictKeysView(self)
99
100 def items(self):
101 "D.items() -> a set-like object providing a view on D's items"
102 return _OrderedDictItemsView(self)
103
104 def values(self):
105 "D.values() -> an object providing a view on D's values"
106 return _OrderedDictValuesView(self)
107
108
109 class _OrderedDictKeysView(_collections_abc.KeysView):
110 def __reversed__(self):
111 yield from reversed_dict(self._mapping)
112
113 class _OrderedDictItemsView(_collections_abc.ItemsView):
114 def __reversed__(self):
115 for key in reversed_dict(self._mapping):
116 yield (key, self._mapping[key])
117
118 class _OrderedDictValuesView(_collections_abc.ValuesView):
119 def __reversed__(self):
120 for key in reversed_dict(self._mapping):
121 yield self._mapping[key]
00 import _imp
1 import os
2 import sys
3 from distutils.spawn import find_executable
14
25 so_ext = _imp.extension_suffixes()[0]
36
7
48 build_time_vars = {
5 "EXT_SUFFIX": so_ext,
6 "SHLIB_SUFFIX": so_ext,
79 "SOABI": '-'.join(so_ext.split('.')[1].split('-')[:2]),
8 "SO": so_ext # deprecated in Python 3, for backward compatibility
10 "SO": so_ext, # deprecated in Python 3, for backward compatibility
11 'CC': "cc -pthread",
12 'CXX': "c++ -pthread",
13 'OPT': "-DNDEBUG -O2",
14 'CFLAGS': "-DNDEBUG -O2",
15 'CCSHARED': "-fPIC",
16 'LDSHARED': "cc -pthread -shared",
17 'EXT_SUFFIX': so_ext,
18 'SHLIB_SUFFIX': ".so",
19 'AR': "ar",
20 'ARFLAGS': "rc",
21 'EXE': "",
22 'LIBDIR': os.path.join(sys.prefix, 'lib'),
23 'VERSION': sys.version[:3]
924 }
25
26 if find_executable("gcc"):
27 build_time_vars.update({
28 "CC": "gcc -pthread",
29 "GNULD": "yes",
30 "LDSHARED": "gcc -pthread -shared",
31 })
32 if find_executable("g++"):
33 build_time_vars["CXX"] = "g++ -pthread"
34
35 if sys.platform[:6] == "darwin":
36 import platform
37 if platform.machine() == 'i386':
38 if platform.architecture()[0] == '32bit':
39 arch = 'i386'
40 else:
41 arch = 'x86_64'
42 else:
43 # just a guess
44 arch = platform.machine()
45 build_time_vars['LDSHARED'] += ' -undefined dynamic_lookup'
46 build_time_vars['CC'] += ' -arch %s' % (arch,)
47 if "CXX" in build_time_vars:
48 build_time_vars['CXX'] += ' -arch %s' % (arch,)
49
9797 def GetOverlappedResult(self, wait):
9898 transferred = _ffi.new('DWORD[1]', [0])
9999 res = _kernel32.GetOverlappedResult(self.handle, self.overlapped, transferred, wait != 0)
100 if not res:
101 res = GetLastError()
102 if res in (ERROR_SUCCESS, ERROR_MORE_DATA, ERROR_OPERATION_ABORTED):
100 if res:
101 err = ERROR_SUCCESS
102 else:
103 err = GetLastError()
104 if err in (ERROR_SUCCESS, ERROR_MORE_DATA, ERROR_OPERATION_ABORTED):
103105 self.completed = 1
104106 self.pending = 0
105107 elif res == ERROR_IO_INCOMPLETE:
132134 assert success == 0
133135 err = _kernel32.GetLastError()
134136 if err == ERROR_IO_PENDING:
135 overlapped[0].pending = 1
137 ov.pending = 1
136138 elif err == ERROR_PIPE_CONNECTED:
137139 _kernel32.SetEvent(ov.overlapped[0].hEvent)
138140 else:
22
33 from .api import FFI
44 from .error import CDefError, FFIError, VerificationError, VerificationMissing
5 from .error import PkgConfigError
56
6 __version__ = "1.11.5"
7 __version_info__ = (1, 11, 5)
7 __version__ = "1.12.0"
8 __version_info__ = (1, 12, 0)
89
910 # The verifier module file names are based on the CRC32 of a string that
1011 # contains the following version number. It may be older than __version__
4949 "import sys\n"
5050 "class FileLike:\n"
5151 " def write(self, x):\n"
52 " of.write(x)\n"
52 " try:\n"
53 " of.write(x)\n"
54 " except: pass\n"
5355 " self.buf += x\n"
5456 "fl = FileLike()\n"
5557 "fl.buf = ''\n"
77 the same works for the other two macros. Py_DEBUG implies them,
88 but not the other way around.
99
10 Issue #350 is still open: on Windows, the code here causes it to link
11 with PYTHON36.DLL (for example) instead of PYTHON3.DLL. A fix was
12 attempted in 164e526a5515 and 14ce6985e1c3, but reverted: virtualenv
13 does not make PYTHON3.DLL available, and so the "correctly" compiled
14 version would not run inside a virtualenv. We will re-apply the fix
15 after virtualenv has been fixed for some time. For explanation, see
16 issue #355. For a workaround if you want PYTHON3.DLL and don't worry
17 about virtualenv, see issue #350. See also 'py_limited_api' in
18 setuptools_ext.py.
10 The implementation is messy (issue #350): on Windows, with _MSC_VER,
11 we have to define Py_LIMITED_API even before including pyconfig.h.
12 In that case, we guess what pyconfig.h will do to the macros above,
13 and check our guess after the #include.
14
15 Note that on Windows, with CPython 3.x, you need virtualenv version
16 >= 16.0.0. Older versions don't copy PYTHON3.DLL. As a workaround
17 you can remove the definition of Py_LIMITED_API here.
18
19 See also 'py_limited_api' in cffi/setuptools_ext.py.
1920 */
2021 #if !defined(_CFFI_USE_EMBEDDING) && !defined(Py_LIMITED_API)
21 # include <pyconfig.h>
22 # if !defined(Py_DEBUG) && !defined(Py_TRACE_REFS) && !defined(Py_REF_DEBUG)
23 # define Py_LIMITED_API
22 # ifdef _MSC_VER
23 # if !defined(_DEBUG) && !defined(Py_DEBUG) && !defined(Py_TRACE_REFS) && !defined(Py_REF_DEBUG)
24 # define Py_LIMITED_API
25 # endif
26 # include <pyconfig.h>
27 /* sanity-check: Py_LIMITED_API will cause crashes if any of these
28 are also defined. Normally, the Python file PC/pyconfig.h does not
29 cause any of these to be defined, with the exception that _DEBUG
30 causes Py_DEBUG. Double-check that. */
31 # ifdef Py_LIMITED_API
32 # if defined(Py_DEBUG)
33 # error "pyconfig.h unexpectedly defines Py_DEBUG, but Py_LIMITED_API is set"
34 # endif
35 # if defined(Py_TRACE_REFS)
36 # error "pyconfig.h unexpectedly defines Py_TRACE_REFS, but Py_LIMITED_API is set"
37 # endif
38 # if defined(Py_REF_DEBUG)
39 # error "pyconfig.h unexpectedly defines Py_REF_DEBUG, but Py_LIMITED_API is set"
40 # endif
41 # endif
42 # else
43 # include <pyconfig.h>
44 # if !defined(Py_DEBUG) && !defined(Py_TRACE_REFS) && !defined(Py_REF_DEBUG)
45 # define Py_LIMITED_API
46 # endif
2447 # endif
2548 #endif
2649
220220
221221 if (f != NULL && f != Py_None) {
222222 PyFile_WriteString("\nFrom: " _CFFI_MODULE_NAME
223 "\ncompiled with cffi version: 1.11.5"
223 "\ncompiled with cffi version: 1.12.0"
224224 "\n_cffi_backend module: ", f);
225225 modules = PyImport_GetModuleDict();
226226 mod = PyDict_GetItemString(modules, "_cffi_backend");
1414 except NameError:
1515 # Python 3.x
1616 basestring = str
17
18 _unspecified = object()
1719
1820
1921
9597 self.CData, self.CType = backend._get_types()
9698 self.buffer = backend.buffer
9799
98 def cdef(self, csource, override=False, packed=False):
100 def cdef(self, csource, override=False, packed=False, pack=None):
99101 """Parse the given C source. This registers all declared functions,
100102 types, and global variables. The functions and global variables can
101103 then be accessed via either 'ffi.dlopen()' or 'ffi.verify()'.
102104 The types can be used in 'ffi.new()' and other functions.
103105 If 'packed' is specified as True, all structs declared inside this
104106 cdef are packed, i.e. laid out without any field alignment at all.
105 """
106 self._cdef(csource, override=override, packed=packed)
107
108 def embedding_api(self, csource, packed=False):
109 self._cdef(csource, packed=packed, dllexport=True)
107 Alternatively, 'pack' can be a small integer, and requests for
108 alignment greater than that are ignored (pack=1 is equivalent to
109 packed=True).
110 """
111 self._cdef(csource, override=override, packed=packed, pack=pack)
112
113 def embedding_api(self, csource, packed=False, pack=None):
114 self._cdef(csource, packed=packed, pack=pack, dllexport=True)
110115 if self._embedding is None:
111116 self._embedding = ''
112117
337342 # """
338343 # note that 'buffer' is a type, set on this instance by __init__
339344
340 def from_buffer(self, python_buffer):
341 """Return a <cdata 'char[]'> that points to the data of the
345 def from_buffer(self, cdecl, python_buffer=_unspecified,
346 require_writable=False):
347 """Return a cdata of the given type pointing to the data of the
342348 given Python object, which must support the buffer interface.
343349 Note that this is not meant to be used on the built-in types
344350 str or unicode (you can build 'char[]' arrays explicitly)
345351 but only on objects containing large quantities of raw data
346352 in some other format, like 'array.array' or numpy arrays.
347 """
348 return self._backend.from_buffer(self.BCharA, python_buffer)
353
354 The first argument is optional and default to 'char[]'.
355 """
356 if python_buffer is _unspecified:
357 cdecl, python_buffer = self.BCharA, cdecl
358 elif isinstance(cdecl, basestring):
359 cdecl = self._typeof(cdecl)
360 return self._backend.from_buffer(cdecl, python_buffer,
361 require_writable)
349362
350363 def memmove(self, dest, src, n):
351364 """ffi.memmove(dest, src, n) copies n bytes of memory from src to dest.
524537
525538 def from_handle(self, x):
526539 return self._backend.from_handle(x)
540
541 def release(self, x):
542 self._backend.release(x)
527543
528544 def set_unicode(self, enabled_flag):
529545 """Windows: if 'enabled_flag' is True, enable the UNICODE and
625641 "name to make a 'package.module' location")
626642 self._assigned_source = (str(module_name), source,
627643 source_extension, kwds)
644
645 def set_source_pkgconfig(self, module_name, pkgconfig_libs, source,
646 source_extension='.c', **kwds):
647 from . import pkgconfig
648 if not isinstance(pkgconfig_libs, list):
649 raise TypeError("the pkgconfig_libs argument must be a list "
650 "of package names")
651 kwds2 = pkgconfig.flags_from_pkgconfig(pkgconfig_libs)
652 pkgconfig.merge_flags(kwds, kwds2)
653 self.set_source(module_name, source, source_extension, **kwds)
628654
629655 def distutils_extension(self, tmpdir='build', verbose=True):
630656 from distutils.dir_util import mkpath
635635 if isinstance(init, bytes):
636636 init = [init[i:i+1] for i in range(len(init))]
637637 else:
638 if isinstance(init, CTypesGenericArray):
639 if (len(init) != len(blob) or
640 not isinstance(init, CTypesArray)):
641 raise TypeError("length/type mismatch: %s" % (init,))
638642 init = tuple(init)
639643 if len(init) > len(blob):
640644 raise IndexError("too many initializers")
729733 return self._new_struct_or_union('union', name, ctypes.Union)
730734
731735 def complete_struct_or_union(self, CTypesStructOrUnion, fields, tp,
732 totalsize=-1, totalalignment=-1, sflags=0):
736 totalsize=-1, totalalignment=-1, sflags=0,
737 pack=0):
733738 if totalsize >= 0 or totalalignment >= 0:
734739 raise NotImplementedError("the ctypes backend of CFFI does not support "
735740 "structures completed by verify(); please "
750755 bfield_types[fname] = Ellipsis
751756 if sflags & 8:
752757 struct_or_union._pack_ = 1
758 elif pack:
759 struct_or_union._pack_ = pack
753760 struct_or_union._fields_ = cfields
754761 CTypesStructOrUnion._bfield_types = bfield_types
755762 #
1414 lock = _thread.allocate_lock()
1515 except ImportError:
1616 lock = None
17
18 def _workaround_for_static_import_finders():
19 # Issue #392: packaging tools like cx_Freeze can not find these
20 # because pycparser uses exec dynamic import. This is an obscure
21 # workaround. This function is never called.
22 import pycparser.yacctab
23 import pycparser.lextab
1724
1825 CDEF_SOURCE_STRING = "<cdef source string>"
1926 _r_comment = re.compile(r"/\*.*?\*/|//([^\n\\]|\\.)*?$",
136143 parts.append(csource)
137144 return ''.join(parts)
138145
146 def _warn_for_string_literal(csource):
147 if '"' in csource:
148 import warnings
149 warnings.warn("String literal found in cdef() or type source. "
150 "String literals are ignored here, but you should "
151 "remove them anyway because some character sequences "
152 "confuse pre-parsing.")
153
139154 def _preprocess(csource):
140155 # Remove comments. NOTE: this only work because the cdef() section
141156 # should not contain any string literal!
162177 #
163178 # Replace `extern "Python"` with start/end markers
164179 csource = _preprocess_extern_python(csource)
180 #
181 # Now there should not be any string literal left; warn if we get one
182 _warn_for_string_literal(csource)
165183 #
166184 # Replace "[...]" with "[__dotdotdotarray__]"
167185 csource = _r_partial_array.sub('[__dotdotdotarray__]', csource)
305323 msg = 'parse error\n%s' % (msg,)
306324 raise CDefError(msg)
307325
308 def parse(self, csource, override=False, packed=False, dllexport=False):
326 def parse(self, csource, override=False, packed=False, pack=None,
327 dllexport=False):
328 if packed:
329 if packed != True:
330 raise ValueError("'packed' should be False or True; use "
331 "'pack' to give another value")
332 if pack:
333 raise ValueError("cannot give both 'pack' and 'packed'")
334 pack = 1
335 elif pack:
336 if pack & (pack - 1):
337 raise ValueError("'pack' must be a power of two, not %r" %
338 (pack,))
339 else:
340 pack = 0
309341 prev_options = self._options
310342 try:
311343 self._options = {'override': override,
312 'packed': packed,
344 'packed': pack,
313345 'dllexport': dllexport}
314346 self._internal_parse(csource)
315347 finally:
00
11 class FFIError(Exception):
2 pass
2 __module__ = 'cffi'
33
44 class CDefError(Exception):
5 __module__ = 'cffi'
56 def __str__(self):
67 try:
78 current_decl = self.args[1]
1516 class VerificationError(Exception):
1617 """ An error raised when verification fails
1718 """
19 __module__ = 'cffi'
1820
1921 class VerificationMissing(Exception):
2022 """ An error raised when incomplete structures are passed into
2123 cdef, but no verification has been done
2224 """
25 __module__ = 'cffi'
26
27 class PkgConfigError(Exception):
28 """ An error raised for missing modules in pkg-config
29 """
30 __module__ = 'cffi'
341341 fixedlayout = None
342342 completed = 0
343343 partial = False
344 packed = False
344 packed = 0
345345
346346 def __init__(self, name, fldnames, fldtypes, fldbitsize, fldquals=None):
347347 self.name = name
413413 fldtypes = [tp.get_cached_btype(ffi, finishlist)
414414 for tp in self.fldtypes]
415415 lst = list(zip(self.fldnames, fldtypes, self.fldbitsize))
416 sflags = 0
416 extra_flags = ()
417417 if self.packed:
418 sflags = 8 # SF_PACKED
418 if self.packed == 1:
419 extra_flags = (8,) # SF_PACKED
420 else:
421 extra_flags = (0, self.packed)
419422 ffi._backend.complete_struct_or_union(BType, lst, self,
420 -1, -1, sflags)
423 -1, -1, *extra_flags)
421424 #
422425 else:
423426 fldtypes = []
0 # pkg-config, https://www.freedesktop.org/wiki/Software/pkg-config/ integration for cffi
1 import sys, os, subprocess
2
3 from .error import PkgConfigError
4
5
6 def merge_flags(cfg1, cfg2):
7 """Merge values from cffi config flags cfg2 to cf1
8
9 Example:
10 merge_flags({"libraries": ["one"]}, {"libraries": ["two"]})
11 {"libraries": ["one", "two"]}
12 """
13 for key, value in cfg2.items():
14 if key not in cfg1:
15 cfg1[key] = value
16 else:
17 if not isinstance(cfg1[key], list):
18 raise TypeError("cfg1[%r] should be a list of strings" % (key,))
19 if not isinstance(value, list):
20 raise TypeError("cfg2[%r] should be a list of strings" % (key,))
21 cfg1[key].extend(value)
22 return cfg1
23
24
25 def call(libname, flag, encoding=sys.getfilesystemencoding()):
26 """Calls pkg-config and returns the output if found
27 """
28 a = ["pkg-config", "--print-errors"]
29 a.append(flag)
30 a.append(libname)
31 try:
32 pc = subprocess.Popen(a, stdout=subprocess.PIPE, stderr=subprocess.PIPE)
33 except EnvironmentError as e:
34 raise PkgConfigError("cannot run pkg-config: %s" % (str(e).strip(),))
35
36 bout, berr = pc.communicate()
37 if pc.returncode != 0:
38 try:
39 berr = berr.decode(encoding)
40 except Exception:
41 pass
42 raise PkgConfigError(berr.strip())
43
44 if sys.version_info >= (3,) and not isinstance(bout, str): # Python 3.x
45 try:
46 bout = bout.decode(encoding)
47 except UnicodeDecodeError:
48 raise PkgConfigError("pkg-config %s %s returned bytes that cannot "
49 "be decoded with encoding %r:\n%r" %
50 (flag, libname, encoding, bout))
51
52 if os.altsep != '\\' and '\\' in bout:
53 raise PkgConfigError("pkg-config %s %s returned an unsupported "
54 "backslash-escaped output:\n%r" %
55 (flag, libname, bout))
56 return bout
57
58
59 def flags_from_pkgconfig(libs):
60 r"""Return compiler line flags for FFI.set_source based on pkg-config output
61
62 Usage
63 ...
64 ffibuilder.set_source("_foo", pkgconfig = ["libfoo", "libbar >= 1.8.3"])
65
66 If pkg-config is installed on build machine, then arguments include_dirs,
67 library_dirs, libraries, define_macros, extra_compile_args and
68 extra_link_args are extended with an output of pkg-config for libfoo and
69 libbar.
70
71 Raises PkgConfigError in case the pkg-config call fails.
72 """
73
74 def get_include_dirs(string):
75 return [x[2:] for x in string.split() if x.startswith("-I")]
76
77 def get_library_dirs(string):
78 return [x[2:] for x in string.split() if x.startswith("-L")]
79
80 def get_libraries(string):
81 return [x[2:] for x in string.split() if x.startswith("-l")]
82
83 # convert -Dfoo=bar to list of tuples [("foo", "bar")] expected by distutils
84 def get_macros(string):
85 def _macro(x):
86 x = x[2:] # drop "-D"
87 if '=' in x:
88 return tuple(x.split("=", 1)) # "-Dfoo=bar" => ("foo", "bar")
89 else:
90 return (x, None) # "-Dfoo" => ("foo", None)
91 return [_macro(x) for x in string.split() if x.startswith("-D")]
92
93 def get_other_cflags(string):
94 return [x for x in string.split() if not x.startswith("-I") and
95 not x.startswith("-D")]
96
97 def get_other_libs(string):
98 return [x for x in string.split() if not x.startswith("-L") and
99 not x.startswith("-l")]
100
101 # return kwargs for given libname
102 def kwargs(libname):
103 fse = sys.getfilesystemencoding()
104 all_cflags = call(libname, "--cflags")
105 all_libs = call(libname, "--libs")
106 return {
107 "include_dirs": get_include_dirs(all_cflags),
108 "library_dirs": get_library_dirs(all_libs),
109 "libraries": get_libraries(all_libs),
110 "define_macros": get_macros(all_cflags),
111 "extra_compile_args": get_other_cflags(all_cflags),
112 "extra_link_args": get_other_libs(all_libs),
113 }
114
115 # merge all arguments together
116 ret = {}
117 for libname in libs:
118 lib_flags = kwargs(libname)
119 merge_flags(ret, lib_flags)
120 return ret
892892 else:
893893 flags.append("_CFFI_F_CHECK_FIELDS")
894894 if tp.packed:
895 if tp.packed > 1:
896 raise NotImplementedError(
897 "%r is declared with 'pack=%r'; only 0 or 1 are "
898 "supported in API mode (try to use \"...;\", which "
899 "does not require a 'pack' declaration)" %
900 (tp, tp.packed))
895901 flags.append("_CFFI_F_PACKED")
896902 else:
897903 flags.append("_CFFI_F_EXTERNAL")
15331539 else:
15341540 return None, updated
15351541
1536 def _verify(ffi, module_name, preamble, *args, **kwds):
1537 # FOR TESTS ONLY
1538 from testing.udir import udir
1539 import imp
1540 assert module_name not in sys.modules, "module name conflict: %r" % (
1541 module_name,)
1542 kwds.setdefault('tmpdir', str(udir))
1543 outputfilename = recompile(ffi, module_name, preamble, *args, **kwds)
1544 module = imp.load_dynamic(module_name, outputfilename)
1545 #
1546 # hack hack hack: copy all *bound methods* from module.ffi back to the
1547 # ffi instance. Then calls like ffi.new() will invoke module.ffi.new().
1548 for name in dir(module.ffi):
1549 if not name.startswith('_'):
1550 attr = getattr(module.ffi, name)
1551 if attr is not getattr(ffi, name, object()):
1552 setattr(ffi, name, attr)
1553 def typeof_disabled(*args, **kwds):
1554 raise NotImplementedError
1555 ffi._typeof = typeof_disabled
1556 for name in dir(ffi):
1557 if not name.startswith('_') and not hasattr(module.ffi, name):
1558 setattr(ffi, name, NotImplemented)
1559 return module.lib
8080 it doesn't so far, creating troubles. That's why we check
8181 for "not hasattr(sys, 'gettotalrefcount')" (the 2.7 compatible equivalent
8282 of 'd' not in sys.abiflags). (http://bugs.python.org/issue28401)
83
84 On Windows, it's better not to use py_limited_api until issue #355
85 can be resolved (by having virtualenv copy PYTHON3.DLL). See also
86 the start of _cffi_include.h.
8783 """
88 if ('py_limited_api' not in kwds and not hasattr(sys, 'gettotalrefcount')
89 and sys.platform != 'win32'):
84 if 'py_limited_api' not in kwds and not hasattr(sys, 'gettotalrefcount'):
9085 import setuptools
9186 try:
9287 setuptools_major_version = int(setuptools.__version__.partition('.')[0])
166161 module_path = module_name.split('.')
167162 module_path[-1] += '.py'
168163 generate_mod(os.path.join(self.build_lib, *module_path))
164 def get_source_files(self):
165 # This is called from 'setup.py sdist' only. Exclude
166 # the generate .py module in this case.
167 saved_py_modules = self.py_modules
168 try:
169 if saved_py_modules:
170 self.py_modules = [m for m in saved_py_modules
171 if m != module_name]
172 return base_class.get_source_files(self)
173 finally:
174 self.py_modules = saved_py_modules
169175 dist.cmdclass['build_py'] = build_py_make_mod
170176
171177 # distutils and setuptools have no notion I could find of a
175181 # the module. So we add it here, which gives a few apparently
176182 # harmless warnings about not finding the file outside the
177183 # build directory.
184 # Then we need to hack more in get_source_files(); see above.
178185 if dist.py_modules is None:
179186 dist.py_modules = []
180187 dist.py_modules.append(module_name)
00 Metadata-Version: 1.1
11 Name: cffi
2 Version: 1.11.5
2 Version: 1.12.0
33 Summary: Foreign Function Interface for Python calling C code.
44 Home-page: http://cffi.readthedocs.org
55 Author: Armin Rigo, Maciej Fijalkowski
44 import os
55 from _pwdgrp_cffi import ffi, lib
66 import _structseq
7 import _thread
8 _lock = _thread.allocate_lock()
79
810 try: from __pypy__ import builtinify
911 except ImportError: builtinify = lambda f: f
3234
3335 @builtinify
3436 def getgrgid(gid):
35 res = lib.getgrgid(gid)
36 if not res:
37 # XXX maybe check error eventually
38 raise KeyError(gid)
39 return _group_from_gstruct(res)
37 with _lock:
38 res = lib.getgrgid(gid)
39 if not res:
40 # XXX maybe check error eventually
41 raise KeyError(gid)
42 return _group_from_gstruct(res)
4043
4144 @builtinify
4245 def getgrnam(name):
4346 if not isinstance(name, str):
4447 raise TypeError("expected string")
45 res = lib.getgrnam(os.fsencode(name))
46 if not res:
47 raise KeyError("'getgrnam(): name not found: %s'" % name)
48 return _group_from_gstruct(res)
48 with _lock:
49 res = lib.getgrnam(os.fsencode(name))
50 if not res:
51 raise KeyError("getgrnam(): name not found: %s" % name)
52 return _group_from_gstruct(res)
4953
5054 @builtinify
5155 def getgrall():
52 lib.setgrent()
5356 lst = []
54 while 1:
55 p = lib.getgrent()
56 if not p:
57 break
58 lst.append(_group_from_gstruct(p))
59 lib.endgrent()
57 with _lock:
58 lib.setgrent()
59 while 1:
60 p = lib.getgrent()
61 if not p:
62 break
63 lst.append(_group_from_gstruct(p))
64 lib.endgrent()
6065 return lst
6166
6267 __all__ = ('struct_group', 'getgrgid', 'getgrnam', 'getgrall')
1111
1212 from _pwdgrp_cffi import ffi, lib
1313 import _structseq
14 import _thread
15 _lock = _thread.allocate_lock()
1416
1517 try: from __pypy__ import builtinify
1618 except ImportError: builtinify = lambda f: f
5355 Return the password database entry for the given numeric user ID.
5456 See pwd.__doc__ for more on password database entries.
5557 """
56 pw = lib.getpwuid(uid)
57 if not pw:
58 raise KeyError("getpwuid(): uid not found: %s" % uid)
59 return _mkpwent(pw)
58 with _lock:
59 pw = lib.getpwuid(uid)
60 if not pw:
61 raise KeyError("getpwuid(): uid not found: %s" % uid)
62 return _mkpwent(pw)
6063
6164 @builtinify
6265 def getpwnam(name):
6972 if not isinstance(name, basestring):
7073 raise TypeError("expected string")
7174 name = str(name)
72 pw = lib.getpwnam(name)
73 if not pw:
74 raise KeyError("getpwname(): name not found: %s" % name)
75 return _mkpwent(pw)
75 with _lock:
76 pw = lib.getpwnam(name)
77 if not pw:
78 raise KeyError("getpwname(): name not found: %s" % name)
79 return _mkpwent(pw)
7680
7781 @builtinify
7882 def getpwall():
8286 See pwd.__doc__ for more on password database entries.
8387 """
8488 users = []
85 lib.setpwent()
86 while True:
87 pw = lib.getpwent()
88 if not pw:
89 break
90 users.append(_mkpwent(pw))
91 lib.endpwent()
89 with _lock:
90 lib.setpwent()
91 while True:
92 pw = lib.getpwent()
93 if not pw:
94 break
95 users.append(_mkpwent(pw))
96 lib.endpwent()
9297 return users
9398
9499 __all__ = ('struct_passwd', 'getpwuid', 'getpwnam', 'getpwall')
6565
6666 while 1:
6767 try:
68 try:
69 sys.stdout.flush()
70 except:
71 pass
6872 ps1 = getattr(sys, 'ps1', '>>> ')
6973 ps2 = getattr(sys, 'ps2', '... ')
7074 try:
2626 from .console import Console, Event
2727 from .unix_eventqueue import EventQueue
2828 from .trace import trace
29 try:
30 from __pypy__ import pyos_inputhook
31 except ImportError:
32 def pyos_inputhook():
33 pass
34
2935
3036 class InvalidTerminal(RuntimeError):
3137 pass
7581 pass
7682 def register(self, fd, flag):
7783 self.fd = fd
78 def poll(self, timeout=None):
79 r,w,e = select.select([self.fd],[],[],timeout)
84 def poll(self): # note: a 'timeout' argument would be *milliseconds*
85 r,w,e = select.select([self.fd],[],[])
8086 return r
8187
8288 POLLIN = getattr(select, "POLLIN", None)
406412 def get_event(self, block=1):
407413 while self.event_queue.empty():
408414 while 1: # All hail Unix!
415 pyos_inputhook()
409416 try:
410417 self.push_char(os.read(self.input_fd, 1))
411418 except (IOError, OSError) as err:
33 from errno import EINVAL, EPERM
44 import _structseq, os
55
6 try: from __pypy__ import builtinify
7 except ImportError: builtinify = lambda f: f
6 try:
7 from __pypy__ import builtinify
8 except ImportError:
9 builtinify = lambda f: f
810
911
1012 class error(Exception):
3436 ru_oublock = _structseq.structseqfield(10, "block output operations")
3537 ru_msgsnd = _structseq.structseqfield(11, "IPC messages sent")
3638 ru_msgrcv = _structseq.structseqfield(12, "IPC messages received")
37 ru_nsignals = _structseq.structseqfield(13,"signals received")
39 ru_nsignals = _structseq.structseqfield(13, "signals received")
3840 ru_nvcsw = _structseq.structseqfield(14, "voluntary context switches")
3941 ru_nivcsw = _structseq.structseqfield(15, "involuntary context switches")
4042
5658 ru.ru_nsignals,
5759 ru.ru_nvcsw,
5860 ru.ru_nivcsw,
59 ))
61 ))
6062
6163 @builtinify
6264 def getrusage(who):
3838 "thread", "itertools", "pyexpat", "cpyext", "array",
3939 "binascii", "_multiprocessing", '_warnings', "_collections",
4040 "_multibytecodec", "_continuation", "_cffi_backend",
41 "_csv", "_pypyjson", "_posixsubprocess", # "_cppyy", "micronumpy"
41 "_csv", "_pypyjson", "_posixsubprocess", "_cppyy", # "micronumpy",
4242 "_jitlog",
4343 ])
4444
45 from rpython.jit.backend import detect_cpu
46 try:
47 if detect_cpu.autodetect().startswith('x86'):
48 if not sys.platform.startswith('openbsd'):
49 working_modules.add('_vmprof')
50 working_modules.add('faulthandler')
51 except detect_cpu.ProcessorAutodetectError:
52 pass
45 import rpython.rlib.rvmprof.cintf
46 if rpython.rlib.rvmprof.cintf.IS_SUPPORTED:
47 working_modules.add('_vmprof')
48 working_modules.add('faulthandler')
5349
5450 translation_modules = default_modules.copy()
5551 translation_modules.update([
5955 # interactive prompt/pdb)
6056 "termios", "_minimal_curses",
6157 ])
58
59 reverse_debugger_disable_modules = set([
60 "_continuation", "_vmprof", "_multiprocessing",
61 "micronumpy",
62 ])
6263
6364 # XXX this should move somewhere else, maybe to platform ("is this posixish"
6465 # check or something)
198199 default=False,
199200 requires=[("objspace.usemodules.cpyext", False)]),
200201
202 BoolOption("disable_entrypoints_in_cffi",
203 "Disable only cffi's embedding mode.",
204 default=False),
205
201206 BoolOption("fstrings",
202207 "if you are really convinced that f-strings are a security "
203208 "issue, you can disable them here",
296301 modules = working_modules.copy()
297302 if config.translation.sandbox:
298303 modules = default_modules
304 if config.translation.reverse_debugger:
305 for mod in reverse_debugger_disable_modules:
306 setattr(config.objspace.usemodules, mod, False)
299307 # ignore names from 'essential_modules', notably 'exceptions', which
300308 # may not be present in config.objspace.usemodules at all
301309 modules = [name for name in modules if name not in essential_modules]
314322 parser = to_optparse(config) #, useoptions=["translation.*"])
315323 option, args = parser.parse_args()
316324 print config
325 print working_modules
1212 # pytest settings
1313 rsyncdirs = ['.', '../lib-python', '../lib_pypy', '../demo']
1414 rsyncignore = ['_cache']
15
16 try:
17 from hypothesis import settings, __version__
18 except ImportError:
19 pass
20 else:
21 if __version__[:2] < '3.6':
22 s = settings(deadline=None)
23 settings.register_profile('default', s)
24 else:
25 settings.register_profile('default', deadline=None)
26 settings.load_profile('default')
1527
1628 # PyPy's command line extra options (these are added
1729 # to py.test's standard options)
33 .. contents::
44
55 This document gives an overview of the goals and architecture of PyPy. If you're
6 interested in :ref:`using PyPy <using-pypy>` or :ref:`hacking on it <developing-pypy>`,
6 interested in :ref:`using PyPy <using-pypy>` or hacking on it,
77 have a look at our :ref:`getting started <getting-started-index>` section.
88
99
7272 This division between bytecode evaluator and object space gives a lot of
7373 flexibility. One can plug in different :doc:`object spaces <objspace>` to get
7474 different or enriched behaviours of the Python objects.
75
76 Layers
77 ------
78
79 RPython
80 ~~~~~~~
81 :ref:`RPython <rpython:language>` is the language in which we write interpreters.
82 Not the entire PyPy project is written in RPython, only the parts that are
83 compiled in the translation process. The interesting point is that RPython
84 has no parser, it's compiled from the live python objects, which makes it
85 possible to do all kinds of metaprogramming during import time. In short,
86 Python is a meta programming language for RPython.
87
88 The RPython standard library is to be found in the ``rlib`` subdirectory.
89
90 Consult `Getting Started with RPython`_ for further reading
91
92 Translation
93 ~~~~~~~~~~~
94 The translation toolchain - this is the part that takes care of translating
95 RPython to flow graphs and then to C. There is more in the
96 :doc:`architecture <architecture>` document written about it.
97
98 It lives in the ``rpython`` directory: ``flowspace``, ``annotator``
99 and ``rtyper``.
100
101 PyPy Interpreter
102 ~~~~~~~~~~~~~~~~
103 This is in the ``pypy`` directory. ``pypy/interpreter`` is a standard
104 interpreter for Python written in RPython. The fact that it is
105 RPython is not apparent at first. Built-in modules are written in
106 ``pypy/module/*``. Some modules that CPython implements in C are
107 simply written in pure Python; they are in the top-level ``lib_pypy``
108 directory. The standard library of Python (with a few changes to
109 accomodate PyPy) is in ``lib-python``.
110
111 JIT Compiler
112 ~~~~~~~~~~~~
113 :ref:`Just-in-Time Compiler (JIT) <rpython:jit>`: we have a tracing JIT that traces the
114 interpreter written in RPython, rather than the user program that it
115 interprets. As a result it applies to any interpreter, i.e. any
116 language. But getting it to work correctly is not trivial: it
117 requires a small number of precise "hints" and possibly some small
118 refactorings of the interpreter. The JIT itself also has several
119 almost-independent parts: the tracer itself in ``rpython/jit/metainterp``, the
120 optimizer in ``rpython/jit/metainterp/optimizer`` that optimizes a list of
121 residual operations, and the backend in ``rpython/jit/backend/<machine-name>``
122 that turns it into machine code. Writing a new backend is a
123 traditional way to get into the project.
124
125 Garbage Collectors
126 ~~~~~~~~~~~~~~~~~~
127 Garbage Collectors (GC): as you may notice if you are used to CPython's
128 C code, there are no ``Py_INCREF/Py_DECREF`` equivalents in RPython code.
129 :ref:`rpython:garbage-collection` is inserted
130 during translation. Moreover, this is not reference counting; it is a real
131 GC written as more RPython code. The best one we have so far is in
132 ``rpython/memory/gc/incminimark.py``.
133
134 .. _`Getting started with RPython`: http://rpython.readthedocs.org/en/latest/getting-started.html
219219 Making a debug build of PyPy
220220 ----------------------------
221221
222 If the Makefile is rerun with the lldebug or lldebug0 target, appropriate
223 compilation flags are added to add debug info and reduce compiler optimizations
224 to ``-O0`` respectively. If you stop in a debugger, you will see the
225 very wordy machine-generated C code from the rpython translation step, which
226 takes a little bit of reading to relate back to the rpython code.
222 Rerun the ``Makefile`` with the ``make lldebug`` or ``make lldebug0`` target,
223 which will build in a way that running under a debugger makes sense.
224 Appropriate compilation flags are added to add debug info, and for ``lldebug0``
225 compiler optimizations are fully disabled. If you stop in a debugger, you will
226 see the very wordy machine-generated C code from the rpython translation step,
227 which takes a little bit of reading to relate back to the rpython code.
227228
228229 Build cffi import libraries for the stdlib
229230 ------------------------------------------
266267 * PyPy 2.5.1 or earlier: normal users would see permission errors.
267268 Installers need to run ``pypy -c "import gdbm"`` and other similar
268269 commands at install time; the exact list is in
269 :source:`pypy/tool/release/package.py <package.py>`. Users
270 :source:`pypy/tool/release/package.py`. Users
270271 seeing a broken installation of PyPy can fix it after-the-fact if they
271272 have sudo rights, by running once e.g. ``sudo pypy -c "import gdbm``.
272273
273274 * PyPy 2.6 and later: anyone would get ``ImportError: no module named
274275 _gdbm_cffi``. Installers need to run ``pypy _gdbm_build.py`` in the
275276 ``lib_pypy`` directory during the installation process (plus others;
276 see the exact list in :source:`pypy/tool/release/package.py <package.py>`).
277 see the exact list in :source:`pypy/tool/release/package.py`).
277278 Users seeing a broken
278279 installation of PyPy can fix it after-the-fact, by running ``pypy
279280 /path/to/lib_pypy/_gdbm_build.py``. This command produces a file
538538
539539 hg help branch
540540
541 .. _official wiki: http://mercurial.selenic.com/wiki/Branch
541 .. _official wiki: https://www.mercurial-scm.org/wiki/
542542
543543
544544 .. _using-development-tracker:
546546 Using the development bug/feature tracker
547547 -----------------------------------------
548548
549 We have a `development tracker`_, based on Richard Jones'
550 `roundup`_ application. You can file bugs,
551 feature requests or see what's going on
552 for the next milestone, both from an E-Mail and from a
553 web interface.
554
555 .. _development tracker: https://bugs.pypy.org/
556 .. _roundup: http://roundup.sourceforge.net/
557
549 We use bitbucket for :source:`issues` tracking and :source:`pull-requests`.
558550
559551 .. _testing:
560552
77 :maxdepth: 1
88
99 man/pypy.1.rst
10 man/pypy3.1.rst
5858
5959 # General information about the project.
6060 project = u'PyPy'
61 copyright = u'2018, The PyPy Project'
61 copyright = u'2019, The PyPy Project'
6262
6363 # The version info for the project you're documenting, acts as replacement for
6464 # |version| and |release|, also used in various other places throughout the
6565 # built documents.
6666 #
67
68 # Make sure to keep this in sync with:
69 # module/sys/version.py
70 # module/cpyext/include/patchlevel.h
71 #
6772 # The short X.Y version.
68 version = '5.8'
73 version = '7.1'
6974 # The full version, including alpha/beta/rc tags.
70 release = '5.8.0'
75 release = '7.1.0'
7176
7277 # The language for content autogenerated by Sphinx. Refer to documentation
7378 # for a list of supported languages.
191196
192197 # Grouping the document tree into LaTeX files. List of tuples
193198 # (source start file, target name, title, author, documentclass [howto/manual]).
194 latex_documents = [
195 ('temp_index', 'PyPy.tex', u'PyPy Documentation',
196 u'The PyPy Project', 'manual'),
197 ]
199 #latex_documents = [
200 # ('temp_index', 'PyPy.tex', u'PyPy Documentation',
201 # u'The PyPy Project', 'manual'),
202 #]
198203
199204 # The name of an image file (relative to this directory) to place at the top of
200205 # the title page.
211216 #latex_appendices = []
212217
213218 # If false, no module index is generated.
214 latex_use_modindex = False
219 #latex_use_modindex = False
215220
216221
217222 # Example configuration for intersphinx: refer to the Python standard library.
0 The internal backend for cppyy
0 An experimental module providing very low-level interface to
0 A module providing very low-level interface to
11 C-level libraries, for use when implementing ctypes, not
2 intended for a direct use at all.
2 intended for a direct use at all.
0 Use (experimental) cpyext module, that tries to load and run CPython extension modules
0 Use cpyext module to load and run CPython extension modules
0 Contributing Guidelines
1 ===========================
2
3 .. contents::
4
5 PyPy is a very large project that has a reputation of being hard to dive into.
6 Some of this fame is warranted, some of it is purely accidental. There are three
7 important lessons that everyone willing to contribute should learn:
8
9 * PyPy has layers. There are many pieces of architecture that are very well
10 separated from each other. More about this below, but often the manifestation
11 of this is that things are at a different layer than you would expect them
12 to be. For example if you are looking for the JIT implementation, you will
13 not find it in the implementation of the Python programming language.
14
15 * Because of the above, we are very serious about Test Driven Development.
16 It's not only what we believe in, but also that PyPy's architecture is
17 working very well with TDD in mind and not so well without it. Often
18 development means progressing in an unrelated corner, one unittest
19 at a time; and then flipping a giant switch, bringing it all together.
20 (It generally works out of the box. If it doesn't, then we didn't
21 write enough unit tests.) It's worth repeating - PyPy's
22 approach is great if you do TDD, and not so great otherwise.
23
24 * PyPy uses an entirely different set of tools - most of them included
25 in the PyPy repository. There is no Makefile, nor autoconf. More below.
26
27 The first thing to remember is that PyPy project is very different than most
28 projects out there. It's also different from a classic compiler project,
29 so academic courses about compilers often don't apply or lead in the wrong
30 direction. However, if you want to understand how designing & building a runtime
31 works in the real world then this is a great project!
32
33 Getting involved
34 ^^^^^^^^^^^^^^^^
35
36 PyPy employs a relatively standard open-source development process. You are
37 encouraged as a first step to join our `pypy-dev mailing list`_ and IRC channel,
38 details of which can be found in our :ref:`contact <contact>` section. The folks
39 there are very friendly, and can point you in the right direction.
40
41 We give out commit rights usually fairly liberally, so if you want to do something
42 with PyPy, you can become a committer. We also run frequent coding sprints which
43 are separately announced and often happen around Python conferences such as
44 EuroPython or PyCon. Upcoming events are usually announced on `the blog`_.
45
46 Further Reading: :ref:`Contact <contact>`
47
48 .. _the blog: http://morepypy.blogspot.com
49 .. _pypy-dev mailing list: http://mail.python.org/mailman/listinfo/pypy-dev
50
51
52 Your first contribution
53 ^^^^^^^^^^^^^^^^^^^^^^^
54
55 The first and most important rule how **not** to contribute to PyPy is
56 "just hacking a feature". This won't work, and you'll find your PR will typically
57 require a lot of re-work. There are a few reasons why not:
58
59 * build times are large
60 * PyPy has very thick layer separation
61 * context of the cPython runtime is often required
62
63 Instead, reach out on the dev mailing list or the IRC channel, and we're more
64 than happy to help! :)
65
66 Some ideas for first contributions are:
67
68 * Documentation - this will give you an understanding of the pypy architecture
69 * Test failures - find a failing test in the `nightly builds`_, and fix it
70 * Missing language features - these are listed in our `issue tracker`_
71
72 .. _nightly builds: http://buildbot.pypy.org/nightly/
73 .. _issue tracker: https://bitbucket.org/pypy/pypy/issues
74
75 Source Control
76 --------------
77
78 PyPy development is based a typical fork/pull request based workflow, centered
79 around Mercurial (hg), hosted on Bitbucket. If you have not used this workflow
80 before, a good introduction can be found here:
81
82 https://www.atlassian.com/git/tutorials/comparing-workflows/forking-workflow
83
84 The cycle for a new PyPy contributor goes typically like this:
85
86 Fork & Clone
87 ------------
88
89 * Make an account on bitbucket_.
90
91 * Go to https://bitbucket.org/pypy/pypy/ and click "fork" (left
92 icons). You get a fork of the repository, e.g. in
93 `https://bitbucket.org/yourname/pypy/`.
94
95 * Clone your new repo (i.e. the fork) to your local machine with the command
96 ``hg clone ssh://hg@bitbucket.org/yourname/pypy``. It is a very slow
97 operation but only ever needs to be done once. See also
98 http://pypy.org/download.html#building-from-source .
99 If you already cloned
100 ``https://bitbucket.org/pypy/pypy`` before, even if some time ago,
101 then you can reuse the same clone by editing the file ``.hg/hgrc`` in
102 your clone to contain the line ``default =
103 ssh://hg@bitbucket.org/yourname/pypy``, and then do ``hg pull && hg
104 up``. If you already have such a clone but don't want to change it,
105 you can clone that copy with ``hg clone /path/to/other/copy``, and
106 then edit ``.hg/hgrc`` as above and do ``hg pull && hg up``.
107
108 * Now you have a complete copy of the PyPy repo. Make a branch
109 with a command like ``hg branch name_of_your_branch``.
110
111 Edit
112 ----
113
114 * Edit things. Use ``hg diff`` to see what you changed. Use ``hg add``
115 to make Mercurial aware of new files you added, e.g. new test files.
116 Use ``hg status`` to see if there are such files. Write and run tests!
117 (See the rest of this page.)
118
119 * Commit regularly with ``hg commit``. A one-line commit message is
120 fine. We love to have tons of commits; make one as soon as you have
121 some progress, even if it is only some new test that doesn't pass yet,
122 or fixing things even if not all tests pass. Step by step, you are
123 building the history of your changes, which is the point of a version
124 control system. (There are commands like ``hg log`` and ``hg up``
125 that you should read about later, to learn how to navigate this
126 history.)
127
128 * The commits stay on your machine until you do ``hg push`` to "push"
129 them back to the repo named in the file ``.hg/hgrc``. Repos are
130 basically just collections of commits (a commit is also called a
131 changeset): there is one repo per url, plus one for each local copy on
132 each local machine. The commands ``hg push`` and ``hg pull`` copy
133 commits around, with the goal that all repos in question end up with
134 the exact same set of commits. By opposition, ``hg up`` only updates
135 the "working copy" by reading the local repository, i.e. it makes the
136 files that you see correspond to the latest (or any other) commit
137 locally present.
138
139 * You should push often; there is no real reason not to. Remember that
140 even if they are pushed, with the setup above, the commits are (1)
141 only in ``bitbucket.org/yourname/pypy``, and (2) in the branch you
142 named. Yes, they are publicly visible, but don't worry about someone
143 walking around the thousands of repos on bitbucket saying "hah, look
144 at the bad coding style of that guy". Try to get into the mindset
145 that your work is not secret and it's fine that way. We might not
146 accept it as is for PyPy, asking you instead to improve some things,
147 but we are not going to judge you.
148
149 Pull Request
150 ------------
151
152 * The final step is to open a pull request, so that we know that you'd
153 like to merge that branch back to the original ``pypy/pypy`` repo.
154 This can also be done several times if you have interesting
155 intermediate states, but if you get there, then we're likely to
156 proceed to the next stage, which is...
157
158 * Get a regular account for pushing directly to
159 ``bitbucket.org/pypy/pypy`` (just ask and you'll get it, basically).
160 Once you have it you can rewrite your file ``.hg/hgrc`` to contain
161 ``default = ssh://hg@bitbucket.org/pypy/pypy``. Your changes will
162 then be pushed directly to the official repo, but (if you follow these
163 rules) they are still on a branch, and we can still review the
164 branches you want to merge.
165
166 * If you get closer to the regular day-to-day development, you'll notice
167 that we generally push small changes as one or a few commits directly
168 to the branch ``default``. Also, we often collaborate even if we are
169 on other branches, which do not really "belong" to anyone. At this
170 point you'll need ``hg merge`` and learn how to resolve conflicts that
171 sometimes occur when two people try to push different commits in
172 parallel on the same branch. But it is likely an issue for later ``:-)``
173
174 .. _bitbucket: https://bitbucket.org/
175
176
177 Architecture
178 ^^^^^^^^^^^^
179
180 PyPy has layers. Just like ogres or onions. Those layers help us keep the
181 respective parts separated enough to be worked on independently and make the
182 complexity manageable. This is, again, just a sanity requirement for such
183 a complex project. For example writing a new optimization for the JIT usually
184 does **not** involve touching a Python interpreter at all or the JIT assembler
185 backend or the garbage collector. Instead it requires writing small tests in
186 ``rpython/jit/metainterp/optimizeopt/test/test_*`` and fixing files there.
187 After that, you can just compile PyPy and things should just work.
188
189 Further Reading: :doc:`architecture <architecture>`
190
191 Where to start?
192 ---------------
193
194 PyPy is made from parts that are relatively independent of each other.
195 You should start looking at the part that attracts you most (all paths are
196 relative to the PyPy top level directory). You may look at our
197 :doc:`directory reference <dir-reference>` or start off at one of the following
198 points:
199
200 * :source:`pypy/interpreter` contains the bytecode interpreter: bytecode dispatcher
201 in :source:`pypy/interpreter/pyopcode.py`, frame and code objects in
202 :source:`pypy/interpreter/eval.py` and :source:`pypy/interpreter/pyframe.py`,
203 function objects and argument passing in :source:`pypy/interpreter/function.py`
204 and :source:`pypy/interpreter/argument.py`, the object space interface
205 definition in :source:`pypy/interpreter/baseobjspace.py`, modules in
206 :source:`pypy/interpreter/module.py` and :source:`pypy/interpreter/mixedmodule.py`.
207 Core types supporting the bytecode interpreter are defined in
208 :source:`pypy/interpreter/typedef.py`.
209
210 * :source:`pypy/interpreter/pyparser` contains a recursive descent parser,
211 and grammar files that allow it to parse the syntax of various Python
212 versions. Once the grammar has been processed, the parser can be
213 translated by the above machinery into efficient code.
214
215 * :source:`pypy/interpreter/astcompiler` contains the compiler. This
216 contains a modified version of the compiler package from CPython
217 that fixes some bugs and is translatable.
218
219 * :source:`pypy/objspace/std` contains the
220 :ref:`Standard object space <standard-object-space>`. The main file
221 is :source:`pypy/objspace/std/objspace.py`. For each type, the file
222 ``xxxobject.py`` contains the implementation for objects of type ``xxx``,
223 as a first approximation. (Some types have multiple implementations.)
224
225 Building
226 ^^^^^^^^
227
228 For building PyPy, we recommend installing a pre-built PyPy first (see
229 :doc:`install`). It is possible to build PyPy with CPython, but it will take a
230 lot longer to run -- depending on your architecture, between two and three
231 times as long.
232
233 Further Reading: :doc:`Build <build>`
234
235 Coding Guide
236 ------------
237
238 As well as the usual pep8 and formatting standards, there are a number of
239 naming conventions and coding styles that are important to understand before
240 browsing the source.
241
242 Further Reading: :doc:`Coding Guide <coding-guide>`
243
244 Testing
245 ^^^^^^^
246
247 Test driven development
248 -----------------------
249
250 Instead, we practice a lot of test driven development. This is partly because
251 of very high quality requirements for compilers and partly because there is
252 simply no other way to get around such complex project, that will keep you sane.
253 There are probably people out there who are smart enough not to need it, we're
254 not one of those. You may consider familiarizing yourself with `pytest`_,
255 since this is a tool we use for tests.
256 This leads to the next issue:
257
258 .. _pytest: http://pytest.org/
259
260 py.test and the py lib
261 ----------------------
262
263 The `py.test testing tool`_ drives all our testing needs.
264
265 We use the `py library`_ for filesystem path manipulations, terminal
266 writing, logging and some other support functionality.
267
268 You don't necessarily need to install these two libraries because
269 we also ship them inlined in the PyPy source tree.
270
271 .. _py library: http://pylib.readthedocs.org/
272
273 Running PyPy's unit tests
274 -------------------------
275
276 PyPy development always was and is still thoroughly test-driven.
277 We use the flexible `py.test testing tool`_ which you can `install independently
278 <http://pytest.org/latest/getting-started.html#getstarted>`_ and use for other projects.
279
280 The PyPy source tree comes with an inlined version of ``py.test``
281 which you can invoke by typing::
282
283 python pytest.py -h
284
285 This is usually equivalent to using an installed version::
286
287 py.test -h
288
289 If you encounter problems with the installed version
290 make sure you have the correct version installed which
291 you can find out with the ``--version`` switch.
292
293 You will need the `build requirements`_ to run tests successfully, since many of
294 them compile little pieces of PyPy and then run the tests inside that minimal
295 interpreter. The `cpyext` tests also require `pycparser`, and many tests build
296 cases with `hypothesis`.
297
298 Now on to running some tests. PyPy has many different test directories
299 and you can use shell completion to point at directories or files::
300
301 py.test pypy/interpreter/test/test_pyframe.py
302
303 # or for running tests of a whole subdirectory
304 py.test pypy/interpreter/
305
306 See `py.test usage and invocations`_ for some more generic info
307 on how you can run tests.
308
309 Beware trying to run "all" pypy tests by pointing to the root
310 directory or even the top level subdirectory ``pypy``. It takes
311 hours and uses huge amounts of RAM and is not recommended.
312
313 To run CPython regression tests you can point to the ``lib-python``
314 directory::
315
316 py.test lib-python/2.7/test/test_datetime.py
317
318 This will usually take a long time because this will run
319 the PyPy Python interpreter on top of CPython. On the plus
320 side, it's usually still faster than doing a full translation
321 and running the regression test with the translated PyPy Python
322 interpreter.
323
324 .. _py.test testing tool: http://pytest.org
325 .. _py.test usage and invocations: http://pytest.org/latest/usage.html#usage
326 .. _`build requirements`: build.html#install-build-time-dependencies
327
328 Testing After Translation
329 ^^^^^^^^^^^^^^^^^^^^^^^^^
330
331 While the usual invocation of `pytest` translates a piece of RPython code and
332 runs it, we have a test extension to run tests without translation, directly
333 on the host python. This is very convenient for modules such as `cpyext`, to
334 compare and contrast test results between CPython and PyPy. Untranslated tests
335 are invoked by using the `-A` or `--runappdirect` option to `pytest`::
336
337 python2 pytest.py -A pypy/module/cpyext/test
338
339 where `python2` can be either `python2` or `pypy2`. On the `py3` branch, the
340 collection phase must be run with `python2` so untranslated tests are run
341 with::
342
343 cpython2 pytest.py -A pypy/module/cpyext/test --python=path/to/pypy3
344
345
346 Tooling & Utilities
347 ^^^^^^^^^^^^^^^^^^^
348
349 If you are interested in the inner workings of the PyPy Python interpreter,
350 there are some features of the untranslated Python interpreter that allow you
351 to introspect its internals.
352
353
354 Interpreter-level console
355 -------------------------
356
357 To start interpreting Python with PyPy, install a C compiler that is
358 supported by distutils and use Python 2.7 or greater to run PyPy::
359
360 cd pypy
361 python bin/pyinteractive.py
362
363 After a few seconds (remember: this is running on top of CPython), you should
364 be at the PyPy prompt, which is the same as the Python prompt, but with an
365 extra ">".
366
367 If you press
368 <Ctrl-C> on the console you enter the interpreter-level console, a
369 usual CPython console. You can then access internal objects of PyPy
370 (e.g. the :ref:`object space <objspace>`) and any variables you have created on the PyPy
371 prompt with the prefix ``w_``::
372
373 >>>> a = 123
374 >>>> <Ctrl-C>
375 *** Entering interpreter-level console ***
376 >>> w_a
377 W_IntObject(123)
378
379 The mechanism works in both directions. If you define a variable with the ``w_`` prefix on the interpreter-level, you will see it on the app-level::
380
381 >>> w_l = space.newlist([space.wrap(1), space.wrap("abc")])
382 >>> <Ctrl-D>
383 *** Leaving interpreter-level console ***
384
385 KeyboardInterrupt
386 >>>> l
387 [1, 'abc']
388
389 Note that the prompt of the interpreter-level console is only '>>>' since
390 it runs on CPython level. If you want to return to PyPy, press <Ctrl-D> (under
391 Linux) or <Ctrl-Z>, <Enter> (under Windows).
392
393 Also note that not all modules are available by default in this mode (for
394 example: ``_continuation`` needed by ``greenlet``) , you may need to use one of
395 ``--withmod-...`` command line options.
396
397 You may be interested in reading more about the distinction between
398 :ref:`interpreter-level and app-level <interpreter-level>`.
399
400 pyinteractive.py options
401 ------------------------
402
403 To list the PyPy interpreter command line options, type::
404
405 cd pypy
406 python bin/pyinteractive.py --help
407
408 pyinteractive.py supports most of the options that CPython supports too (in addition to a
409 large amount of options that can be used to customize pyinteractive.py).
410 As an example of using PyPy from the command line, you could type::
411
412 python pyinteractive.py --withmod-time -c "from test import pystone; pystone.main(10)"
413
414 Alternatively, as with regular Python, you can simply give a
415 script name on the command line::
416
417 python pyinteractive.py --withmod-time ../../lib-python/2.7/test/pystone.py 10
418
419 The ``--withmod-xxx`` option enables the built-in module ``xxx``. By
420 default almost none of them are, because initializing them takes time.
421 If you want anyway to enable all built-in modules, you can use
422 ``--allworkingmodules``.
423
424 See our :doc:`configuration sections <config/index>` for details about what all the commandline
425 options do.
426
427
428 .. _trace example:
429
430 Tracing bytecode and operations on objects
431 ------------------------------------------
432
433 You can use a simple tracing mode to monitor the interpretation of
434 bytecodes. To enable it, set ``__pytrace__ = 1`` on the interactive
435 PyPy console::
436
437 >>>> __pytrace__ = 1
438 Tracing enabled
439 >>>> x = 5
440 <module>: LOAD_CONST 0 (5)
441 <module>: STORE_NAME 0 (x)
442 <module>: LOAD_CONST 1 (None)
443 <module>: RETURN_VALUE 0
444 >>>> x
445 <module>: LOAD_NAME 0 (x)
446 <module>: PRINT_EXPR 0
447 5
448 <module>: LOAD_CONST 0 (None)
449 <module>: RETURN_VALUE 0
450 >>>>
451
452
453 Demos
454 ^^^^^
455
456 The `example-interpreter`_ repository contains an example interpreter
457 written using the RPython translation toolchain.
458
459 .. _example-interpreter: https://bitbucket.org/pypy/example-interpreter
460
461
462 graphviz & pygame for flow graph viewing (highly recommended)
463 ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
464
465 graphviz and pygame are both necessary if you want to look at generated flow
466 graphs:
467
468 graphviz: http://www.graphviz.org/Download.php
469
470 pygame: http://www.pygame.org/download.shtml
471
66 Armin Rigo
77 Maciej Fijalkowski
88 Carl Friedrich Bolz-Tereick
9 Antonio Cuni
910 Amaury Forgeot d'Arc
10 Antonio Cuni
1111 Matti Picus
1212 Samuele Pedroni
1313 Ronan Lamy
1414 Alex Gaynor
1515 Philip Jenvey
16 Richard Plangger
1617 Brian Kearns
17 Richard Plangger
18 Michael Hudson
18 Michael Hudson-Doyle
1919 Manuel Jacob
2020 David Schneider
2121 Holger Krekel
2525 Anders Chrigstrom
2626 Wim Lavrijsen
2727 Eric van Riet Paap
28 Remi Meier
2829 Richard Emslie
29 Remi Meier
3030 Alexander Schremmer
3131 Dan Villiom Podlaski Christiansen
3232 Lukas Diekmann
3636 Niklaus Haldimann
3737 Camillo Bruni
3838 Laura Creighton
39 Romain Guillebert
4039 Toon Verwaest
4140 Leonardo Santagada
4241 Seo Sanghyeon
42 Romain Guillebert
4343 Ronny Pfannschmidt
4444 Justin Peel
4545 Raffael Tfirst
8080 Squeaky
8181 Edd Barrett
8282 Timo Paulssen
83 Laurence Tratt
8384 Marius Gedminas
8485 Nicolas Truessel
8586 Alexandre Fayolle
8687 Simon Burton
8788 Martin Matusiak
88 Laurence Tratt
8989 Wenzhu Man
9090 Konstantin Lopuhin
9191 John Witulski
100100 Jean-Philippe St. Pierre
101101 Guido van Rossum
102102 Pavel Vinogradov
103 Stefan Beyer
104 William Leslie
103105 Paweł Piotr Przeradowski
104 William Leslie
105106 marky1991
106107 Ilya Osadchiy
107108 Tobias Oberstein
110111 Taavi Burns
111112 Adrian Kuhn
112113 tav
114 Stian Andreassen
113115 Georg Brandl
114116 Joannah Nanjekye
115117 Bert Freudenberg
116 Stian Andreassen
117118 Wanja Saatkamp
118119 Mike Blume
119120 Gerald Klix
129130 Vasily Kuznetsov
130131 Preston Timmons
131132 David Ripton
133 Pieter Zieschang
132134 Dusty Phillips
133135 Lukas Renggli
134136 Guenter Jantzen
142144 Andrew Durdin
143145 Ben Young
144146 Michael Schneider
147 Yusuke Tsutsumi
145148 Nicholas Riley
146149 Jason Chu
147150 Igor Trindade Oliveira
153156 Mariano Anaya
154157 anatoly techtonik
155158 Karl Bartel
156 Stefan Beyer
157159 Gabriel Lavoie
158160 Jared Grubb
159161 Alecsandru Patrascu
164166 Victor Stinner
165167 Andrews Medina
166168 Aaron Iles
167 p_zieschang@yahoo.de
168169 Toby Watson
169170 Daniel Patrick
170171 Stuart Williams
176177 Mikael Schönenberg
177178 Stanislaw Halik
178179 Mihnea Saracin
180 Matt Jackson
179181 Berkin Ilbeyi
180182 Gasper Zejn
181183 Faye Zhao
183185 Anders Qvist
184186 Corbin Simpson
185187 Chirag Jadwani
188 Pauli Virtanen
186189 Jonathan David Riehl
187190 Beatrice During
188191 Alex Perry
189192 Robert Zaremba
190193 Alan McIntyre
191194 Alexander Sedov
195 David C Ellis
192196 Vaibhav Sood
193197 Reuben Cummings
194198 Attila Gobi
208212 Arjun Naik
209213 Aaron Gallagher
210214 Alexis Daboville
211 Pieter Zieschang
212215 Karl Ramm
213216 Lukas Vacek
214217 Omer Katz
236239 Catalin Gabriel Manciu
237240 Jacob Oscarson
238241 Ryan Gonzalez
242 Antoine Dupre
239243 Kristjan Valur Jonsson
240244 Lucio Torre
241245 Richard Lancaster
242246 Dan Buch
243247 Lene Wagner
244248 Tomo Cocoa
249 Miro Hrončok
250 Anthony Sottile
245251 David Lievens
246252 Neil Blakey-Milner
247253 Henrik Vendelbo
256262 Bobby Impollonia
257263 Roberto De Ioris
258264 Jeong YunWon
265 andrewjlawrence
259266 Christopher Armstrong
260267 Aaron Tubbs
261268 Vasantha Ganesh K
262269 Jason Michalski
270 Radu Ciorba
263271 Markus Holtermann
264272 Andrew Thompson
265273 Yusei Tahara
267275 Fabio Niephaus
268276 Akira Li
269277 Gustavo Niemeyer
270 Rafał Gałczyński
278 Nate Bragg
271279 Lucas Stadler
272280 roberto@goyle
281 Carl Bordum Hansen
273282 Matt Bogosian
274283 Yury V. Zaytsev
275284 florinpapa
276285 Anders Sigfridsson
277 Matt Jackson
278286 Nikolay Zinov
279287 rafalgalczynski@gmail.com
280288 Joshua Gilbert
281289 Anna Katrina Dominguez
282290 Kim Jin Su
283291 Amber Brown
284 Miro Hrončok
285 Anthony Sottile
286 Nate Bragg
292 Andrew Stepanov
293 Rafał Gałczyński
287294 Ben Darnell
288295 Juan Francisco Cantero Hurtado
289296 Godefroid Chappelle
290297 Julian Berman
291 Michael Hudson-Doyle
292298 Stephan Busemann
293299 Dan Colish
294300 timo
298304 halgari
299305 Jim Baker
300306 Chris Lambacher
307 John Aldis
301308 coolbutuseless@gmail.com
302309 Mike Bayer
303310 Rodrigo Araújo
306313 OlivierBlanvillain
307314 Jonas Pfannschmidt
308315 Zearin
316 Johan Forsberg
309317 Andrey Churin
310318 Dan Crosta
311319 reubano@gmail.com
315323 Steve Papanik
316324 Eli Stevens
317325 Boglarka Vezer
318 gabrielg
326 gabrielg@ec2-54-146-239-158.compute-1.amazonaws.com
319327 PavloKapyshin
328 Hervé Beraud
320329 Tomer Chachamu
321330 Christopher Groskopf
322331 Asmo Soinio
330339 Michael Chermside
331340 Anna Ravencroft
332341 remarkablerocket
333 Pauli Virtanen
334342 Petre Vijiac
335343 Berker Peksag
336344 Christian Muirhead
350358 Zooko Wilcox-O Hearn
351359 James Lan
352360 jiaaro
361 Evgenii Gorinov
353362 Markus Unterwaditzer
354363 Kristoffer Kleine
355364 Graham Markall
356365 Dan Loewenherz
357366 werat
358 Andrew Stepanov
367 Filip Salomonsson
359368 Niclas Olofsson
360369 Chris Pressey
361370 Tobias Diaz
329329 -------------
330330
331331 * Hash randomization (``-R``) `is ignored in PyPy`_. In CPython
332 before 3.4 it has `little point`_.
332 before 3.4 it has `little point`_. Both CPython >= 3.4 and PyPy3
333 implement the randomized SipHash algorithm and ignore ``-R``.
333334
334335 * You can't store non-string keys in type objects. For example::
335336
399400
400401 * some functions and attributes of the ``gc`` module behave in a
401402 slightly different way: for example, ``gc.enable`` and
402 ``gc.disable`` are supported, but instead of enabling and disabling
403 the GC, they just enable and disable the execution of finalizers.
403 ``gc.disable`` are supported, but "enabling and disabling the GC" has
404 a different meaning in PyPy than in CPython. These functions
405 actually enable and disable the major collections and the
406 execution of finalizers.
404407
405408 * PyPy prints a random line from past #pypy IRC topics at startup in
406409 interactive mode. In a released version, this behaviour is suppressed, but
140140
141141 .. _pyglet: http://pyglet.org/
142142
143
144 ctypes configure
145 -----------------
146
147 We also released ``ctypes-configure``, which is an experimental package
148 trying to approach the portability issues of ctypes-based code.
149
150 idea
151 ~~~~
152
153 One of ctypes problems is that ctypes programs are usually not very
154 platform-independent. We created ctypes_configure, which invokes c
155 compiler (via distutils) for various platform-dependent details like
156 exact sizes of types (for example size_t), ``#defines``, exact outline of
157 structures etc. It replaces in this regard code generator (h2py).
158
159 installation
160 ~~~~~~~~~~~~
161
162 ``easy_install ctypes_configure``
163
164 usage
165 ~~~~~
166
167 :source:`ctypes_configure/doc/sample.py` explains in details how to use it.
0 Embedding PyPy
1 ==============
0 Embedding PyPy (DEPRECATED)
1 ===========================
22
33 PyPy has a very minimal and a very strange embedding interface, based on
44 the usage of `cffi`_ and the philosophy that Python is a better language than
3939 Main focus of the sprint will be on the goals of the upcoming June 0.9
4040 release.
4141
42 Read more in `the sprint announcement`__, see who is planning to attend
43 on the `people page`_.
44
45 __ https://bitbucket.org/pypy/extradoc/raw/tip/sprintinfo/ddorf2006/announce.html
46 .. _people page: https://bitbucket.org/pypy/extradoc/raw/tip/sprintinfo/ddorf2006/people.txt
42 Read more about `the sprint`__
43
44 __ https://bitbucket.org/pypy/extradoc/src/extradoc/sprintinfo/ddorf2006/
4745
4846
4947 PyPy sprint at Akihabara (Tokyo, Japan)
7474 .. _A Way Forward in Parallelising Dynamic Languages: https://bitbucket.org/pypy/extradoc/raw/extradoc/talk/icooolps2014/position-paper.pdf
7575 .. _Runtime Feedback in a Meta-Tracing JIT for Efficient Dynamic Languages: https://bitbucket.org/pypy/extradoc/raw/extradoc/talk/icooolps2011/jit-hints.pdf
7676 .. _Allocation Removal by Partial Evaluation in a Tracing JIT: https://bitbucket.org/pypy/extradoc/raw/extradoc/talk/pepm2011/bolz-allocation-removal.pdf
77 .. _Towards a Jitting VM for Prolog Execution: http://www.stups.uni-duesseldorf.de/mediawiki/images/a/a7/Pub-BoLeSch2010.pdf
77 .. _Towards a Jitting VM for Prolog Execution: http://stups.hhu.de/mediawiki/images/a/a7/Pub-BoLeSch2010.pdf
7878 .. _High performance implementation of Python for CLI/.NET with JIT compiler generation for dynamic languages: http://buildbot.pypy.org/misc/antocuni-thesis.pdf
7979 .. _How to *not* write Virtual Machines for Dynamic Languages: https://bitbucket.org/pypy/extradoc/raw/tip/talk/dyla2007/dyla.pdf
8080 .. _`Tracing the Meta-Level: PyPy's Tracing JIT Compiler`: https://bitbucket.org/pypy/extradoc/raw/tip/talk/icooolps2009/bolz-tracing-jit.pdf
8181 .. _`Faster than C#: Efficient Implementation of Dynamic Languages on .NET`: https://bitbucket.org/pypy/extradoc/raw/tip/talk/icooolps2009-dotnet/cli-jit.pdf
82 .. _Automatic JIT Compiler Generation with Runtime Partial Evaluation: http://stups.hhu.de/mediawiki/images/b/b9/Master_bolz.pdf
82 .. _Automatic JIT Compiler Generation with Runtime Partial Evaluation: https://www.researchgate.net/profile/Davide_Ancona/publication/252023163_Automatic_generation_of_JIT_compilers_for_dynamic_languages_in_NET/links/53f2098e0cf2bc0c40e70023/Automatic-generation-of-JIT-compilers-for-dynamic-languages-in-NET.pdf
8383 .. _`RPython: A Step towards Reconciling Dynamically and Statically Typed OO Languages`: http://www.disi.unige.it/person/AnconaD/papers/DynamicLanguages_abstracts.html#AACM-DLS07
8484 .. _EU Reports: index-report.html
8585 .. _Hardware Transactional Memory Support for Lightweight Dynamic Language Evolution: http://sabi.net/nriley/pubs/dls6-riley.pdf
367367 .. _LLVM: http://llvm.org/
368368 .. _IronPython: http://ironpython.codeplex.com/
369369 .. _Dynamic Native Optimization of Native Interpreters: http://people.csail.mit.edu/gregs/dynamorio.html
370 .. _JikesRVM: http://jikesrvm.org/
370 .. _JikesRVM: http://www.jikesrvm.org/
371371 .. _Tunes: http://tunes.org
372372 .. _old Tunes Wiki: http://buildbot.pypy.org/misc/cliki.tunes.org/
6666 you may need to run the command with `sudo` for a global installation.
6767 The other commands of ``setup.py`` are available too, like ``build``.
6868
69 .. _PyPI: https://pypi.python.org/pypi
69 .. _PyPI: https://pypi.org
7070 .. _`use virtualenv (as documented here)`: install.html#installing-using-virtualenv
7171
7272
359359 (produced during a sprint). On the `PyPy bitbucket page`_ there is also a
360360 Scheme and an Io implementation; both of these are unfinished at the moment.
361361
362 .. _Topaz: http://topazruby.com/
362 .. _Topaz: http://docs.topazruby.com/en/latest/
363363 .. _Hippy: http://morepypy.blogspot.ch/2012/07/hello-everyone.html
364364 .. _JavaScript interpreter: https://bitbucket.org/pypy/lang-js/
365365 .. _Prolog interpreter: https://bitbucket.org/cfbolz/pyrolog/
2121 larger. (A third category, the very large objects, are initially allocated
2222 outside the nursery and never move.)
2323
24 Since Incminimark is an incremental GC, the major collection is incremental,
25 meaning there should not be any pauses longer than 1ms.
24 Since Incminimark is an incremental GC, the major collection is incremental:
25 the goal is not to have any pause longer than 1ms, but in practice it depends
26 on the size and characteristics of the heap: occasionally, there can be pauses
27 between 10-100ms.
28
29
30 Semi-manual GC management
31 --------------------------
32
33 If there are parts of the program where it is important to have a low latency,
34 you might want to control precisely when the GC runs, to avoid unexpected
35 pauses. Note that this has effect only on major collections, while minor
36 collections continue to work as usual.
37
38 As explained above, a full major collection consists of ``N`` steps, where
39 ``N`` depends on the size of the heap; generally speaking, it is not possible
40 to predict how many steps will be needed to complete a collection.
41
42 ``gc.enable()`` and ``gc.disable()`` control whether the GC runs collection
43 steps automatically. When the GC is disabled the memory usage will grow
44 indefinitely, unless you manually call ``gc.collect()`` and
45 ``gc.collect_step()``.
46
47 ``gc.collect()`` runs a full major collection.
48
49 ``gc.collect_step()`` runs a single collection step. It returns an object of
50 type GcCollectStepStats_, the same which is passed to the corresponding `GC
51 Hooks`_. The following code is roughly equivalent to a ``gc.collect()``::
52
53 while True:
54 if gc.collect_step().major_is_done:
55 break
56
57 For a real-world example of usage of this API, you can look at the 3rd-party
58 module `pypytools.gc.custom`_, which also provides a ``with customgc.nogc()``
59 context manager to mark sections where the GC is forbidden.
60
61 .. _`pypytools.gc.custom`: https://bitbucket.org/antocuni/pypytools/src/0273afc3e8bedf0eb1ef630c3bc69e8d9dd661fe/pypytools/gc/custom.py?at=default&fileviewer=file-view-default
2662
2763
2864 Fragmentation
151187 to wait until it reaches a point in which the interpreter is in a known state
152188 and calling user-defined code is harmless. It might happen that multiple
153189 events occur before the hook is invoked: in this case, you can inspect the
154 value ``stats.count`` to know how many times the event occured since the last
190 value ``stats.count`` to know how many times the event occurred since the last
155191 time the hook was called. Similarly, ``stats.duration`` contains the
156192 **total** time spent by the GC for this specific event since the last time the
157193 hook was called.
162198 The attributes for ``GcMinorStats`` are:
163199
164200 ``count``
165 The number of minor collections occured since the last hook call.
201 The number of minor collections occurred since the last hook call.
166202
167203 ``duration``
168204 The total time spent inside minor collections since the last hook
183219 the number of pinned objects.
184220
185221
222 .. _GcCollectStepStats:
223
186224 The attributes for ``GcCollectStepStats`` are:
187225
188226 ``count``, ``duration``, ``duration_min``, ``duration_max``
191229 ``oldstate``, ``newstate``
192230 Integers which indicate the state of the GC before and after the step.
193231
232 ``major_is_done``
233 Boolean which indicate whether this was the last step of the major
234 collection
235
194236 The value of ``oldstate`` and ``newstate`` is one of these constants, defined
195237 inside ``gc.GcCollectStepStats``: ``STATE_SCANNING``, ``STATE_MARKING``,
196 ``STATE_SWEEPING``, ``STATE_FINALIZING``. It is possible to get a string
197 representation of it by indexing the ``GC_STATS`` tuple.
238 ``STATE_SWEEPING``, ``STATE_FINALIZING``, ``STATE_USERDEL``. It is possible
239 to get a string representation of it by indexing the ``GC_STATES`` tuple.
198240
199241
200242 The attributes for ``GcCollectStats`` are:
+0
-345
pypy/doc/getting-started-dev.rst less more
0 Getting Started Developing With PyPy
1 ====================================
2
3 .. contents::
4
5
6 Using Mercurial
7 ---------------
8
9 PyPy development is based on Mercurial (hg). If you are not used to
10 version control, the cycle for a new PyPy contributor goes typically
11 like this:
12
13 * Make an account on bitbucket_.
14
15 * Go to https://bitbucket.org/pypy/pypy/ and click "fork" (left
16 icons). You get a fork of the repository, e.g. in
17 https://bitbucket.org/yourname/pypy/.
18
19 * Clone this new repo (i.e. the fork) to your local machine with the command
20 ``hg clone ssh://hg@bitbucket.org/yourname/pypy``. It is a very slow
21 operation but only ever needs to be done once. See also
22 http://pypy.org/download.html#building-from-source .
23 If you already cloned
24 ``https://bitbucket.org/pypy/pypy`` before, even if some time ago,
25 then you can reuse the same clone by editing the file ``.hg/hgrc`` in
26 your clone to contain the line ``default =
27 ssh://hg@bitbucket.org/yourname/pypy``, and then do ``hg pull && hg
28 up``. If you already have such a clone but don't want to change it,
29 you can clone that copy with ``hg clone /path/to/other/copy``, and
30 then edit ``.hg/hgrc`` as above and do ``hg pull && hg up``.
31
32 * Now you have a complete copy of the PyPy repo. Make a branch
33 with a command like ``hg branch name_of_your_branch``.
34
35 * Edit things. Use ``hg diff`` to see what you changed. Use ``hg add``
36 to make Mercurial aware of new files you added, e.g. new test files.
37 Use ``hg status`` to see if there are such files. Write and run tests!
38 (See the rest of this page.)
39
40 * Commit regularly with ``hg commit``. A one-line commit message is
41 fine. We love to have tons of commits; make one as soon as you have
42 some progress, even if it is only some new test that doesn't pass yet,
43 or fixing things even if not all tests pass. Step by step, you are
44 building the history of your changes, which is the point of a version
45 control system. (There are commands like ``hg log`` and ``hg up``
46 that you should read about later, to learn how to navigate this
47 history.)
48
49 * The commits stay on your machine until you do ``hg push`` to "push"
50 them back to the repo named in the file ``.hg/hgrc``. Repos are
51 basically just collections of commits (a commit is also called a
52 changeset): there is one repo per url, plus one for each local copy on
53 each local machine. The commands ``hg push`` and ``hg pull`` copy
54 commits around, with the goal that all repos in question end up with
55 the exact same set of commits. By opposition, ``hg up`` only updates
56 the "working copy" by reading the local repository, i.e. it makes the
57 files that you see correspond to the latest (or any other) commit
58 locally present.
59
60 * You should push often; there is no real reason not to. Remember that
61 even if they are pushed, with the setup above, the commits are (1)
62 only in ``bitbucket.org/yourname/pypy``, and (2) in the branch you
63 named. Yes, they are publicly visible, but don't worry about someone
64 walking around the thousands of repos on bitbucket saying "hah, look
65 at the bad coding style of that guy". Try to get into the mindset
66 that your work is not secret and it's fine that way. We might not
67 accept it as is for PyPy, asking you instead to improve some things,
68 but we are not going to judge you.
69
70 * The final step is to open a pull request, so that we know that you'd
71 like to merge that branch back to the original ``pypy/pypy`` repo.
72 This can also be done several times if you have interesting
73 intermediate states, but if you get there, then we're likely to
74 proceed to the next stage, which is...
75
76 * Get a regular account for pushing directly to
77 ``bitbucket.org/pypy/pypy`` (just ask and you'll get it, basically).
78 Once you have it you can rewrite your file ``.hg/hgrc`` to contain
79 ``default = ssh://hg@bitbucket.org/pypy/pypy``. Your changes will
80 then be pushed directly to the official repo, but (if you follow these
81 rules) they are still on a branch, and we can still review the
82 branches you want to merge.
83
84 * If you get closer to the regular day-to-day development, you'll notice
85 that we generally push small changes as one or a few commits directly
86 to the branch ``default``. Also, we often collaborate even if we are
87 on other branches, which do not really "belong" to anyone. At this
88 point you'll need ``hg merge`` and learn how to resolve conflicts that
89 sometimes occur when two people try to push different commits in
90 parallel on the same branch. But it is likely an issue for later ``:-)``
91
92 .. _bitbucket: https://bitbucket.org/
93
94
95 Running PyPy's unit tests
96 -------------------------
97
98 PyPy development always was and is still thoroughly test-driven.
99 We use the flexible `py.test testing tool`_ which you can `install independently
100 <http://pytest.org/latest/getting-started.html#getstarted>`_ and use for other projects.
101
102 The PyPy source tree comes with an inlined version of ``py.test``
103 which you can invoke by typing::
104
105 python pytest.py -h
106
107 This is usually equivalent to using an installed version::
108
109 py.test -h
110
111 If you encounter problems with the installed version
112 make sure you have the correct version installed which
113 you can find out with the ``--version`` switch.
114
115 You will need the `build requirements`_ to run tests successfully, since many of
116 them compile little pieces of PyPy and then run the tests inside that minimal
117 interpreter
118
119 Now on to running some tests. PyPy has many different test directories
120 and you can use shell completion to point at directories or files::
121
122 py.test pypy/interpreter/test/test_pyframe.py
123
124 # or for running tests of a whole subdirectory
125 py.test pypy/interpreter/
126
127 See `py.test usage and invocations`_ for some more generic info
128 on how you can run tests.
129
130 Beware trying to run "all" pypy tests by pointing to the root
131 directory or even the top level subdirectory ``pypy``. It takes
132 hours and uses huge amounts of RAM and is not recommended.
133
134 To run CPython regression tests you can point to the ``lib-python``
135 directory::
136
137 py.test lib-python/2.7/test/test_datetime.py
138
139 This will usually take a long time because this will run
140 the PyPy Python interpreter on top of CPython. On the plus
141 side, it's usually still faster than doing a full translation
142 and running the regression test with the translated PyPy Python
143 interpreter.
144
145 .. _py.test testing tool: http://pytest.org
146 .. _py.test usage and invocations: http://pytest.org/latest/usage.html#usage
147 .. _`build requirements`: build.html#install-build-time-dependencies
148
149 Special Introspection Features of the Untranslated Python Interpreter
150 ---------------------------------------------------------------------
151
152 If you are interested in the inner workings of the PyPy Python interpreter,
153 there are some features of the untranslated Python interpreter that allow you
154 to introspect its internals.
155
156
157 Interpreter-level console
158 ~~~~~~~~~~~~~~~~~~~~~~~~~
159
160 To start interpreting Python with PyPy, install a C compiler that is
161 supported by distutils and use Python 2.7 or greater to run PyPy::
162
163 cd pypy
164 python bin/pyinteractive.py
165
166 After a few seconds (remember: this is running on top of CPython), you should
167 be at the PyPy prompt, which is the same as the Python prompt, but with an
168 extra ">".
169
170 If you press
171 <Ctrl-C> on the console you enter the interpreter-level console, a
172 usual CPython console. You can then access internal objects of PyPy
173 (e.g. the :ref:`object space <objspace>`) and any variables you have created on the PyPy
174 prompt with the prefix ``w_``::
175
176 >>>> a = 123
177 >>>> <Ctrl-C>
178 *** Entering interpreter-level console ***
179 >>> w_a
180 W_IntObject(123)
181
182 The mechanism works in both directions. If you define a variable with the ``w_`` prefix on the interpreter-level, you will see it on the app-level::
183
184 >>> w_l = space.newlist([space.wrap(1), space.wrap("abc")])
185 >>> <Ctrl-D>
186 *** Leaving interpreter-level console ***
187
188 KeyboardInterrupt
189 >>>> l
190 [1, 'abc']
191
192 Note that the prompt of the interpreter-level console is only '>>>' since
193 it runs on CPython level. If you want to return to PyPy, press <Ctrl-D> (under
194 Linux) or <Ctrl-Z>, <Enter> (under Windows).
195
196 Also note that not all modules are available by default in this mode (for
197 example: ``_continuation`` needed by ``greenlet``) , you may need to use one of
198 ``--withmod-...`` command line options.
199
200 You may be interested in reading more about the distinction between
201 :ref:`interpreter-level and app-level <interpreter-level>`.
202
203 pyinteractive.py options
204 ~~~~~~~~~~~~~~~~~~~~~~~~
205
206 To list the PyPy interpreter command line options, type::
207
208 cd pypy
209 python bin/pyinteractive.py --help
210
211 pyinteractive.py supports most of the options that CPython supports too (in addition to a
212 large amount of options that can be used to customize pyinteractive.py).
213 As an example of using PyPy from the command line, you could type::
214
215 python pyinteractive.py --withmod-time -c "from test import pystone; pystone.main(10)"
216
217 Alternatively, as with regular Python, you can simply give a
218 script name on the command line::
219
220 python pyinteractive.py --withmod-time ../../lib-python/2.7/test/pystone.py 10
221
222 The ``--withmod-xxx`` option enables the built-in module ``xxx``. By
223 default almost none of them are, because initializing them takes time.
224 If you want anyway to enable all built-in modules, you can use
225 ``--allworkingmodules``.
226
227 See our :doc:`configuration sections <config/index>` for details about what all the commandline
228 options do.
229
230
231 .. _trace example:
232
233 Tracing bytecode and operations on objects
234 ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
235
236 You can use a simple tracing mode to monitor the interpretation of
237 bytecodes. To enable it, set ``__pytrace__ = 1`` on the interactive
238 PyPy console::
239
240 >>>> __pytrace__ = 1
241 Tracing enabled
242 >>>> x = 5
243 <module>: LOAD_CONST 0 (5)
244 <module>: STORE_NAME 0 (x)
245 <module>: LOAD_CONST 1 (None)
246 <module>: RETURN_VALUE 0
247 >>>> x
248 <module>: LOAD_NAME 0 (x)
249 <module>: PRINT_EXPR 0
250 5
251 <module>: LOAD_CONST 0 (None)
252 <module>: RETURN_VALUE 0
253 >>>>
254
255
256 Demos
257 -----
258
259 The `example-interpreter`_ repository contains an example interpreter
260 written using the RPython translation toolchain.
261
262 .. _example-interpreter: https://bitbucket.org/pypy/example-interpreter
263
264
265 Additional Tools for running (and hacking) PyPy
266 -----------------------------------------------
267
268 We use some optional tools for developing PyPy. They are not required to run
269 the basic tests or to get an interactive PyPy prompt but they help to
270 understand and debug PyPy especially for the translation process.
271
272
273 graphviz & pygame for flow graph viewing (highly recommended)
274 ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
275
276 graphviz and pygame are both necessary if you
277 want to look at generated flow graphs:
278
279 graphviz: http://www.graphviz.org/Download.php
280
281 pygame: http://www.pygame.org/download.shtml
282
283
284 py.test and the py lib
285 ~~~~~~~~~~~~~~~~~~~~~~
286
287 The `py.test testing tool`_ drives all our testing needs.
288
289 We use the `py library`_ for filesystem path manipulations, terminal
290 writing, logging and some other support functionality.
291
292 You don't necessarily need to install these two libraries because
293 we also ship them inlined in the PyPy source tree.
294
295 .. _py library: http://pylib.readthedocs.org/
296
297
298 Getting involved
299 ----------------
300
301 PyPy employs an open development process. You are invited to join our
302 `pypy-dev mailing list`_ or look at the other :ref:`contact
303 possibilities <contact>`. Usually we give out commit rights fairly liberally, so if you
304 want to do something with PyPy, you can become a committer. We also run frequent
305 coding sprints which are separately announced and often happen around Python
306 conferences such as EuroPython or PyCon. Upcoming events are usually announced
307 on `the blog`_.
308
309 .. _the blog: http://morepypy.blogspot.com
310 .. _pypy-dev mailing list: http://mail.python.org/mailman/listinfo/pypy-dev
311
312
313 .. _start-reading-sources:
314
315 Where to start reading the sources
316 ----------------------------------
317
318 PyPy is made from parts that are relatively independent of each other.
319 You should start looking at the part that attracts you most (all paths are
320 relative to the PyPy top level directory). You may look at our :doc:`directory reference <dir-reference>`
321 or start off at one of the following points:
322
323 * :source:`pypy/interpreter` contains the bytecode interpreter: bytecode dispatcher
324 in :source:`pypy/interpreter/pyopcode.py`, frame and code objects in
325 :source:`pypy/interpreter/eval.py` and :source:`pypy/interpreter/pyframe.py`,
326 function objects and argument passing in :source:`pypy/interpreter/function.py`
327 and :source:`pypy/interpreter/argument.py`, the object space interface
328 definition in :source:`pypy/interpreter/baseobjspace.py`, modules in
329 :source:`pypy/interpreter/module.py` and :source:`pypy/interpreter/mixedmodule.py`.
330 Core types supporting the bytecode interpreter are defined in :source:`pypy/interpreter/typedef.py`.
331
332 * :source:`pypy/interpreter/pyparser` contains a recursive descent parser,
333 and grammar files that allow it to parse the syntax of various Python
334 versions. Once the grammar has been processed, the parser can be
335 translated by the above machinery into efficient code.
336
337 * :source:`pypy/interpreter/astcompiler` contains the compiler. This
338 contains a modified version of the compiler package from CPython
339 that fixes some bugs and is translatable.
340
341 * :source:`pypy/objspace/std` contains the :ref:`Standard object space <standard-object-space>`. The main file
342 is :source:`pypy/objspace/std/objspace.py`. For each type, the file
343 ``xxxobject.py`` contains the implementation for objects of type ``xxx``,
344 as a first approximation. (Some types have multiple implementations.)
+0
-93
pypy/doc/how-to-contribute.rst less more
0 How to contribute to PyPy
1 =========================
2
3 This page describes how to contribute to the PyPy project. The first thing
4 to remember is that PyPy project is very different than most projects out there.
5 It's also different from a classic compiler project, so academic courses
6 about compilers often don't apply or lead in the wrong direction.
7
8
9 Don't just hack
10 ---------------
11
12 The first and most important rule how not to contribute to PyPy is
13 "just hacking". This won't work. There are two major reasons why not
14 -- build times are large and PyPy has very thick layer separation which
15 make it harder to "just hack a feature".
16
17
18 Test driven development
19 -----------------------
20
21 Instead, we practice a lot of test driven development. This is partly because
22 of very high quality requirements for compilers and partly because there is
23 simply no other way to get around such complex project, that will keep you sane.
24 There are probably people out there who are smart enough not to need it, we're
25 not one of those. You may consider familiarizing yourself with `pytest`_,
26 since this is a tool we use for tests.
27 This leads to the next issue:
28
29 .. _pytest: http://pytest.org/
30
31
32 Layers
33 ------
34
35 PyPy has layers. Just like Ogres or onions.
36 Those layers help us keep the respective parts separated enough
37 to be worked on independently and make the complexity manageable. This is,
38 again, just a sanity requirement for such a complex project. For example writing
39 a new optimization for the JIT usually does **not** involve touching a Python
40 interpreter at all or the JIT assembler backend or the garbage collector.
41 Instead it requires writing small tests in
42 ``rpython/jit/metainterp/optimizeopt/test/test_*`` and fixing files there.
43 After that, you can just compile PyPy and things should just work.
44
45 The short list of layers for further reading. For each of those layers, a good
46 entry point is a test subdirectory in respective directories. It usually
47 describes (better or worse) the interfaces between the submodules. For the
48 ``pypy`` subdirectory, most tests are small snippets of python programs that
49 check for correctness (calls ``AppTestXxx``) that will call the appropriate
50 part of the interpreter. For the ``rpython`` directory, most tests are small
51 RPython interpreters that perform certain tasks. To see how they translate
52 to low-level graphs, run them with ``--view``. To see small interpreters
53 with a JIT compiler, use ``--viewloops`` option.
54
55 * **python interpreter** - it's the part implemented in the ``pypy/`` directory.
56 It's implemented in RPython, which is a high level static language with
57 classes, garbage collection, just-in-time compiler generation and the ability
58 to call C. A cool part about it is that it can be run untranslated, so all
59 the tests are runnable without translating PyPy.
60
61 **interpreter** contains the interpreter core
62
63 **objspace** contains implementations of various objects exported to
64 the Python layer
65
66 **module** directory contains extension modules written in RPython
67
68 * **rpython compiler** that resides in ``rpython/annotator`` and
69 ``rpython/rtyper`` directories. Consult `Getting Started with RPython`_
70 for further reading
71
72 * **JIT generator** lives in ``rpython/jit`` directory. optimizations live
73 in ``rpython/jit/metainterp/optimizeopt``, the main JIT in
74 ``rpython/jit/metainterp`` (runtime part) and
75 ``rpython/jit/codewriter`` (translation-time part). Backends live in
76 ``rpython/jit/backend``.
77
78 * **garbage collection** lives in ``rpython/memory``
79
80 The rest of directories serve specific niche goal and are unlikely a good
81 entry point.
82
83
84 More documentation
85 ------------------
86
87 * `Getting Started Developing With PyPy`_
88
89 * `Getting Started with RPython`_
90
91 .. _`Getting Started Developing With PyPy`: getting-started-dev.html
92 .. _`Getting started with RPython`: http://rpython.readthedocs.org/en/latest/getting-started.html
1515 How to Create a PyPy Release
1616 ++++++++++++++++++++++++++++
1717
18 Overview
19 --------
20
2118 As a meta rule setting up issues in the tracker for items here may help not
2219 forgetting things. A set of todo files may also work.
2320
2724
2825
2926 Release Steps
30 -------------
27 ++++++++++++++
3128
32 * If needed, make a release branch
33 * Bump the
34 pypy version number in module/sys/version.py and in
35 module/cpyext/include/patchlevel.h and in doc/conf.py. The branch
36 will capture the revision number of this change for the release.
29 Make the release branch
30 ------------------------
3731
38 Some of the next updates may be done before or after branching; make
39 sure things are ported back to the trunk and to the branch as
40 necessary.
32 This is needed only in case you are doing a new major version; if not, you can
33 probably reuse the existing release branch.
34
35 We want to be able to freely merge default into the branch and vice-versa;
36 thus we need to do a complicate dance to avoid to patch the version number
37 when we do a merge::
38
39 $ hg up -r default
40 $ # edit the version to e.g. 7.0.0-final
41 $ hg ci
42 $ hg branch release-pypy2.7-7.x && hg ci
43 $ hg up -r default
44 $ # edit the version to 7.1.0-alpha0
45 $ hg ci
46 $ hg up -r release-pypy2.7-7.x
47 $ hg merge default
48 $ # edit the version to AGAIN 7.0.0-final
49 $ hg ci
50
51 Then, we need to do the same for the 3.x branch::
52
53 $ hg up -r py3.5
54 $ hg merge default # this brings the version fo 7.1.0-alpha0
55 $ hg branch release-pypy3.5-7.x
56 $ # edit the version to 7.0.0-final
57 $ hg ci
58 $ hg up -r py3.5
59 $ hg merge release-pypy3.5-7.x
60 $ # edit the version to 7.1.0-alpha0
61 $ hg ci
62
63 To change the version, you need to edit three files:
64
65 - ``module/sys/version.py``
66
67 - ``module/cpyext/include/patchlevel.h``
68
69 - ``doc/conf.py``
70
71
72 Other steps
73 -----------
74
4175
4276 * Make sure the RPython builds on the buildbot pass with no failures
4377
55
66 .. toctree::
77
8 release-v7.0.0.rst
89 release-v6.0.0.rst
910 release-v5.10.1.rst
1011 release-v5.10.0.rst
66 .. toctree::
77
88 whatsnew-head.rst
9 whatsnew-pypy2-7.0.0.rst
910 whatsnew-pypy2-6.0.0.rst
1011 whatsnew-pypy2-5.10.0.rst
1112 whatsnew-pypy2-5.10.0.rst
3334 whatsnew-2.0.0-beta1.rst
3435 whatsnew-1.9.rst
3536
37
3638 CPython 3.5 compatible versions
3739 -------------------------------
3840
3941 .. toctree::
4042
4143 whatsnew-pypy3-head.rst
44 whatsnew-pypy3-7.0.0.rst
4245 whatsnew-pypy3-5.9.0.rst
4346 whatsnew-pypy3-5.8.0.rst
4447 whatsnew-pypy3-5.7.0.rst
88
99 * If you're interested in trying PyPy out, check out the :doc:`installation instructions <install>`.
1010
11 * If you want to help develop PyPy, please have a look at :doc:`how to contribute <how-to-contribute>`
11 * If you want to help develop PyPy, please have a look at :doc:`contributing <contributing>`
1212 and get in touch (:ref:`contact`)!
1313
1414 All of the documentation and source code is available under the MIT license,
2828 :maxdepth: 1
2929
3030 introduction
31 architecture
3132 install
3233 build
34 windows
3335 faq
3436
3537
3941 ----------
4042
4143 .. toctree::
42 :maxdepth: 1
44 :maxdepth: 2
4345
4446 cpython_differences
4547 extending
46 embedding
4748 gc_info
4849 jit-hooks
4950 stackless
5051 __pypy__-module
51 objspace-proxies
5252 sandbox
5353 stm
54 windows
5554
56
57 .. _developing-pypy:
58
59 Development documentation
60 -------------------------
55 Development
56 -----------
6157
6258 .. toctree::
63 :maxdepth: 1
59 :maxdepth: 2
6460
65 getting-started-dev
66 how-to-contribute
67 you-want-to-help
68 architecture
61 contributing
6962 configuration
7063 project-ideas
7164 project-documentation
7265 how-to-release
73
74 .. TODO: audit ^^
75
76
77 .. TODO: Fill this in
7866
7967
8068 Further resources
8371 .. toctree::
8472 :maxdepth: 1
8573
86 extradoc
87 eventhistory
88 discussions
8974 index-of-release-notes
9075 index-of-whatsnew
9176 contributor
92
77 glossary
9378
9479 .. _contact:
9580
117102 the `development mailing list`_.
118103
119104 .. _#pypy on irc.freenode.net: irc://irc.freenode.net/pypy
120 .. _here: http://www.tismer.com/pypy/irc-logs/pypy/
105 .. _here: https://botbot.me/freenode/pypy/
121106 .. _Development mailing list: http://mail.python.org/mailman/listinfo/pypy-dev
122107 .. _Commit mailing list: http://mail.python.org/mailman/listinfo/pypy-commit
123108 .. _Development bug/feature tracker: https://bitbucket.org/pypy/pypy/issues
1919 OS and architecture. You may be able to use either use the
2020 `most recent release`_ or one of our `development nightly build`_. These
2121 builds depend on dynamically linked libraries that may not be available on your
22 OS. See the section about `Linux binaries` for more info and alternatives that
22 OS. See the section about `Linux binaries`_ for more info and alternatives that
2323 may work on your system.
2424
2525 Please note that the nightly builds are not
101101 program flows with homogeneous name-value assignments on
102102 function invocations.
103103
104 .. _how-to guide for descriptors: http://users.rcn.com/python/download/Descriptor.htm
104 .. _how-to guide for descriptors: https://docs.python.org/3/howto/descriptor.html
105105
106106
107107 Bytecode Interpreter Implementation Classes
155155 environment found in `Frames`. Frames and Functions have references
156156 to a code object. Here is a list of Code attributes:
157157
158 * ``co_flags`` flags if this code object has nested scopes/generators
158 * ``co_flags`` flags if this code object has nested scopes/generators/etc.
159159 * ``co_stacksize`` the maximum depth the stack can reach while executing the code
160160 * ``co_code`` the actual bytecode string
161161
0 What PyPy can do for your objects
1 =================================
2
3 .. contents::
4
5
6 Thanks to the :doc:`Object Space <objspace>` architecture, any feature that is
7 based on proxying, extending, changing or otherwise controlling the
8 behavior of objects in a running program is easy to implement on top of PyPy.
9
10 Here is what we have implemented so far, in historical order:
11
12 * *Dump Object Space*: dumps all operations performed on all the objects
13 into a large log file. For debugging your applications.
14
15 * *Transparent Proxies Extension*: adds new proxy objects to
16 the Standard Object Space that enable applications to
17 control operations on application and builtin objects,
18 e.g lists, dictionaries, tracebacks.
19
20
210 .. _tproxy:
221
23 Transparent Proxies
24 -------------------
2 Transparent Proxies (DEPRECATED)
3 --------------------------------
254
265 .. warning::
276
193172 application-level code.
194173
195174 Transparent proxies are implemented on top of the :ref:`standard object
196 space <standard-object-space>`, in :source:`pypy/objspace/std/proxy_helpers.py`,
175 space <standard-object-space>`, in :source:`pypy/objspace/std/proxyobject.py`,
197176 :source:`pypy/objspace/std/proxyobject.py` and :source:`pypy/objspace/std/transparent.py`.
198177 To use them you will need to pass a `--objspace-std-withtproxy`_ option to ``pypy``
199178 or ``translate.py``. This registers implementations named :py:class:`W_TransparentXxx`
473473 :source:`pypy/objspace/std/bytesobject.py` defines ``W_AbstractBytesObject``,
474474 which contains everything needed to build the ``str`` app-level type;
475475 and there are subclasses ``W_BytesObject`` (the usual string) and
476 ``W_StringBufferObject`` (a special implementation tweaked for repeated
477 additions, in :source:`pypy/objspace/std/strbufobject.py`). For mutable data
476 ``W_Buffer`` (a special implementation tweaked for repeated
477 additions, in :source:`pypy/objspace/std/bufferobject.py`). For mutable data
478478 types like lists and dictionaries, we have a single class
479479 ``W_ListObject`` or ``W_DictMultiObject`` which has an indirection to
480480 the real data and a strategy; the strategy can change as the content of
2727 .. toctree::
2828 :hidden:
2929
30 architecture
3130 coding-guide
3231 sprint-reports
3332 extradoc
33 eventhistory
3434 video-index
3535 index-report
36 discussions
3637 dev_method
37 glossary
38 embedding
39 objspace-proxies
3840
3941
4042 Source Code Documentation
110110 --------------
111111
112112 Our cpyext C-API compatiblity layer can now run upstream NumPy unmodified.
113 Release PyPy2.7-v5.4 still fails about 60 of the ~6000 test in the NumPy
114 test suite. We could use help analyzing the failures and fixing them either
115 as patches to upstream NumPy, or as fixes to PyPy.
113 Release PyPy2.7-v6.0 still fails about 10 of the ~6000 test in the NumPy
114 test suite. We need to improve our ctypes structure -> memoryview conversions_,
115 and to refactor the way `NumPy adds docstrings`_.
116
117 .. _conversions: https://bitbucket.org/pypy/pypy/issues/2930
118 .. _`NumPy adds docstrings`: https://github.com/numpy/numpy/issues/10167
116119
117120 We also are looking for help in how to hijack NumPy dtype conversion and
118121 ufunc calls to allow the JIT to make them fast, using our internal _numpypy
164167
165168 Or maybe not. We can also play around with the idea of using a single
166169 representation: as a byte string in utf-8. (This idea needs some extra logic
167 for efficient indexing, like a cache.)
168
170 for efficient indexing, like a cache.) Work has begun on the ``unicode-utf``
171 and ``unicode-utf8-py3`` branches. More is needed, for instance there are
172 SIMD optimizations that are not yet used.
173
174 Convert RPython to Python3
175 --------------------------
176
177 The world is moving on, we should too.
178
179 Improve performance
180 -------------------
181
182 * Make uninlined Python-level calls faster
183 * Switch to a `sea-of-nodes`_ IR, or a `Lua-Jit`_-like IR which iterates on
184 on the sea-of-nodes approach
185 * Use real register-allocation
186 * Improve instruction selection / scheduling
187 * Create a hybrid tracing/method JIT
188
189 .. _`sea-of-nodes`: https://darksi.de/d.sea-of-nodes/
190 .. _`Lua-JIT`: http://wiki.luajit.org/SSA-IR-2.0
191
192 Improve warmup
193 --------------
194 * Interpreter speed-ups
195 * Optimize while tracing
196 * Cache information between runs
169197
170198 Translation Toolchain
171199 ---------------------
233261 .. _runner: http://speed.pypy.org
234262 .. _`CPython site`: https://speed.python.org/
235263
264
265 Interfacing with C
266 ------------------
267
268 While we could make ``cpyext`` faster_, we would also like to explore other
269 ideas. It seems cffi is only appropriate for small to medium-sized extensions,
270 and it is hard to imagine NumPy abandoning the C-API. Here are a few ideas:
271 * Extend Cython to have a backend that can be understood by the JIT
272 * Collaborate with C-extension authors to ensure full PyPy support (see below)
273 * Put PyPy compatible packages on PyPI and in conda
274
275
276 .. _faster: https://morepypy.blogspot.com/2018/09#next-steps
277
278 Support more platforms
279 ----------------------
280
281 We have a plan for a `Windows 64`_ port.
282
283 .. _`Windows 64`: windows.html#what-is-missing-for-a-full-64-bit-translation
284
236285 ======================================
237286 Make more python modules pypy-friendly
238287 ======================================
77 the dual release.
88
99 This release is a feature release following our previous 5.10 incremental
10 release in late December 2017. Our C-API compatability layer ``cpyext`` is
10 release in late December 2017. Our C-API compatibility layer ``cpyext`` is
1111 now much faster (see the `blog post`_) as well as more complete. We have made
1212 many other improvements in speed and CPython compatibility. Since the changes
1313 affect the included python development header files, all c-extension modules must
1414 be recompiled for this version.
1515
16 First-time python users are often stumped by silly typos and emissions when
16 Until we can work with downstream providers to distribute builds with PyPy, we
17 have made packages for some common packages `available as wheels`_. You may
18 compile yourself using ``pip install --no-build-isolation <package>``, the
19 ``no-build-isolation`` is currently needed for pip v10.
20
21 First-time python users are often stumped by silly typos and omissions when
1722 getting started writing code. We have improved our parser to emit more friendly
1823 `syntax errors`_, making PyPy not only faster but more friendly.
1924
5964 .. _`hooks`: gc_info.html#gc-hooks
6065 .. _`cffi`: http://cffi.readthedocs.io
6166 .. _`cppyy`: https://cppyy.readthedocs.io
67 .. _`available as wheels`: https://github.com/antocuni/pypy-wheels
6268
6369 What is PyPy?
6470 =============
109115 * Fix JIT bugs exposed in the sre module
110116 * Improve speed of Python parser, improve ParseError messages and SyntaxError
111117 * Handle JIT hooks more efficiently
112 * Fix a rare GC bug exposed by intensive use of cpyext `Buffer` s
118 * Fix a rare GC bug exposed by intensive use of cpyext ``Buffer`` s
113119
114120 We also refactored many parts of the JIT bridge optimizations, as well as cpyext
115121 internals, and together with new contributors fixed issues, added new
0 ======================================================
1 PyPy v7.0.0: triple release of 2.7, 3.5 and 3.6-alpha
2 ======================================================
3
4 The PyPy team is proud to release the version 7.0.0 of PyPy, which includes
5 three different interpreters:
6
7 - PyPy2.7, which is an interpreter supporting the syntax and the features of
8 Python 2.7
9
10 - PyPy3.5, which supports Python 3.5
11
12 - PyPy3.6-alpha: this is the first official release of PyPy to support 3.6
13 features, although it is still considered alpha quality.
14
15 All the interpreters are based on much the same codebase, thus the triple
16 release.
17
18 Until we can work with downstream providers to distribute builds with PyPy, we
19 have made packages for some common packages `available as wheels`_.
20
21 The GC `hooks`_ , which can be used to gain more insights into its
22 performance, has been improved and it is now possible to manually manage the
23 GC by using a combination of ``gc.disable`` and ``gc.collect_step``. See the
24 `GC blog post`_.
25
26
27 We updated the `cffi`_ module included in PyPy to version 1.12, and the
28 `cppyy`_ backend to 1.4. Please use these to wrap your C and C++ code,
29 respectively, for a JIT friendly experience.
30
31 As always, this release is 100% compatible with the previous one and fixed
32 several issues and bugs raised by the growing community of PyPy users.
33 We strongly recommend updating.
34
35 The PyPy3.6 release and the Windows PyPy3.5 release are still not production
36 quality so your mileage may vary. There are open issues with incomplete
37 compatibility and c-extension support.
38
39 The utf8 branch that changes internal representation of unicode to utf8 did not
40 make it into the release, so there is still more goodness coming.
41 You can download the v6.0 releases here:
42
43 http://pypy.org/download.html
44
45 We would like to thank our donors for the continued support of the PyPy
46 project. If PyPy is not quite good enough for your needs, we are available for
47 direct consulting work.
48
49 We would also like to thank our contributors and encourage new people to join
50 the project. PyPy has many layers and we need help with all of them: `PyPy`_
51 and `RPython`_ documentation improvements, tweaking popular `modules`_ to run
52 on pypy, or general `help`_ with making RPython's JIT even better.
53
54 .. _`PyPy`: index.html
55 .. _`RPython`: https://rpython.readthedocs.org
56 .. _`help`: project-ideas.html
57 .. _`cffi`: http://cffi.readthedocs.io
58 .. _`cppyy`: https://cppyy.readthedocs.io
59 .. _`available as wheels`: https://github.com/antocuni/pypy-wheels
60 .. _`GC blog post`: https://morepypy.blogspot.com/2019/01/pypy-for-low-latency-systems.html
61
62
63 What is PyPy?
64 =============
65
66 PyPy is a very compliant Python interpreter, almost a drop-in replacement for
67 CPython 2.7, 3.5 and 3.6. It's fast (`PyPy and CPython 2.7.x`_ performance
68 comparison) due to its integrated tracing JIT compiler.
69
70 We also welcome developers of other `dynamic languages`_ to see what RPython
71 can do for them.
72
73 The PyPy release supports:
74
75 * **x86** machines on most common operating systems
76 (Linux 32/64 bits, Mac OS X 64 bits, Windows 32 bits, OpenBSD, FreeBSD)
77
78 * big- and little-endian variants of **PPC64** running Linux,
79
80 * **s390x** running Linux
81
82 Unfortunately at the moment of writing our ARM buildbots are out of service,
83 so for now we are **not** releasing any binary for the ARM architecture.
84
85 .. _`PyPy and CPython 2.7.x`: http://speed.pypy.org
86 .. _`dynamic languages`: http://rpython.readthedocs.io/en/latest/examples.html
87
88
89 Changelog
90 =========
91
92 If not specified, the changes are shared across versions
93
94 * Support ``__set_name__``, ``__init_subclass__`` (Py3.6)
95 * Support ``cppyy`` in Py3.5 and Py3.6
96 * Use implementation-specific site directories in ``sysconfig`` (Py3.5, Py3.6)
97 * Adding detection of gcc to ``sysconfig`` (Py3.5, Py3.6)
98 * Fix multiprocessing regression on newer glibcs
99 * Make sure 'blocking-ness' of socket is set along with default timeout
100 * Include ``crypt.h`` for ``crypt()`` on Linux
101 * Improve and re-organize the contributing_ documentation
102 * Make the ``__module__`` attribute writable, fixing an incompatibility with
103 NumPy 1.16
104 * Implement ``Py_ReprEnter``, ``Py_ReprLeave(), ``PyMarshal_ReadObjectFromString``,
105 ``PyMarshal_WriteObjectToString``, ``PyObject_DelItemString``,
106 ``PyMapping_DelItem``, ``PyMapping_DelItemString``, ``PyEval_GetFrame``,
107 ``PyOS_InputHook``, ``PyErr_FormatFromCause`` (Py3.6),
108 * Implement new wordcode instruction encoding (Py3.6)
109 * Log additional gc-minor and gc-collect-step info in the PYPYLOG
110 * The ``reverse-debugger`` (revdb) branch has been merged to the default
111 branch, so it should always be up-to-date. You still need a special pypy
112 build, but you can compile it from the same source as the one we distribute
113 for the v7.0.0 release. For more information, see
114 https://bitbucket.org/pypy/revdb
115 * Support underscores in numerical literals like ``'4_2'`` (Py3.6)
116 * Pre-emptively raise MemoryError if the size of dequeue in ``_collections.deque``
117 is too large (Py3.5)
118 * Fix multithreading issues in calls to ``os.setenv``
119 * Add missing defines and typedefs for numpy and pandas on MSVC
120 * Add CPython macros like ``Py_NAN`` to header files
121 * Rename the ``MethodType`` to ``instancemethod``, like CPython
122 * Better support for `async with` in generators (Py3.5, Py3.6)
123 * Improve the performance of ``pow(a, b, c)`` if ``c`` is a large integer
124 * Now ``vmprof`` works on FreeBSD
125 * Support GNU Hurd, fixes for FreeBSD
126 * Add deprecation warning if type of result of ``__float__`` is float inherited
127 class (Py3.6)
128 * Fix async generator bug when yielding a ``StopIteration`` (Py3.6)
129 * Speed up ``max(list-of-int)`` from non-jitted code
130 * Fix Windows ``os.listdir()`` for some cases (see CPython #32539)
131 * Add ``select.PIPE_BUF``
132 * Use ``subprocess`` to avoid shell injection in ``shutil`` module - backport
133 of https://bugs.python.org/issue34540
134 * Rename ``_Py_ZeroStruct`` to ``_Py_FalseStruct`` (Py3.5, Py3.6)
135 * Remove some cpyext names for Py3.5, Py3.6
136 * Enable use of unicode file names in ``dlopen``
137 * Backport CPython fix for ``thread.RLock``
138 * Make GC hooks measure time in seconds (as opposed to an opaque unit)
139 * Refactor and reorganize tests in ``test_lib_pypy``
140 * Check error values in ``socket.setblocking`` (Py3.6)
141 * Add support for FsPath to os.unlink() (Py3.6)
142 * Fix freezing builtin modules at translation
143 * Tweak ``W_UnicodeDictionaryStrategy`` which speeds up dictionaries with only
144 unicode keys
145
146 We also refactored many parts of the JIT bridge optimizations, as well as cpyext
147 internals, and together with new contributors fixed issues, added new
148 documentation, and cleaned up the codebase.
149
150 .. _contributing: http://doc.pypy.org/en/latest/contributing.html
11
22 PyPy's sandboxing features
33 ==========================
4
5 .. warning:: This is not actively maintained. You will likely have to fix
6 some issues yourself, or otherwise play around on your own. We provide
7 this documentation for historical reasions, it will not translate or
8 run on the latest PyPy code base.
49
510 Introduction
611 ------------
1717 'Antonio Cuni': ['antocuni', 'anto'],
1818 'Armin Rigo': ['arigo', 'arfigo', 'armin', 'arigato'],
1919 'Maciej Fijalkowski': ['fijal'],
20 'Carl Friedrich Bolz-Tereick': ['Carl Friedrich Bolz', 'cfbolz', 'cf'],
20 'Carl Friedrich Bolz-Tereick': ['Carl Friedrich Bolz', 'cfbolz', 'cf', 'cbolz'],
2121 'Samuele Pedroni': ['pedronis', 'samuele', 'samule'],
22 'Richard Plangger':['planrich'],
23 'Michael Hudson': ['mwh'],
22 'Richard Plangger': ['planrich', 'plan_rich'],
23 'Remi Meier': ['remi'],
24 'Michael Hudson-Doyle': ['mwh', 'Michael Hudson'],
2425 'Holger Krekel': ['hpk', 'holger krekel', 'holger', 'hufpk'],
25 "Amaury Forgeot d'Arc": ['afa'],
26 "Amaury Forgeot d'Arc": ['afa', 'amauryfa@gmail.com'],
2627 'Alex Gaynor': ['alex', 'agaynor'],
2728 'David Schneider': ['bivab', 'david'],
2829 'Christian Tismer': ['chris', 'christian', 'tismer',
4041 'Mark Pearse': ['mwp'],
4142 'Toon Verwaest': ['tverwaes'],
4243 'Eric van Riet Paap': ['ericvrp'],
43 'Jacob Hallen': ['jacob', 'jakob'],
44 'Jacob Hallen': ['jacob', 'jakob', 'jacob hallen'],
4445 'Anders Lehmann': ['ale', 'anders'],
4546 'Bert Freudenberg': ['bert'],
4647 'Boris Feigin': ['boris', 'boria'],
6869 'Manuel Jacob': ['mjacob'],
6970 'Rami Chowdhury': ['necaris'],
7071 'Stanislaw Halik': ['Stanislaw Halik', 'w31rd0'],
71 'Wenzhu Man':['wenzhu man', 'wenzhuman'],
72 'Anton Gulenko':['anton gulenko', 'anton_gulenko'],
73 'Richard Lancaster':['richardlancaster'],
74 'William Leslie':['William ML Leslie'],
75 'Spenser Bauman':['Spenser Andrew Bauman'],
76 'Raffael Tfirst':['raffael.tfirst@gmail.com'],
77 'timo':['timo@eistee.fritz.box'],
78 'Jasper Schulz':['Jasper.Schulz', 'jbs'],
79 'Aaron Gallagher':['"Aaron Gallagher'],
80 'Yasir Suhail':['yasirs'],
72 'Wenzhu Man': ['wenzhu man', 'wenzhuman'],
73 'Anton Gulenko': ['anton gulenko', 'anton_gulenko'],
74 'Richard Lancaster': ['richardlancaster'],
75 'William Leslie': ['William ML Leslie'],
76 'Spenser Bauman': ['Spenser Andrew Bauman'],
77 'Raffael Tfirst': ['raffael.tfirst@gmail.com'],
78 'timo': ['timo@eistee.fritz.box'],
79 'Jasper Schulz': ['Jasper.Schulz', 'jbs'],
80 'Aaron Gallagher': ['"Aaron Gallagher'],
81 'Yasir Suhail': ['yasirs'],
8182 'Squeaky': ['squeaky'],
82 "Amaury Forgeot d'Arc": ['amauryfa@gmail.com'],
8383 "Dodan Mihai": ['mihai.dodan@gmail.com'],
84 'Wim Lavrijsen': ['wlav'],
85 'Toon Verwaest': ['toon', 'tverwaes'],
86 'Seo Sanghyeon': ['sanxiyn'],
87 'Leonardo Santagada': ['santagada'],
88 'Laurence Tratt': ['ltratt'],
89 'Pieter Zieschang': ['pzieschang', 'p_zieschang@yahoo.de'],
90 'John Witulski': ['witulski'],
8491 }
8592
8693 alias_map = {}
102109 return set()
103110 ignore_words = ['around', 'consulting', 'yesterday', 'for a bit', 'thanks',
104111 'in-progress', 'bits of', 'even a little', 'floating',
105 'a bit', 'reviewing']
112 'a bit', 'reviewing', 'looking', 'advising', 'partly', 'ish',
113 'watching', 'mostly', 'jumping']
106114 sep_words = ['and', ';', '+', '/', 'with special by']
107115 nicknames = match.group(1)
108116 for word in ignore_words:
00 ==========================
1 What's new in PyPy2.7 6.0+
1 What's new in PyPy2.7 7.0+
22 ==========================
33
4 .. this is a revision shortly after release-pypy-6.0.0
5 .. startrev: e50e11af23f1
4 .. this is a revision shortly after release-pypy-7.0.0
5 .. startrev: 481c69f7d81f
66
7
8
3131
3232 .. branch: fix-vmprof-stacklet-switch
3333 .. branch: fix-vmprof-stacklet-switch-2
34
3435 Fix a vmprof+continulets (i.e. greenelts, eventlet, gevent, ...)
3536
3637 .. branch: win32-vcvars
3839 .. branch: rdict-fast-hash
3940
4041 Make it possible to declare that the hash function of an r_dict is fast in RPython.
41
0 ==========================
1 What's new in PyPy2.7 6.0+
2 ==========================
3
4 .. this is a revision shortly after release-pypy-6.0.0
5 .. startrev: e50e11af23f1
6
7 .. branch: cppyy-packaging
8
9 Main items: vastly better template resolution and improved performance. In
10 detail: upgrade to backend 1.4, improved handling of templated methods and
11 functions (in particular automatic deduction of types), improved pythonization
12 interface, range of compatibility fixes for Python3, free functions now take
13 fast libffi path when possible, moves for strings (incl. from Python str),
14 easier/faster handling of std::vector by numpy, improved and faster object
15 identity preservation
16
17 .. branch: socket_default_timeout_blockingness
18
19 Make sure 'blocking-ness' of socket is set along with default timeout
20
21 .. branch: crypt_h
22
23 Include crypt.h for crypt() on Linux
24
25 .. branch: gc-more-logging
26
27 Log additional gc-minor and gc-collect-step info in the PYPYLOG
28
29 .. branch: reverse-debugger
30
31 The reverse-debugger branch has been merged. For more information, see
32 https://bitbucket.org/pypy/revdb
33
34
35 .. branch: pyparser-improvements-3
36
37 Small refactorings in the Python parser.
38
39 .. branch: fix-readme-typo
40
41 .. branch: avoid_shell_injection_in_shutil
42
43 Backport CPython fix for possible shell injection issue in `distutils.spawn`,
44 https://bugs.python.org/issue34540
45
46 .. branch: cffi_dlopen_unicode
47
48 Enable use of unicode file names in `dlopen`
49
50 .. branch: rlock-in-rpython
51
52 Backport CPython fix for `thread.RLock`
53
54
55 .. branch: expose-gc-time
56
57 Make GC hooks measure time in seconds (as opposed to an opaque unit).
58
59 .. branch: cleanup-test_lib_pypy
60
61 Update most test_lib_pypy/ tests and move them to extra_tests/.
62
63 .. branch: gc-disable
64
65 Make it possible to manually manage the GC by using a combination of
66 gc.disable() and gc.collect_step(). Make sure to write a proper release
67 announcement in which we explain that existing programs could leak memory if
68 they run for too much time between a gc.disable()/gc.enable()
0 ========================
1 What's new in PyPy3 6.0+
2 ========================
3
4 .. this is the revision after release-pypy3.5-v6.0
5 .. startrev: 580e3e26cd32
6
7 .. branch: hroncok/fix-multiprocessing-regression-on-newer--1524656522151
8
9 Fix multiprocessing regression on newer glibcs
10
11 .. branch: py3.5-user-site-impl
12
13 Use implementation-specific site directories in sysconfig like in Python2
14
15 .. branch: py3.5-reverse-debugger
16
17 The reverse-debugger branch has been merged. For more information, see
18 https://bitbucket.org/pypy/revdb
0 ========================
1 What's new in PyPy3 6.0+
2 ========================
3
4 .. this is the revision after release-pypy3.5-v6.0
5 .. startrev: 580e3e26cd32
6
0 ========================
1 What's new in PyPy3 7.0+
2 ========================
3
4 .. this is the revision after release-pypy3.5-v7.0
5 .. startrev: 9d2fa7c63b7c
6
2424
2525 This compiler, while the standard one for Python 2.7, is deprecated. Microsoft has
2626 made it available as the `Microsoft Visual C++ Compiler for Python 2.7`_ (the link
27 was checked in Nov 2016). Note that the compiler suite may be installed in
27 was checked in May 2018). Note that the compiler suite may be installed in
2828 ``C:\Users\<user name>\AppData\Local\Programs\Common\Microsoft\Visual C++ for Python``
2929 or in
3030 ``C:\Program Files (x86)\Common Files\Microsoft\Visual C++ for Python``.
31 A current version of ``setuptools`` will be able to find it there. For
32 Windows 10, you must right-click the download, and under ``Properties`` ->
33 ``Compatibility`` mark it as ``Run run this program in comatibility mode for``
34 ``Previous version...``. Also, you must download and install the ``.Net Framework 3.5``,
31 A current version of ``setuptools`` will be able to find it there.
32 Also, you must download and install the ``.Net Framework 3.5``,
3533 otherwise ``mt.exe`` will silently fail. Installation will begin automatically
3634 by running the mt.exe command by hand from a DOS window (that is how the author
3735 discovered the problem).
3836
39 .. _Microsoft Visual C++ Compiler for Python 2.7: https://www.microsoft.com/en-us/download/details.aspx?id=44266
40
41 Installing "Build Tools for Visual Studio 2017" (for Python 3)
37 .. _Microsoft Visual C++ Compiler for Python 2.7: https://www.microsoft.com/EN-US/DOWNLOAD/DETAILS.ASPX?ID=44266
38
39 Installing "Build Tools for Visual Studio 2015" (for Python 3)
4240 --------------------------------------------------------------
4341
44 As documented in the CPython Wiki_, CPython now recommends Visual C++ version
45 14.0. A compact version of the compiler suite can be obtained from Microsoft_
46 downloads, search the page for "Build Tools for Visual Studio 2017".
47
48 You will also need to install the the `Windows SDK`_ in order to use the
49 `mt.exe` mainfest compiler.
42 As documented in the CPython Wiki_, CPython recommends Visual C++ version
43 14.0 for python version 3.5. A compact version of the compiler suite can be
44 obtained from Microsoft_ downloads, search the page for "Microsoft Build Tools 2015".
45
46 You will need to reboot the computer for the installation to successfully install and
47 run the `mt.exe` mainfest compiler. The installation will set the
48 `VS140COMNTOOLS` environment variable, this is key to distutils/setuptools
49 finding the compiler
5050
5151 .. _Wiki: https://wiki.python.org/moin/WindowsCompilers
52 .. _Microsoft: https://www.visualstudio.com/downloads
53 .. _`Windows SDK`: https://developer.microsoft.com/en-us/windows/downloads/windows-10-sdk
52 .. _Microsoft: https://www.visualstudio.com/vs/older-downloads/
5453
5554 Translating PyPy with Visual Studio
5655 -----------------------------------
9897 Setting Up Visual Studio 9.0 for building SSL in Python3
9998 --------------------------------------------------------
10099
100 **Note: this is old information, left for historical reference. We recommend
101 using Visual Studio 2015, which now seems to properly set this all up.**
102
101103 On Python3, the ``ssl`` module is based on ``cffi``, and requires a build step after
102104 translation. However ``distutils`` does not support the Micorosft-provided Visual C
103105 compiler, and ``cffi`` depends on ``distutils`` to find the compiler. The
145147 Installing external packages
146148 ----------------------------
147149
148 We uses a `repository` parallel to pypy to hold binary compiled versions of the
150 We uses a subrepository_ inside pypy to hold binary compiled versions of the
149151 build dependencies for windows. As part of the `rpython` setup stage, environment
150152 variables will be set to use these dependencies. The repository has a README
151153 file on how to replicate, and a branch for each supported platform. You may run
152 the `get_externals.py` utility to checkout the proper branch for your platform
154 the `get_externals.py` utility to checkout the proper branch for your platform
153155 and PyPy version.
154156
155 .. _repository: https://bitbucket.org/pypy/external
157 .. _subrepository: https://bitbucket.org/pypy/external
156158
157159 Using the mingw compiler
158160 ------------------------
+0
-81
pypy/doc/you-want-to-help.rst less more
0 You want to help with PyPy, now what?
1 =====================================
2
3 PyPy is a very large project that has a reputation of being hard to dive into.
4 Some of this fame is warranted, some of it is purely accidental. There are three
5 important lessons that everyone willing to contribute should learn:
6
7 * PyPy has layers. There are many pieces of architecture that are very well
8 separated from each other. More about this below, but often the manifestation
9 of this is that things are at a different layer than you would expect them
10 to be. For example if you are looking for the JIT implementation, you will
11 not find it in the implementation of the Python programming language.
12
13 * Because of the above, we are very serious about Test Driven Development.
14 It's not only what we believe in, but also that PyPy's architecture is
15 working very well with TDD in mind and not so well without it. Often
16 development means progressing in an unrelated corner, one unittest
17 at a time; and then flipping a giant switch, bringing it all together.
18 (It generally works out of the box. If it doesn't, then we didn't
19 write enough unit tests.) It's worth repeating - PyPy's
20 approach is great if you do TDD, and not so great otherwise.
21
22 * PyPy uses an entirely different set of tools - most of them included
23 in the PyPy repository. There is no Makefile, nor autoconf. More below.
24
25
26 Architecture
27 ------------
28
29 PyPy has layers. The 100 miles view:
30
31 * :ref:`RPython <rpython:language>` is the language in which we write interpreters. Not the entire
32 PyPy project is written in RPython, only the parts that are compiled in
33 the translation process. The interesting point is that RPython has no parser,
34 it's compiled from the live python objects, which makes it possible to do
35 all kinds of metaprogramming during import time. In short, Python is a meta
36 programming language for RPython.
37
38 The RPython standard library is to be found in the ``rlib`` subdirectory.
39
40 * The translation toolchain - this is the part that takes care of translating
41 RPython to flow graphs and then to C. There is more in the :doc:`architecture <architecture>`
42 document written about it.
43
44 It lives in the ``rpython`` directory: ``flowspace``, ``annotator``
45 and ``rtyper``.
46
47 * Python Interpreter and modules
48
49 This is in the ``pypy`` directory. ``pypy/interpreter`` is a standard
50 interpreter for Python written in RPython. The fact that it is
51 RPython is not apparent at first. Built-in modules are written in
52 ``pypy/module/*``. Some modules that CPython implements in C are
53 simply written in pure Python; they are in the top-level ``lib_pypy``
54 directory. The standard library of Python (with a few changes to
55 accomodate PyPy) is in ``lib-python``.
56
57 * :ref:`Just-in-Time Compiler (JIT) <rpython:jit>`: we have a tracing JIT that traces the
58 interpreter written in RPython, rather than the user program that it
59 interprets. As a result it applies to any interpreter, i.e. any
60 language. But getting it to work correctly is not trivial: it
61 requires a small number of precise "hints" and possibly some small
62 refactorings of the interpreter. The JIT itself also has several
63 almost-independent parts: the tracer itself in ``rpython/jit/metainterp``, the
64 optimizer in ``rpython/jit/metainterp/optimizer`` that optimizes a list of
65 residual operations, and the backend in ``rpython/jit/backend/<machine-name>``
66 that turns it into machine code. Writing a new backend is a
67 traditional way to get into the project.
68
69 * Garbage Collectors (GC): as you may notice if you are used to CPython's
70 C code, there are no ``Py_INCREF/Py_DECREF`` equivalents in RPython code.
71 :ref:`rpython:garbage-collection` is inserted
72 during translation. Moreover, this is not reference counting; it is a real
73 GC written as more RPython code. The best one we have so far is in
74 ``rpython/memory/gc/incminimark.py``.
75
76
77 Toolset
78 -------
79
80 xxx
385385 def get_gchooks(self):
386386 from pypy.module.gc.hook import LowLevelGcHooks
387387 if self.space is None:
388 raise Exception("get_gchooks must be called afeter get_entry_point")
388 raise Exception("get_gchooks must be called after get_entry_point")
389389 return self.space.fromcache(LowLevelGcHooks)
390390
391391 def get_entry_point(self, config):
22 # See test/test_app_main.
33
44 # Missing vs CPython: -b, -d, -x
5 from __future__ import print_function, unicode_literals
65 USAGE1 = __doc__ = """\
76 Options and arguments (and corresponding environment variables):
87 -B : don't write .py[co] files on import; also PYTHONDONTWRITEBYTECODE=x
8786 run_protected() handles details like forwarding exceptions to
8887 sys.excepthook(), catching SystemExit, etc.
8988 """
89 # don't use try:except: here, otherwise the exception remains
90 # visible in user code. Make sure revdb_stop is a callable, so
91 # that we can call it immediately after finally: below. Doing
92 # so minimizes the number of "blind" lines that we need to go
93 # back from, with "bstep", after we do "continue" in revdb.
94 if '__pypy__' in sys.builtin_module_names:
95 from __pypy__ import revdb_stop
96 else:
97 revdb_stop = None
98 if revdb_stop is None:
99 revdb_stop = lambda: None
100
90101 try:
91102 # run it
92103 try:
93104 f(*fargs, **fkwds)
94105 finally:
106 revdb_stop()
95107 sys.settrace(None)
96108 sys.setprofile(None)
97109 except SystemExit as e:
320332 del encerr
321333
322334 def create_stdio(fd, writing, name, encoding, errors, unbuffered):
323 import io
335 import _io
324336 # stdin is always opened in buffered mode, first because it
325337 # shouldn't make a difference in common use cases, second because
326338 # TextIOWrapper depends on the presence of a read1() method which
328340 buffering = 0 if unbuffered and writing else -1
329341 mode = 'w' if writing else 'r'
330342 try:
331 buf = io.open(fd, mode + 'b', buffering, closefd=False)
343 buf = _io.open(fd, mode + 'b', buffering, closefd=False)
332344 except OSError as e:
333345 if e.errno != errno.EBADF:
334346 raise
338350 raw.name = name
339351 # translate \r\n to \n for sys.stdin on Windows
340352 newline = None if sys.platform == 'win32' and not writing else '\n'
341 stream = io.TextIOWrapper(buf, encoding, errors, newline=newline,
353 stream = _io.TextIOWrapper(buf, encoding, errors, newline=newline,
342354 line_buffering=unbuffered or raw.isatty())
343355 stream.mode = mode
344356 return stream
535547
536548 return options
537549
538 # this indirection is needed to be able to import this module on python2, else
539 # we have a SyntaxError: unqualified exec in a nested function
540 @hidden_applevel
541 def exec_(src, dic):
542 exec(src, dic)
543
544550 @hidden_applevel
545551 def run_command_line(interactive,
546552 inspect,
589595 warnoptions = pythonwarnings.split(',') + warnoptions
590596 if warnoptions:
591597 sys.warnoptions[:] = warnoptions
592 from warnings import _processoptions
593 _processoptions(sys.warnoptions)
598 try:
599 if 'warnings' in sys.modules:
600 from warnings import _processoptions
601 _processoptions(sys.warnoptions)
602 else:
603 import warnings
604 except ImportError as e:
605 pass # CPython just eats any exception here
594606
595607 # set up the Ctrl-C => KeyboardInterrupt signal handler, if the
596608 # signal module is available
643655 else:
644656 if not isolated:
645657 sys.path.insert(0, '')
646 success = run_toplevel(exec_, bytes, mainmodule.__dict__)
658 success = run_toplevel(exec, bytes, mainmodule.__dict__)
647659 elif run_module != 0:
648660 # handle the "-m" command
649661 # '' on sys.path is required also here
683695 python_startup,
684696 'exec',
685697 PyCF_ACCEPT_NULL_BYTES)
686 exec_(co_python_startup, mainmodule.__dict__)
698 exec(co_python_startup, mainmodule.__dict__)
687699 mainmodule.__file__ = python_startup
688700 mainmodule.__cached__ = None
689701 run_toplevel(run_it)
701713 def run_it():
702714 co_stdin = compile(sys.stdin.read(), '<stdin>', 'exec',
703715 PyCF_ACCEPT_NULL_BYTES)
704 exec_(co_stdin, mainmodule.__dict__)
716 exec(co_stdin, mainmodule.__dict__)
705717 mainmodule.__file__ = '<stdin>'
706718 mainmodule.__cached__ = None
707719 success = run_toplevel(run_it)
743755 co = marshal.load(f)
744756 if type(co) is not type((lambda:0).__code__):
745757 raise RuntimeError("Bad code object in .pyc file")
746 exec_(co, namespace)
758 exec(co, namespace)
747759 args = (execfile, filename, mainmodule.__dict__)
748760 else:
749761 filename = sys.argv[0]
771783 code = f.read()
772784 co = compile(code, filename, 'exec',
773785 PyCF_ACCEPT_NULL_BYTES)
774 exec_(co, namespace)
786 exec(co, namespace)
775787 args = (execfile, filename, mainmodule.__dict__)
776788 success = run_toplevel(*args)
777789
691691
692692 # TODO
693693 ops.BUILD_LIST_FROM_ARG: 1,
694 ops.LOAD_REVDB_VAR: 1,
694695
695696 ops.LOAD_CLASSDEREF: 1,
696697 }
17321732 return Num.from_object(space, w_node)
17331733 if space.isinstance_w(w_node, get(space).w_Str):
17341734 return Str.from_object(space, w_node)
1735 if space.isinstance_w(w_node, get(space).w_RevDBMetaVar):
1736 return RevDBMetaVar.from_object(space, w_node)
17351737 if space.isinstance_w(w_node, get(space).w_FormattedValue):
17361738 return FormattedValue.from_object(space, w_node)
17371739 if space.isinstance_w(w_node, get(space).w_JoinedStr):
26402642 return Str(_s, _lineno, _col_offset)
26412643
26422644 State.ast_type('Str', 'expr', ['s'])
2645
2646
2647 class RevDBMetaVar(expr):
2648
2649 def __init__(self, metavar, lineno, col_offset):
2650 self.metavar = metavar
2651 expr.__init__(self, lineno, col_offset)
2652
2653 def walkabout(self, visitor):
2654 visitor.visit_RevDBMetaVar(self)
2655
2656 def mutate_over(self, visitor):
2657 return visitor.visit_RevDBMetaVar(self)
2658
2659 def to_object(self, space):
2660 w_node = space.call_function(get(space).w_RevDBMetaVar)
2661 w_metavar = space.newint(self.metavar) # int
2662 space.setattr(w_node, space.newtext('metavar'), w_metavar)
2663 w_lineno = space.newint(self.lineno) # int
2664 space.setattr(w_node, space.newtext('lineno'), w_lineno)
2665 w_col_offset = space.newint(self.col_offset) # int
2666 space.setattr(w_node, space.newtext('col_offset'), w_col_offset)
2667 return w_node
2668
2669 @staticmethod
2670 def from_object(space, w_node):
2671 w_metavar = get_field(space, w_node, 'metavar', False)
2672 w_lineno = get_field(space, w_node, 'lineno', False)
2673 w_col_offset = get_field(space, w_node, 'col_offset', False)
2674 _metavar = space.int_w(w_metavar)
2675 _lineno = space.int_w(w_lineno)
2676 _col_offset = space.int_w(w_col_offset)
2677 return RevDBMetaVar(_metavar, _lineno, _col_offset)
2678
2679 State.ast_type('RevDBMetaVar', 'expr', ['metavar'])
26432680
26442681
26452682 class FormattedValue(expr):
41294166 return self.default_visitor(node)
41304167 def visit_Str(self, node):
41314168 return self.default_visitor(node)
4169 def visit_RevDBMetaVar(self, node):
4170 return self.default_visitor(node)
41324171 def visit_FormattedValue(self, node):
41334172 return self.default_visitor(node)
41344173 def visit_JoinedStr(self, node):
43604399 pass
43614400
43624401 def visit_Str(self, node):
4402 pass
4403
4404 def visit_RevDBMetaVar(self, node):
43634405 pass
43644406
43654407 def visit_FormattedValue(self, node):
12631263 else:
12641264 # a dictionary display
12651265 return self.handle_dictdisplay(maker, atom_node)
1266 elif first_child_type == tokens.REVDBMETAVAR:
1267 string = atom_node.get_child(0).get_value()
1268 return ast.RevDBMetaVar(int(string[1:]),
1269 atom_node.get_lineno(),
1270 atom_node.get_column())
12661271 else:
12671272 raise AssertionError("unknown atom")
12681273
366366 names)
367367 self._visit_arg_annotations(args.kwonlyargs, names)
368368 kwarg = args.kwarg
369 if args.kwarg:
370 self._visit_arg_annotation(args.kwarg.arg, args.kwarg.annotation,
369 if kwarg:
370 self._visit_arg_annotation(kwarg.arg, kwarg.annotation,
371371 names)
372372 self._visit_arg_annotation("return", returns, names)
373373 l = len(names)
15181518 fmt.format_spec.walkabout(self)
15191519 self.emit_op_arg(ops.FORMAT_VALUE, arg)
15201520
1521 def _revdb_metavar(self, node):
1522 # moved in its own function for the import statement
1523 from pypy.interpreter.reverse_debugging import dbstate
1524 if not dbstate.standard_code:
1525 self.emit_op_arg(ops.LOAD_REVDB_VAR, node.metavar)
1526 return True
1527 return False
1528
1529 def visit_RevDBMetaVar(self, node):
1530 if self.space.reverse_debugging and self._revdb_metavar(node):
1531 return
1532 self.error("Unknown character ('$NUM' is only valid in the "
1533 "reverse-debugger)", node)
1534
15211535
15221536 class TopLevelCodeGenerator(PythonCodeGenerator):
15231537
621621 assert isinstance(args, ast.arguments)
622622 if args.args:
623623 self._visit_arg_annotations(args.args)
624 if args.vararg:
625 self._visit_arg_annotation(args.vararg)
626 if args.kwarg:
627 self._visit_arg_annotation(args.kwarg)
624628 if args.kwonlyargs:
625629 self._visit_arg_annotations(args.kwonlyargs)
626630 if func.returns:
629633 def _visit_arg_annotations(self, args):
630634 for arg in args:
631635 assert isinstance(arg, ast.arg)
632 if arg.annotation:
633 arg.annotation.walkabout(self)
636 self._visit_arg_annotation(arg)
637
638 def _visit_arg_annotation(self, arg):
639 if arg.annotation:
640 arg.annotation.walkabout(self)
634641
635642 def visit_Name(self, name):
636643 if name.ctx == ast.Load:
11301130 assert isinstance(s, ast.Bytes)
11311131 assert space.eq_w(s.s, space.newbytes("hi implicitly extra"))
11321132 raises(SyntaxError, self.get_first_expr, "b'hello' 'world'")
1133 sentence = u"Die Männer ärgen sich!"
1133 sentence = u"Die Männer ärgern sich!"
11341134 source = u"# coding: utf-7\nstuff = '%s'" % (sentence,)
11351135 info = pyparse.CompileInfo("<test>", "exec")
11361136 tree = self.parser.parse_source(source.encode("utf-7"), info)
3030 generator._resolve_block_targets(blocks)
3131 return generator, blocks
3232
33 class TestCompiler:
33 class BaseTestCompiler:
3434 """These tests compile snippets of code and check them by
3535 running them with our own interpreter. These are thus not
3636 completely *unit* tests, but given that our interpreter is
9595
9696 def error_test(self, source, exc_type):
9797 py.test.raises(exc_type, self.simple_test, source, None, None)
98
99
100 class TestCompiler(BaseTestCompiler):
98101
99102 def test_issue_713(self):
100103 func = "def f(_=2): return (_ if _ else _) if False else _"
12401243 yield self.st, src, 'z', 0xd8
12411244
12421245
1246 class TestCompilerRevDB(BaseTestCompiler):
1247 spaceconfig = {"translation.reverse_debugger": True}
1248
1249 def test_revdb_metavar(self):
1250 from pypy.interpreter.reverse_debugging import dbstate, setup_revdb
1251 self.space.config.translation.reverse_debugger = True
1252 self.space.reverse_debugging = True
1253 try:
1254 setup_revdb(self.space)
1255 dbstate.standard_code = False
1256 dbstate.metavars = [self.space.wrap(6)]
1257 self.simple_test("x = 7*$0", "x", 42)
1258 dbstate.standard_code = True
1259 self.error_test("x = 7*$0", SyntaxError)
1260 finally:
1261 self.space.reverse_debugging = False
1262
1263
12431264 class AppTestCompiler:
12441265
12451266 def setup_class(cls):
00 import os
1 from pytest import raises
12 from pypy.interpreter.error import OperationError
23 from pypy.interpreter.baseobjspace import W_Root
34 from pypy.interpreter.astcompiler import ast
6969 | Call(expr func, expr* args, keyword* keywords)
7070 | Num(object n) -- a number as a PyObject.
7171 | Str(string s) -- need to specify raw, unicode, etc?
72 | RevDBMetaVar(int metavar)
7273 | FormattedValue(expr value, int? conversion, expr? format_spec)
7374 | JoinedStr(expr* values)
7475 | Bytes(bytes s)
424424 node.slice.walkabout(self)
425425 self._validate_expr(node.value)
426426
427 def visit_RevDBMetaVar(self, node):
428 pass
429
427430 # Subscripts
428431 def visit_Slice(self, node):
429432 if node.lower:
401401 """Base class for the interpreter-level implementations of object spaces.
402402 http://pypy.readthedocs.org/en/latest/objspace.html"""
403403
404 reverse_debugging = False
405
404406 @not_rpython
405407 def __init__(self, config=None):
406408 "Basic initialization of objects."
412414 from pypy.config.pypyoption import get_pypy_config
413415 config = get_pypy_config(translating=False)
414416 self.config = config
417 self.reverse_debugging = config.translation.reverse_debugger
415418
416419 self.builtin_modules = {}
417420 self.reloading_modules = {}
429432
430433 def startup(self):
431434 # To be called before using the space
435 if self.reverse_debugging:
436 self._revdb_startup()
437
432438 self.threadlocals.enter_thread(self)
433439
434440 # Initialize already imported builtin modules
819825 w_u1 = self.interned_strings.get(u)
820826 if w_u1 is None:
821827 w_u1 = w_u
822 self.interned_strings.set(u, w_u1)
828 if self._side_effects_ok():
829 self.interned_strings.set(u, w_u1)
823830 return w_u1
824831
825832 def new_interned_str(self, s):
831838 w_s1 = self.interned_strings.get(u)
832839 if w_s1 is None:
833840 w_s1 = self.newunicode(u)
834 self.interned_strings.set(u, w_s1)
841 if self._side_effects_ok():
842 self.interned_strings.set(u, w_s1)
835843 return w_s1
844
845 def _revdb_startup(self):
846 # moved in its own function for the import statement
847 from pypy.interpreter.reverse_debugging import setup_revdb
848 setup_revdb(self)
849
850 def _revdb_standard_code(self):
851 # moved in its own function for the import statement
852 from pypy.interpreter.reverse_debugging import dbstate
853 return dbstate.standard_code
854
855 def _side_effects_ok(self):
856 # For the reverse debugger: we run compiled watchpoint
857 # expressions in a fast way that will crash if they have
858 # side-effects. The obvious Python code with side-effects is
859 # documented "don't do that"; but some non-obvious side
860 # effects are also common, like interning strings (from
861 # unmarshalling the code object containing the watchpoint
862 # expression) to the two attribute caches in mapdict.py and
863 # typeobject.py. For now, we have to identify such places
864 # that are not acceptable for "reasonable" read-only
865 # watchpoint expressions, and write:
866 #
867 # if not space._side_effects_ok():
868 # don't cache.
869 #
870 if self.reverse_debugging:
871 return self._revdb_standard_code()
872 return True
836873
837874 def get_interned_str(self, s):
838875 """Assumes an identifier (utf-8 encoded str). Returns None if
14721509 if readonly and flags & self.BUF_WRITABLE == self.BUF_WRITABLE:
14731510 raise oefmt(self.w_BufferError, "Object is not writable.")
14741511
1512 def _try_buffer_w(self, w_obj, flags):
1513 if not we_are_translated():
1514 if w_obj.buffer_w.im_func != W_Root.buffer_w.im_func:
1515 # when 'buffer_w()' is overridden in the subclass of
1516 # W_Root, we need to specify __buffer="read" or
1517 # __buffer="read-write" in the TypeDef.
1518 assert type(w_obj).typedef.buffer is not None
1519 return w_obj.buffer_w(self, flags)
1520
14751521 def buffer_w(self, w_obj, flags):
14761522 # New buffer interface, returns a buffer based on flags (PyObject_GetBuffer)
14771523 try:
1478 return w_obj.buffer_w(self, flags)
1524 return self._try_buffer_w(w_obj, flags)
14791525 except BufferInterfaceNotFound:
14801526 raise oefmt(self.w_TypeError,
14811527 "'%T' does not support the buffer interface", w_obj)
14831529 def readbuf_w(self, w_obj):
14841530 # Old buffer interface, returns a readonly buffer (PyObject_AsReadBuffer)
14851531 try:
1486 return w_obj.buffer_w(self, self.BUF_SIMPLE).as_readbuf()
1532 return self._try_buffer_w(w_obj, self.BUF_SIMPLE).as_readbuf()
14871533 except BufferInterfaceNotFound:
14881534 self._getarg_error("bytes-like object", w_obj)
14891535
14901536 def writebuf_w(self, w_obj):
14911537 # Old buffer interface, returns a writeable buffer (PyObject_AsWriteBuffer)
14921538 try:
1493 return w_obj.buffer_w(self, self.BUF_WRITABLE).as_writebuf()
1539 return self._try_buffer_w(w_obj, self.BUF_WRITABLE).as_writebuf()
14941540 except (BufferInterfaceNotFound, OperationError):
14951541 self._getarg_error("read-write bytes-like object", w_obj)
14961542
15241570 # NB. CPython forbids surrogates here
15251571 return StringBuffer(w_obj.text_w(self))
15261572 try:
1527 return w_obj.buffer_w(self, self.BUF_SIMPLE).as_readbuf()
1573 return self._try_buffer_w(w_obj, self.BUF_SIMPLE).as_readbuf()
15281574 except BufferInterfaceNotFound:
15291575 self._getarg_error("bytes or buffer", w_obj)
15301576 elif code == 's#':
15361582 if self.isinstance_w(w_obj, self.w_unicode): # NB. CPython forbids
15371583 return w_obj.text_w(self) # surrogates here
15381584 try:
1539 return w_obj.buffer_w(self, self.BUF_SIMPLE).as_str()
1585 return self._try_buffer_w(w_obj, self.BUF_SIMPLE).as_str()
15401586 except BufferInterfaceNotFound:
15411587 self._getarg_error("bytes or read-only buffer", w_obj)
15421588 elif code == 'w*':
7070 return frame
7171
7272 def enter(self, frame):
73 if self.space.reverse_debugging:
74 self._revdb_enter(frame)
7375 frame.f_backref = self.topframeref
7476 self.topframeref = jit.virtual_ref(frame)
7577
9092 # be accessed also later
9193 frame_vref()
9294 jit.virtual_ref_finish(frame_vref, frame)
95 if self.space.reverse_debugging:
96 self._revdb_leave(got_exception)
9397
9498 # ________________________________________________________________
9599
159163 Like bytecode_trace() but doesn't invoke any other events besides the
160164 trace function.
161165 """
166 if self.space.reverse_debugging:
167 self._revdb_potential_stop_point(frame)
162168 if (frame.get_w_f_trace() is None or self.is_tracing or
163169 self.gettrace() is None):
164170 return
372378 if self.space.check_signal_action is not None:
373379 self.space.check_signal_action.perform(self, None)
374380
381 def _revdb_enter(self, frame):
382 # moved in its own function for the import statement
383 from pypy.interpreter.reverse_debugging import enter_call
384 enter_call(self.topframeref(), frame)
385
386 def _revdb_leave(self, got_exception):
387 # moved in its own function for the import statement
388 from pypy.interpreter.reverse_debugging import leave_call
389 leave_call(self.topframeref(), got_exception)
390
391 def _revdb_potential_stop_point(self, frame):
392 # moved in its own function for the import statement
393 from pypy.interpreter.reverse_debugging import potential_stop_point
394 potential_stop_point(frame)
395
375396 def _freeze_(self):
376397 raise Exception("ExecutionContext instances should not be seen during"
377398 " translation. Now is a good time to inspect the"
528528
529529 def visit_kwonly(self, typ):
530530 raise FastFuncNotSupported
531
531
532 @staticmethod
532533 def make_fastfunc(unwrap_spec, func):
533534 unwrap_info = UnwrapSpec_FastFunc_Unwrap()
534535 unwrap_info.apply_over(unwrap_spec)
559560 exec compile2(source) in unwrap_info.miniglobals, d
560561 fastfunc = d['fastfunc_%s_%d' % (func.__name__.replace('-', '_'), narg)]
561562 return narg, fastfunc
562 make_fastfunc = staticmethod(make_fastfunc)
563563
564564
565565 def int_unwrapping_space_method(typ):
269269 if self.frame is None:
270270 return # nothing to do in this case
271271 space = self.space
272 operr = get_generator_exit(space)
272 operr = None
273273 # note: w_yielded_from is always None if 'self.running'
274274 w_yf = self.w_yielded_from
275275 if w_yf is not None:
277277 self._gen_close_iter(space)
278278 except OperationError as e:
279279 operr = e
280 if operr is None:
281 operr = OperationError(space.w_GeneratorExit, space.w_None)
280282 try:
281283 self.send_error(operr)
282284 except OperationError as e:
450452 space.call_function(space.w_StopIteration, w_value))
451453
452454
453 @specialize.memo()
454 def get_generator_exit(space):
455 return OperationError(space.w_GeneratorExit,
456 space.call_function(space.w_GeneratorExit))
457
458455 def gen_close_iter(space, w_yf):
459456 # This helper function is used by close() and throw() to
460457 # close a subiterator being delegated to by yield-from.
773773 def fget_f_builtins(self, space):
774774 return self.get_builtin().getdict(space)
775775
776 def get_f_back(self):
777 return ExecutionContext.getnextframe_nohidden(self)
778
776779 def fget_f_back(self, space):
777 f_back = ExecutionContext.getnextframe_nohidden(self)
778 return f_back
780 return self.get_f_back()
779781
780782 def fget_f_lasti(self, space):
781783 return self.space.newint(self.last_instr)
437437 self.FORMAT_VALUE(oparg, next_instr)
438438 elif opcode == opcodedesc.BUILD_STRING.index:
439439 self.BUILD_STRING(oparg, next_instr)
440 elif opcode == opcodedesc.LOAD_REVDB_VAR.index:
441 self.LOAD_REVDB_VAR(oparg, next_instr)
440442 else:
441443 self.MISSING_OPCODE(oparg, next_instr)
442444
11131115 # final result and returns. In that case, we can just continue
11141116 # with the next bytecode.
11151117
1118 def _revdb_jump_backward(self, jumpto):
1119 # moved in its own function for the import statement
1120 from pypy.interpreter.reverse_debugging import jump_backward
1121 jump_backward(self, jumpto)
1122
11161123 def jump_absolute(self, jumpto, ec):
11171124 # this function is overridden by pypy.module.pypyjit.interp_jit
11181125 check_nonneg(jumpto)
1126 if self.space.reverse_debugging:
1127 self._revdb_jump_backward(jumpto)
11191128 return jumpto
11201129
11211130 def JUMP_FORWARD(self, jumpby, next_instr):
12501259
12511260 def WITH_CLEANUP_FINISH(self, oparg, next_instr):
12521261 w_suppress = self.popvalue()
1253 if self.space.is_true(w_suppress):
1254 # __exit__() returned True -> Swallow the exception.
1255 self.settopvalue(self.space.w_None)
1262 w_unroller = self.peekvalue()
1263 if isinstance(w_unroller, SApplicationException):
1264 if self.space.is_true(w_suppress):
1265 # __exit__() returned True -> Swallow the exception.
1266 self.settopvalue(self.space.w_None)
12561267 # this is always followed by END_FINALLY
12571268 # in the stack now: [w_unroller-or-w_None..]
12581269
14231434 @jit.unroll_safe
14241435 def BUILD_SET_UNPACK(self, itemcount, next_instr):
14251436 space = self.space
1426 w_sum = space.newset()
1437 w_set = space.newset()
14271438 for i in range(itemcount, 0, -1):
14281439 w_item = self.peekvalue(i-1)
1429 # cannot use w_sum.update, w_item might not be a set
1430 iterator = space.iter(w_item)
1431 while True:
1432 try:
1433 w_value = space.next(iterator)
1434 except OperationError:
1435 break
1436 w_sum.add(w_value)
1437 while itemcount != 0:
1438 self.popvalue()
1439 itemcount -= 1
1440 self.pushvalue(w_sum)
1440 space.call_method(w_set, "update", w_item)
1441 self.popvalues(itemcount)
1442 self.pushvalue(w_set)
14411443
14421444 @jit.unroll_safe
14431445 def list_unpack_helper(frame, itemcount):
14461448 for i in range(itemcount, 0, -1):
14471449 w_item = frame.peekvalue(i-1)
14481450 w_sum.extend(w_item)
1449 while itemcount != 0:
1450 frame.popvalue()
1451 itemcount -= 1
1451 frame.popvalues(itemcount)
14521452 return w_sum
14531453
14541454 @jit.unroll_safe
14881488 space.call_method(w_dict, 'update', w_item)
14891489 if with_call and space.len_w(w_dict) < expected_length:
14901490 self._build_map_unpack_error(itemcount)
1491 while itemcount > 0:
1492 self.popvalue()
1493 itemcount -= 1
1491 self.popvalues(itemcount)
14941492 self.pushvalue(w_dict)
14951493
14961494 @jit.dont_look_inside
16541652 self.dropvalues(itemcount)
16551653 w_res = space.newunicode(u''.join(lst))
16561654 self.pushvalue(w_res)
1655
1656 def _revdb_load_var(self, oparg):
1657 # moved in its own function for the import statement
1658 from pypy.interpreter.reverse_debugging import load_metavar
1659 w_var = load_metavar(oparg)
1660 self.pushvalue(w_var)
1661
1662 def LOAD_REVDB_VAR(self, oparg, next_instr):
1663 if self.space.reverse_debugging:
1664 self._revdb_load_var(oparg)
1665 else:
1666 self.MISSING_OPCODE(oparg, next_instr)
1667
16571668
16581669 ### ____________________________________________________________ ###
16591670
20642075 else:
20652076 skip_leading_underscores = False
20662077 for name in all:
2067 if skip_leading_underscores and name[0]=='_':
2078 if skip_leading_underscores and name and name[0] == '_':
20682079 continue
20692080 into_locals[name] = getattr(module, name)
20702081 ''', filename=__file__)
2222
2323 ERROR_STATE = chr(255)
2424
25 # NB: all non-ascii bytes (>= 128) will be turned into 128
26 NON_ASCII = chr(128)
27
28
2529 class DFA:
2630 # ____________________________________________________________
2731 def __init__(self, states, accepts, start = 0):
3539 for key in state:
3640 if key == DEFAULT:
3741 continue
38 maximum = max(ord(key), maximum)
42 ordkey = ord(key)
43 if ordkey > 128:
44 raise ValueError("DFA does not support matching of specific non-ASCII character %r. Use NON_ASCII instead" % key)
45 maximum = max(ordkey, maximum)
3946 self.max_char = maximum + 1
4047
4148 defaults = []
7279 for i in range(pos, len(inVec)):
7380 item = inVec[i]
7481 if ord(item) > 0x80:
75 item = "\x80" # NON_ASCII
82 item = NON_ASCII
7683 accept = self.accepts[crntState]
7784 crntState = self._next_state(item, crntState)
7885 if crntState != ERROR_STATE:
104111 i = pos
105112 for i in range(pos, len(inVec)):
106113 item = inVec[i]
114 if ord(item) > 0x80:
115 item = NON_ASCII
107116 accept = self.accepts[crntState]
108117 if accept:
109118 return i
103103 '[' [listmaker] ']' |
104104 '{' [dictorsetmaker] '}' |
105105 '`' testlist1 '`' |
106 NAME | NUMBER | STRING+)
106 NAME | NUMBER | STRING+ | '$NUM')
107107 listmaker: test ( list_for | (',' test)* [','] )
108108 testlist_comp: test ( comp_for | (',' test)* [','] )
109109 lambdef: 'lambda' [varargslist] ':' test
102102 atom: ('(' [yield_expr|testlist_comp] ')' |
103103 '[' [testlist_comp] ']' |
104104 '{' [dictorsetmaker] '}' |
105 NAME | NUMBER | STRING+ | '...' | 'None' | 'True' | 'False')
105 NAME | NUMBER | STRING+ | '$NUM' | '...' | 'None' | 'True' | 'False')
106106 testlist_comp: (test|star_expr) ( comp_for | (',' (test|star_expr))* [','] )
107107 trailer: '(' [arglist] ')' | '[' subscriptlist ']' | '.' NAME
108108 subscriptlist: subscript (',' subscript)* [',']
102102 atom: ('(' [yield_expr|testlist_comp] ')' |
103103 '[' [testlist_comp] ']' |
104104 '{' [dictorsetmaker] '}' |
105 NAME | NUMBER | STRING+ | '...' | 'None' | 'True' | 'False')
105 NAME | NUMBER | STRING+ | '$NUM' | '...' | 'None' | 'True' | 'False')
106106 testlist_comp: (test|star_expr) ( comp_for | (',' (test|star_expr))* [','] )
107107 trailer: '(' [arglist] ')' | '[' subscriptlist ']' | '.' NAME
108108 subscriptlist: subscript (',' subscript)* [',']
107107 atom: ('(' [yield_expr|testlist_comp] ')' |
108108 '[' [testlist_comp] ']' |
109109 '{' [dictorsetmaker] '}' |
110 NAME | NUMBER | STRING+ | '...' | 'None' | 'True' | 'False')
110 NAME | NUMBER | STRING+ | '$NUM' | '...' | 'None' | 'True' | 'False')
111111 testlist_comp: (test|star_expr) ( comp_for | (',' (test|star_expr))* [','] )
112112 trailer: '(' [arglist] ')' | '[' subscriptlist ']' | '.' NAME
113113 subscriptlist: subscript (',' subscript)* [',']
55 from pypy.interpreter.pyparser import automata
66 accepts = [True, True, True, True, True, True, True, True,
77 True, True, True, False, True, True, True, True,
8 True, False, False, False, True, False, False,
9 False, True, False, True, False, True, False,
10 False, True, False, False, True, False, False,
11 True, True, True, False, False, True, False,
12 False, False, True]
8 True, False, False, False, False, True, False,
9 False, False, True, False, True, False, True,
10 False, True, False, True, False, False, True,
11 False, False, True, True, True, False, False,
12 True, False, False, False, True]
1313 states = [
1414 # 0
1515 {'\t': 0, '\n': 15, '\x0c': 0,
16 '\r': 16, ' ': 0, '!': 11, '"': 18,
17 '#': 20, '%': 14, '&': 14, "'": 17,
18 '(': 15, ')': 15, '*': 8, '+': 14,
19 ',': 15, '-': 12, '.': 7, '/': 13,
20 '0': 5, '1': 6, '2': 6, '3': 6,
21 '4': 6, '5': 6, '6': 6, '7': 6,
22 '8': 6, '9': 6, ':': 15, ';': 15,
23 '<': 10, '=': 14, '>': 9, '@': 14,
24 'A': 1, 'B': 2, 'C': 1, 'D': 1,
25 'E': 1, 'F': 2, 'G': 1, 'H': 1,
26 'I': 1, 'J': 1, 'K': 1, 'L': 1,
27 'M': 1, 'N': 1, 'O': 1, 'P': 1,
28 'Q': 1, 'R': 3, 'S': 1, 'T': 1,
29 'U': 4, 'V': 1, 'W': 1, 'X': 1,
30 'Y': 1, 'Z': 1, '[': 15, '\\': 19,
31 ']': 15, '^': 14, '_': 1, '`': 15,
32 'a': 1, 'b': 2, 'c': 1, 'd': 1,
33 'e': 1, 'f': 2, 'g': 1, 'h': 1,
34 'i': 1, 'j': 1, 'k': 1, 'l': 1,
35 'm': 1, 'n': 1, 'o': 1, 'p': 1,
36 'q': 1, 'r': 3, 's': 1, 't': 1,
37 'u': 4, 'v': 1, 'w': 1, 'x': 1,
38 'y': 1, 'z': 1, '{': 15, '|': 14,
39 '}': 15, '~': 15, '\x80': 1},
16 '\r': 16, ' ': 0, '!': 11, '"': 19,
17 '#': 21, '$': 17, '%': 14, '&': 14,
18 "'": 18, '(': 15, ')': 15, '*': 8,
19 '+': 14, ',': 15, '-': 12, '.': 7,
20 '/': 13, '0': 5, '1': 6, '2': 6,
21 '3': 6, '4': 6, '5': 6, '6': 6,
22 '7': 6, '8': 6, '9': 6, ':': 15,
23 ';': 15, '<': 10, '=': 14, '>': 9,
24 '@': 14, 'A': 1, 'B': 2, 'C': 1,
25 'D': 1, 'E': 1, 'F': 2, 'G': 1,
26 'H': 1, 'I': 1, 'J': 1, 'K': 1,
27 'L': 1, 'M': 1, 'N': 1, 'O': 1,
28 'P': 1, 'Q': 1, 'R': 3, 'S': 1,
29 'T': 1, 'U': 4, 'V': 1, 'W': 1,
30 'X': 1, 'Y': 1, 'Z': 1, '[': 15,
31 '\\': 20, ']': 15, '^': 14, '_': 1,
32 '`': 15, 'a': 1, 'b': 2, 'c': 1,
33 'd': 1, 'e': 1, 'f': 2, 'g': 1,
34 'h': 1, 'i': 1, 'j': 1, 'k': 1,
35 'l': 1, 'm': 1, 'n': 1, 'o': 1,
36 'p': 1, 'q': 1, 'r': 3, 's': 1,
37 't': 1, 'u': 4, 'v': 1, 'w': 1,
38 'x': 1, 'y': 1, 'z': 1, '{': 15,
39 '|': 14, '}': 15, '~': 15,
40 '\x80': 1},
4041 # 1
4142 {'0': 1, '1': 1, '2': 1, '3': 1,
4243 '4': 1, '5': 1, '6': 1, '7': 1,
5556 't': 1, 'u': 1, 'v': 1, 'w': 1,
5657 'x': 1, 'y': 1, 'z': 1, '\x80': 1},
5758 # 2
58 {'"': 18, "'": 17, '0': 1, '1': 1,
59 {'"': 19, "'": 18, '0': 1, '1': 1,
5960 '2': 1, '3': 1, '4': 1, '5': 1,
6061 '6': 1, '7': 1, '8': 1, '9': 1,
6162 'A': 1, 'B': 1, 'C': 1, 'D': 1,
7374 'v': 1, 'w': 1, 'x': 1, 'y': 1,
7475 'z': 1, '\x80': 1},
7576 # 3
76 {'"': 18, "'": 17, '0': 1, '1': 1,
77 {'"': 19, "'": 18, '0': 1, '1': 1,
7778 '2': 1, '3': 1, '4': 1, '5': 1,
7879 '6': 1, '7': 1, '8': 1, '9': 1,
7980 'A': 1, 'B': 4, 'C': 1, 'D': 1,
9192 'v': 1, 'w': 1, 'x': 1, 'y': 1,
9293 'z': 1, '\x80': 1},
9394 # 4
94 {'"': 18, "'": 17, '0': 1, '1': 1,
95 {'"': 19, "'": 18, '0': 1, '1': 1,
9596 '2': 1, '3': 1, '4': 1, '5': 1,
9697 '6': 1, '7': 1, '8': 1, '9': 1,
9798 'A': 1, 'B': 1, 'C': 1, 'D': 1,
109110 'v': 1, 'w': 1, 'x': 1, 'y': 1,
110111 'z': 1, '\x80': 1},
111112 # 5
112 {'.': 26, '0': 24, '1': 25, '2': 25,
113 '3': 25, '4': 25, '5': 25, '6': 25,
114 '7': 25, '8': 25, '9': 25, 'B': 23,
115 'E': 27, 'J': 15, 'O': 22, 'X': 21,
116 'b': 23, 'e': 27, 'j': 15, 'o': 22,
117 'x': 21},
113 {'.': 27, '0': 25, '1': 26, '2': 26,
114 '3': 26, '4': 26, '5': 26, '6': 26,
115 '7': 26, '8': 26, '9': 26, 'B': 24,
116 'E': 28, 'J': 15, 'O': 23, 'X': 22,
117 'b': 24, 'e': 28, 'j': 15, 'o': 23,
118 'x': 22},
118119 # 6
119 {'.': 26, '0': 6, '1': 6, '2': 6,
120 {'.': 27, '0': 6, '1': 6, '2': 6,
120121 '3': 6, '4': 6, '5': 6, '6': 6,
121 '7': 6, '8': 6, '9': 6, 'E': 27,
122 'J': 15, 'e': 27, 'j': 15},
122 '7': 6, '8': 6, '9': 6, 'E': 28,
123 'J': 15, 'e': 28, 'j': 15},
123124 # 7
124 {'.': 29, '0': 28, '1': 28, '2': 28,
125 '3': 28, '4': 28, '5': 28, '6': 28,
126 '7': 28, '8': 28, '9': 28},
125 {'.': 30, '0': 29, '1': 29, '2': 29,
126 '3': 29, '4': 29, '5': 29, '6': 29,
127 '7': 29, '8': 29, '9': 29},
127128 # 8
128129 {'*': 14, '=': 15},
129130 # 9
143144 # 16
144145 {'\n': 15},
145146 # 17
146 {automata.DEFAULT: 33, '\n': 30,
147 '\r': 30, "'": 31, '\\': 32},
147 {'0': 31, '1': 31, '2': 31, '3': 31,
148 '4': 31, '5': 31, '6': 31, '7': 31,
149 '8': 31, '9': 31},
148150 # 18
149 {automata.DEFAULT: 36, '\n': 30,
150 '\r': 30, '"': 34, '\\': 35},
151 {automata.DEFAULT: 35, '\n': 32,
152 '\r': 32, "'": 33, '\\': 34},
151153 # 19
154 {automata.DEFAULT: 38, '\n': 32,
155 '\r': 32, '"': 36, '\\': 37},
156 # 20
152157 {'\n': 15, '\r': 16},
153 # 20
154 {automata.DEFAULT: 20, '\n': 30, '\r': 30},
155158 # 21
156 {'0': 37, '1': 37, '2': 37, '3': 37,
157 '4': 37, '5': 37, '6': 37, '7': 37,
158 '8': 37, '9': 37, 'A': 37, 'B': 37,
159 'C': 37, 'D': 37, 'E': 37, 'F': 37,
160 'a': 37, 'b': 37, 'c': 37, 'd': 37,
161 'e': 37, 'f': 37},
159 {automata.DEFAULT: 21, '\n': 32, '\r': 32},
162160 # 22
163 {'0': 38, '1': 38, '2': 38, '3': 38,
164 '4': 38, '5': 38, '6': 38, '7': 38},
161 {'0': 39, '1': 39, '2': 39, '3': 39,
162 '4': 39, '5': 39, '6': 39, '7': 39,
163 '8': 39, '9': 39, 'A': 39, 'B': 39,
164 'C': 39, 'D': 39, 'E': 39, 'F': 39,
165 'a': 39, 'b': 39, 'c': 39, 'd': 39,
166 'e': 39, 'f': 39},
165167 # 23
166 {'0': 39, '1': 39},
168 {'0': 40, '1': 40, '2': 40, '3': 40,
169 '4': 40, '5': 40, '6': 40, '7': 40},
167170 # 24
168 {'.': 26, '0': 24, '1': 25, '2': 25,
169 '3': 25, '4': 25, '5': 25, '6': 25,
170 '7': 25, '8': 25, '9': 25, 'E': 27,
171 'J': 15, 'e': 27, 'j': 15},
171 {'0': 41, '1': 41},
172172 # 25
173 {'.': 26, '0': 25, '1': 25, '2': 25,
174 '3': 25, '4': 25, '5': 25, '6': 25,
175 '7': 25, '8': 25, '9': 25, 'E': 27,
176 'J': 15, 'e': 27, 'j': 15},
173 {'.': 27, '0': 25, '1': 26, '2': 26,
174 '3': 26, '4': 26, '5': 26, '6': 26,
175 '7': 26, '8': 26, '9': 26, 'E': 28,
176 'J': 15, 'e': 28, 'j': 15},
177177 # 26
178 {'0': 26, '1': 26, '2': 26, '3': 26,
179 '4': 26, '5': 26, '6': 26, '7': 26,
180 '8': 26, '9': 26, 'E': 40, 'J': 15,
181 'e': 40, 'j': 15},
178 {'.': 27, '0': 26, '1': 26, '2': 26,
179 '3': 26, '4': 26, '5': 26, '6': 26,
180 '7': 26, '8': 26, '9': 26, 'E': 28,
181 'J': 15, 'e': 28, 'j': 15},
182182 # 27
183 {'+': 41, '-': 41, '0': 42, '1': 42,
184 '2': 42, '3': 42, '4': 42, '5': 42,
185 '6': 42, '7': 42, '8': 42, '9': 42},
183 {'0': 27, '1': 27, '2': 27, '3': 27,
184 '4': 27, '5': 27, '6': 27, '7': 27,
185 '8': 27, '9': 27, 'E': 42, 'J': 15,
186 'e': 42, 'j': 15},
186187 # 28
187 {'0': 28, '1': 28, '2': 28, '3': 28,
188 '4': 28, '5': 28, '6': 28, '7': 28,
189 '8': 28, '9': 28, 'E': 40, 'J': 15,
190 'e': 40, 'j': 15},
188 {'+': 43, '-': 43, '0': 44, '1': 44,
189 '2': 44, '3': 44, '4': 44, '5': 44,
190 '6': 44, '7': 44, '8': 44, '9': 44},
191191 # 29
192 {'0': 29, '1': 29, '2': 29, '3': 29,
193 '4': 29, '5': 29, '6': 29, '7': 29,
194 '8': 29, '9': 29, 'E': 42, 'J': 15,
195 'e': 42, 'j': 15},
196 # 30
192197 {'.': 15},
193 # 30
198 # 31
199 {'0': 31, '1': 31, '2': 31, '3': 31,
200 '4': 31, '5': 31, '6': 31, '7': 31,
201 '8': 31, '9': 31},
202 # 32
194203 {},
195 # 31
204 # 33
196205 {"'": 15},
197 # 32
198 {automata.DEFAULT: 43, '\n': 15, '\r': 16},
199 # 33
200 {automata.DEFAULT: 33, '\n': 30,
201 '\r': 30, "'": 15, '\\': 32},
202206 # 34
207 {automata.DEFAULT: 45, '\n': 15, '\r': 16},
208 # 35
209 {automata.DEFAULT: 35, '\n': 32,
210 '\r': 32, "'": 15, '\\': 34},
211 # 36
203212 {'"': 15},
204 # 35
205 {automata.DEFAULT: 44, '\n': 15, '\r': 16},
206 # 36
207 {automata.DEFAULT: 36, '\n': 30,
208 '\r': 30, '"': 15, '\\': 35},
209213 # 37
210 {'0': 37, '1': 37, '2': 37, '3': 37,
211 '4': 37, '5': 37, '6': 37, '7': 37,
212 '8': 37, '9': 37, 'A': 37, 'B': 37,
213 'C': 37, 'D': 37, 'E': 37, 'F': 37,
214 'a': 37, 'b': 37, 'c': 37, 'd': 37,
215 'e': 37, 'f': 37},
214 {automata.DEFAULT: 46, '\n': 15, '\r': 16},
216215 # 38
217 {'0': 38, '1': 38, '2': 38, '3': 38,
218 '4': 38, '5': 38, '6': 38, '7': 38},
216 {automata.DEFAULT: 38, '\n': 32,
217 '\r': 32, '"': 15, '\\': 37},
219218 # 39
220 {'0': 39, '1': 39},
219 {'0': 39, '1': 39, '2': 39, '3': 39,
220 '4': 39, '5': 39, '6': 39, '7': 39,
221 '8': 39, '9': 39, 'A': 39, 'B': 39,
222 'C': 39, 'D': 39, 'E': 39, 'F': 39,
223 'a': 39, 'b': 39, 'c': 39, 'd': 39,
224 'e': 39, 'f': 39},
221225 # 40
222 {'+': 45, '-': 45, '0': 46, '1': 46,
223 '2': 46, '3': 46, '4': 46, '5': 46,
224 '6': 46, '7': 46, '8': 46, '9': 46},
226 {'0': 40, '1': 40, '2': 40, '3': 40,
227 '4': 40, '5': 40, '6': 40, '7': 40},
225228 # 41
226 {'0': 42, '1': 42, '2': 42, '3': 42,
227 '4': 42, '5': 42, '6': 42, '7': 42,
228 '8': 42, '9': 42},
229 {'0': 41, '1': 41},
229230 # 42
230 {'0': 42, '1': 42, '2': 42, '3': 42,
231 '4': 42, '5': 42, '6': 42, '7': 42,
232 '8': 42, '9': 42, 'J': 15, 'j': 15},
231 {'+': 47, '-': 47, '0': 48, '1': 48,
232 '2': 48, '3': 48, '4': 48, '5': 48,
233 '6': 48, '7': 48, '8': 48, '9': 48},
233234 # 43
234 {automata.DEFAULT: 43, '\n': 30,
235 '\r': 30, "'": 15, '\\': 32},
235 {'0': 44, '1': 44, '2': 44, '3': 44,
236 '4': 44, '5': 44, '6': 44, '7': 44,
237 '8': 44, '9': 44},
236238 # 44
237 {automata.DEFAULT: 44, '\n': 30,
238 '\r': 30, '"': 15, '\\': 35},
239 {'0': 44, '1': 44, '2': 44, '3': 44,
240 '4': 44, '5': 44, '6': 44, '7': 44,
241 '8': 44, '9': 44, 'J': 15, 'j': 15},
239242 # 45
240 {'0': 46, '1': 46, '2': 46, '3': 46,
241 '4': 46, '5': 46, '6': 46, '7': 46,
242 '8': 46, '9': 46},
243 {automata.DEFAULT: 45, '\n': 32,
244 '\r': 32, "'": 15, '\\': 34},
243245 # 46
244 {'0': 46, '1': 46, '2': 46, '3': 46,
245 '4': 46, '5': 46, '6': 46, '7': 46,
246 '8': 46, '9': 46, 'J': 15, 'j': 15},
246 {automata.DEFAULT: 46, '\n': 32,
247 '\r': 32, '"': 15, '\\': 37},
248 # 47
249 {'0': 48, '1': 48, '2': 48, '3': 48,
250 '4': 48, '5': 48, '6': 48, '7': 48,
251 '8': 48, '9': 48},
252 # 48
253 {'0': 48, '1': 48, '2': 48, '3': 48,
254 '4': 48, '5': 48, '6': 48, '7': 48,
255 '8': 48, '9': 48, 'J': 15, 'j': 15},
247256 ]
248257 pseudoDFA = automata.DFA(states, accepts)
249258
4444 self.tok = self.tokens[index]
4545
4646 def skip(self, n):
47 if self.tok[0] == n:
47 if self.tok.token_type == n:
4848 self.next()
4949 return True
5050 else:
5252
5353 def skip_name(self, name):
5454 from pypy.interpreter.pyparser import pygram
55 if self.tok[0] == pygram.tokens.NAME and self.tok[1] == name:
55 if self.tok.token_type == pygram.tokens.NAME and self.tok.value == name:
5656 self.next()
5757 return True
5858 else:
6060
6161 def next_feature_name(self):
6262 from pypy.interpreter.pyparser import pygram
63 if self.tok[0] == pygram.tokens.NAME:
64 name = self.tok[1]
63 if self.tok.token_type == pygram.tokens.NAME:
64 name = self.tok.value
6565 self.next()
6666 if self.skip_name("as"):
6767 self.skip(pygram.tokens.NAME)
9898 # somewhere inside the last __future__ import statement
9999 # (at the start would be fine too, but it's easier to grab a
100100 # random position inside)
101 last_position = (it.tok[2], it.tok[3])
101 last_position = (it.tok.lineno, it.tok.column)
102102 result |= future_flags.get_compiler_feature(it.next_feature_name())
103103 while it.skip(pygram.tokens.COMMA):
104104 result |= future_flags.get_compiler_feature(it.next_feature_name())
145145 makeEOL(),
146146 chainStr(states, "..."),
147147 groupStr(states, "@:;.,`"))
148 funny = group(states, operator, bracket, special)
148 revdb_metavar = chain(states,
149 groupStr(states, "$"),
150 atleastonce(states, makeDigits()))
151 funny = group(states, operator, bracket, special, revdb_metavar)
149152 # ____________________________________________________________
150153 def makeStrPrefix ():
151154 return group(states,
2727 new.symbol_ids = self.symbol_ids
2828 new.symbols_names = self.symbol_names
2929 new.keyword_ids = self.keyword_ids
30 new.token_to_error_string = self.token_to_error_string
3031 new.dfas = self.dfas
3132 new.labels = self.labels
3233 new.token_ids = self.token_ids
3334 return new
35
36
37 def classify(self, token):
38 """Find the label for a token."""
39 if token.token_type == self.KEYWORD_TOKEN:
40 label_index = self.keyword_ids.get(token.value, -1)
41 if label_index != -1:
42 return label_index
43 label_index = self.token_ids.get(token.token_type, -1)
44 if label_index == -1:
45 raise ParseError("invalid token", token)
46 return label_index
3447
3548 def _freeze_(self):
3649 # Remove some attributes not used in parsing.
6477 b[pos] |= bit
6578 return str(b)
6679
80
81 class Token(object):
82 def __init__(self, token_type, value, lineno, column, line):
83 self.token_type = token_type
84 self.value = value
85 self.lineno = lineno
86 # 0-based offset
87 self.column = column
88 self.line = line
89
90 def __repr__(self):
91 return "Token(%s, %s)" % (self.token_type, self.value)
92
93 def __eq__(self, other):
94 # for tests
95 return (
96 self.token_type == other.token_type and
97 self.value == other.value and
98 self.lineno == other.lineno and
99 self.column == other.column and
100 self.line == other.line
101 )
102
103 def __ne__(self, other):
104 return not self == other
105
106
67107 class Node(object):
68108
69109 __slots__ = ("type", )
103143 self.value = value
104144 self.lineno = lineno
105145 self.column = column
146
147 @staticmethod
148 def fromtoken(token):
149 return Terminal(
150 token.token_type, token.value, token.lineno, token.column)
106151
107152 def __repr__(self):
108153 return "Terminal(type=%s, value=%r)" % (self.type, self.value)
192237
193238 class ParseError(Exception):
194239
195 def __init__(self, msg, token_type, value, lineno, column, line,
196 expected=-1, expected_str=None):
240 def __init__(self, msg, token, expected=-1, expected_str=None):
197241 self.msg = msg
198 self.token_type = token_type
199 self.value = value
200 self.lineno = lineno
201 # this is a 0-based index
202 self.column = column
203 self.line = line
242 self.token = token
204243 self.expected = expected
205244 self.expected_str = expected_str
206245
207246 def __str__(self):
208 return "ParserError(%s, %r)" % (self.token_type, self.value)
247 return "ParserError(%s)" % (self.token, )
209248
210249
211250 class StackEntry(object):
248287 self.root = None
249288 self.stack = StackEntry(None, self.grammar.dfas[start - 256], 0)
250289
251 def add_token(self, token_type, value, lineno, column, line):
252 label_index = self.classify(token_type, value, lineno, column, line)
290 def add_token(self, token):
291 label_index = self.grammar.classify(token)
253292 sym_id = 0 # for the annotator
254293 while True:
255294 dfa = self.stack.dfa
260299 sym_id = self.grammar.labels[i]
261300 if label_index == i:
262301 # We matched a non-terminal.
263 self.shift(next_state, token_type, value, lineno, column)
302 self.shift(next_state, token)
264303 state = states[next_state]
265304 # While the only possible action is to accept, pop nodes off
266305 # the stack.
277316 sub_node_dfa = self.grammar.dfas[sym_id - 256]
278317 # Check if this token can start a child node.
279318 if sub_node_dfa.could_match_token(label_index):
280 self.push(sub_node_dfa, next_state, sym_id, lineno,
281 column)
319 self.push(sub_node_dfa, next_state, sym_id)
282320 break
283321 else:
284322 # We failed to find any arcs to another state, so unless this
286324 if is_accepting:
287325 self.pop()
288326 if self.stack is None:
289 raise ParseError("too much input", token_type, value,
290 lineno, column, line)
327 raise ParseError("too much input", token)
291328 else:
292329 # If only one possible input would satisfy, attach it to the
293330 # error.
298335 else:
299336 expected = -1
300337 expected_str = None
301 raise ParseError("bad input", token_type, value, lineno,
302 column, line, expected, expected_str)
303
304 def classify(self, token_type, value, lineno, column, line):
305 """Find the label for a token."""
306 if token_type == self.grammar.KEYWORD_TOKEN:
307 label_index = self.grammar.keyword_ids.get(value, -1)
308 if label_index != -1:
309 return label_index
310 label_index = self.grammar.token_ids.get(token_type, -1)
311 if label_index == -1:
312 raise ParseError("invalid token", token_type, value, lineno, column,
313 line)
314 return label_index
315
316 def shift(self, next_state, token_type, value, lineno, column):
338 raise ParseError("bad input", token, expected, expected_str)
339
340
341 def shift(self, next_state, token):
317342 """Shift a non-terminal and prepare for the next state."""
318 new_node = Terminal(token_type, value, lineno, column)
343 new_node = Terminal.fromtoken(token)
319344 self.stack.node_append_child(new_node)
320345 self.stack.state = next_state
321346
322 def push(self, next_dfa, next_state, node_type, lineno, column):
347 def push(self, next_dfa, next_state, node_type):
323348 """Push a terminal and adjust the current state."""
324349 self.stack.state = next_state
325350 self.stack = self.stack.push(next_dfa, 0)
1919
2020 python_grammar = _get_python_grammar()
2121
22 python_grammar_revdb = python_grammar.shared_copy()
23 copied_token_ids = python_grammar.token_ids.copy()
24 python_grammar_revdb.token_ids = copied_token_ids
25
26 metavar_token_id = pytoken.python_tokens['REVDBMETAVAR']
27 del python_grammar.token_ids[metavar_token_id]
28
2229 class _Tokens(object):
2330 pass
2431 for tok_name, idx in pytoken.python_tokens.iteritems():
3542 syms._rev_lookup = rev_lookup # for debugging
3643
3744 del _get_python_grammar, _Tokens, tok_name, sym_name, idx
45
46 def choose_grammar(print_function, revdb):
47 assert print_function
48 if revdb:
49 return python_grammar_revdb
50 else:
51 return python_grammar
52
162162 flags &= ~consts.PyCF_DONT_IMPLY_DEDENT
163163
164164 self.prepare(_targets[compile_info.mode])
165 tp = 0
166165 try:
167 last_value_seen = None
168 next_value_seen = None
166 last_token_seen = None
167 next_token_seen = None
169168 try:
170169 # Note: we no longer pass the CO_FUTURE_* to the tokenizer,
171170 # which is expected to work independently of them. It's
172171 # certainly the case for all futures in Python <= 2.7.
173172 tokens = pytokenizer.generate_tokens(source_lines, flags)
174
175 newflags, last_future_import = (
176 future.add_future_flags(self.future_flags, tokens))
177 compile_info.last_future_import = last_future_import
178 compile_info.flags |= newflags
179 self.grammar = pygram.python_grammar
173 except error.TokenError as e:
174 e.filename = compile_info.filename
175 raise
176 except error.TokenIndentationError as e:
177 e.filename = compile_info.filename
178 raise
179
180 newflags, last_future_import = (
181 future.add_future_flags(self.future_flags, tokens))
182 compile_info.last_future_import = last_future_import
183 compile_info.flags |= newflags
184
185 self.grammar = pygram.choose_grammar(
186 print_function=True,
187 revdb=self.space.config.translation.reverse_debugger)
188 try:
180189 tokens_stream = iter(tokens)
181190
182 for tp, value, lineno, column, line in tokens_stream:
183 next_value_seen = value
184 if self.add_token(tp, value, lineno, column, line):
191 for token in tokens_stream:
192 next_token_seen = token
193 if self.add_token(token):
185194 break
186 last_value_seen = value
187 last_value_seen = None
188 next_value_seen = None
195 last_token_seen = token
196 last_token_seen = None
197 next_token_seen = None
189198
190199 if compile_info.mode == 'single':
191 for tp, value, lineno, column, line in tokens_stream:
192 if tp == pygram.tokens.ENDMARKER:
200 for token in tokens_stream:
201 if token.token_type == pygram.tokens.ENDMARKER:
193202 break
194 if tp == pygram.tokens.NEWLINE:
203 if token.token_type == pygram.tokens.NEWLINE:
195204 continue
196205
197 if tp == pygram.tokens.COMMENT:
198 for tp, _, _, _, _ in tokens_stream:
199 if tp == pygram.tokens.NEWLINE:
206 if token.token_type == pygram.tokens.COMMENT:
207 for token in tokens_stream:
208 if token.token_type == pygram.tokens.NEWLINE:
200209 break
201210 else:
202211 new_err = error.SyntaxError
203212 msg = ("multiple statements found while "
204213 "compiling a single statement")
205 raise new_err(msg, lineno, column,
206 line, compile_info.filename)
214 raise new_err(msg, token.lineno, token.column,
215 token.line, compile_info.filename)
207216
208217 except error.TokenError as e:
209218 e.filename = compile_info.filename
215224 # Catch parse errors, pretty them up and reraise them as a
216225 # SyntaxError.
217226 new_err = error.IndentationError
218 if tp == pygram.tokens.INDENT:
227 if token.token_type == pygram.tokens.INDENT:
219228 msg = "unexpected indent"
220229 elif e.expected == pygram.tokens.INDENT:
221230 msg = "expected an indented block"
222231 else:
223232 new_err = error.SyntaxError
224 if (last_value_seen in ('print', 'exec') and
225 bool(next_value_seen) and
226 next_value_seen != '('):
233 if (last_token_seen is not None and
234 last_token_seen.value in ('print', 'exec') and
235 next_token_seen is not None and
236 next_token_seen.value != '('):
227237 msg = "Missing parentheses in call to '%s'" % (
228 last_value_seen,)
238 last_token_seen.value,)
229239 else:
230240 msg = "invalid syntax"
231241 if e.expected_str is not None:
233243
234244 # parser.ParseError(...).column is 0-based, but the offsets in the
235245 # exceptions in the error module are 1-based, hence the '+ 1'
236 raise new_err(msg, e.lineno, e.column + 1, e.line,
246 raise new_err(msg, e.token.lineno, e.token.column + 1, e.token.line,
237247 compile_info.filename)
238248 else:
239249 tree = self.root
7171 # extra PyPy-specific tokens
7272 _add_tok("COMMENT")
7373 _add_tok("NL")
74 _add_tok("REVDBMETAVAR", "$NUM")
7475
7576 del _add_tok
00 # ______________________________________________________________________
11 """Module pytokenize
2
3 THIS FILE WAS COPIED FROM pypy/module/parser/pytokenize.py AND ADAPTED
4 TO BE ANNOTABLE (Mainly made lists homogeneous)
52
63 This is a modified version of Ka-Ping Yee's tokenize module found in the
74 Python standard library.
118 expressions have been replaced with hand built DFA's using the
129 basil.util.automata module.
1310
14 $Id: pytokenize.py,v 1.3 2003/10/03 16:31:53 jriehl Exp $
1511 """
1612 # ______________________________________________________________________
1713
8682
8783 tabsize = 8
8884 alttabsize = 1
89
90 # PYPY MODIFICATION: removed TokenError class as it's not needed here
91
92 # PYPY MODIFICATION: removed StopTokenizing class as it's not needed here
93
94 # PYPY MODIFICATION: removed printtoken() as it's not needed here
95
96 # PYPY MODIFICATION: removed tokenize() as it's not needed here
97
98 # PYPY MODIFICATION: removed tokenize_loop() as it's not needed here
99
100 # PYPY MODIFICATION: removed generate_tokens() as it was copied / modified
101 # in pythonlexer.py
102
103 # PYPY MODIFICATION: removed main() as it's not needed here
104
105 # ______________________________________________________________________
106 # End of pytokenize.py
107
00 from pypy.interpreter.pyparser import automata
1 from pypy.interpreter.pyparser.parser import Token
12 from pypy.interpreter.pyparser.pygram import tokens
23 from pypy.interpreter.pyparser.pytoken import python_opmap
34 from pypy.interpreter.pyparser.error import TokenError, TokenIndentationError, TabError
143144 endmatch = endDFA.recognize(line)
144145 if endmatch >= 0:
145146 pos = end = endmatch
146 tok = (tokens.STRING, contstr + line[:end], strstart[0],
147 tok = Token(tokens.STRING, contstr + line[:end], strstart[0],
147148 strstart[1], line)
148149 token_list.append(tok)
149150 last_comment = ''
151152 contline = None
152153 elif (needcont and not line.endswith('\\\n') and
153154 not line.endswith('\\\r\n')):
154 tok = (tokens.ERRORTOKEN, contstr + line, strstart[0],
155 tok = Token(tokens.ERRORTOKEN, contstr + line, strstart[0],
155156 strstart[1], line)
156157 token_list.append(tok)
157158 last_comment = ''
199200 raise TabError(lnum, pos, line)
200201 indents.append(column)
201202 altindents.append(altcolumn)
202 token_list.append((tokens.INDENT, line[:pos], lnum, 0, line))
203 token_list.append(Token(tokens.INDENT, line[:pos], lnum, 0, line))
203204 last_comment = ''
204205 else:
205206 while column < indents[-1]:
206207 indents.pop()
207208 altindents.pop()
208 token_list.append((tokens.DEDENT, '', lnum, pos, line))
209 token_list.append(Token(tokens.DEDENT, '', lnum, pos, line))
209210 last_comment = ''
210211 if column != indents[-1]:
211212 err = "unindent does not match any outer indentation level"
245246 if (initial in numchars or \
246247 (initial == '.' and token != '.' and token != '...')):
247248 # ordinary number
248 token_list.append((tokens.NUMBER, token, lnum, start, line))
249 token_list.append(Token(tokens.NUMBER, token, lnum, start, line))
249250 last_comment = ''
250251 elif initial in '\r\n':
251252 if not parenstack:
252253 if async_def:
253254 async_def_nl = True
254 tok = (tokens.NEWLINE, last_comment, lnum, start, line)
255 tok = Token(tokens.NEWLINE, last_comment, lnum, start, line)
255256 token_list.append(tok)
256257 last_comment = ''
257258 elif initial == '#':
266267 if endmatch >= 0: # all on one line
267268 pos = endmatch
268269 token = line[start:pos]
269 tok = (tokens.STRING, token, lnum, start, line)
270 tok = Token(tokens.STRING, token, lnum, start, line)
270271 token_list.append(tok)
271272 last_comment = ''
272273 else:
285286 contline = line
286287 break
287288 else: # ordinary string
288 tok = (tokens.STRING, token, lnum, start, line)
289 tok = Token(tokens.STRING, token, lnum, start, line)
289290 token_list.append(tok)
290291 last_comment = ''
291292 elif (initial in namechars or # ordinary name
302303
303304 if async_def: # inside 'async def' function
304305 if token == 'async':
305 token_list.append((tokens.ASYNC, token, lnum, start, line))
306 token_list.append(Token(tokens.ASYNC, token, lnum, start, line))
306307 elif token == 'await':
307 token_list.append((tokens.AWAIT, token, lnum, start, line))
308 token_list.append(Token(tokens.AWAIT, token, lnum, start, line))
308309 else:
309 token_list.append((tokens.NAME, token, lnum, start, line))
310 token_list.append(Token(tokens.NAME, token, lnum, start, line))
310311 elif token == 'async': # async token, look ahead
311312 #ahead token
312313 if pos < max:
318319 if ahead_token == 'def':
319320 async_def = True
320321 async_def_indent = indents[-1]
321 token_list.append((tokens.ASYNC, token, lnum, start, line))
322 token_list.append(Token(tokens.ASYNC, token, lnum, start, line))
322323 else:
323 token_list.append((tokens.NAME, token, lnum, start, line))
324 token_list.append(Token(tokens.NAME, token, lnum, start, line))
324325 else:
325 token_list.append((tokens.NAME, token, lnum, start, line))
326 token_list.append(Token(tokens.NAME, token, lnum, start, line))
326327 else:
327 token_list.append((tokens.NAME, token, lnum, start, line))
328 token_list.append(Token(tokens.NAME, token, lnum, start, line))
328329 last_comment = ''
329330 elif initial == '\\': # continued stmt
330331 continued = 1
332 elif initial == '$':
333 token_list.append(Token(tokens.REVDBMETAVAR, token,
334 lnum, start, line))
335 last_comment = ''
331336 else:
332337 if initial in '([{':
333338 parenstack.append((initial, lnum, start, line))
350355 punct = python_opmap[token]
351356 else:
352357 punct = tokens.OP
353 token_list.append((punct, token, lnum, start, line))
358 token_list.append(Token(punct, token, lnum, start, line))
354359 last_comment = ''
355360 else:
356361 start = whiteSpaceDFA.recognize(line, pos)
359364 if start<max and line[start] in single_quoted:
360365 raise TokenError("end of line (EOL) while scanning string literal",
361366 line, lnum, start+1, token_list)
362 tok = (tokens.ERRORTOKEN, line[pos], lnum, pos, line)
367 tok = Token(tokens.ERRORTOKEN, line[pos], lnum, pos, line)
363368 token_list.append(tok)
364369 last_comment = ''
365370 pos = pos + 1
366371
367372 lnum -= 1
368373 if not (flags & consts.PyCF_DONT_IMPLY_DEDENT):
369 if token_list and token_list[-1][0] != tokens.NEWLINE:
370 tok = (tokens.NEWLINE, '', lnum, 0, '\n')
374 if token_list and token_list[-1].token_type != tokens.NEWLINE:
375 tok = Token(tokens.NEWLINE, '', lnum, 0, '\n')
371376 token_list.append(tok)
372377 for indent in indents[1:]: # pop remaining indent levels
373 token_list.append((tokens.DEDENT, '', lnum, pos, line))
374 tok = (tokens.NEWLINE, '', lnum, 0, '\n')
378 token_list.append(Token(tokens.DEDENT, '', lnum, pos, line))
379 tok = Token(tokens.NEWLINE, '', lnum, 0, '\n')
375380 token_list.append(tok)
376381
377 token_list.append((tokens.ENDMARKER, '', lnum, pos, line))
382 token_list.append(Token(tokens.ENDMARKER, '', lnum, pos, line))
378383 return token_list
379384
380385
0 from pypy.interpreter.pyparser.automata import DFA, DEFAULT
0 # coding: utf-8
1 import pytest
2
3 from pypy.interpreter.pyparser.automata import DFA, NonGreedyDFA, DEFAULT, NON_ASCII
14
25 def test_states():
36 d = DFA([{"\x00": 1}, {"\x01": 0}], [False, True])
912 assert d.states == "\x01\x00"
1013 assert d.defaults == "\xff\x00"
1114 assert d.max_char == 1
15
16 def test_recognize():
17 d = DFA([{"a": 1}, {"b": 0}], [False, True])
18 assert d.recognize("ababab") == 5
19 assert d.recognize("c") == -1
20
21 d = DFA([{"a": 1}, {DEFAULT: 0}], [False, True])
22 assert d.recognize("a,a?ab") == 5
23 assert d.recognize("c") == -1
24
25 d = NonGreedyDFA([{"a": 1}, {"b": 0}], [False, True])
26 assert d.recognize("ababab") == 1
27 assert d.recognize("c") == -1
28
29 d = NonGreedyDFA([{"a": 1}, {DEFAULT: 0}], [False, True])
30 assert d.recognize("a,a?ab") == 1
31 assert d.recognize("c") == -1
32
33 def test_nonascii():
34 d = DFA([{"a": 1}, {NON_ASCII: 1}], [False, True])
35 input = u"aüüüü".encode("utf-8")
36 assert d.recognize(input) == len(input)
37 assert d.recognize("c") == -1
38 assert d.recognize("ü") == -1
39
40 d = NonGreedyDFA([{NON_ASCII: 0, "b": 1}, {"b": 0}], [False, True])
41 input = u"üübbbb".encode("utf-8")
42 assert d.recognize(input) == len(u"üüb".encode("utf-8"))
43 assert d.recognize("c") == -1
44
45 pytest.raises(ValueError, DFA, [{"\x81": 2}], [True])
46
1919 rl = StringIO.StringIO(input + "\n").readline
2020 gen = tokenize.generate_tokens(rl)
2121 for tp, value, begin, end, line in gen:
22 if self.add_token(tp, value, begin[0], begin[1], line):
22 if self.add_token(parser.Token(tp, value, begin[0], begin[1], line)):
2323 py.test.raises(StopIteration, gen.next)
2424 return self.root
2525
55 from pypy.interpreter.astcompiler import consts
66
77
8 class TestPythonParserWithoutSpace:
8 class TestPythonParser:
9 spaceconfig = {}
910
1011 def setup_class(self):
11 self.parser = pyparse.PythonParser(None)
12 self.parser = pyparse.PythonParser(self.space)
1213
1314 def parse(self, source, mode="exec", info=None):
1415 if info is None:
3435 info = pyparse.CompileInfo("<test>", "exec")
3536 tree = self.parse("""foo = '日本'""", info=info)
3637 assert info.encoding == 'utf-8'
38
39 def test_encoding(self):
40 info = pyparse.CompileInfo("<test>", "exec")
41 tree = self.parse("""# coding: latin-1
42 stuff = "nothing"
43 """, info=info)
44 assert tree.type == syms.file_input
45 assert info.encoding == "iso-8859-1"
46 sentence = u"u'Die Männer ärgern sich!'"
47 input = (u"# coding: utf-7\nstuff = %s" % (sentence,)).encode("utf-7")
48 tree = self.parse(input, info=info)
49 assert info.encoding == "utf-7"
50 input = "# coding: iso-8859-15\nx"
51 self.parse(input, info=info)
52 assert info.encoding == "iso-8859-15"
53 input = "\xEF\xBB\xBF# coding: utf-8\nx"
54 self.parse(input, info=info)
55 assert info.encoding == "utf-8"
56 input = "\xEF\xBB\xBF# coding: latin-1\nx"
57 exc = py.test.raises(SyntaxError, self.parse, input).value
58 assert exc.msg == "UTF-8 BOM with latin-1 coding cookie"
59 input = "# coding: not-here"
60 exc = py.test.raises(SyntaxError, self.parse, input).value
61 assert exc.msg == "Unknown encoding: not-here"
62 input = u"# coding: ascii\n\xe2".encode('utf-8')
63 exc = py.test.raises(SyntaxError, self.parse, input).value
64 assert exc.msg == ("'ascii' codec can't decode byte 0xc3 "
65 "in position 16: ordinal not in range(128)")
3766
3867 def test_unicode_identifier(self):
3968 tree = self.parse("a日本 = 32")
145174 for linefeed in ["\r\n","\r"]:
146175 tree = self.parse(fmt % linefeed)
147176 assert expected_tree == tree
177
178 def test_revdb_dollar_num(self):
179 assert not self.space.config.translation.reverse_debugger
180 py.test.raises(SyntaxError, self.parse, '$0')
181 py.test.raises(SyntaxError, self.parse, '$0 + 5')
182 py.test.raises(SyntaxError, self.parse,
183 "from __future__ import print_function\nx = ($0, print)")
148184
149185 def test_py3k_reject_old_binary_literal(self):
150186 py.test.raises(SyntaxError, self.parse, '0777')
254290 info = py.test.raises(SyntaxError, self.parse, "def f:\n print 1")
255291 assert "(expected '(')" in info.value.msg
256292
293 class TestPythonParserRevDB(TestPythonParser):
294 spaceconfig = {"translation.reverse_debugger": True}
295
296 def test_revdb_dollar_num(self):
297 self.parse('$0')
298 self.parse('$5')
299 self.parse('$42')
300 self.parse('2+$42.attrname')
301 self.parse("from __future__ import print_function\nx = ($0, print)")
302 py.test.raises(SyntaxError, self.parse, '$')
303 py.test.raises(SyntaxError, self.parse, '$a')
304 py.test.raises(SyntaxError, self.parse, '$.5')
305
306
00 import pytest
11 from pypy.interpreter.pyparser import pytokenizer
2 from pypy.interpreter.pyparser.parser import Token
23 from pypy.interpreter.pyparser.pygram import tokens
34 from pypy.interpreter.pyparser.error import TokenError
45
2122 line = "a+1"
2223 tks = tokenize(line)
2324 assert tks == [
24 (tokens.NAME, 'a', 1, 0, line),
25 (tokens.PLUS, '+', 1, 1, line),
26 (tokens.NUMBER, '1', 1, 2, line),
27 (tokens.NEWLINE, '', 2, 0, '\n'),
28 (tokens.NEWLINE, '', 2, 0, '\n'),
29 (tokens.ENDMARKER, '', 2, 0, ''),
25 Token(tokens.NAME, 'a', 1, 0, line),
26 Token(tokens.PLUS, '+', 1, 1, line),
27 Token(tokens.NUMBER, '1', 1, 2, line),
28 Token(tokens.NEWLINE, '', 2, 0, '\n'),
29 Token(tokens.NEWLINE, '', 2, 0, '\n'),
30 Token(tokens.ENDMARKER, '', 2, 0, ''),
3031 ]
3132
3233 def test_error_parenthesis(self):
0 import sys
1 from rpython.rlib import revdb
2 from rpython.rlib.debug import make_sure_not_resized
3 from rpython.rlib.objectmodel import specialize, we_are_translated
4 from rpython.rtyper.annlowlevel import cast_gcref_to_instance
5 from pypy.interpreter.error import OperationError, oefmt
6 from pypy.interpreter.baseobjspace import W_Root
7 from pypy.interpreter import gateway, typedef, pycode, pytraceback, pyframe
8 from pypy.module.marshal import interp_marshal
9 from pypy.interpreter.executioncontext import AbstractActionFlag, ActionFlag
10
11
12 class DBState:
13 standard_code = True
14 breakpoint_stack_id = 0
15 breakpoint_funcnames = None
16 breakpoint_filelines = None
17 breakpoint_by_file = None
18 breakpoint_version = 0
19 printed_objects = {}
20 metavars = []
21 watch_progs = []
22 watch_futures = {}
23
24 dbstate = DBState()
25
26
27 pycode.PyCode.co_revdb_linestarts = None # or a string: see below
28 pycode.PyCode.co_revdb_bkpt_version = 0 # see check_and_trigger_bkpt()
29 pycode.PyCode.co_revdb_bkpt_cache = None # see check_and_trigger_bkpt()
30
31 # invariant: "f_revdb_nextline_instr" is the bytecode offset of
32 # the start of the line that follows "last_instr".
33 pyframe.PyFrame.f_revdb_nextline_instr = -1
34
35
36 # ____________________________________________________________
37
38
39 def setup_revdb(space):
40 """Called at run-time, before the space is set up.
41
42 The various register_debug_command() lines attach functions
43 to some commands that 'revdb.py' can call, if we are running
44 in replay mode.
45 """
46 assert space.config.translation.reverse_debugger
47 dbstate.space = space
48
49 make_sure_not_resized(dbstate.watch_progs)
50 make_sure_not_resized(dbstate.metavars)
51
52 revdb.register_debug_command(revdb.CMD_PRINT, lambda_print)
53 revdb.register_debug_command(revdb.CMD_BACKTRACE, lambda_backtrace)
54 revdb.register_debug_command(revdb.CMD_LOCALS, lambda_locals)
55 revdb.register_debug_command(revdb.CMD_BREAKPOINTS, lambda_breakpoints)
56 revdb.register_debug_command(revdb.CMD_STACKID, lambda_stackid)
57 revdb.register_debug_command("ALLOCATING", lambda_allocating)
58 revdb.register_debug_command(revdb.CMD_ATTACHID, lambda_attachid)
59 revdb.register_debug_command(revdb.CMD_COMPILEWATCH, lambda_compilewatch)
60 revdb.register_debug_command(revdb.CMD_CHECKWATCH, lambda_checkwatch)
61 revdb.register_debug_command(revdb.CMD_WATCHVALUES, lambda_watchvalues)
62
63
64 # ____________________________________________________________
65
66
67 def enter_call(caller_frame, callee_frame):
68 if dbstate.breakpoint_funcnames is not None:
69 name = callee_frame.getcode().co_name
70 if name in dbstate.breakpoint_funcnames:
71 revdb.breakpoint(dbstate.breakpoint_funcnames[name])
72 if dbstate.breakpoint_stack_id != 0 and caller_frame is not None:
73 if dbstate.breakpoint_stack_id == revdb.get_unique_id(caller_frame):
74 revdb.breakpoint(-1)
75 #
76 code = callee_frame.pycode
77 if code.co_revdb_linestarts is None:
78 build_co_revdb_linestarts(code)
79
80 def leave_call(caller_frame, got_exception):
81 if dbstate.breakpoint_stack_id != 0 and caller_frame is not None:
82 if dbstate.breakpoint_stack_id == revdb.get_unique_id(caller_frame):
83 revdb.breakpoint(-2)
84 if we_are_translated():
85 stop_point_activate(-2 + got_exception)
86
87 def stop_point():
88 if we_are_translated():
89 revdb.breakpoint(-3)
90
91
92 def jump_backward(frame, jumpto):
93 # When we see a jump backward, we set 'f_revdb_nextline_instr' in
94 # such a way that the next instruction, at 'jumpto', will trigger
95 # stop_point_activate(). We have to trigger it even if
96 # 'jumpto' is not actually a start of line. For example, after a
97 # 'while foo:', the body ends with a JUMP_ABSOLUTE which
98 # jumps back to the *second* opcode of the while.
99 frame.f_revdb_nextline_instr = jumpto
100
101
102 def potential_stop_point(frame):
103 if not we_are_translated():
104 return
105 #
106 # We only record a stop_point at every line, not every bytecode.
107 # Uses roughly the same algo as ExecutionContext.run_trace_func()
108 # to know where the line starts are, but tweaked for speed,
109 # avoiding the quadratic complexity when run N times with a large
110 # code object.
111 #
112 cur = frame.last_instr
113 if cur < frame.f_revdb_nextline_instr:
114 return # fast path: we're still inside the same line as before
115 #
116 call_stop_point_at_line = True
117 co_revdb_linestarts = frame.pycode.co_revdb_linestarts
118 if cur > frame.f_revdb_nextline_instr:
119 #
120 # We jumped forward over the start of the next line. We're
121 # inside a different line, but we will only trigger a stop
122 # point if we're at the starting bytecode of that line. Fetch
123 # from co_revdb_linestarts the start of the line that is at or
124 # follows 'cur'.
125 ch = ord(co_revdb_linestarts[cur])
126 if ch == 0:
127 pass # we are at the start of a line now
128 else:
129 # We are not, so don't call stop_point_activate().
130 # We still have to fill f_revdb_nextline_instr.
131 call_stop_point_at_line = False
132 #
133 if call_stop_point_at_line:
134 stop_point_activate(pycode=frame.pycode, opindex=cur)
135 cur += 1
136 ch = ord(co_revdb_linestarts[cur])
137 #
138 # Update f_revdb_nextline_instr. Check if 'ch' was greater than
139 # 255, in which case it was rounded down to 255 and we have to
140 # continue looking
141 nextline_instr = cur + ch
142 while ch == 255:
143 ch = ord(co_revdb_linestarts[nextline_instr])
144 nextline_instr += ch
145 frame.f_revdb_nextline_instr = nextline_instr
146
147
148 def build_co_revdb_linestarts(code):
149 # Inspired by findlinestarts() in the 'dis' standard module.
150 # Set up 'bits' so that it contains \x00 at line starts and \xff
151 # in-between.
152 bits = ['\xff'] * (len(code.co_code) + 1)
153 if not code.hidden_applevel:
154 lnotab = code.co_lnotab
155 addr = 0
156 p = 0
157 newline = 1
158 while p + 1 < len(lnotab):
159 byte_incr = ord(lnotab[p])
160 line_incr = ord(lnotab[p+1])
161 if byte_incr:
162 if newline != 0:
163 bits[addr] = '\x00'
164 newline = 0
165 addr += byte_incr
166 newline |= line_incr
167 p += 2
168 if newline:
169 bits[addr] = '\x00'
170 bits[len(code.co_code)] = '\x00'
171 #
172 # Change 'bits' so that the character at 'i', if not \x00, measures
173 # how far the next \x00 is
174 next_null = len(code.co_code)
175 p = next_null - 1
176 while p >= 0:
177 if bits[p] == '\x00':
178 next_null = p
179 else:
180 ch = next_null - p
181 if ch > 255: ch = 255
182 bits[p] = chr(ch)
183 p -= 1
184 lstart = ''.join(bits)
185 code.co_revdb_linestarts = lstart
186 return lstart
187
188 def get_final_lineno(code):
189 lineno = code.co_firstlineno
190 lnotab = code.co_lnotab
191 p = 1
192 while p < len(lnotab):
193 line_incr = ord(lnotab[p])
194 lineno += line_incr
195 p += 2
196 return lineno
197
198 def find_line_starts(code):
199 # RPython version of dis.findlinestarts()
200 lnotab = code.co_lnotab
201 lastlineno = -1
202 lineno = code.co_firstlineno
203 addr = 0
204 p = 0
205 result = []
206 while p < len(lnotab) - 1:
207 byte_incr = ord(lnotab[p + 0])
208 line_incr = ord(lnotab[p + 1])
209 if byte_incr:
210 if lineno != lastlineno:
211 result.append((addr, lineno))
212 lastlineno = lineno
213 addr += byte_incr
214 lineno += line_incr
215 p += 2
216 if lineno != lastlineno:
217 result.append((addr, lineno))
218 return result
219
220 class NonStandardCode(object):
221 def __enter__(self):
222 dbstate.standard_code = False
223 self.t = dbstate.space.actionflag._ticker
224 self.c = dbstate.space.actionflag._ticker_revdb_count
225 def __exit__(self, *args):
226 dbstate.space.actionflag._ticker = self.t
227 dbstate.space.actionflag._ticker_revdb_count = self.c
228 dbstate.standard_code = True
229 non_standard_code = NonStandardCode()
230
231
232 def stop_point_activate(place=0, pycode=None, opindex=-1):
233 if revdb.watch_save_state():
234 any_watch_point = False
235 # ^^ this flag is set to True if we must continue to enter this
236 # block of code. If it is still False for watch_restore_state()
237 # below, then future watch_save_state() will return False too---
238 # until the next time revdb.c:set_revdb_breakpoints() is called.
239 space = dbstate.space
240 with non_standard_code:
241 watch_id = -1
242 if dbstate.breakpoint_by_file is not None:
243 any_watch_point = True
244 if pycode is not None:
245 watch_id = check_and_trigger_bkpt(pycode, opindex)
246 if watch_id == -1:
247 for prog, watch_id, expected in dbstate.watch_progs:
248 any_watch_point = True
249 try:
250 got = _run_watch(space, prog)
251 except OperationError as e:
252 got = e.errorstr(space)
253 except Exception:
254 break
255 if got != expected:
256 break
257 else:
258 watch_id = -1
259 revdb.watch_restore_state(any_watch_point)
260 if watch_id != -1:
261 revdb.breakpoint(watch_id)
262 revdb.stop_point(place)
263
264
265 def future_object(space):
266 return space.w_Ellipsis # a random prebuilt object
267
268 def load_metavar(index):
269 assert index >= 0
270 space = dbstate.space
271 metavars = dbstate.metavars
272 w_var = metavars[index] if index < len(metavars) else None
273 if w_var is None:
274 raise oefmt(space.w_NameError, "no constant object '$%d'",
275 index)
276 if w_var is future_object(space):
277 raise oefmt(space.w_RuntimeError,
278 "'$%d' refers to an object created later in time",
279 index)
280 return w_var
281
282 def set_metavar(index, w_obj):
283 assert index >= 0
284 if index >= len(dbstate.metavars):
285 missing = index + 1 - len(dbstate.metavars)
286 dbstate.metavars = dbstate.metavars + [None] * missing
287 dbstate.metavars[index] = w_obj
288
289
290 # ____________________________________________________________
291
292
293 def fetch_cur_frame(silent=False):
294 ec = dbstate.space.threadlocals.get_ec()
295 if ec is None:
296 frame = None
297 else:
298 frame = ec.topframeref()
299 if frame is None and not silent:
300 revdb.send_print("No stack.")
301 return frame
302
303 def compile(source, mode):
304 assert not dbstate.standard_code
305 space = dbstate.space
306 compiler = space.createcompiler()
307 code = compiler.compile(source, '<revdb>', mode, 0,
308 hidden_applevel=True)
309 return code
310
311
312 class W_RevDBOutput(W_Root):
313 softspace = 0
314
315 def __init__(self, space):
316 self.space = space
317
318 def descr_write(self, w_buffer):
319 assert not dbstate.standard_code
320 space = self.space
321 if space.isinstance_w(w_buffer, space.w_unicode):
322 w_buffer = space.call_method(w_buffer, 'encode',
323 space.newtext('utf-8')) # safe?
324 revdb.send_output(space.bytes_w(w_buffer))
325
326 def descr_get_softspace(space, revdb):
327 return space.newint(revdb.softspace)
328 def descr_set_softspace(space, revdb, w_newvalue):
329 revdb.softspace = space.int_w(w_newvalue)
330
331 W_RevDBOutput.typedef = typedef.TypeDef(
332 "revdb_output",
333 write = gateway.interp2app(W_RevDBOutput.descr_write),
334 # XXX is 'softspace' still necessary in Python 3?
335 softspace = typedef.GetSetProperty(descr_get_softspace,
336 descr_set_softspace,
337 cls=W_RevDBOutput),
338 )
339
340 def revdb_displayhook(space, w_obj):
341 """Modified sys.displayhook() that also outputs '$NUM = ',
342 for non-prebuilt objects. Such objects are then recorded in
343 'printed_objects'.
344 """
345 assert not dbstate.standard_code
346 if space.is_w(w_obj, space.w_None):
347 return
348 uid = revdb.get_unique_id(w_obj)
349 if uid > 0:
350 dbstate.printed_objects[uid] = w_obj
351 revdb.send_nextnid(uid) # outputs '$NUM = '
352 space.setitem(space.builtin.w_dict, space.newtext('_'), w_obj)
353 # do repr() after setitem: if w_obj was produced successfully,
354 # but its repr crashes because it tries to do I/O, then we already
355 # have it recorded in '_' and in '$NUM ='.
356 w_repr = space.repr(w_obj)
357 if space.isinstance_w(w_repr, space.w_unicode):
358 w_repr = space.call_method(w_repr, 'encode',
359 space.newtext('utf-8')) # safe?
360 revdb.send_print(space.bytes_w(w_repr))
361
362 @gateway.unwrap_spec(name='text0', level=int)
363 def revdb_importhook(space, name, w_globals=None,
364 w_locals=None, w_fromlist=None, level=-1):
365 # Incredibly simplified version of __import__, which only returns
366 # already-imported modules and doesn't call any custom import
367 # hooks. Recognizes only absolute imports. With a 'fromlist'
368 # argument that is a non-empty list, returns the module 'name3' if
369 # the 'name' argument is 'name1.name2.name3'. With an empty or
370 # None 'fromlist' argument, returns the module 'name1' instead.
371 return space.appexec([space.newtext(name), w_fromlist or space.w_None,
372 space.newint(level), space.sys],
373 """(name, fromlist, level, sys):
374 if level > 0:
375 raise ImportError("only absolute imports are "
376 "supported in the debugger")
377 basename = name.split('.')[0]
378 try:
379 basemod = sys.modules[basename]
380 mod = sys.modules[name]
381 except KeyError:
382 raise ImportError("'%s' not found or not imported yet "
383 "(the debugger can't import new modules, "
384 "and only supports absolute imports)" % (name,))
385 if fromlist:
386 return mod
387 return basemod
388 """)
389
390 @specialize.memo()
391 def get_revdb_displayhook(space):
392 return gateway.interp2app(revdb_displayhook).spacebind(space)
393
394 @specialize.memo()
395 def get_revdb_importhook(space):
396 return gateway.interp2app(revdb_importhook).spacebind(space)
397
398
399 def prepare_print_environment(space):
400 assert not dbstate.standard_code
401 w_revdb_output = W_RevDBOutput(space)
402 w_displayhook = get_revdb_displayhook(space)
403 w_import = get_revdb_importhook(space)
404 space.sys.setdictvalue(space, 'stdout', w_revdb_output)
405 space.sys.setdictvalue(space, 'stderr', w_revdb_output)
406 space.sys.setdictvalue(space, 'displayhook', w_displayhook)
407 space.builtin.setdictvalue(space, '__import__', w_import)
408
409 def command_print(cmd, expression):
410 frame = fetch_cur_frame()
411 if frame is None:
412 return
413 space = dbstate.space
414 with non_standard_code:
415 try:
416 prepare_print_environment(space)
417 code = compile(expression, 'single')
418 try:
419 code.exec_code(space,
420 frame.get_w_globals(),
421 frame.getdictscope())
422
423 except OperationError as operationerr:
424 # can't use sys.excepthook: it will likely try to do 'import
425 # traceback', which might not be doable without using I/O
426 tb = operationerr.get_traceback()
427 if tb is not None:
428 revdb.send_print("Traceback (most recent call last):")
429 while tb is not None:
430 if not isinstance(tb, pytraceback.PyTraceback):
431 revdb.send_print(" ??? %s" % tb)
432 break
433 show_frame(tb.frame, tb.get_lineno(), indent=' ')
434 tb = tb.next
435 revdb.send_print(operationerr.errorstr(space))
436
437 # set the sys.last_xxx attributes
438 w_type = operationerr.w_type
439 w_value = operationerr.get_w_value(space)
440 w_tb = operationerr.get_traceback()
441 w_dict = space.sys.w_dict
442 space.setitem(w_dict, space.newtext('last_type'), w_type)
443 space.setitem(w_dict, space.newtext('last_value'), w_value)
444 space.setitem(w_dict, space.newtext('last_traceback'), w_tb)
445
446 except OperationError as e:
447 revdb.send_print(e.errorstr(space, use_repr=True))
448 lambda_print = lambda: command_print
449
450
451 def file_and_lineno(frame, lineno):
452 code = frame.getcode()
453 return 'File "%s", line %d in %s' % (
454 code.co_filename, lineno, code.co_name)
455
456 def show_frame(frame, lineno=0, indent=''):
457 if lineno == 0:
458 lineno = frame.get_last_lineno()
459 revdb.send_output("%s%s\n%s " % (
460 indent,
461 file_and_lineno(frame, lineno),
462 indent))
463 revdb.send_linecache(frame.getcode().co_filename, lineno)
464
465 def display_function_part(frame, max_lines_before, max_lines_after):
466 if frame is None:
467 return
468 code = frame.getcode()
469 if code.co_filename.startswith('<builtin>'):
470 return
471 first_lineno = code.co_firstlineno
472 current_lineno = frame.get_last_lineno()
473 final_lineno = get_final_lineno(code)
474 #
475 ellipsis_after = False
476 if first_lineno < current_lineno - max_lines_before - 1:
477 first_lineno = current_lineno - max_lines_before
478 revdb.send_print("...")
479 if final_lineno > current_lineno + max_lines_after + 1:
480 final_lineno = current_lineno + max_lines_after
481 ellipsis_after = True
482 #
483 for i in range(first_lineno, final_lineno + 1):
484 if i == current_lineno:
485 if revdb.current_place() == -2: # <= this is the arg to stop_point()
486 prompt = "<< " # return
487 elif revdb.current_place() == -1:
488 prompt = "!! " # exceptional return
489 else:
490 prompt = " > " # plain line
491 revdb.send_output(prompt)
492 else:
493 revdb.send_output(" ")
494 revdb.send_linecache(code.co_filename, i, strip=False)
495 #
496 if ellipsis_after:
497 revdb.send_print("...")
498
499 def command_backtrace(cmd, extra):
500 frame = fetch_cur_frame(silent=True)
501 if cmd.c_arg1 == 0:
502 if frame is not None:
503 revdb.send_print("%s:" % (
504 file_and_lineno(frame, frame.get_last_lineno()),))
505 display_function_part(frame, max_lines_before=8, max_lines_after=5)
506 elif cmd.c_arg1 == 2:
507 display_function_part(frame, max_lines_before=1000,max_lines_after=1000)
508 else:
509 revdb.send_print("Current call stack (most recent call last):")
510 if frame is None:
511 revdb.send_print(" (empty)")
512 frames = []
513 while frame is not None:
514 frames.append(frame)
515 if len(frames) == 200:
516 revdb.send_print(" ...")
517 break
518 frame = frame.get_f_back()
519 while len(frames) > 0:
520 show_frame(frames.pop(), indent=' ')
521 lambda_backtrace = lambda: command_backtrace
522
523
524 def command_locals(cmd, extra):
525 frame = fetch_cur_frame()
526 if frame is None:
527 return
528 space = dbstate.space
529 with non_standard_code:
530 try:
531 prepare_print_environment(space)
532 space.appexec([space.sys,
533 frame.getdictscope()], """(sys, locals):
534 lst = sorted(locals.keys())
535 print('Locals:')
536 for key in lst:
537 try:
538 print(' %s =' % key, end=' ', flush=True)
539 s = '%r' % locals[key]
540 if len(s) > 140:
541 s = s[:100] + '...' + s[-30:]
542 print(s)
543 except:
544 exc, val, tb = sys.exc_info()
545 print('!<%s: %r>' % (exc, val))
546 """)
547 except OperationError as e:
548 revdb.send_print(e.errorstr(space, use_repr=True))
549 lambda_locals = lambda: command_locals
550
551 # ____________________________________________________________
552
553
554 def check_and_trigger_bkpt(pycode, opindex):
555 # We cache on 'pycode.co_revdb_bkpt_cache' either None or a dict
556 # mapping {opindex: bkpt_num}. This cache is updated when the
557 # version in 'pycode.co_revdb_bkpt_version' does not match
558 # 'dbstate.breakpoint_version' any more.
559 if pycode.co_revdb_bkpt_version != dbstate.breakpoint_version:
560 update_bkpt_cache(pycode)
561 cache = pycode.co_revdb_bkpt_cache
562 if cache is not None and opindex in cache:
563 return cache[opindex]
564 else:
565 return -1
566
567 def update_bkpt_cache(pycode):
568 # initialized by command_breakpoints():
569 # dbstate.breakpoint_filelines == [('FILENAME', lineno, bkpt_num)]
570 # computed lazily (here, first half of the logic):
571 # dbstate.breakpoint_by_file == {'co_filename': {lineno: bkpt_num}}
572 # the goal is to set:
573 # pycode.co_revdb_bkpt_cache == {opindex: bkpt_num}
574
575 co_filename = pycode.co_filename
576 try:
577 linenos = dbstate.breakpoint_by_file[co_filename]
578 except KeyError:
579 linenos = None
580 match = co_filename.upper() # ignore cAsE in filename matching
581 for filename, lineno, bkpt_num in dbstate.breakpoint_filelines:
582 if match.endswith(filename) and (
583 len(match) == len(filename) or
584 match[-len(filename)-1] in '/\\'): # a valid prefix
585 if linenos is None:
586 linenos = {}
587 linenos[lineno] = bkpt_num
588 dbstate.breakpoint_by_file[co_filename] = linenos
589
590 newcache = None
591 if linenos is not None:
592 # parse co_lnotab to figure out the opindexes that correspond
593 # to the marked line numbers. here, linenos == {lineno: bkpt_num}
594 for addr, lineno in find_line_starts(pycode):
595 if lineno in linenos:
596 if newcache is None:
597 newcache = {}
598 newcache[addr] = linenos[lineno]
599
600 pycode.co_revdb_bkpt_cache = newcache
601 pycode.co_revdb_bkpt_version = dbstate.breakpoint_version
602
603
604 def valid_identifier(s):
605 if not s:
606 return False
607 if s[0].isdigit():
608 return False
609 for c in s:
610 if not (c.isalnum() or c == '_'):
611 return False
612 return True
613
614 def add_breakpoint_funcname(name, i):
615 if dbstate.breakpoint_funcnames is None:
616 dbstate.breakpoint_funcnames = {}
617 dbstate.breakpoint_funcnames[name] = i
618
619 def add_breakpoint_fileline(filename, lineno, i):
620 # dbstate.breakpoint_filelines is just a list of (FILENAME, lineno, i).
621 # dbstate.breakpoint_by_file is {co_filename: {lineno: i}}, but
622 # computed lazily when we encounter a code object with the given
623 # co_filename. Any suffix 'filename' matches 'co_filename'.
624 if dbstate.breakpoint_filelines is None:
625 dbstate.breakpoint_filelines = []
626 dbstate.breakpoint_by_file = {}
627 dbstate.breakpoint_filelines.append((filename.upper(), lineno, i))
628
629 def add_breakpoint(name, i):
630 # if it is empty, complain
631 if not name:
632 revdb.send_print("Empty breakpoint name")
633 revdb.send_change_breakpoint(i)
634 return
635 # if it is surrounded by < >, it is the name of a code object
636 if name.startswith('<') and name.endswith('>'):
637 add_breakpoint_funcname(name, i)
638 return
639 # if it has no ':', it can be a valid identifier (which we
640 # register as a function name), or a lineno
641 original_name = name
642 j = name.rfind(':')
643 if j < 0:
644 try:
645 lineno = int(name)
646 except ValueError:
647 if name.endswith('()'):
648 n = len(name) - 2
649 assert n >= 0
650 name = name[:n]
651 if not valid_identifier(name):
652 revdb.send_print(
653 'Note: "%s()" doesn''t look like a function name. '
654 'Setting breakpoint anyway' % name)
655 add_breakpoint_funcname(name, i)
656 name += '()'
657 if name != original_name:
658 revdb.send_change_breakpoint(i, name)
659 return
660 # "number" does the same as ":number"
661 filename = ''
662 else:
663 # if it has a ':', it must end in ':lineno'
664 try:
665 lineno = int(name[j+1:])
666 except ValueError:
667 revdb.send_print('expected a line number after colon')
668 revdb.send_change_breakpoint(i)
669 return
670 filename = name[:j]
671
672 # the text before must be a pathname, possibly a relative one,
673 # or be escaped by < >. if it isn't, make it absolute and normalized
674 # and warn if it doesn't end in '.py'.
675 if filename == '':
676 frame = fetch_cur_frame()
677 if frame is None:
678 revdb.send_change_breakpoint(i)
679 return
680 filename = frame.getcode().co_filename
681 elif filename.startswith('<') and filename.endswith('>'):
682 pass # use unmodified
683 elif not filename.lower().endswith('.py'):
684 # use unmodified, but warn
685 revdb.send_print(
686 'Note: "%s" doesn''t look like a Python filename. '
687 'Setting breakpoint anyway' % (filename,))
688
689 add_breakpoint_fileline(filename, lineno, i)
690 name = '%s:%d' % (filename, lineno)
691 if name != original_name:
692 revdb.send_change_breakpoint(i, name)
693
694 def command_breakpoints(cmd, extra):
695 space = dbstate.space
696 dbstate.breakpoint_stack_id = cmd.c_arg1
697 revdb.set_thread_breakpoint(cmd.c_arg2)
698 dbstate.breakpoint_funcnames = None
699 dbstate.breakpoint_filelines = None
700 dbstate.breakpoint_by_file = None
701 dbstate.breakpoint_version += 1
702 watch_progs = []
703 with non_standard_code:
704 for i, kind, name in revdb.split_breakpoints_arg(extra):
705 if kind == 'B':
706 add_breakpoint(name, i)
707 elif kind == 'W':
708 code = interp_marshal.loads(space, space.newbytes(name))
709 watch_progs.append((code, i, ''))
710 dbstate.watch_progs = watch_progs[:]
711 lambda_breakpoints = lambda: command_breakpoints
712
713
714 def command_watchvalues(cmd, extra):
715 expected = extra.split('\x00')
716 for j in range(len(dbstate.watch_progs)):
717 prog, i, _ = dbstate.watch_progs[j]
718 if i >= len(expected):
719 raise IndexError
720 dbstate.watch_progs[j] = prog, i, expected[i]
721 lambda_watchvalues = lambda: command_watchvalues
722
723
724 def command_stackid(cmd, extra):
725 frame = fetch_cur_frame(silent=True)
726 if frame is not None and cmd.c_arg1 != 0: # parent_flag
727 frame = dbstate.space.getexecutioncontext().getnextframe_nohidden(frame)
728 if frame is None:
729 uid = 0
730 else:
731 uid = revdb.get_unique_id(frame)
732 if revdb.current_place() == -2:
733 hidden_level = 1 # hide the "<<" events from next/bnext commands
734 else:
735 hidden_level = 0
736 revdb.send_answer(revdb.ANSWER_STACKID, uid, hidden_level)
737 lambda_stackid = lambda: command_stackid
738
739
740 def command_allocating(uid, gcref):
741 w_obj = cast_gcref_to_instance(W_Root, gcref)
742 dbstate.printed_objects[uid] = w_obj
743 try:
744 index_metavar = dbstate.watch_futures.pop(uid)
745 except KeyError:
746 pass
747 else:
748 set_metavar(index_metavar, w_obj)
749 lambda_allocating = lambda: command_allocating
750
751
752 def command_attachid(cmd, extra):
753 space = dbstate.space
754 index_metavar = cmd.c_arg1
755 uid = cmd.c_arg2
756 try:
757 w_obj = dbstate.printed_objects[uid]
758 except KeyError:
759 # uid not found, probably a future object
760 dbstate.watch_futures[uid] = index_metavar
761 w_obj = future_object(space)
762 set_metavar(index_metavar, w_obj)
763 lambda_attachid = lambda: command_attachid
764
765
766 def command_compilewatch(cmd, expression):
767 space = dbstate.space
768 with non_standard_code:
769 try:
770 code = compile(expression, 'eval')
771 marshalled_code = space.bytes_w(interp_marshal.dumps(
772 space, code,
773 space.newint(interp_marshal.Py_MARSHAL_VERSION)))
774 except OperationError as e:
775 revdb.send_watch(e.errorstr(space), ok_flag=0)
776 else:
777 revdb.send_watch(marshalled_code, ok_flag=1)
778 lambda_compilewatch = lambda: command_compilewatch
779
780 def command_checkwatch(cmd, marshalled_code):
781 space = dbstate.space
782 with non_standard_code:
783 try:
784 code = interp_marshal.loads(space, space.newbytes(marshalled_code))
785 text = _run_watch(space, code)
786 except OperationError as e:
787 revdb.send_watch(e.errorstr(space), ok_flag=0)
788 else:
789 revdb.send_watch(text, ok_flag=1)
790 lambda_checkwatch = lambda: command_checkwatch
791
792
793 def _run_watch(space, prog):
794 # must be called from non_standard_code!
795 w_dict = space.builtin.w_dict
796 w_res = prog.exec_code(space, w_dict, w_dict)
797 return space.text_w(space.repr(w_res))
798
799
800 # ____________________________________________________________
801
802
803 ActionFlag._ticker_revdb_count = -1
804
805 class RDBSignalActionFlag(AbstractActionFlag):
806 # Used instead of pypy.module.signal.interp_signal.SignalActionFlag
807 # when we have reverse-debugging. That other class would work too,
808 # but inefficiently: it would generate two words of data per bytecode.
809 # This class is tweaked to generate one byte per _SIG_TICKER_COUNT
810 # bytecodes, at the expense of not reacting to signals instantly.
811
812 # Threads: after 10'000 calls to decrement_ticker(), it should
813 # return -1. It should also return -1 if there was a signal.
814 # This is done by calling _update_ticker_from_signals() every 100
815 # calls, and invoking rsignal.pypysig_check_and_reset(); this in
816 # turn returns -1 if there was a signal or if it was called 100
817 # times.
818
819 _SIG_TICKER_COUNT = 100
820 _ticker = 0
821 _ticker_revdb_count = _SIG_TICKER_COUNT * 10
822
823 def get_ticker(self):
824 return self._ticker
825
826 def reset_ticker(self, value):
827 self._ticker = value
828
829 def rearm_ticker(self):
830 self._ticker = -1
831
832 def decrement_ticker(self, by):
833 if we_are_translated():
834 c = self._ticker_revdb_count - 1
835 if c < 0:
836 c = self._update_ticker_from_signals()
837 self._ticker_revdb_count = c
838 #if self.has_bytecode_counter: # this 'if' is constant-folded
839 # print ("RDBSignalActionFlag: has_bytecode_counter: "
840 # "not supported for now")
841 # raise NotImplementedError
842 return self._ticker
843
844 def _update_ticker_from_signals(self):
845 from rpython.rlib import rsignal
846 if dbstate.standard_code:
847 if rsignal.pypysig_check_and_reset():
848 self.rearm_ticker()
849 return self._SIG_TICKER_COUNT
850 _update_ticker_from_signals._dont_inline_ = True
374374 child.expect('>>>')
375375
376376 def test_atexit(self):
377 skip("Python3 atexit is a builtin module")
377 py.test.skip("Python3 atexit is a builtin module")
378378 child = self.spawn([])
379379 child.expect('>>> ')
380380 child.sendline('def f(): print("foobye")')
469469
470470 def test_cmd_co_name(self):
471471 child = self.spawn(['-c',
472 'import sys; print sys._getframe(0).f_code.co_name'])
472 'import sys; print(sys._getframe(0).f_code.co_name)'])
473473 child.expect('<module>')
474474
475475 def test_ignore_python_inspect(self):
524524
525525 def test_options_i_m(self, monkeypatch):
526526 if sys.platform == "win32":
527 skip("close_fds is not supported on Windows platforms")
527 py.test.skip("close_fds is not supported on Windows platforms")
528528 if not hasattr(runpy, '_run_module_as_main'):
529 skip("requires CPython >= 2.6")
529 py.test.skip("requires CPython >= 2.6")
530530 p = os.path.join(os.path.realpath(os.path.dirname(__file__)), 'mymodule.py')
531531 p = os.path.abspath(p)
532532 monkeypatch.chdir(os.path.dirname(app_main))
556556
557557 def test_options_u_i(self):
558558 if sys.platform == "win32":
559 skip("close_fds is not supported on Windows platforms")
559 py.test.skip("close_fds is not supported on Windows platforms")
560560 import subprocess, select, os
561561 pipe = subprocess.Popen([get_python3(), app_main, "-u", "-i"],
562562 stdout=subprocess.PIPE,
613613 del os.environ['PYTHONINSPECT_']
614614
615615 def test_stdout_flushes_before_stdin_blocks(self):
616 skip("Python3 does not implement this behavior")
616 py.test.skip("Python3 does not implement this behavior")
617617 # This doesn't really test app_main.py, but a behavior that
618618 # can only be checked on top of py.py with pexpect.
619619 path = getscript("""
631631
632632 def test_no_space_before_argument(self, monkeypatch):
633633 if not hasattr(runpy, '_run_module_as_main'):
634 skip("requires CPython >= 2.6")
634 py.test.skip("requires CPython >= 2.6")
635635 child = self.spawn(['-cprint("hel" + "lo")'])
636636 child.expect('hello')
637637
752752
753753 def test_option_m(self, monkeypatch):
754754 if not hasattr(runpy, '_run_module_as_main'):
755 skip("requires CPython >= 2.6")
755 py.test.skip("requires CPython >= 2.6")
756756 p = os.path.join(os.path.realpath(os.path.dirname(__file__)), 'mymodule.py')
757757 p = os.path.abspath(p)
758758 monkeypatch.chdir(os.path.dirname(app_main))
766766
767767 def test_option_m_package(self, monkeypatch):
768768 if not hasattr(runpy, '_run_module_as_main'):
769 skip("requires CPython >= 2.6")
769 py.test.skip("requires CPython >= 2.6")
770770 p = os.path.join(os.path.realpath(os.path.dirname(__file__)),
771771 'mypackage', '__main__.py')
772772 p = os.path.abspath(p)
10421042 assert data.startswith("15\\u20ac ('strict', 'backslashreplace')")
10431043
10441044
1045 class TestAppMain:
1046 def test_print_info(self):
1047 from pypy.interpreter import app_main
1048 import sys, cStringIO
1049 prev_so = sys.stdout
1050 prev_ti = getattr(sys, 'pypy_translation_info', 'missing')
1051 sys.pypy_translation_info = {
1052 'translation.foo': True,
1053 'translation.bar': 42,
1054 'translation.egg.something': None,
1055 'objspace.x': 'hello',
1056 }
1057 try:
1058 sys.stdout = f = cStringIO.StringIO()
1059 py.test.raises(SystemExit, app_main.print_info)
1060 finally:
1061 sys.stdout = prev_so
1062 if prev_ti == 'missing':
1063 del sys.pypy_translation_info
1064 else:
1065 sys.pypy_translation_info = prev_ti
1066 assert f.getvalue() == ("[objspace]\n"
1067 " x = 'hello'\n"
1068 "[translation]\n"
1069 " bar = 42\n"
1070 " [egg]\n"
1071 " something = None\n"
1072 " foo = True\n")
1073
1074
1045 @py.test.mark.skipif('config.getoption("runappdirect")')
10751046 class AppTestAppMain:
10761047 def setup_class(self):
10771048 # ----------------------------------------
111111 assert seen == ['aenter', 'aexit']
112112 """
113113
114 def test_async_with_exit_True(self): """
115 seen = []
116 class X:
117 async def __aenter__(self):
118 seen.append('aenter')
119 async def __aexit__(self, *args):
120 seen.append('aexit')
121 return True
122 async def f(x):
123 async with x:
124 return 42
125 c = f(X())
126 try:
127 c.send(None)
128 except StopIteration as e:
129 assert e.value == 42
130 else:
131 assert False, "should have raised"
132 assert seen == ['aenter', 'aexit']
133 """
134
114135 def test_await(self): """
115136 class X:
116137 def __await__(self):
4141 class Action1(executioncontext.AsyncAction):
4242 def perform(self, ec, frame):
4343 events.append('one')
44
44
4545 class Action2(executioncontext.AsyncAction):
4646 def perform(self, ec, frame):
4747 events.append('two')
7474
7575 class Action1(executioncontext.AsyncAction):
7676 _count = 0
77
77
7878 def perform(self, ec, frame):
7979 events.append('one')
8080 if self._count == 0:
137137
138138 def test_llprofile(self):
139139 l = []
140
140
141141 def profile_func(space, w_arg, frame, event, w_aarg):
142142 assert w_arg is space.w_None
143143 l.append(event)
144
144
145145 space = self.space
146146 space.getexecutioncontext().setllprofile(profile_func, space.w_None)
147147 space.appexec([], """():
148148 pass
149149 """)
150150 space.getexecutioncontext().setllprofile(None, None)
151 assert l == ['call', 'return', 'call', 'return']
151 assert l[-4:] == ['call', 'return', 'call', 'return']
152152
153153 def test_llprofile_c_call(self):
154154 from pypy.interpreter.function import Function, Method
155155 l = []
156156 seen = []
157157 space = self.space
158
158
159159 def profile_func(space, w_arg, frame, event, w_func):
160160 assert w_arg is space.w_None
161161 l.append(event)
172172 return
173173 """ % snippet)
174174 space.getexecutioncontext().setllprofile(None, None)
175 assert l == ['call', 'return', 'call', 'c_call', 'c_return', 'return']
176 if isinstance(seen[0], Method):
177 w_class = space.type(seen[0].w_instance)
175 assert l[-6:] == ['call', 'return', 'call', 'c_call', 'c_return', 'return']
176 if isinstance(seen[-1], Method):
177 w_class = space.type(seen[-1].w_instance)
178178 found = 'method %s of %s' % (
179 seen[0].w_function.name,
179 seen[-1].w_function.name,
180180 w_class.getname(space).encode('utf-8'))
181181 else:
182 assert isinstance(seen[0], Function)
183 found = 'builtin %s' % seen[0].name
182 assert isinstance(seen[-1], Function)
183 found = 'builtin %s' % seen[-1].name
184184 assert found == expected_c_call
185185
186186 check_snippet('l = []; l.append(42)', 'method append of list')
189189 check_snippet('max(1, 2, **{})', 'builtin max')
190190 check_snippet('args = (1, 2); max(*args, **{})', 'builtin max')
191191 check_snippet('abs(val=0)', 'builtin abs')
192
192
193193 def test_llprofile_c_exception(self):
194194 l = []
195
195
196196 def profile_func(space, w_arg, frame, event, w_aarg):
197197 assert w_arg is space.w_None
198198 l.append(event)
209209 return
210210 """ % snippet)
211211 space.getexecutioncontext().setllprofile(None, None)
212 assert l == ['call', 'return', 'call', 'c_call', 'c_exception', 'return']
212 assert l[-6:] == ['call', 'return', 'call', 'c_call', 'c_exception', 'return']
213213
214214 check_snippet('d = {}; d.__getitem__(42)')
215215
307307 space = self.space
308308 w_res = space.appexec([], """():
309309 l = []
310
310
311311 def profile(*args):
312312 l.append(sys.exc_info()[0])
313313
326326 """)
327327
328328
329 class AppTestDelNotBlocked:
330
331 def setup_method(self, meth):
332 if not self.runappdirect:
333 py.test.skip("test is meant for running with py.test -A")
334 from rpython.tool.udir import udir
335 tmpfile = udir.join('test_execution_context')
336 tmpfile.write("""
337 import gc
338 class X(object):
339 def __del__(self):
340 print("Called", self.num)
341 def f():
342 x1 = X(); x1.num = 1
343 x2 = X(); x2.num = 2
344 x1.next = x2
345 f()
346 gc.collect()
347 gc.collect()
348 """)
349 self.tmpfile = str(tmpfile)
350 self.w_tmpfile = self.space.wrap(self.tmpfile)
351
352 def test_del_not_blocked(self):
353 # test the behavior fixed in r71420: before, only one __del__
354 # would be called
355 import os, sys
356 print(sys.executable, self.tmpfile)
357 if sys.platform == "win32":
358 cmdformat = '"%s" "%s"'
359 else:
360 cmdformat = "'%s' '%s'"
361 g = os.popen(cmdformat % (sys.executable, self.tmpfile), 'r')
362 data = g.read()
363 g.close()
364 assert 'Called 1' in data
365 assert 'Called 2' in data
366
367
368329 class AppTestProfile:
369330
370331 def test_return(self):
169169 h = get_h()
170170 raises(ValueError, "f.__code__ = h.__code__")
171171
172 @pytest.mark.skipif("config.option.runappdirect")
172173 def test_write_code_builtin_forbidden(self):
173174 def f(*args):
174175 return 42
338339 assert meth() == obj
339340
340341 def test_none_get_interaction(self):
341 skip("XXX issue #2083")
342342 assert type(None).__repr__(None) == 'None'
343343
344344 def test_none_get_interaction_2(self):
543543 pass
544544 r = repr(ClsB().f)
545545 assert "ClsA.f of <" in r
546 assert "ClsB object at " in r
546 assert repr(type(ClsA.f)) == "<class 'function'>"
547 assert repr(type(ClsA().f)) == "<class 'method'>"
548
547549
548550 def test_method_call(self):
549551 class C(object):
524524 w_app_g3_i = space.wrap(app_g3_i)
525525 assert space.eq_w(space.call_function(w_app_g3_i,w(1)),w(1))
526526 assert space.eq_w(space.call_function(w_app_g3_i,w(1L)),w(1))
527 raises(gateway.OperationError,space.call_function,w_app_g3_i,w(sys.maxint*2))
528 raises(gateway.OperationError,space.call_function,w_app_g3_i,w(None))
529 raises(gateway.OperationError,space.call_function,w_app_g3_i,w("foo"))
530 raises(gateway.OperationError,space.call_function,w_app_g3_i,w(1.0))
527 space.raises_w(space.w_OverflowError, space.call_function,w_app_g3_i,w(sys.maxint*2))
528 space.raises_w(space.w_TypeError, space.call_function,w_app_g3_i,w(None))
529 space.raises_w(space.w_TypeError, space.call_function,w_app_g3_i,w("foo"))
530 space.raises_w(space.w_TypeError, space.call_function,w_app_g3_i,w(1.0))
531531
532532 app_g3_s = gateway.interp2app_temp(g3_id,
533533 unwrap_spec=[gateway.ObjSpace,
534534 'text'])
535535 w_app_g3_s = space.wrap(app_g3_s)
536536 assert space.eq_w(space.call_function(w_app_g3_s,w("foo")),w("foo"))
537 raises(gateway.OperationError,space.call_function,w_app_g3_s,w(None))
538 raises(gateway.OperationError,space.call_function,w_app_g3_s,w(1))
539 raises(gateway.OperationError,space.call_function,w_app_g3_s,w(1.0))
537 space.raises_w(space.w_TypeError, space.call_function,w_app_g3_s,w(None))
538 space.raises_w(space.w_TypeError, space.call_function,w_app_g3_s,w(1))
539 space.raises_w(space.w_TypeError, space.call_function,w_app_g3_s,w(1.0))
540540
541541 app_g3_f = gateway.interp2app_temp(g3_id,
542542 unwrap_spec=[gateway.ObjSpace,
545545 assert space.eq_w(space.call_function(w_app_g3_f,w(1.0)),w(1.0))
546546 assert space.eq_w(space.call_function(w_app_g3_f,w(1)),w(1.0))
547547 assert space.eq_w(space.call_function(w_app_g3_f,w(1L)),w(1.0))
548 raises(gateway.OperationError,space.call_function,w_app_g3_f,w(None))
549 raises(gateway.OperationError,space.call_function,w_app_g3_f,w("foo"))
548 space.raises_w(space.w_TypeError, space.call_function,w_app_g3_f,w(None))
549 space.raises_w(space.w_TypeError, space.call_function,w_app_g3_f,w("foo"))
550550
551551 app_g3_r = gateway.interp2app_temp(g3_id,
552552 unwrap_spec=[gateway.ObjSpace,
553553 r_longlong])
554554 w_app_g3_r = space.wrap(app_g3_r)
555 raises(gateway.OperationError,space.call_function,w_app_g3_r,w(1.0))
555 space.raises_w(space.w_TypeError, space.call_function,w_app_g3_r,w(1.0))
556556
557557 def test_interp2app_unwrap_spec_unicode(self):
558558 space = self.space
569569 assert self.space.eq_w(
570570 space.call_function(w_app_g3_u, w("baz")),
571571 w(3))
572 raises(gateway.OperationError, space.call_function, w_app_g3_u,
572 space.raises_w(space.w_TypeError, space.call_function, w_app_g3_u,
573573 w(None))
574 raises(gateway.OperationError, space.call_function, w_app_g3_u,
574 space.raises_w(space.w_TypeError, space.call_function, w_app_g3_u,
575575 w(42))
576576
577577 def test_interp2app_unwrap_spec_unwrapper(self):
588588 Unwrapper])
589589 assert self.space.eq_w(
590590 space.call_function(w(app_g3_u), w(42)), w(43))
591 raises(gateway.OperationError, space.call_function,
591 space.raises_w(space.w_TypeError, space.call_function,
592592 w(app_g3_u), w(None))
593593
594594 def test_interp2app_classmethod(self):
264264 return a, b, c, d
265265 """
266266 assert self.codetest(code, "f", [1, 2], {"d" : 4, "c" : 3}) == (1, 2, 3, 4)
267
267
268268 def test_build_set_unpack(self):
269269 code = """ def f():
270270 return {*range(4), 4, *(5, 6, 7)}
273273 res = self.codetest(code, "f", [])
274274 l_res = space.call_function(space.w_list, res)
275275 assert space.unwrap(l_res) == [0, 1, 2, 3, 4, 5, 6, 7]
276
276
277 def test_build_set_unpack_exception(self):
278 code = """ if 1:
279 def g():
280 yield 1
281 yield 2
282 raise TypeError
283 def f():
284 try:
285 {*g(), 1, 2}
286 except TypeError:
287 return True
288 return False
289 """
290 assert self.codetest(code, "f", [])
291
277292 def test_build_tuple_unpack(self):
278293 code = """ def f():
279294 return (*range(4), 4)
280295 """
281296 assert self.codetest(code, "f", []) == (0, 1, 2, 3, 4)
282
297
283298 def test_build_list_unpack(self):
284299 code = """ def f():
285300 return [*range(4), 4]
152152 r"""
153153 seen = []
154154 def tracer(f, event, *args):
155 if f.f_code.co_name == "decode":
156 return tracer
155157 seen.append((event, f.f_lineno))
156158 if len(seen) == 5:
157159 f.f_lineno = 1 # bug shown only when setting lineno to 1
296298
297299 l = []
298300 def trace(a,b,c):
299 l.append((a,b,c))
301 if a.f_code.co_name != "decode":
302 l.append((a,b,c))
300303
301304 def f():
302305 h = _testing.Hidden()
308308 return object()
309309 raises(TypeError, "raise MyException")
310310
311 def test_with_exit_True(self):
312 class X:
313 def __enter__(self):
314 pass
315 def __exit__(self, *args):
316 return True
317 def g():
318 with X():
319 return 42
320 assert False, "unreachable"
321 assert g() == 42
311322
312323 def test_pop_exception_value(self):
313324 # assert that this code don't crash
0 import dis
1 from pypy.interpreter.reverse_debugging import *
2 from pypy.interpreter import reverse_debugging
3 from rpython.rlib import revdb
4
5
6 class FakeCode:
7 hidden_applevel = False
8 def __init__(self, co_code='', co_lnotab='', co_filename='?'):
9 self.co_firstlineno = 43
10 self.co_code = co_code
11 self.co_lnotab = co_lnotab
12 self.co_revdb_linestarts = None
13 self.co_filename = co_filename
14
15
16 try:
17 from hypothesis import given, strategies, example
18 except ImportError:
19 pass
20 else:
21 @given(strategies.binary())
22 @example("\x01\x02\x03\x04"
23 "\x00\xFF\x20\x30\x00\xFF\x00\x40"
24 "\xFF\x00\x0A\x0B\xFF\x00\x0C\x00")
25 def test_build_co_revdb_linestarts(lnotab):
26 if len(lnotab) & 1:
27 lnotab = lnotab + '\x00' # make the length even
28 code = FakeCode("?" * sum(map(ord, lnotab[0::2])), lnotab)
29 lstart = build_co_revdb_linestarts(code)
30 assert lstart is code.co_revdb_linestarts
31
32 expected_starts = set()
33 for addr, lineno in dis.findlinestarts(code):
34 expected_starts.add(addr)
35
36 next_start = len(code.co_code)
37 for index in range(len(code.co_code), -1, -1):
38 if index in expected_starts:
39 next_start = index
40 assert lstart[index] == chr(next_start - index
41 if next_start - index <= 255
42 else 255)
43
44
45 class FakeFrame:
46 def __init__(self, code):
47 self.__code = code
48 def getcode(self):
49 return self.__code
50
51 def check_add_breakpoint(input, curfilename=None,
52 expected_funcname=None,
53 expected_fileline=None,
54 expected_output=None,
55 expected_chbkpt=None):
56 dbstate.__dict__.clear()
57 prev = revdb.send_answer, reverse_debugging.fetch_cur_frame
58 try:
59 messages = []
60 def got_message(cmd, arg1=0, arg2=0, arg3=0, extra=""):
61 messages.append((cmd, arg1, arg2, arg3, extra))
62 def my_cur_frame():
63 assert curfilename is not None
64 return FakeFrame(FakeCode(co_filename=curfilename))
65 revdb.send_answer = got_message
66 reverse_debugging.fetch_cur_frame = my_cur_frame
67 add_breakpoint(input, 5)
68 finally:
69 revdb.send_answer, reverse_debugging.fetch_cur_frame = prev
70
71 if expected_funcname is None:
72 assert dbstate.breakpoint_funcnames is None
73 else:
74 assert dbstate.breakpoint_funcnames == {expected_funcname: 5}
75
76 if expected_fileline is None:
77 assert dbstate.breakpoint_filelines is None
78 else:
79 filename, lineno = expected_fileline
80 assert dbstate.breakpoint_filelines == [(filename.upper(), lineno, 5)]
81
82 got_output = None
83 got_chbkpt = None
84 for msg in messages:
85 if msg[0] == revdb.ANSWER_TEXT:
86 assert got_output is None
87 got_output = msg[-1]
88 assert msg[1] in (0, 1)
89 if msg[1]:
90 got_output += "\n"
91 elif msg[0] == revdb.ANSWER_CHBKPT:
92 assert got_chbkpt is None
93 assert msg[1] == 5
94 got_chbkpt = msg[-1]
95
96 assert got_output == expected_output
97 assert got_chbkpt == expected_chbkpt
98
99 def test_add_breakpoint():
100 check_add_breakpoint('', expected_output="Empty breakpoint name\n",
101 expected_chbkpt='')
102 check_add_breakpoint('foo42', expected_funcname="foo42",
103 expected_chbkpt="foo42()")
104 check_add_breakpoint('foo42()', expected_funcname="foo42")
105 check_add_breakpoint('foo.bar', expected_funcname="foo.bar",
106 expected_output='Note: "foo.bar()" doesn''t look like a function name.'
107 ' Setting breakpoint anyway\n',
108 expected_chbkpt="foo.bar()")
109 check_add_breakpoint('<foo.bar>', expected_funcname="<foo.bar>")
110 check_add_breakpoint('42', curfilename='abcd',
111 expected_fileline=('abcd', 42),
112 expected_chbkpt='abcd:42')
113 check_add_breakpoint(':42', curfilename='abcd',
114 expected_fileline=('abcd', 42),
115 expected_chbkpt='abcd:42')
116 check_add_breakpoint('abcd:42', expected_fileline=('abcd', 42),
117 expected_output='Note: "abcd" doesnt look like a Python filename.'
118 ' Setting breakpoint anyway\n')
119 check_add_breakpoint('abcd.py:42',
120 expected_fileline=('abcd.py', 42))
121 check_add_breakpoint('42:abc',
122 expected_output='expected a line number after colon\n',
123 expected_chbkpt='')
690690 "bye" : 5, "kw" : 6, "return" : 42}
691691 """
692692
693 def test_bug_annotations_lambda(self):
694 """
695 # those used to crash
696 def broken(*a: lambda x: None):
697 pass
698
699 def broken(**a: lambda x: None):
700 pass
701 """
702
703 def test_bug_annotation_inside_nested_function(self):
704 """
705 # this used to crash
706 def f1():
707 def f2(*args: int):
708 pass
709 f1()
710 """
711
693712 class AppTestSyntaxError:
694713
695714 def test_tokenizer_error_location(self):
426426 def test_builtin_readonly_property(self):
427427 import sys
428428 x = lambda: 5
429 e = raises(AttributeError, 'x.func_globals = {}')
429 e = raises(AttributeError, 'x.__globals__ = {}')
430430 if '__pypy__' in sys.builtin_module_names:
431 assert str(e.value) == "readonly attribute 'func_globals'"
431 assert str(e.value) == "readonly attribute '__globals__'"
2727 self.bases = bases
2828 # Used in cpyext to fill tp_as_buffer slots
2929 assert __buffer in {None, 'read-write', 'read'}, "Unknown value for __buffer"
30 for base in bases:
31 if __buffer is None:
32 __buffer = base.buffer
3033 self.buffer = __buffer
3134 self.heaptype = False
3235 self.hasdict = '__dict__' in rawdict
165165 # encoding error, it should always be reversible, and the reverse is
166166 # encode_utf8sp().
167167 return decode_utf8(space, string, allow_surrogates=True)
168
169 # ____________________________________________________________
170 # utf-16
171
172 def str_decode_utf_16(s, size, errors, final=True,
173 errorhandler=None):
174 result, length, byteorder = str_decode_utf_16_helper(s, size, errors, final,
175 errorhandler, "native",
176 'utf-16-' + BYTEORDER2)
177 return result, length
178
179 def str_decode_utf_16_be(s, size, errors, final=True,
180 errorhandler=None):
181 result, length, byteorder = str_decode_utf_16_helper(s, size, errors, final,
182 errorhandler, "big",
183 'utf-16-be')
184 return result, length
185
186 def str_decode_utf_16_le(s, size, errors, final=True,
187 errorhandler=None):
188 result, length, byteorder = str_decode_utf_16_helper(s, size, errors, final,
189 errorhandler, "little",
190 'utf-16-le')
191 return result, length
192
193 def str_decode_utf_16_helper(s, size, errors, final=True,
194 errorhandler=None,
195 byteorder="native",
196 public_encoding_name='utf16'):
197 if errorhandler is None:
198 errorhandler = default_unicode_error_decode
199 bo = 0
200
201 if BYTEORDER == 'little':
202 ihi = 1
203 ilo = 0
204 else:
205 ihi = 0
206 ilo = 1
207
208 # Check for BOM marks (U+FEFF) in the input and adjust current
209 # byte order setting accordingly. In native mode, the leading BOM
210 # mark is skipped, in all other modes, it is copied to the output
211 # stream as-is (giving a ZWNBSP character).
212 pos = 0
213 if byteorder == 'native':
214 if size >= 2:
215 bom = (ord(s[ihi]) << 8) | ord(s[ilo])
216 if BYTEORDER == 'little':
217 if bom == 0xFEFF:
218 pos += 2
219 bo = -1
220 elif bom == 0xFFFE:
221 pos += 2
222 bo = 1
223 else:
224 if bom == 0xFEFF:
225 pos += 2
226 bo = 1
227 elif bom == 0xFFFE:
228 pos += 2
229 bo = -1
230 elif byteorder == 'little':
231 bo = -1
232 else:
233 bo = 1
234 if size == 0:
235 return u'', 0, bo
236 if bo == -1:
237 # force little endian
238 ihi = 1
239 ilo = 0
240
241 elif bo == 1:
242 # force big endian
243 ihi = 0
244 ilo = 1
245
246 result = UnicodeBuilder(size // 2)
247
248 #XXX I think the errors are not correctly handled here
249 while pos < size:
250 # remaining bytes at the end? (size should be even)
251 if len(s) - pos < 2:
252 if not final:
253 break
254 r, pos = errorhandler(errors, public_encoding_name,
255 "truncated data",
256 s, pos, len(s))
257 result.append(r)
258 if len(s) - pos < 2:
259 break
260 ch = (ord(s[pos + ihi]) << 8) | ord(s[pos + ilo])
261 pos += 2
262 if ch < 0xD800 or ch > 0xDFFF:
263 result.append(unichr(ch))
264 continue
265 # UTF-16 code pair:
266 if len(s) - pos < 2:
267 pos -= 2
268 if not final:
269 break
270 errmsg = "unexpected end of data"
271 r, pos = errorhandler(errors, public_encoding_name,
272 errmsg, s, pos, len(s))
273 result.append(r)
274 if len(s) - pos < 2:
275 break
276 elif 0xD800 <= ch <= 0xDBFF:
277 ch2 = (ord(s[pos+ihi]) << 8) | ord(s[pos+ilo])
278 pos += 2
279 if 0xDC00 <= ch2 <= 0xDFFF:
280 if MAXUNICODE < 65536:
281 result.append(unichr(ch))
282 result.append(unichr(ch2))
283 else:
284 result.append(UNICHR((((ch & 0x3FF)<<10) |
285 (ch2 & 0x3FF)) + 0x10000))
286 continue
287 else:
288 r, pos = errorhandler(errors, public_encoding_name,
289 "illegal UTF-16 surrogate",
290 s, pos - 4, pos - 2)
291 result.append(r)
292 else:
293 r, pos = errorhandler(errors, public_encoding_name,
294 "illegal encoding",
295 s, pos - 2, pos)
296 result.append(r)
297 return result.build(), pos, bo
298
299 def _STORECHAR(result, CH, byteorder):
300 hi = chr(((CH) >> 8) & 0xff)
301 lo = chr((CH) & 0xff)
302 if byteorder == 'little':
303 result.append(lo)
304 result.append(hi)
305 else:
306 result.append(hi)
307 result.append(lo)
308
309 def unicode_encode_utf_16_helper(s, size, errors,
310 errorhandler=None,
311 allow_surrogates=True,
312 byteorder='little',
313 public_encoding_name='utf16'):
314 if errorhandler is None:
315 errorhandler = default_unicode_error_encode
316 if size == 0:
317 if byteorder == 'native':
318 result = StringBuilder(2)
319 _STORECHAR(result, 0xFEFF, BYTEORDER)
320 return result.build()
321 return ""
322
323 result = StringBuilder(size * 2 + 2)
324 if byteorder == 'native':
325 _STORECHAR(result, 0xFEFF, BYTEORDER)
326 byteorder = BYTEORDER
327
328 pos = 0
329 while pos < size:
330 ch = ord(s[pos])
331 pos += 1
332
333 if ch < 0xD800:
334 _STORECHAR(result, ch, byteorder)
335 elif ch >= 0x10000:
336 _STORECHAR(result, 0xD800 | ((ch-0x10000) >> 10), byteorder)
337 _STORECHAR(result, 0xDC00 | ((ch-0x10000) & 0x3FF), byteorder)
338 elif ch >= 0xE000 or allow_surrogates:
339 _STORECHAR(result, ch, byteorder)
340 else:
341 ru, rs, pos = errorhandler(errors, public_encoding_name,
342 'surrogates not allowed',
343 s, pos-1, pos)
344 if rs is not None:
345 # py3k only
346 if len(rs) % 2 != 0:
347 errorhandler('strict', public_encoding_name,
348 'surrogates not allowed',
349 s, pos-1, pos)
350 result.append(rs)
351 continue
352 for ch in ru:
353 if ord(ch) < 0xD800:
354 _STORECHAR(result, ord(ch), byteorder)
355 else:
356 errorhandler('strict', public_encoding_name,
357 'surrogates not allowed',
358 s, pos-1, pos)
359 continue
360
361 return result.build()
362
363 def unicode_encode_utf_16(s, size, errors,
364 errorhandler=None,
365 allow_surrogates=True):
366 return unicode_encode_utf_16_helper(s, size, errors, errorhandler,
367 allow_surrogates, "native",
368 'utf-16-' + BYTEORDER2)
369
370 def unicode_encode_utf_16_be(s, size, errors,
371 errorhandler=None,
372 allow_surrogates=True):
373 return unicode_encode_utf_16_helper(s, size, errors, errorhandler,
374 allow_surrogates, "big",
375 'utf-16-be')
376
377 def unicode_encode_utf_16_le(s, size, errors,
378 errorhandler=None,
379 allow_surrogates=True):
380 return unicode_encode_utf_16_helper(s, size, errors, errorhandler,
381 allow_surrogates, "little",
382 'utf-16-le')
383
168384
169385 # ____________________________________________________________
170386 # utf-32
107107 max_jitdriver = jit.JitDriver(name='max',
108108 greens=['has_key', 'has_item', 'w_type'], reds='auto')
109109
110 def make_min_max(unroll):
111 @specialize.arg(2)
112 def min_max_impl(space, args, implementation_of):
113 if implementation_of == "max":
114 compare = space.gt
115 jitdriver = max_jitdriver
116 else:
117 compare = space.lt
118 jitdriver = min_jitdriver
119 any_kwds = bool(args.keywords)
120 args_w = args.arguments_w
121 if len(args_w) > 1:
122 if unroll and len(args_w) == 2 and not any_kwds:
123 # a fast path for the common case, useful for interpreted
124 # mode and to reduce the length of the jit trace
125 w0, w1 = args_w
126 if space.is_true(compare(w1, w0)):
127 return w1
128 else:
129 return w0
130 w_sequence = space.newtuple(args_w)
131 elif len(args_w):
132 w_sequence = args_w[0]
133 else:
134 raise oefmt(space.w_TypeError,
135 "%s() expects at least one argument",
136 implementation_of)
137 w_key = None
138 w_default = None
139 if any_kwds:
140 kwds = args.keywords
141 for n in range(len(kwds)):
142 if kwds[n] == "key":
143 w_key = args.keywords_w[n]
144 elif kwds[n] == "default":
145 w_default = args.keywords_w[n]
146 else:
147 raise oefmt(space.w_TypeError,
148 "%s() got unexpected keyword argument",
149 implementation_of)
150
151 if w_default is not None and len(args_w) > 1:
152 raise oefmt(space.w_TypeError,
153 "Cannot specify a default for %s() with multiple positional arguments",
154 implementation_of)
155
156 w_iter = space.iter(w_sequence)
157 w_type = space.type(w_iter)
158 has_key = w_key is not None
159 has_item = False
160 w_max_item = None
161 w_max_val = None
162 while True:
163 if not unroll:
164 jitdriver.jit_merge_point(has_key=has_key, has_item=has_item, w_type=w_type)
165 try:
166 w_item = space.next(w_iter)
167 except OperationError as e:
168 if not e.match(space, space.w_StopIteration):
169 raise
170 break
171 if has_key:
172 w_compare_with = space.call_function(w_key, w_item)
173 else:
174 w_compare_with = w_item
175 if not has_item or \
176 space.is_true(compare(w_compare_with, w_max_val)):
177 has_item = True
178 w_max_item = w_item
179 w_max_val = w_compare_with
180 if w_max_item is None:
181 if w_default is not None:
182 w_max_item = w_default
183 else:
184 raise oefmt(space.w_ValueError, "arg is an empty sequence")
185 return w_max_item
186 if unroll:
187 min_max_impl = jit.unroll_safe(min_max_impl)
188 return min_max_impl
189
190 min_max_unroll = make_min_max(True)
191 min_max_normal = make_min_max(False)
192
110 @specialize.arg(4)
111 def min_max_sequence(space, w_sequence, w_key, w_default, implementation_of):
112 if implementation_of == "max":
113 compare = space.gt
114 jitdriver = max_jitdriver
115 else:
116 compare = space.lt
117 jitdriver = min_jitdriver
118 w_iter = space.iter(w_sequence)
119 w_type = space.type(w_iter)
120 has_key = w_key is not None
121 has_item = False
122 w_max_item = w_default
123 w_max_val = None
124 while True:
125 jitdriver.jit_merge_point(has_key=has_key, has_item=has_item,
126 w_type=w_type)
127 try:
128 w_item = space.next(w_iter)
129 except OperationError as e:
130 if not e.match(space, space.w_StopIteration):
131 raise
132 break
133 if has_key:
134 w_compare_with = space.call_function(w_key, w_item)
135 else:
136 w_compare_with = w_item
137 if (not has_item or
138 space.is_true(compare(w_compare_with, w_max_val))):
139 has_item = True
140 w_max_item = w_item
141 w_max_val = w_compare_with
142 if w_max_item is None:
143 raise oefmt(space.w_ValueError, "arg is an empty sequence")
144 return w_max_item
145
146 @specialize.arg(3)
147 @jit.look_inside_iff(lambda space, args_w, w_key, implementation_of:
148 jit.loop_unrolling_heuristic(args_w, len(args_w), 3))
149 def min_max_multiple_args(space, args_w, w_key, implementation_of):
150 # case of multiple arguments (at least two). We unroll it if there
151 # are 2 or 3 arguments.
152 if implementation_of == "max":
153 compare = space.gt
154 else:
155 compare = space.lt
156 w_max_item = args_w[0]
157 if w_key is not None:
158 w_max_val = space.call_function(w_key, w_max_item)
159 else:
160 w_max_val = w_max_item
161 for i in range(1, len(args_w)):
162 w_item = args_w[i]
163 if w_key is not None:
164 w_compare_with = space.call_function(w_key, w_item)
165 else:
166 w_compare_with = w_item
167 if space.is_true(compare(w_compare_with, w_max_val)):
168 w_max_item = w_item
169 w_max_val = w_compare_with
170 return w_max_item
171
172 @jit.unroll_safe # the loop over kwds
193173 @specialize.arg(2)
194174 def min_max(space, args, implementation_of):
195 if not jit.we_are_jitted() or len(args.arguments_w) != 1 and \
196 jit.loop_unrolling_heuristic(args.arguments_w, len(args.arguments_w)):
197 return min_max_unroll(space, args, implementation_of)
198 else:
199 return min_max_normal(space, args, implementation_of)
200 min_max._always_inline = True
175 w_key = None
176 w_default = None
177 if bool(args.keywords):
178 kwds = args.keywords
179 for n in range(len(kwds)):
180 if kwds[n] == "key":
181 w_key = args.keywords_w[n]
182 elif kwds[n] == "default":
183 w_default = args.keywords_w[n]
184 else:
185 raise oefmt(space.w_TypeError,
186 "%s() got unexpected keyword argument",
187 implementation_of)
188 #
189 args_w = args.arguments_w
190 if len(args_w) > 1:
191 if w_default is not None:
192 raise oefmt(space.w_TypeError,
193 "Cannot specify a default for %s() with multiple "
194 "positional arguments", implementation_of)
195 return min_max_multiple_args(space, args_w, w_key, implementation_of)
196 elif len(args_w):
197 return min_max_sequence(space, args_w[0], w_key, w_default,
198 implementation_of)
199 else:
200 raise oefmt(space.w_TypeError,
201 "%s() expects at least one argument",
202 implementation_of)
201203
202204 def max(space, __args__):
203205 """max(iterable[, key=func]) -> value
2626 @unwrap_spec(code=int)
2727 def chr(space, code):
2828 "Return a Unicode string of one character with the given ordinal."
29 try:
30 c = UNICHR(code)
31 except ValueError:
29 if code < 0 or code > 0x10FFFF:
3230 raise oefmt(space.w_ValueError, "chr() arg out of range")
31 c = UNICHR(code)
3332 return space.newunicode(c)
3433
3534 def len(space, w_obj):
136135 """iter(collection) -> iterator over the elements of the collection.
137136
138137 iter(callable, sentinel) -> iterator calling callable() until it returns
139 the sentinal.
138 the sentinel.
140139 """
141140 if w_sentinel is None:
142141 return space.iter(w_collection_or_callable)
11 class State:
22 def __init__(self, space):
33 self.w_open = space.appexec([], """():
4 import io
5 return io.open""")
6
4 import _io
5 return _io.open""")
6
77 def get(space):
88 return space.fromcache(State)
653653 raises(TypeError, max, 1, default=0)
654654 raises(TypeError, max, default=1)
655655
656 def test_max_list_and_key(self):
657 assert max(["100", "50", "30", "-200"], key=int) == "100"
658 assert max("100", "50", "30", "-200", key=int) == "100"
659
656660
657661 try:
658662 from hypothesis import given, strategies, example
4747 'int_lshift': 'interp_intop.int_lshift',
4848 'int_rshift': 'interp_intop.int_rshift',
4949 'uint_rshift': 'interp_intop.uint_rshift',
50 'int_mulmod': 'interp_intop.int_mulmod',
5051 }
5152
5253
104105 '_promote' : 'interp_magic._promote',
105106 'normalize_exc' : 'interp_magic.normalize_exc',
106107 'StdErrPrinter' : 'interp_stderrprinter.W_StdErrPrinter',
108 'side_effects_ok' : 'interp_magic.side_effects_ok',
107109 'stack_almost_full' : 'interp_magic.stack_almost_full',
108110 'fsencode' : 'interp_magic.fsencode',
109111 'fsdecode' : 'interp_magic.fsdecode',
112 'pyos_inputhook' : 'interp_magic.pyos_inputhook',
110113 }
111114
112115 submodules = {
143146 features = detect_cpu.getcpufeatures(model)
144147 self.extra_interpdef('jit_backend_features',
145148 'space.wrap(%r)' % features)
149 if self.space.config.translation.reverse_debugger:
150 self.extra_interpdef('revdb_stop', 'interp_magic.revdb_stop')
151 else:
152 self.extra_interpdef('revdb_stop', 'space.w_None')
55 from rpython.tool.sourcetools import func_with_new_name
66
77
8 def create_builder(name, strtype, builder_cls):
9 if strtype is str:
10 unwrap = 'bytes'
11 else:
12 unwrap = unicode
13 class W_Builder(W_Root):
14 def __init__(self, space, size):
15 if size < 0:
16 self.builder = builder_cls()
17 else:
18 self.builder = builder_cls(size)
8 class W_BytesBuilder(W_Root):
9 def __init__(self, space, size):
10 if size < 0:
11 self.builder = StringBuilder()
12 else:
13 self.builder = StringBuilder(size)
1914
20 @unwrap_spec(size=int)
21 def descr__new__(space, w_subtype, size=-1):
22 return W_Builder(space, size)
15 @unwrap_spec(size=int)
16 def descr__new__(space, w_subtype, size=-1):
17 return W_BytesBuilder(space, size)
2318
24 @unwrap_spec(s=unwrap)
25 def descr_append(self, space, s):
26 self.builder.append(s)
19 @unwrap_spec(s='bytes')
20 def descr_append(self, space, s):
21 self.builder.append(s)
2722
28 @unwrap_spec(s=unwrap, start=int, end=int)
29 def descr_append_slice(self, space, s, start, end):
30 if not 0 <= start <= end <= len(s):
31 raise oefmt(space.w_ValueError, "bad start/stop")
32 self.builder.append_slice(s, start, end)
23 @unwrap_spec(s='bytes', start=int, end=int)
24 def descr_append_slice(self, space, s, start, end):
25 if not 0 <= start <= end <= len(s):
26 raise oefmt(space.w_ValueError, "bad start/stop")
27 self.builder.append_slice(s, start, end)
3328
34 def descr_build(self, space):
35 s = self.builder.build()
36 # after build(), we can continue to append more strings
37 # to the same builder. This is supported since
38 # 2ff5087aca28 in RPython.
39 if strtype is str:
40 return space.newbytes(s)
41 else:
42 return space.newunicode(s)
29 def descr_build(self, space):
30 w_s = space.newbytes(self.builder.build())
31 # after build(), we can continue to append more strings
32 # to the same builder. This is supported since
33 # 2ff5087aca28 in RPython.
34 return w_s
4335
44 def descr_len(self, space):
45 if self.builder is None:
46 raise oefmt(space.w_ValueError, "no length of built builder")
47 return space.newint(self.builder.getlength())
36 def descr_len(self, space):
37 if self.builder is None:
38 raise oefmt(space.w_ValueError, "no length of built builder")
39 return space.newint(self.builder.getlength())
4840
49 W_Builder.__name__ = "W_%s" % name
50 W_Builder.typedef = TypeDef(name,
51 __new__ = interp2app(func_with_new_name(
52 W_Builder.descr__new__.im_func,
53 '%s_new' % (name,))),
54 append = interp2app(W_Builder.descr_append),
55 append_slice = interp2app(W_Builder.descr_append_slice),
56 build = interp2app(W_Builder.descr_build),
57 __len__ = interp2app(W_Builder.descr_len),
58 )
59 W_Builder.typedef.acceptable_as_base_class = False
60 return W_Builder
41 W_BytesBuilder.typedef = TypeDef("BytesBuilder",
42 __new__ = interp2app(func_with_new_name(
43 W_BytesBuilder.descr__new__.im_func,
44 'BytesBuilder_new')),
45 append = interp2app(W_BytesBuilder.descr_append),
46 append_slice = interp2app(W_BytesBuilder.descr_append_slice),
47 build = interp2app(W_BytesBuilder.descr_build),
48 __len__ = interp2app(W_BytesBuilder.descr_len),
49 )
50 W_BytesBuilder.typedef.acceptable_as_base_class = False
6151
62 W_StringBuilder = create_builder("StringBuilder", unicode, UnicodeBuilder)
63 W_BytesBuilder = create_builder("BytesBuilder", str, StringBuilder)
52 class W_UnicodeBuilder(W_Root):
53 def __init__(self, space, size):
54 if size < 0:
55 self.builder = UnicodeBuilder()
56 else:
57 self.builder = UnicodeBuilder(size)
58
59 @unwrap_spec(size=int)
60 def descr__new__(space, w_subtype, size=-1):
61 return W_UnicodeBuilder(space, size)
62
63 @unwrap_spec(s=unicode)
64 def descr_append(self, space, s):
65 self.builder.append(s)
66
67 @unwrap_spec(s=unicode, start=int, end=int)
68 def descr_append_slice(self, space, s, start, end):
69 if not 0 <= start <= end <= len(s):
70 raise oefmt(space.w_ValueError, "bad start/stop")
71 self.builder.append_slice(s, start, end)
72
73 def descr_build(self, space):
74 w_s = space.newunicode(self.builder.build())
75 # after build(), we can continue to append more strings
76 # to the same builder. This is supported since
77 # 2ff5087aca28 in RPython.
78 return w_s
79
80 def descr_len(self, space):
81 if self.builder is None:
82 raise oefmt(space.w_ValueError, "no length of built builder")
83 return space.newint(self.builder.getlength())
84
85 W_UnicodeBuilder.typedef = TypeDef("StringBuilder",
86 __new__ = interp2app(func_with_new_name(
87 W_UnicodeBuilder.descr__new__.im_func,
88 'UnicodeBuilder_new')),
89 append = interp2app(W_UnicodeBuilder.descr_append),
90 append_slice = interp2app(W_UnicodeBuilder.descr_append_slice),
91 build = interp2app(W_UnicodeBuilder.descr_build),
92 __len__ = interp2app(W_UnicodeBuilder.descr_len),
93 )
94 W_UnicodeBuilder.typedef.acceptable_as_base_class = False
95 W_StringBuilder = W_UnicodeBuilder
11 from rpython.rtyper.lltypesystem import lltype
22 from rpython.rtyper.lltypesystem.lloperation import llop
33 from rpython.rlib.rarithmetic import r_uint, intmask
4 from rpython.rlib.rarithmetic import int_c_div, int_c_mod
4 from rpython.rlib.rarithmetic import int_c_div, int_c_mod, mulmod
55 from rpython.rlib import jit
66
77
3838 n = r_uint(n)
3939 x = llop.uint_rshift(lltype.Unsigned, n, m)
4040 return space.newint(intmask(x))
41
42 @unwrap_spec(a=int, b=int, c=int)
43 def int_mulmod(space, a, b, c):
44 return space.newint(mulmod(a, b, c))
188188 def fsdecode(space, w_obj):
189189 """Direct access to the interp-level fsdecode()"""
190190 return space.fsdecode(w_obj)
191
192 def side_effects_ok(space):
193 """For use with the reverse-debugger: this function normally returns
194 True, but will return False if we are evaluating a debugging command
195 like a watchpoint. You are responsible for not doing any side effect
196 at all (including no caching) when evaluating watchpoints. This
197 function is meant to help a bit---you can write:
198
199 if not __pypy__.side_effects_ok():
200 skip the caching logic
201
202 inside getter methods or properties, to make them usable from
203 watchpoints. Note that you need to re-run ``REVDB=.. pypy''
204 after changing the Python code.
205 """
206 return space.newbool(space._side_effects_ok())
207
208 def revdb_stop(space):
209 from pypy.interpreter.reverse_debugging import stop_point
210 stop_point()
211
212 def pyos_inputhook(space):
213 """Call PyOS_InputHook() from the CPython C API."""
214 if not space.config.objspace.usemodules.cpyext:
215 return
216 w_modules = space.sys.get('modules')
217 if space.finditem_str(w_modules, 'cpyext') is None:
218 return # cpyext not imported yet, ignore
219 from pypy.module.cpyext.api import invoke_pyos_inputhook
220 invoke_pyos_inputhook(space)
33 def test_simple(self):
44 from __pypy__.builders import StringBuilder
55 b = StringBuilder()
6 b.append("abc")
7 b.append("123")
8 b.append("1")
6 b.append(u"abc")
7 b.append(u"123")
8 b.append(u"1")
99 s = b.build()
10 assert s == "abc1231"
10 assert s == u"abc1231"
1111 assert b.build() == s
12 b.append("123")
13 assert b.build() == s + "123"
12 b.append(u"123")
13 assert b.build() == s + u"123"
1414
1515 def test_preallocate(self):
1616 from __pypy__.builders import StringBuilder
1717 b = StringBuilder(10)
18 b.append("abc")
19 b.append("123")
18 b.append(u"abc")
19 b.append(u"123")
2020 s = b.build()
21 assert s == "abc123"
21 assert s == u"abc123"
2222
2323 def test_append_slice(self):
2424 from __pypy__.builders import StringBuilder
2525 b = StringBuilder()
26 b.append_slice("abcdefgh", 2, 5)
27 raises(ValueError, b.append_slice, "1", 2, 1)
26 b.append_slice(u"abcdefgh", 2, 5)
27 raises(ValueError, b.append_slice, u"1", 2, 1)
2828 s = b.build()
29 assert s == "cde"
30 b.append_slice("abc", 1, 2)
31 assert b.build() == "cdeb"
29 assert s == u"cde"
30 b.append_slice(u"abc", 1, 2)
31 assert b.build() == u"cdeb"
3232
3333 def test_stringbuilder(self):
3434 from __pypy__.builders import BytesBuilder
101101 assert intop.uint_rshift(-1, 1) == sys.maxsize
102102 assert intop.uint_rshift(-1, bits-2) == 3
103103 assert intop.uint_rshift(-1, bits-1) == 1
104
105 def test_mulmod(self):
106 from __pypy__ import intop
107 assert intop.int_mulmod(9373891, 9832739, 2**31-1) == 1025488209
134134 cls.w_runappdirect = cls.space.wrap(cls.runappdirect)
135135
136136 def test_jit_backend_features(self):
137 from __pypy__ import jit_backend_features
137 try:
138 from __pypy__ import jit_backend_features
139 except ImportError:
140 skip("compiled without jit")
138141 supported_types = jit_backend_features
139142 assert isinstance(supported_types, list)
140143 for x in supported_types:
22 from rpython.rlib import rdynload, clibffi
33 from rpython.rtyper.lltypesystem import rffi
44
5 VERSION = "1.11.5"
5 VERSION = "1.12.0"
66
77 FFI_DEFAULT_ABI = clibffi.FFI_DEFAULT_ABI
88 try:
5151 'unpack': 'func.unpack',
5252 'buffer': 'cbuffer.MiniBuffer',
5353 'memmove': 'func.memmove',
54 'release': 'func.release',
5455
5556 'get_errno': 'cerrno.get_errno',
5657 'set_errno': 'cerrno.set_errno',
7071 def __init__(self, space, *args):
7172 MixedModule.__init__(self, space, *args)
7273 #
73 if not space.config.objspace.disable_entrypoints:
74 if (not space.config.objspace.disable_entrypoints and
75 not space.config.objspace.disable_entrypoints_in_cffi):
7476 # import 'embedding', which has the side-effect of registering
7577 # the 'pypy_init_embedded_cffi_module' entry point
7678 from pypy.module._cffi_backend import embedding
155155 return MiniBuffer(LLBuffer(ptr, size), w_cdata)
156156
157157 MiniBuffer.typedef = TypeDef(
158 "_cffi_backend.buffer",
158 "_cffi_backend.buffer", None, None, "read-write",
159159 __new__ = interp2app(MiniBuffer___new__),
160160 __len__ = interp2app(MiniBuffer.descr_len),
161161 __getitem__ = interp2app(MiniBuffer.descr_getitem),
22 """
33 import sys, os, py
44
5 from rpython.rlib import clibffi, jit, rgc, objectmodel
5 from rpython.rlib import clibffi, jit, objectmodel
66 from rpython.rlib.objectmodel import keepalive_until_here
7 from rpython.rtyper.lltypesystem import lltype, llmemory, rffi
7 from rpython.rtyper.lltypesystem import lltype, rffi
88
99 from pypy.interpreter.error import OperationError, oefmt
1010 from pypy.module._cffi_backend import cerrno, misc, parse_c_type
1212 from pypy.module._cffi_backend.ctypefunc import SIZE_OF_FFI_ARG, W_CTypeFunc
1313 from pypy.module._cffi_backend.ctypeprim import W_CTypePrimitiveSigned
1414 from pypy.module._cffi_backend.ctypevoid import W_CTypeVoid
15 from pypy.module._cffi_backend.hide_reveal import hide_reveal1
1516
1617 BIG_ENDIAN = sys.byteorder == 'big'
1718
2930 return cdata
3031
3132 def reveal_callback(raw_ptr):
32 addr = rffi.cast(llmemory.Address, raw_ptr)
33 gcref = rgc.reveal_gcref(addr)
34 return rgc.try_cast_gcref_to_instance(W_ExternPython, gcref)
33 return hide_reveal1().reveal_object(W_ExternPython, raw_ptr)
3534
3635
3736 class Closure(object):
9190 return ctype
9291
9392 def hide_object(self):
94 gcref = rgc.cast_instance_to_gcref(self)
95 raw = rgc.hide_nonmovable_gcref(gcref)
96 return rffi.cast(rffi.VOIDP, raw)
93 return hide_reveal1().hide_object(rffi.VOIDP, self)
9794
9895 def _repr_extra(self):
9996 space = self.space
7676 def int(self, space):
7777 with self as ptr:
7878 w_result = self.ctype.cast_to_int(ptr)
79 return w_result
80
81 def long(self, space):
82 w_result = self.int(space)
83 space = self.space
84 if space.is_w(space.type(w_result), space.w_int):
85 w_result = space.newlong(space.int_w(w_result))
8679 return w_result
8780
8881 def float(self):
482475 def get_structobj(self):
483476 return None
484477
478 def enter_exit(self, exit_now):
479 raise oefmt(self.space.w_ValueError,
480 "only 'cdata' object from ffi.new(), ffi.gc(), ffi.from_buffer() "
481 "or ffi.new_allocator()() can be used with the 'with' keyword or "
482 "ffi.release()")
483
484 def descr_enter(self):
485 self.enter_exit(False)
486 return self
487
488 def descr_exit(self, args_w):
489 self.enter_exit(True)
490
485491
486492 class W_CDataMem(W_CData):
487493 """This is used only by the results of cffi.cast('int', x)
534540 def get_structobj(self):
535541 return self
536542
543 def enter_exit(self, exit_now):
544 from pypy.module._cffi_backend.ctypeptr import W_CTypePtrOrArray
545 if not isinstance(self.ctype, W_CTypePtrOrArray):
546 W_CData.enter_exit(self, exit_now)
547 elif exit_now:
548 self._do_exit()
549
550 def _do_exit(self):
551 raise NotImplementedError
552
537553
538554 class W_CDataNewStd(W_CDataNewOwning):
539555 """Subclass using the standard allocator, lltype.malloc()/lltype.free()"""
540 _attrs_ = []
556 _attrs_ = ['explicitly_freed']
557 explicitly_freed = False
541558
542559 @rgc.must_be_light_finalizer
543560 def __del__(self):
544 lltype.free(self._ptr, flavor='raw')
561 if not self.explicitly_freed:
562 lltype.free(self._ptr, flavor='raw')
563
564 def _do_exit(self):
565 if not self.explicitly_freed:
566 rgc.add_memory_pressure(-self._sizeof(), self)
567 self.explicitly_freed = True
568 rgc.may_ignore_finalizer(self)
569 lltype.free(self._ptr, flavor='raw')
545570
546571
547572 class W_CDataNewNonStd(W_CDataNewOwning):
549574 _attrs_ = ['w_raw_cdata', 'w_free']
550575
551576 def _finalize_(self):
552 self.space.call_function(self.w_free, self.w_raw_cdata)
577 if self.w_free is not None:
578 self.space.call_function(self.w_free, self.w_raw_cdata)
579
580 def _do_exit(self):
581 w_free = self.w_free
582 if w_free is not None:
583 rgc.add_memory_pressure(-self._sizeof(), self)
584 self.w_free = None
585 self.may_unregister_rpython_finalizer(self.space)
586 self.space.call_function(w_free, self.w_raw_cdata)
553587
554588
555589 class W_CDataPtrToStructOrUnion(W_CData):
579613 else:
580614 return None
581615
616 def enter_exit(self, exit_now):
617 if exit_now:
618 structobj = self.structobj
619 if isinstance(structobj, W_CDataNewOwning):
620 structobj._do_exit()
621
582622
583623 class W_CDataSliced(W_CData):
584624 """Subclass with an explicit length, for slices."""
617657
618658 class W_CDataFromBuffer(W_CData):
619659 _attrs_ = ['buf', 'length', 'w_keepalive']
620 _immutable_fields_ = ['buf', 'length', 'w_keepalive']
621
622 def __init__(self, space, cdata, ctype, buf, w_object):
660 _immutable_fields_ = ['buf', 'length']
661
662 def __init__(self, space, cdata, length, ctype, buf, w_object):
623663 W_CData.__init__(self, space, cdata, ctype)
624664 self.buf = buf
625 self.length = buf.getlength()
665 self.length = length
626666 self.w_keepalive = w_object
627667
628668 def get_array_length(self):
629669 return self.length
630670
631671 def _repr_extra(self):
632 w_repr = self.space.repr(self.w_keepalive)
633 return "buffer len %d from '%s' object" % (
634 self.length, self.space.type(self.w_keepalive).name)
672 if self.w_keepalive is not None:
673 name = self.space.type(self.w_keepalive).name
674 else:
675 name = "(released)"
676 return "buffer len %d from '%s' object" % (self.length, name)
677
678 def enter_exit(self, exit_now):
679 # for now, limited effect on PyPy
680 if exit_now:
681 self.w_keepalive = None
635682
636683
637684 class W_CDataGCP(W_CData):
646693 self.register_finalizer(space)
647694
648695 def _finalize_(self):
696 self.invoke_finalizer()
697
698 def invoke_finalizer(self):
649699 w_destructor = self.w_destructor
650700 if w_destructor is not None:
651701 self.w_destructor = None
654704 def detach_destructor(self):
655705 self.w_destructor = None
656706 self.may_unregister_rpython_finalizer(self.space)
707
708 def enter_exit(self, exit_now):
709 if exit_now:
710 self.may_unregister_rpython_finalizer(self.space)
711 self.invoke_finalizer()
657712
658713
659714 W_CData.typedef = TypeDef(
663718 __repr__ = interp2app(W_CData.repr),
664719 __bool__ = interp2app(W_CData.bool),
665720 __int__ = interp2app(W_CData.int),
666 __long__ = interp2app(W_CData.long),
667721 __float__ = interp2app(W_CData.float),
668722 __complex__ = interp2app(W_CData.complex),
669723 __len__ = interp2app(W_CData.len),
685739 __iter__ = interp2app(W_CData.iter),
686740 __weakref__ = make_weakref_descr(W_CData),
687741 __dir__ = interp2app(W_CData.dir),
742 __enter__ = interp2app(W_CData.descr_enter),
743 __exit__ = interp2app(W_CData.descr_exit),
688744 )
689745 W_CData.typedef.acceptable_as_base_class = False
00 from rpython.rtyper.lltypesystem import lltype, llmemory, rffi
11 from rpython.rlib.objectmodel import specialize, we_are_translated
2 from rpython.rlib.rdynload import DLLHANDLE, dlopen, dlsym, dlclose, DLOpenError
2 from rpython.rlib.rdynload import DLLHANDLE, dlsym, dlclose
33
44 from pypy.interpreter.error import oefmt
5 from pypy.module._rawffi.interp_rawffi import wrap_dlopenerror
65
76 from pypy.module._cffi_backend.parse_c_type import (
87 _CFFI_OPCODE_T, GLOBAL_S, CDL_INTCONST_S, STRUCT_UNION_S, FIELD_S,
98 ENUM_S, TYPENAME_S, ll_set_cdl_realize_global_int)
109 from pypy.module._cffi_backend.realize_c_type import getop
1110 from pypy.module._cffi_backend.lib_obj import W_LibObject
12 from pypy.module._cffi_backend import cffi_opcode, cffi1_module
13
11 from pypy.module._cffi_backend import cffi_opcode, cffi1_module, misc
1412
1513 class W_DlOpenLibObject(W_LibObject):
1614
17 def __init__(self, ffi, filename, flags):
18 with rffi.scoped_str2charp(filename) as ll_libname:
19 if filename is None:
20 filename = "<None>"
21 try:
22 handle = dlopen(ll_libname, flags)
23 except DLOpenError as e:
24 raise wrap_dlopenerror(ffi.space, e, filename)
25 W_LibObject.__init__(self, ffi, filename)
15 def __init__(self, ffi, w_filename, flags):
16 space = ffi.space
17 fname, handle = misc.dlopen_w(space, w_filename, flags)
18 W_LibObject.__init__(self, ffi, fname)
2619 self.libhandle = handle
27 self.register_finalizer(ffi.space)
20 self.register_finalizer(space)
2821
2922 def _finalize_(self):
3023 h = self.libhandle
2424 assert isinstance(ctptr, W_CTypePointer)
2525 W_CTypePtrOrArray.__init__(self, space, arraysize, extra, 0,
2626 ctptr.ctitem)
27 self.length = length
27 self.length = length # -1 if no length is given, e.g. 'int[]'
2828 self.ctptr = ctptr
2929
3030 def _alignof(self):
8585 def _check_subscript_index(self, w_cdata, i):
8686 space = self.space
8787 if i < 0:
88 raise oefmt(space.w_IndexError, "negative index not supported")
88 raise oefmt(space.w_IndexError, "negative index")
8989 if i >= w_cdata.get_array_length():
9090 raise oefmt(space.w_IndexError,
9191 "index too large for cdata '%s' (expected %d < %d)",
9595 def _check_slice_index(self, w_cdata, start, stop):
9696 space = self.space
9797 if start < 0:
98 raise oefmt(space.w_IndexError, "negative index not supported")
98 raise oefmt(space.w_IndexError, "negative index")
9999 if stop > w_cdata.get_array_length():
100100 raise oefmt(space.w_IndexError,
101101 "index too large (expected %d <= %d)",
103103 return self.ctptr
104104
105105 def convert_from_object(self, cdata, w_ob):
106 self.convert_array_from_object(cdata, w_ob)
106 if isinstance(w_ob, cdataobj.W_CData) and w_ob.ctype is self:
107 length = w_ob.get_array_length()
108 with w_ob as source:
109 source = rffi.cast(rffi.VOIDP, source)
110 target = rffi.cast(rffi.VOIDP, cdata)
111 size = rffi.cast(rffi.SIZE_T, self.ctitem.size * length)
112 rffi.c_memcpy(target, source, size)
113 else:
114 self.convert_array_from_object(cdata, w_ob)
107115
108116 def convert_to_object(self, cdata):
109117 if self.length < 0:
5050 def unpack_list_of_float_items(self, ptr, length):
5151 return None
5252
53 def pack_list_of_items(self, cdata, w_ob):
53 def pack_list_of_items(self, cdata, w_ob, expected_length):
5454 return False
55
56 def _within_bounds(self, actual_length, expected_length):
57 return expected_length < 0 or actual_length <= expected_length
5558
5659 def newp(self, w_init, allocator):
5760 space = self.space
101104 # ctype 'A' must be a pointer to same type, not cdata
102105 # 'B'", but with A=B, then give instead a different error
103106 # message to try to clear up the confusion
107 if self is w_got.ctype:
108 raise oefmt(space.w_SystemError,
109 "initializer for ctype '%s' is correct, but we get "
110 "an internal mismatch--please report a bug",
111 self.name)
104112 return oefmt(space.w_TypeError,
105113 "initializer for ctype '%s' appears indeed to "
106114 "be '%s', but the types are different (check "
291291 return res
292292 return None
293293
294 def pack_list_of_items(self, cdata, w_ob):
294 def pack_list_of_items(self, cdata, w_ob, expected_length):
295295 int_list = self.space.listview_int(w_ob)
296 if int_list is not None:
296 if (int_list is not None and
297 self._within_bounds(len(int_list), expected_length)):
297298 if self.size == rffi.sizeof(rffi.LONG): # fastest path
298299 from rpython.rlib.rrawarray import copy_list_to_raw_array
299300 cdata = rffi.cast(rffi.LONGP, cdata)
304305 if overflowed != 0:
305306 self._overflow(self.space.newint(overflowed))
306307 return True
307 return W_CTypePrimitive.pack_list_of_items(self, cdata, w_ob)
308 return W_CTypePrimitive.pack_list_of_items(self, cdata, w_ob,
309 expected_length)
308310
309311
310312 class W_CTypePrimitiveUnsigned(W_CTypePrimitive):
374376 return res
375377 return None
376378
377 def pack_list_of_items(self, cdata, w_ob):
379 def pack_list_of_items(self, cdata, w_ob, expected_length):
378380 int_list = self.space.listview_int(w_ob)
379 if int_list is not None:
381 if (int_list is not None and
382 self._within_bounds(len(int_list), expected_length)):
380383 overflowed = misc.pack_list_to_raw_array_bounds_unsigned(
381384 int_list, cdata, self.size, self.vrangemax)
382385 if overflowed != 0:
383386 self._overflow(self.space.newint(overflowed))
384387 return True
385 return W_CTypePrimitive.pack_list_of_items(self, cdata, w_ob)
388 return W_CTypePrimitive.pack_list_of_items(self, cdata, w_ob,
389 expected_length)
386390
387391
388392 class W_CTypePrimitiveBool(W_CTypePrimitiveUnsigned):
470474 return res
471475 return None
472476
473 def pack_list_of_items(self, cdata, w_ob):
477 def pack_list_of_items(self, cdata, w_ob, expected_length):
474478 float_list = self.space.listview_float(w_ob)
475 if float_list is not None:
479 if (float_list is not None and
480 self._within_bounds(len(float_list), expected_length)):
476481 if self.size == rffi.sizeof(rffi.DOUBLE): # fastest path
477482 from rpython.rlib.rrawarray import copy_list_to_raw_array
478483 cdata = rffi.cast(rffi.DOUBLEP, cdata)
482487 misc.pack_float_list_to_raw_array(float_list, cdata,
483488 rffi.FLOAT, rffi.FLOATP)
484489 return True
485 return W_CTypePrimitive.pack_list_of_items(self, cdata, w_ob)
490 return W_CTypePrimitive.pack_list_of_items(self, cdata, w_ob,
491 expected_length)
486492
487493 def unpack_ptr(self, w_ctypeptr, ptr, length):
488494 result = self.unpack_list_of_float_items(ptr, length)
552558 # 'list(array-of-longdouble)' returns a list of cdata objects,
553559 # not a list of floats.
554560
555 def pack_list_of_items(self, cdata, w_ob):
561 def pack_list_of_items(self, cdata, w_ob, expected_length):
556562 float_list = self.space.listview_float(w_ob)
557 if float_list is not None:
563 if (float_list is not None and
564 self._within_bounds(len(float_list), expected_length)):
558565 misc.pack_float_list_to_raw_array(float_list, cdata,
559566 rffi.LONGDOUBLE, rffi.LONGDOUBLEP)
560567 return True
561 return W_CTypePrimitive.pack_list_of_items(self, cdata, w_ob)
568 return W_CTypePrimitive.pack_list_of_items(self, cdata, w_ob,
569 expected_length)
562570
563571 @jit.dont_look_inside
564572 def nonzero(self, cdata):
5757
5858 def _convert_array_from_listview(self, cdata, lst_w):
5959 space = self.space
60 if self.length >= 0 and len(lst_w) > self.length:
60 if not self._within_bounds(len(lst_w), self.length):
6161 raise oefmt(space.w_IndexError,
6262 "too many initializers for '%s' (got %d)",
6363 self.name, len(lst_w))
7070 space = self.space
7171 if (space.isinstance_w(w_ob, space.w_list) or
7272 space.isinstance_w(w_ob, space.w_tuple)):
73 if self.ctitem.pack_list_of_items(cdata, w_ob): # fast path
74 pass
73 if self.ctitem.pack_list_of_items(cdata, w_ob, self.length):
74 pass # fast path
7575 else:
7676 self._convert_array_from_listview(cdata, space.listview(w_ob))
7777 elif self.accept_str:
316316 if isinstance(self.ctitem, ctypeprim.W_CTypePrimitiveBool):
317317 self._must_be_string_of_zero_or_one(value)
318318 keepalives[i] = value
319 buf, buf_flag = rffi.get_nonmovingbuffer_final_null(value)
320 rffi.cast(rffi.CCHARPP, cdata)[0] = buf
321 return ord(buf_flag) # 4, 5 or 6
319 return misc.write_string_as_charp(cdata, value)
322320 #
323321 if (space.isinstance_w(w_init, space.w_list) or
324322 space.isinstance_w(w_init, space.w_tuple)):
9494 if os.name == 'nt':
9595
9696 do_includes = r"""
97 #ifndef _WIN32_WINNT
9798 #define _WIN32_WINNT 0x0501
99 #endif
98100 #include <windows.h>
99101
100102 static void _cffi_init(void);
6868 import sys
6969 class FileLike:
7070 def write(self, x):
71 of.write(x)
71 try:
72 of.write(x)
73 except:
74 pass
7275 self.buf += x
7376 fl = FileLike()
7477 fl.buf = ''
326326 return w_ctype.cast(w_ob)
327327
328328
329 def descr_from_buffer(self, w_python_buffer):
329 @unwrap_spec(require_writable=int)
330 def descr_from_buffer(self, w_cdecl, w_python_buffer=None,
331 require_writable=0):
330332 """\
331333 Return a <cdata 'char[]'> that points to the data of the given Python
332334 object, which must support the buffer interface. Note that this is
335337 containing large quantities of raw data in some other format, like
336338 'array.array' or numpy arrays."""
337339 #
338 w_ctchara = newtype._new_chara_type(self.space)
339 return func._from_buffer(self.space, w_ctchara, w_python_buffer)
340 if w_python_buffer is None:
341 w_python_buffer = w_cdecl
342 w_ctype = newtype._new_chara_type(self.space)
343 else:
344 w_ctype = self.ffi_type(w_cdecl, ACCEPT_STRING | ACCEPT_CTYPE)
345 return func.from_buffer(self.space, w_ctype, w_python_buffer,
346 require_writable)
340347
341348
342349 @unwrap_spec(w_arg=W_CData)
571578 return self.ffi_type(w_arg, ACCEPT_STRING | ACCEPT_CDATA)
572579
573580
574 @unwrap_spec(filename="fsencode_or_none", flags=int)
575 def descr_dlopen(self, filename, flags=0):
581 @unwrap_spec(flags=int)
582 def descr_dlopen(self, w_filename, flags=0):
576583 """\
577584 Load and return a dynamic library identified by 'name'. The standard
578585 C library can be loaded by passing None.
583590 first access."""
584591 #
585592 from pypy.module._cffi_backend import cdlopen
586 return cdlopen.W_DlOpenLibObject(self, filename, flags)
593 return cdlopen.W_DlOpenLibObject(self, w_filename, flags)
587594
588595
589596 def descr_dlclose(self, w_lib):
699706 # waiting for lock.__enter__() above
700707 pass
701708 return w_res
709
710 @unwrap_spec(w_cdata=W_CData)
711 def descr_release(self, w_cdata):
712 """\
713 Release now the resources held by a 'cdata' object from ffi.new(),
714 ffi.gc() or ffi.from_buffer(). The cdata object must not be used
715 afterwards.
716
717 'ffi.release(cdata)' is equivalent to 'cdata.__exit__()'."""
718 w_cdata.enter_exit(True)
702719
703720
704721 class W_InitOnceLock(W_Root):
774791 new_allocator = interp2app(W_FFIObject.descr_new_allocator),
775792 new_handle = interp2app(W_FFIObject.descr_new_handle),
776793 offsetof = interp2app(W_FFIObject.descr_offsetof),
794 release = interp2app(W_FFIObject.descr_release),
777795 sizeof = interp2app(W_FFIObject.descr_sizeof),
778796 string = interp2app(W_FFIObject.descr_string),
779797 typeof = interp2app(W_FFIObject.descr_typeof),
109109 def _fetch_as_write_buffer(space, w_x):
110110 return space.writebuf_w(w_x)
111111
112 @unwrap_spec(w_ctype=ctypeobj.W_CType)
113 def from_buffer(space, w_ctype, w_x):
114 from pypy.module._cffi_backend import ctypearray, ctypeprim
115 #
116 if (not isinstance(w_ctype, ctypearray.W_CTypeArray) or
117 not isinstance(w_ctype.ctptr.ctitem, ctypeprim.W_CTypePrimitiveChar)):
118 raise oefmt(space.w_TypeError,
119 "needs 'char[]', got '%s'", w_ctype.name)
120 #
121 return _from_buffer(space, w_ctype, w_x)
122
123 def _from_buffer(space, w_ctype, w_x):
112 @unwrap_spec(w_ctype=ctypeobj.W_CType, require_writable=int)
113 def from_buffer(space, w_ctype, w_x, require_writable=0):
114 from pypy.module._cffi_backend import ctypearray
115 if not isinstance(w_ctype, ctypearray.W_CTypeArray):
116 raise oefmt(space.w_TypeError, "expected an array ctype, got '%s'",
117 w_ctype.name)
124118 if space.isinstance_w(w_x, space.w_unicode):
125119 raise oefmt(space.w_TypeError,
126 "from_buffer() cannot return the address a unicode")
127 buf = _fetch_as_read_buffer(space, w_x)
120 "from_buffer() cannot return the address of a unicode object")
121 if require_writable:
122 buf = _fetch_as_write_buffer(space, w_x)
123 else:
124 buf = _fetch_as_read_buffer(space, w_x)
128125 if space.isinstance_w(w_x, space.w_bytes):
129126 _cdata = get_raw_address_of_string(space, w_x)
130127 else:
136133 "buffer interface but cannot be rendered as a plain "
137134 "raw address on PyPy", w_x)
138135 #
139 return cdataobj.W_CDataFromBuffer(space, _cdata, w_ctype, buf, w_x)
136 buffersize = buf.getlength()
137 arraylength = w_ctype.length
138 if arraylength >= 0:
139 # it's an array with a fixed length; make sure that the
140 # buffer contains enough bytes.
141 if buffersize < w_ctype.size:
142 raise oefmt(space.w_ValueError,
143 "buffer is too small (%d bytes) for '%s' (%d bytes)",
144 buffersize, w_ctype.name, w_ctype.size)
145 else:
146 # it's an open 'array[]'
147 itemsize = w_ctype.ctitem.size
148 if itemsize == 1:
149 # fast path, performance only
150 arraylength = buffersize
151 elif itemsize > 0:
152 # give it as many items as fit the buffer. Ignore a
153 # partial last element.
154 arraylength = buffersize / itemsize
155 else:
156 # it's an array 'empty[]'. Unsupported obscure case:
157 # the problem is that setting the length of the result
158 # to anything large (like SSIZE_T_MAX) is dangerous,
159 # because if someone tries to loop over it, it will
160 # turn effectively into an infinite loop.
161 raise oefmt(space.w_ZeroDivisionError,
162 "from_buffer('%s', ..): the actual length of the array "
163 "cannot be computed", w_ctype.name)
164 #
165 return cdataobj.W_CDataFromBuffer(space, _cdata, arraylength,
166 w_ctype, buf, w_x)
140167
141168 # ____________________________________________________________
142169
167194 rawbytes = cache.wdict.get(w_x)
168195 if rawbytes is None:
169196 data = space.bytes_w(w_x)
170 if we_are_translated() and not rgc.can_move(data):
197 if (we_are_translated() and not rgc.can_move(data)
198 and not rgc.must_split_gc_address_space()):
171199 lldata = llstr(data)
172200 data_start = (llmemory.cast_ptr_to_adr(lldata) +
173201 rffi.offsetof(STR, 'chars') +
259287 @unwrap_spec(w_cdata=cdataobj.W_CData, size=int)
260288 def gcp(space, w_cdata, w_destructor, size=0):
261289 return w_cdata.with_gc(w_destructor, size)
290
291 @unwrap_spec(w_cdata=cdataobj.W_CData)
292 def release(space, w_cdata):
293 w_cdata.enter_exit(True)
22 from pypy.interpreter.gateway import unwrap_spec
33 from pypy.interpreter.baseobjspace import W_Root
44 from pypy.module._cffi_backend import ctypeobj, ctypeptr, cdataobj
5 from pypy.module._cffi_backend.hide_reveal import hide_reveal2
56 from rpython.rtyper.lltypesystem import lltype, llmemory, rffi
6 from rpython.rlib import rgc, objectmodel, jit
7 from rpython.rlib import objectmodel, jit
78
89 # ____________________________________________________________
910
1415 # we can cast the CCHARP back to a W_CDataHandle with reveal_gcref().
1516 new_cdataobj = objectmodel.instantiate(cdataobj.W_CDataHandle,
1617 nonmovable=True)
17 gcref = rgc.cast_instance_to_gcref(new_cdataobj)
18 _cdata = rgc.hide_nonmovable_gcref(gcref)
19 _cdata = rffi.cast(rffi.CCHARP, _cdata)
18 _cdata = hide_reveal2().hide_object(rffi.CCHARP, new_cdataobj)
2019 cdataobj.W_CDataHandle.__init__(new_cdataobj, space, _cdata, w_ctype, w_x)
2120 return new_cdataobj
2221
4241 @jit.dont_look_inside
4342 def _reveal(space, ptr):
4443 addr = rffi.cast(llmemory.Address, ptr)
45 gcref = rgc.reveal_gcref(addr)
46 if not gcref:
44 if not addr:
4745 raise oefmt(space.w_RuntimeError,
4846 "cannot use from_handle() on NULL pointer")
49 cd = rgc.try_cast_gcref_to_instance(cdataobj.W_CDataHandle, gcref)
47 cd = hide_reveal2().reveal_object(cdataobj.W_CDataHandle, addr)
5048 if cd is None:
5149 raise oefmt(space.w_SystemError,
5250 "ffi.from_handle(): dead or bogus object handle")
0 from rpython.rlib import rgc
1 from rpython.rlib.rweaklist import RWeakListMixin
2 from rpython.rtyper.lltypesystem import lltype, llmemory, rffi
3
4
5 class HideRevealRWeakList:
6 """Slow implementation of HideReveal: uses a RWeakListMixin."""
7
8 def __init__(self):
9 class GlobGcrefs(RWeakListMixin):
10 pass
11 glob_gcrefs = GlobGcrefs()
12 glob_gcrefs.initialize()
13
14 def hide_object(PTR, obj):
15 # XXX leaks if we call this function often on the same object
16 index = glob_gcrefs.add_handle(obj)
17 return rffi.cast(PTR, index + 1)
18
19 def reveal_object(Class, addr):
20 index = rffi.cast(lltype.Signed, addr) - 1
21 return glob_gcrefs.fetch_handle(index)
22
23 self.hide_object = hide_object
24 self.reveal_object = reveal_object
25
26 def _freeze_(self):
27 return True
28
29
30 class HideRevealCast:
31 """Fast implementation of HideReveal: just a cast."""
32
33 def __init__(self):
34
35 def hide_object(PTR, obj):
36 gcref = rgc.cast_instance_to_gcref(obj)
37 raw = rgc.hide_nonmovable_gcref(gcref)
38 return rffi.cast(PTR, raw)
39
40 def reveal_object(Class, raw_ptr):
41 addr = rffi.cast(llmemory.Address, raw_ptr)
42 gcref = rgc.reveal_gcref(addr)
43 return rgc.try_cast_gcref_to_instance(Class, gcref)
44
45 self.hide_object = hide_object
46 self.reveal_object = reveal_object
47
48 def _freeze_(self):
49 return True
50
51
52 def make_hide_reveal():
53 hide_reveal_slow = HideRevealRWeakList()
54 hide_reveal_fast = HideRevealCast()
55
56 def hide_reveal():
57 if rgc.must_split_gc_address_space():
58 return hide_reveal_slow
59 else:
60 return hide_reveal_fast
61
62 return hide_reveal
63
64 hide_reveal1 = make_hide_reveal() # for ccallback.py
65 hide_reveal2 = make_hide_reveal() # for handles.py
33 from pypy.interpreter.error import oefmt
44 from pypy.interpreter.gateway import interp2app, unwrap_spec
55 from pypy.interpreter.typedef import TypeDef
6 from pypy.module._rawffi.interp_rawffi import wrap_dlopenerror
76
87 from rpython.rtyper.lltypesystem import rffi
9 from rpython.rlib.rdynload import DLLHANDLE, dlopen, dlsym, dlclose, DLOpenError
8 from rpython.rlib.rdynload import DLLHANDLE, dlsym, dlclose
109
1110 from pypy.module._cffi_backend.cdataobj import W_CData
1211 from pypy.module._cffi_backend.ctypeobj import W_CType
12 from pypy.module._cffi_backend import misc
1313
1414
1515 class W_Library(W_Root):
1616 _immutable_ = True
1717
18 def __init__(self, space, filename, flags):
18 def __init__(self, space, w_filename, flags):
1919 self.space = space
20 with rffi.scoped_str2charp(filename) as ll_libname:
21 if filename is None:
22 filename = "<None>"
23 try:
24 self.handle = dlopen(ll_libname, flags)
25 except DLOpenError as e:
26 raise wrap_dlopenerror(space, e, filename)
27 self.name = filename
20 self.name, self.handle = misc.dlopen_w(space, w_filename, flags)
2821 self.register_finalizer(space)
2922
3023 def _finalize_(self):
10396 W_Library.typedef.acceptable_as_base_class = False
10497
10598
106 @unwrap_spec(filename="fsencode_or_none", flags=int)
107 def load_library(space, filename, flags=0):
108 lib = W_Library(space, filename, flags)
99 @unwrap_spec(flags=int)
100 def load_library(space, w_filename, flags=0):
101 lib = W_Library(space, w_filename, flags)
109102 return lib
00 from __future__ import with_statement
1 import sys
12
23 from pypy.interpreter.error import OperationError, oefmt
4 from pypy.module._rawffi.interp_rawffi import wrap_dlopenerror
35
46 from rpython.rlib import jit
5 from rpython.rlib.objectmodel import specialize
7 from rpython.rlib.objectmodel import specialize, we_are_translated
68 from rpython.rlib.rarithmetic import r_uint, r_ulonglong
79 from rpython.rlib.unroll import unrolling_iterable
10 from rpython.rlib.rdynload import dlopen, DLOpenError
11 from rpython.rlib.nonconst import NonConstant
812 from rpython.rtyper.lltypesystem import lltype, llmemory, rffi
913 from rpython.translator.tool.cbuild import ExternalCompilationInfo
14
15 if sys.platform == 'win32':
16 from rpython.rlib.rdynload import dlopenU
17 WIN32 = True
18 else:
19 WIN32 = False
1020
1121
1222 # ____________________________________________________________
101111 def write_raw_longdouble_data(target, source):
102112 rffi.cast(rffi.LONGDOUBLEP, target)[0] = source
103113
114 @jit.dont_look_inside # lets get_nonmovingbuffer_final_null be inlined
115 def write_string_as_charp(target, string):
116 buf, buf_flag = rffi.get_nonmovingbuffer_final_null(string)
117 rffi.cast(rffi.CCHARPP, target)[0] = buf
118 return ord(buf_flag) # 4, 5 or 6
119
104120 # ____________________________________________________________
105121
106122 sprintf_longdouble = rffi.llexternal(
128144 # This version accepts a Python int too, and does convertions from
129145 # other types of objects. It refuses floats.
130146 try:
131 value = space.int_w(w_ob)
147 return space.int_w(w_ob, allow_conversion=False)
132148 except OperationError as e:
133149 if not (e.match(space, space.w_OverflowError) or
134150 e.match(space, space.w_TypeError)):
135151 raise
136 else:
137 return value
138 try:
139 bigint = space.bigint_w(w_ob, allow_conversion=False)
140 except OperationError as e:
141 if not e.match(space, space.w_TypeError):
142 raise
143152 if _is_a_float(space, w_ob):
144153 raise
145 bigint = space.bigint_w(space.int(w_ob), allow_conversion=False)
154 bigint = space.bigint_w(w_ob, allow_conversion=True)
146155 try:
147156 return bigint.tolonglong()
148157 except OverflowError:
150159
151160 def as_long(space, w_ob):
152161 # Same as as_long_long(), but returning an int instead.
153 if space.is_w(space.type(w_ob), space.w_int): # shortcut
154 return space.int_w(w_ob)
155 try:
156 bigint = space.bigint_w(w_ob, allow_conversion=False)
162 try:
163 return space.int_w(w_ob, allow_conversion=False)
157164 except OperationError as e:
158 if not e.match(space, space.w_TypeError):
165 if not (e.match(space, space.w_OverflowError) or
166 e.match(space, space.w_TypeError)):
159167 raise
160168 if _is_a_float(space, w_ob):
161169 raise
162 bigint = space.bigint_w(space.int(w_ob), allow_conversion=False)
163 try:
164 return bigint.toint()
165 except OverflowError:
166 raise OperationError(space.w_OverflowError, space.newtext(ovf_msg))
170 return space.int_w(w_ob, allow_conversion=True)
167171
168172 def as_unsigned_long_long(space, w_ob, strict):
169173 # (possibly) convert and cast a Python object to an unsigned long long.
171175 # objects. If 'strict', complains with OverflowError; if 'not strict',
172176 # mask the result and round floats.
173177 try:
174 value = space.int_w(w_ob)
178 value = space.int_w(w_ob, allow_conversion=False)
175179 except OperationError as e:
176180 if not (e.match(space, space.w_OverflowError) or
177181 e.match(space, space.w_TypeError)):
178182 raise
183 if strict and _is_a_float(space, w_ob):
184 raise
179185 else:
180186 if strict and value < 0:
181187 raise OperationError(space.w_OverflowError, space.newtext(neg_msg))
182188 return r_ulonglong(value)
183 try:
184 bigint = space.bigint_w(w_ob, allow_conversion=False)
185 except OperationError as e:
186 if not e.match(space, space.w_TypeError):
187 raise
188 if strict and _is_a_float(space, w_ob):
189 raise
190 bigint = space.bigint_w(space.int(w_ob), allow_conversion=False)
189 # note that if not 'strict', then space.int() will round down floats
190 bigint = space.bigint_w(space.int(w_ob), allow_conversion=False)
191191 if strict:
192192 try:
193193 return bigint.toulonglong()
201201 def as_unsigned_long(space, w_ob, strict):
202202 # same as as_unsigned_long_long(), but returning just an Unsigned
203203 try:
204 bigint = space.bigint_w(w_ob, allow_conversion=False)
204 value = space.int_w(w_ob, allow_conversion=False)
205205 except OperationError as e:
206 if not e.match(space, space.w_TypeError):
206 if not (e.match(space, space.w_OverflowError) or
207 e.match(space, space.w_TypeError)):
207208 raise
208209 if strict and _is_a_float(space, w_ob):
209210 raise
210 bigint = space.bigint_w(space.int(w_ob), allow_conversion=False)
211 else:
212 if strict and value < 0:
213 raise OperationError(space.w_OverflowError, space.newtext(neg_msg))
214 if not we_are_translated():
215 if isinstance(value, NonConstant): # hack for test_ztranslation
216 return r_uint(0)
217 return r_uint(value)
218 # note that if not 'strict', then space.int() will round down floats
219 bigint = space.bigint_w(space.int(w_ob), allow_conversion=False)
211220 if strict:
212221 try:
213222 return bigint.touint()
240249
241250 def _standard_object_as_bool(space, w_ob):
242251 if space.isinstance_w(w_ob, space.w_int):
243 return space.bigint_w(w_ob).tobool()
252 try:
253 return space.int_w(w_ob) != 0
254 except OperationError as e:
255 if not e.match(space, space.w_OverflowError):
256 raise
257 return space.bigint_w(w_ob).tobool()
244258 if space.isinstance_w(w_ob, space.w_float):
245259 return space.float_w(w_ob) != 0.0
246260 raise _NotStandardObject
387401 ptr = rffi.cast(rffi.FLOATP, source)
388402 for i in range(len(float_list)):
389403 float_list[i] = rffi.cast(lltype.Float, ptr[i])
404
405 # ____________________________________________________________
406
407 def dlopen_w(space, w_filename, flags):
408 if WIN32 and space.isinstance_w(w_filename, space.w_unicode):
409 fname = space.text_w(space.repr(w_filename))
410 unicode_name = space.unicode_w(w_filename)
411 with rffi.scoped_unicode2wcharp(unicode_name) as ll_libname:
412 try:
413 handle = dlopenU(ll_libname, flags)
414 except DLOpenError as e:
415 raise wrap_dlopenerror(space, e, fname)
416 else:
417 if space.is_none(w_filename):
418 fname = None
419 else:
420 fname = space.fsencode_w(w_filename)
421 with rffi.scoped_str2charp(fname) as ll_libname:
422 if fname is None:
423 fname = "<None>"
424 try:
425 handle = dlopen(ll_libname, flags)
426 except DLOpenError as e:
427 raise wrap_dlopenerror(space, e, fname)
428 return fname, handle
257257 SF_PACKED = 0x08
258258 SF_STD_FIELD_POS = 0x80
259259
260 if sys.platform == 'win32':
261 SF_DEFAULT_PACKING = 8
262 else:
263 SF_DEFAULT_PACKING = 0x40000000 # a huge power of two
264
260265
261266 if sys.platform == 'win32':
262267 DEFAULT_SFLAGS_PLATFORM = SF_MSVC_BITFIELDS
308313 w_ctype._custom_field_pos = True
309314
310315 @unwrap_spec(w_ctype=ctypeobj.W_CType, totalsize=int, totalalignment=int,
311 sflags=int)
316 sflags=int, pack=int)
312317 def complete_struct_or_union(space, w_ctype, w_fields, w_ignored=None,
313 totalsize=-1, totalalignment=-1, sflags=0):
318 totalsize=-1, totalalignment=-1, sflags=0,
319 pack=0):
314320 sflags = complete_sflags(sflags)
321 if sflags & SF_PACKED:
322 pack = 1
323 elif pack <= 0:
324 pack = SF_DEFAULT_PACKING
325 else:
326 sflags |= SF_PACKED
327
315328 if (not isinstance(w_ctype, ctypestruct.W_CTypeStructOrUnion)
316329 or w_ctype.size >= 0):
317330 raise oefmt(space.w_TypeError,
361374 # update the total alignment requirement, but skip it if the
362375 # field is an anonymous bitfield or if SF_PACKED
363376 falignorg = ftype.alignof()
364 falign = 1 if sflags & SF_PACKED else falignorg
377 falign = min(pack, falignorg)
365378 do_align = True
366379 if (sflags & SF_GCC_ARM_BITFIELDS) == 0 and fbitsize >= 0:
367380 if (sflags & SF_MSVC_BITFIELDS) == 0:
00 # ____________________________________________________________
11
22 import sys
3 assert __version__ == "1.11.5", ("This test_c.py file is for testing a version"
3 assert __version__ == "1.12.0", ("This test_c.py file is for testing a version"
44 " of cffi that differs from the one that we"
55 " get from 'import _cffi_backend'")
66 if sys.version_info < (3,):
333333 max = (1 << (8*size-1)) - 1
334334 assert newp(pp, min)[0] == min
335335 assert newp(pp, max)[0] == max
336 py.test.raises(OverflowError, newp, pp, min - 2 ** 32)
337 py.test.raises(OverflowError, newp, pp, min - 2 ** 64)
338 py.test.raises(OverflowError, newp, pp, max + 2 ** 32)
339 py.test.raises(OverflowError, newp, pp, max + 2 ** 64)
336340 py.test.raises(OverflowError, newp, pp, min - 1)
337341 py.test.raises(OverflowError, newp, pp, max + 1)
342 py.test.raises(OverflowError, newp, pp, min - 1 - 2 ** 32)
343 py.test.raises(OverflowError, newp, pp, min - 1 - 2 ** 64)
344 py.test.raises(OverflowError, newp, pp, max + 1)
345 py.test.raises(OverflowError, newp, pp, max + 1 + 2 ** 32)
346 py.test.raises(OverflowError, newp, pp, max + 1 + 2 ** 64)
347 py.test.raises(TypeError, newp, pp, 1.0)
338348 for name in ['char', 'short', 'int', 'long', 'long long']:
339349 p = new_primitive_type('unsigned ' + name)
340350 pp = new_pointer_type(p)
18611871
18621872 def test_newp_copying():
18631873 """Test that we can do newp(<type>, <cdata of the given type>) for most
1864 types, with the exception of arrays, like in C.
1874 types, including same-type arrays.
18651875 """
18661876 BInt = new_primitive_type("int")
18671877 p = newp(new_pointer_type(BInt), cast(BInt, 42))
18901900 a1 = newp(BArray, [1, 2, 3, 4])
18911901 py.test.raises(TypeError, newp, BArray, a1)
18921902 BArray6 = new_array_type(new_pointer_type(BInt), 6)
1893 a1 = newp(BArray6, None)
1894 py.test.raises(TypeError, newp, BArray6, a1)
1903 a1 = newp(BArray6, [10, 20, 30])
1904 a2 = newp(BArray6, a1)
1905 assert list(a2) == [10, 20, 30, 0, 0, 0]
18951906 #
18961907 s1 = newp(BStructPtr, [42])
18971908 s2 = newp(BStructPtr, s1[0])
35403551 BLong = new_primitive_type("long")
35413552 BChar = new_primitive_type("char")
35423553 BShort = new_primitive_type("short")
3543 BStruct = new_struct_type("struct foo")
3544 complete_struct_or_union(BStruct, [('a1', BLong, -1),
3545 ('a2', BChar, -1),
3546 ('a3', BShort, -1)],
3547 None, -1, -1, SF_PACKED)
3548 d = BStruct.fields
3549 assert len(d) == 3
3550 assert d[0][0] == 'a1'
3551 assert d[0][1].type is BLong
3554 for extra_args in [(SF_PACKED,), (0, 1)]:
3555 BStruct = new_struct_type("struct foo")
3556 complete_struct_or_union(BStruct, [('a1', BLong, -1),
3557 ('a2', BChar, -1),
3558 ('a3', BShort, -1)],
3559 None, -1, -1, *extra_args)
3560 d = BStruct.fields
3561 assert len(d) == 3
3562 assert d[0][0] == 'a1'
3563 assert d[0][1].type is BLong
3564 assert d[0][1].offset == 0
3565 assert d[0][1].bitshift == -1
3566 assert d[0][1].bitsize == -1
3567 assert d[1][0] == 'a2'
3568 assert d[1][1].type is BChar
3569 assert d[1][1].offset == sizeof(BLong)
3570 assert d[1][1].bitshift == -1
3571 assert d[1][1].bitsize == -1
3572 assert d[2][0] == 'a3'
3573 assert d[2][1].type is BShort
3574 assert d[2][1].offset == sizeof(BLong) + sizeof(BChar)
3575 assert d[2][1].bitshift == -1
3576 assert d[2][1].bitsize == -1
3577 assert sizeof(BStruct) == sizeof(BLong) + sizeof(BChar) + sizeof(BShort)
3578 assert alignof(BStruct) == 1
3579 #
3580 BStruct2 = new_struct_type("struct foo")
3581 complete_struct_or_union(BStruct2, [('b1', BChar, -1),
3582 ('b2', BLong, -1)],
3583 None, -1, -1, 0, 2)
3584 d = BStruct2.fields
3585 assert len(d) == 2
3586 assert d[0][0] == 'b1'
3587 assert d[0][1].type is BChar
35523588 assert d[0][1].offset == 0
35533589 assert d[0][1].bitshift == -1
35543590 assert d[0][1].bitsize == -1
3555 assert d[1][0] == 'a2'
3556 assert d[1][1].type is BChar
3557 assert d[1][1].offset == sizeof(BLong)
3591 assert d[1][0] == 'b2'
3592 assert d[1][1].type is BLong
3593 assert d[1][1].offset == 2
35583594 assert d[1][1].bitshift == -1
35593595 assert d[1][1].bitsize == -1
3560 assert d[2][0] == 'a3'
3561 assert d[2][1].type is BShort
3562 assert d[2][1].offset == sizeof(BLong) + sizeof(BChar)
3563 assert d[2][1].bitshift == -1
3564 assert d[2][1].bitsize == -1
3565 assert sizeof(BStruct) == sizeof(BLong) + sizeof(BChar) + sizeof(BShort)
3566 assert alignof(BStruct) == 1
3596 assert sizeof(BStruct2) == 2 + sizeof(BLong)
3597 assert alignof(BStruct2) == 2
35673598
35683599 def test_packed_with_bitfields():
35693600 if sys.platform == "win32":
36983729 check(4 | 8, "CHB", "GTB")
36993730 check(4 | 16, "CHB", "ROB")
37003731
3732 def test_from_buffer_require_writable():
3733 BChar = new_primitive_type("char")
3734 BCharP = new_pointer_type(BChar)
3735 BCharA = new_array_type(BCharP, None)
3736 p1 = from_buffer(BCharA, b"foo", False)
3737 assert p1 == from_buffer(BCharA, b"foo", False)
3738 py.test.raises((TypeError, BufferError), from_buffer, BCharA, b"foo", True)
3739 ba = bytearray(b"foo")
3740 p1 = from_buffer(BCharA, ba, True)
3741 p1[0] = b"g"
3742 assert ba == b"goo"
3743
3744 def test_from_buffer_types():
3745 BInt = new_primitive_type("int")
3746 BIntP = new_pointer_type(BInt)
3747 BIntA = new_array_type(BIntP, None)
3748 lst = [-12345678, 87654321, 489148]
3749 bytestring = buffer(newp(BIntA, lst))[:] + b'XYZ'
3750 #
3751 p1 = from_buffer(BIntA, bytestring) # int[]
3752 assert typeof(p1) is BIntA
3753 assert len(p1) == 3
3754 assert p1[0] == lst[0]
3755 assert p1[1] == lst[1]
3756 assert p1[2] == lst[2]
3757 py.test.raises(IndexError, "p1[3]")
3758 py.test.raises(IndexError, "p1[-1]")
3759 #
3760 py.test.raises(TypeError, from_buffer, BInt, bytestring)
3761 py.test.raises(TypeError, from_buffer, BIntP, bytestring)
3762 #
3763 BIntA2 = new_array_type(BIntP, 2)
3764 p2 = from_buffer(BIntA2, bytestring) # int[2]
3765 assert typeof(p2) is BIntA2
3766 assert len(p2) == 2
3767 assert p2[0] == lst[0]
3768 assert p2[1] == lst[1]
3769 py.test.raises(IndexError, "p2[2]")
3770 py.test.raises(IndexError, "p2[-1]")
3771 assert p2 == p1
3772 #
3773 BIntA4 = new_array_type(BIntP, 4) # int[4]: too big
3774 py.test.raises(ValueError, from_buffer, BIntA4, bytestring)
3775 #
3776 BStruct = new_struct_type("foo")
3777 complete_struct_or_union(BStruct, [('a1', BInt, -1),
3778 ('a2', BInt, -1)])
3779 BStructP = new_pointer_type(BStruct)
3780 BStructA = new_array_type(BStructP, None)
3781 p1 = from_buffer(BStructA, bytestring) # struct[]
3782 assert len(p1) == 1
3783 assert typeof(p1) is BStructA
3784 assert p1[0].a1 == lst[0]
3785 assert p1[0].a2 == lst[1]
3786 py.test.raises(IndexError, "p1[1]")
3787 #
3788 BEmptyStruct = new_struct_type("empty")
3789 complete_struct_or_union(BEmptyStruct, [], Ellipsis, 0)
3790 assert sizeof(BEmptyStruct) == 0
3791 BEmptyStructP = new_pointer_type(BEmptyStruct)
3792 BEmptyStructA = new_array_type(BEmptyStructP, None)
3793 py.test.raises(ZeroDivisionError, from_buffer, # empty[]
3794 BEmptyStructA, bytestring)
3795 #
3796 BEmptyStructA5 = new_array_type(BEmptyStructP, 5)
3797 p1 = from_buffer(BEmptyStructA5, bytestring) # struct empty[5]
3798 assert typeof(p1) is BEmptyStructA5
3799 assert len(p1) == 5
3800 assert cast(BIntP, p1) == from_buffer(BIntA, bytestring)
3801
37013802 def test_memmove():
37023803 Short = new_primitive_type("short")
37033804 ShortA = new_array_type(new_pointer_type(Short), None)
39144015
39154016 def test_char_pointer_conversion():
39164017 import warnings
3917 assert __version__.startswith(("1.8", "1.9", "1.10", "1.11")), (
3918 "consider turning the warning into an error")
4018 assert __version__.startswith("1."), (
4019 "the warning will be an error if we ever release cffi 2.x")
39194020 BCharP = new_pointer_type(new_primitive_type("char"))
39204021 BIntP = new_pointer_type(new_primitive_type("int"))
39214022 BVoidP = new_pointer_type(new_void_type())
39254026 z3 = cast(BVoidP, 0)
39264027 z4 = cast(BUCharP, 0)
39274028 with warnings.catch_warnings(record=True) as w:
4029 warnings.simplefilter("always")
39284030 newp(new_pointer_type(BIntP), z1) # warn
39294031 assert len(w) == 1
39304032 newp(new_pointer_type(BVoidP), z1) # fine
40294131 assert_eq(cast(t5, 7.0), cast(t3, 7))
40304132 assert_lt(cast(t5, 3.1), 3.101)
40314133 assert_gt(cast(t5, 3.1), 3)
4134
4135 def test_explicit_release_new():
4136 # release() on a ffi.new() object has no effect on CPython, but
4137 # really releases memory on PyPy. We can't test that effect
4138 # though, because a released cdata is not marked.
4139 BIntP = new_pointer_type(new_primitive_type("int"))
4140 p = newp(BIntP)
4141 p[0] = 42
4142 py.test.raises(IndexError, "p[1]")
4143 release(p)
4144 # here, reading p[0] might give garbage or segfault...
4145 release(p) # no effect
4146 #
4147 BStruct = new_struct_type("struct foo")
4148 BStructP = new_pointer_type(BStruct)
4149 complete_struct_or_union(BStruct, [('p', BIntP, -1)])
4150 pstruct = newp(BStructP)
4151 assert pstruct.p == cast(BIntP, 0)
4152 release(pstruct)
4153 # here, reading pstruct.p might give garbage or segfault...
4154 release(pstruct) # no effect
4155
4156 def test_explicit_release_new_contextmgr():
4157 BIntP = new_pointer_type(new_primitive_type("int"))
4158 with newp(BIntP) as p:
4159 p[0] = 42
4160 assert p[0] == 42
4161 # here, reading p[0] might give garbage or segfault...
4162 release(p) # no effect
4163
4164 def test_explicit_release_badtype():
4165 BIntP = new_pointer_type(new_primitive_type("int"))
4166 p = cast(BIntP, 12345)
4167 py.test.raises(ValueError, release, p)
4168 py.test.raises(ValueError, release, p)
4169 BStruct = new_struct_type("struct foo")
4170 BStructP = new_pointer_type(BStruct)
4171 complete_struct_or_union(BStruct, [('p', BIntP, -1)])
4172 pstruct = newp(BStructP)
4173 py.test.raises(ValueError, release, pstruct[0])
4174
4175 def test_explicit_release_badtype_contextmgr():
4176 BIntP = new_pointer_type(new_primitive_type("int"))
4177 p = cast(BIntP, 12345)
4178 py.test.raises(ValueError, "with p: pass")
4179 py.test.raises(ValueError, "with p: pass")
4180
4181 def test_explicit_release_gc():
4182 BIntP = new_pointer_type(new_primitive_type("int"))
4183 seen = []
4184 intp1 = newp(BIntP, 12345)
4185 p1 = cast(BIntP, intp1)
4186 p = gcp(p1, seen.append)
4187 assert seen == []
4188 release(p)
4189 assert seen == [p1]
4190 assert p1[0] == 12345
4191 assert p[0] == 12345 # true so far, but might change to raise RuntimeError
4192 release(p) # no effect
4193
4194 def test_explicit_release_gc_contextmgr():
4195 BIntP = new_pointer_type(new_primitive_type("int"))
4196 seen = []
4197 intp1 = newp(BIntP, 12345)
4198 p1 = cast(BIntP, intp1)
4199 p = gcp(p1, seen.append)
4200 with p:
4201 assert p[0] == 12345
4202 assert seen == []
4203 assert seen == [p1]
4204 assert p1[0] == 12345
4205 assert p[0] == 12345 # true so far, but might change to raise RuntimeError
4206 release(p) # no effect
4207
4208 def test_explicit_release_from_buffer():
4209 a = bytearray(b"xyz")
4210 BChar = new_primitive_type("char")
4211 BCharP = new_pointer_type(BChar)
4212 BCharA = new_array_type(BCharP, None)
4213 p = from_buffer(BCharA, a)
4214 assert p[2] == b"z"
4215 release(p)
4216 assert p[2] == b"z" # true so far, but might change to raise RuntimeError
4217 release(p) # no effect
4218
4219 def test_explicit_release_from_buffer_contextmgr():
4220 a = bytearray(b"xyz")
4221 BChar = new_primitive_type("char")
4222 BCharP = new_pointer_type(BChar)
4223 BCharA = new_array_type(BCharP, None)
4224 p = from_buffer(BCharA, a)
4225 with p:
4226 assert p[2] == b"z"
4227 assert p[2] == b"z" # true so far, but might change to raise RuntimeError
4228 release(p) # no effect
4229
4230 def test_explicit_release_bytearray_on_cpython():
4231 if '__pypy__' in sys.builtin_module_names:
4232 py.test.skip("pypy's bytearray are never locked")
4233 a = bytearray(b"xyz")
4234 BChar = new_primitive_type("char")
4235 BCharP = new_pointer_type(BChar)
4236 BCharA = new_array_type(BCharP, None)
4237 a += b't' * 10
4238 p = from_buffer(BCharA, a)
4239 py.test.raises(BufferError, "a += b'u' * 100")
4240 release(p)
4241 a += b'v' * 100
4242 release(p) # no effect
4243 a += b'w' * 1000
4244 assert a == bytearray(b"xyz" + b't' * 10 + b'v' * 100 + b'w' * 1000)
266266 assert lst == [1.25, -2.5, 3.75]
267267 if not self.runappdirect:
268268 assert self.get_count() == 1
269
270 def test_too_many_initializers(self):
271 import _cffi_backend
272 ffi = _cffi_backend.FFI()
273 raises(IndexError, ffi.new, "int[4]", [10, 20, 30, 40, 50])
274 raises(IndexError, ffi.new, "int[4]", tuple(range(999)))
275 raises(IndexError, ffi.new, "unsigned int[4]", [10, 20, 30, 40, 50])
276 raises(IndexError, ffi.new, "float[4]", [10, 20, 30, 40, 50])
277 raises(IndexError, ffi.new, "long double[4]", [10, 20, 30, 40, 50])
278 raises(IndexError, ffi.new, "char[4]", [10, 20, 30, 40, 50])
279 raises(IndexError, ffi.new, "wchar_t[4]", [10, 20, 30, 40, 50])
280 raises(IndexError, ffi.new, "_Bool[4]", [10, 20, 30, 40, 50])
281 raises(IndexError, ffi.new, "int[4][4]", [[3,4,5,6]] * 5)
282 raises(IndexError, ffi.new, "int[4][4]", [[3,4,5,6,7]] * 4)
281281 import _cffi_backend as _cffi1_backend
282282 import array
283283 ffi = _cffi1_backend.FFI()
284 a = array.array('H', [10000, 20000, 30000])
284 a = array.array('H', [10000, 20000, 30000, 40000])
285285 c = ffi.from_buffer(a)
286286 assert ffi.typeof(c) is ffi.typeof("char[]")
287 assert len(c) == 8
287288 ffi.cast("unsigned short *", c)[1] += 500
288 assert list(a) == [10000, 20500, 30000]
289 assert list(a) == [10000, 20500, 30000, 40000]
290 raises(TypeError, ffi.from_buffer, a, True)
291 assert c == ffi.from_buffer("char[]", a, True)
292 assert c == ffi.from_buffer(a, require_writable=True)
293 #
294 c = ffi.from_buffer("unsigned short[]", a)
295 assert len(c) == 4
296 assert c[1] == 20500
297 #
298 c = ffi.from_buffer("unsigned short[2][2]", a)
299 assert len(c) == 2
300 assert len(c[0]) == 2
301 assert c[0][1] == 20500
302 #
303 p = ffi.from_buffer(b"abcd")
304 assert p[2] == b"c"
305 #
306 assert p == ffi.from_buffer(b"abcd", require_writable=False)
307 raises((TypeError, BufferError), ffi.from_buffer,
308 "char[]", b"abcd", True)
309 raises((TypeError, BufferError), ffi.from_buffer, b"abcd",
310 require_writable=True)
289311
290312 def test_from_buffer_BytesIO(self):
291313 from _cffi_backend import FFI
571593 assert len(z) == 2
572594 assert ffi.cast("int *", z)[0] == 0x12345
573595 assert list(z) == [u'\U00012345', u'\x00'] # maybe a 2-unichars str
596
597 def test_ffi_array_as_init(self):
598 import _cffi_backend as _cffi1_backend
599 ffi = _cffi1_backend.FFI()
600 p = ffi.new("int[4]", [10, 20, 30, 400])
601 q = ffi.new("int[4]", p)
602 assert list(q) == [10, 20, 30, 400]
603 raises(TypeError, ffi.new, "int[3]", p)
604 raises(TypeError, ffi.new, "int[5]", p)
605 raises(TypeError, ffi.new, "int16_t[4]", p)
00 import py
1 import sys, shutil, os
12 from rpython.tool.udir import udir
23 from pypy.interpreter.gateway import interp2app
34 from pypy.module._cffi_backend.newtype import _clean_cache
45
6 if sys.platform == 'win32':
7 WIN32 = True
8 else:
9 WIN32 = False
510
611 class AppTestRecompilerPython:
712 spaceconfig = dict(usemodules=['_cffi_backend'])
3944 'globalconst42', 'globalconsthello'])
4045 outputfilename = ffiplatform.compile(str(tmpdir), ext)
4146 cls.w_extmod = space.wrap(outputfilename)
47 if WIN32:
48 unicode_name = u'load\u03betest.dll'
49 else:
50 unicode_name = u'load_caf\xe9' + os.path.splitext(outputfilename)[1]
51 try:
52 unicode_name.encode(sys.getfilesystemencoding())
53 except UnicodeEncodeError:
54 unicode_name = None # skip test_dlopen_unicode
55 if unicode_name is not None:
56 outputfileUname = os.path.join(unicode(udir), unicode_name)
57 shutil.copyfile(outputfilename, outputfileUname)
58 cls.w_extmodU = space.wrap(outputfileUname)
4259 #mod.tmpdir = tmpdir
4360 #
4461 ffi = FFI()
107124 assert lib.add42(-10) == 32
108125 assert type(lib.add42) is _cffi_backend.FFI.CData
109126
127 def test_dlopen_unicode(self):
128 if not getattr(self, 'extmodU', None):
129 skip("no unicode file name")
130 import _cffi_backend, sys
131 sys.pypy_initfsencoding() # initialize space.sys.filesystemencoding
132 self.fix_path()
133 from re_python_pysrc import ffi
134 lib = ffi.dlopen(self.extmodU)
135 assert lib.add42(-10) == 32
136
110137 def test_dlclose(self):
111138 import _cffi_backend
112139 self.fix_path()
21072107 else:
21082108 assert lib.__loader__ is None
21092109 assert lib.__spec__ is None
2110
2111 def test_release(self):
2112 ffi, lib = self.prepare("", "test_release", "")
2113 p = ffi.new("int[]", 123)
2114 ffi.release(p)
2115 # here, reading p[0] might give garbage or segfault...
2116 ffi.release(p) # no effect
2117
2118 def test_release_new_allocator(self):
2119 ffi, lib = self.prepare("struct ab { int a, b; };",
2120 "test_release_new_allocator",
2121 "struct ab { int a, b; };")
2122 seen = []
2123 def myalloc(size):
2124 seen.append(size)
2125 return ffi.new("char[]", b"X" * size)
2126 def myfree(raw):
2127 seen.append(raw)
2128 alloc2 = ffi.new_allocator(alloc=myalloc, free=myfree)
2129 p = alloc2("int[]", 15)
2130 assert seen == [15 * 4]
2131 ffi.release(p)
2132 assert seen == [15 * 4, p]
2133 ffi.release(p) # no effect
2134 assert seen == [15 * 4, p]
2135 #
2136 del seen[:]
2137 p = alloc2("struct ab *")
2138 assert seen == [2 * 4]
2139 ffi.release(p)
2140 assert seen == [2 * 4, p]
2141 ffi.release(p) # no effect
2142 assert seen == [2 * 4, p]
555555 to the default encoding. errors may be given to set a different error
556556 handling scheme. Default is 'strict' meaning that encoding errors raise
557557 a ValueError. Other possible values are 'ignore' and 'replace'
558 as well as any other name registerd with codecs.register_error that is
558 as well as any other name registered with codecs.register_error that is
559559 able to handle ValueErrors.
560560 """
561561 if w_encoding is None:
620620 try:
621621 func = getattr(unicodehelper, impl_name)
622622 except AttributeError:
623 if hasattr(runicode, 'py3k_' + impl_name):
624 impl_name = 'py3k_' + impl_name
625623 func = getattr(runicode, impl_name)
626624 return func
627625
760760 assert b"\\u3042\u3xxx".decode("unicode-escape", "test.handler1") == \
761761 u"\u3042[<92><117><51>]xxx"
762762
763 def test_unicode_internal_error_handler_infinite_loop(self):
764 import codecs
765 class MyException(Exception):
766 pass
767 seen = [0]
768 def handler_unicodeinternal(exc):
769 if not isinstance(exc, UnicodeDecodeError):
770 raise TypeError("don't know how to handle %r" % exc)
771 seen[0] += 1
772 if seen[0] == 20: # stop the 20th time this is called
773 raise MyException
774 return (u"\x01", 4) # 4 < len(input), so will try and fail again
775 codecs.register_error("test.inf", handler_unicodeinternal)
776 try:
777 b"\x00\x00\x00\x00\x00".decode("unicode-internal", "test.inf")
778 except MyException:
779 pass
780 else:
781 raise AssertionError("should have gone into infinite loop")
782
763783 def test_encode_error_bad_handler(self):
764784 import codecs
765785 codecs.register_error("test.bad_handler", lambda e: (repl, 1))
77
88 appleveldefs = {
99 'defaultdict': 'app_defaultdict.defaultdict',
10 'OrderedDict': 'app_odict.OrderedDict',
1011 }
1112
1213 interpleveldefs = {
2425 space = self.space
2526 space.getattr(self, space.newtext('defaultdict')) # force importing
2627 space.delattr(self, space.newtext('__missing__'))
27
28 def startup(self, space):
29 # OrderedDict is normally present, but in some cases the line
30 # "from __pypy__ import reversed_dict, move_to_end" from
31 # _pypy_collections.py raises
32 space.appexec([self], """(mod):
33 try:
34 from _pypy_collections import OrderedDict
35 mod.OrderedDict = OrderedDict
36 except ImportError:
37 pass
38 """)
0 from __pypy__ import reversed_dict, move_to_end, objects_in_repr
1 from _operator import eq as _eq
2
3
4 class OrderedDict(dict):
5 '''Dictionary that remembers insertion order.
6
7 In PyPy all dicts are ordered anyway. This is mostly useful as a
8 placeholder to mean "this dict must be ordered even on CPython".
9
10 Known difference: iterating over an OrderedDict which is being
11 concurrently modified raises RuntimeError in PyPy. In CPython
12 instead we get some behavior that appears reasonable in some
13 cases but is nonsensical in other cases. This is officially
14 forbidden by the CPython docs, so we forbid it explicitly for now.
15 '''
16 def __init__(*args, **kwds):
17 '''Initialize an ordered dictionary. The signature is the same as
18 regular dictionaries, but keyword arguments are not recommended because
19 their insertion order is arbitrary.
20
21 '''
22 if not args:
23 raise TypeError("descriptor '__init__' of 'OrderedDict' object "
24 "needs an argument")
25 self, *args = args
26 if len(args) > 1:
27 raise TypeError('expected at most 1 arguments, got %d' % len(args))
28 self.__update(*args, **kwds)
29
30 def update(*args, **kwds):
31 ''' D.update([E, ]**F) -> None. Update D from mapping/iterable E and F.
32 If E present and has a .keys() method, does: for k in E: D[k] = E[k]
33 If E present and lacks .keys() method, does: for (k, v) in E: D[k] = v
34 In either case, this is followed by: for k, v in F.items(): D[k] = v
35 '''
36 if not args:
37 raise TypeError("descriptor 'update' of 'OrderedDict' object "
38 "needs an argument")
39 self, *args = args
40 if len(args) > 1:
41 raise TypeError('update expected at most 1 arguments, got %d' %
42 len(args))
43 if args:
44 other = args[0]
45 if hasattr(other, 'items'):
46 for key, value in other.items():
47 self[key] = value
48 elif hasattr(other, "keys"):
49 for key in other.keys():
50 self[key] = other[key]
51 else:
52 for key, value in other:
53 self[key] = value
54 for key, value in kwds.items():
55 self[key] = value
56 __update = update
57
58 def __reversed__(self):
59 return reversed_dict(self)
60
61 def popitem(self, last=True):
62 '''od.popitem() -> (k, v), return and remove a (key, value) pair.
63 Pairs are returned in LIFO order if last is true or FIFO order if false.
64
65 '''
66 if last:
67 return dict.popitem(self)
68 else:
69 it = dict.__iter__(self)
70 try:
71 k = next(it)
72 except StopIteration:
73 raise KeyError('dictionary is empty')
74 return (k, self.pop(k))
75
76 def move_to_end(self, key, last=True):
77 '''Move an existing element to the end (or beginning if last==False).
78
79 Raises KeyError if the element does not exist.
80 When last=True, acts like a fast version of self[key]=self.pop(key).
81
82 '''
83 return move_to_end(self, key, last)
84
85 def __repr__(self):
86 'od.__repr__() <==> repr(od)'
87 if not self:
88 return '%s()' % (self.__class__.__name__,)
89 currently_in_repr = objects_in_repr()
90 if self in currently_in_repr:
91 return '...'
92 currently_in_repr[self] = 1
93 try:
94 return '%s(%r)' % (self.__class__.__name__, list(self.items()))
95 finally:
96 try:
97 del currently_in_repr[self]
98 except:
99 pass
100
101 def __reduce__(self):
102 'Return state information for pickling'
103 inst_dict = vars(self).copy()
104 return self.__class__, (), inst_dict or None, None, iter(self.items())
105
106 def copy(self):
107 'od.copy() -> a shallow copy of od'
108 return self.__class__(self)
109
110 def __eq__(self, other):
111 '''od.__eq__(y) <==> od==y. Comparison to another OD is order-sensitive
112 while comparison to a regular mapping is order-insensitive.
113
114 '''
115 if isinstance(other, OrderedDict):
116 return dict.__eq__(self, other) and all(map(_eq, self, other))
117 return dict.__eq__(self, other)
118
119 __ne__ = object.__ne__
120
121 def keys(self):
122 "D.keys() -> a set-like object providing a view on D's keys"
123 return _OrderedDictKeysView(self)
124
125 def items(self):
126 "D.items() -> a set-like object providing a view on D's items"
127 return _OrderedDictItemsView(self)
128
129 def values(self):
130 "D.values() -> an object providing a view on D's values"
131 return _OrderedDictValuesView(self)
132
133 dict_keys = type({}.keys())
134 dict_values = type({}.values())
135 dict_items = type({}.items())
136
137 class _OrderedDictKeysView(dict_keys):
138 def __reversed__(self):
139 yield from reversed_dict(self._dict)
140
141 class _OrderedDictItemsView(dict_items):
142 def __reversed__(self):
143 for key in reversed_dict(self._dict):
144 yield (key, self._dict[key])
145
146 class _OrderedDictValuesView(dict_values):
147 def __reversed__(self):
148 for key in reversed_dict(self._dict):
149 yield self._dict[key]
00 import sys
11 from rpython.rlib.objectmodel import specialize
2 from rpython.rlib.rarithmetic import ovfcheck
23 from pypy.interpreter import gateway
34 from pypy.interpreter.baseobjspace import W_Root
45 from pypy.interpreter.typedef import TypeDef, make_weakref_descr
191192
192193 def mul(self, w_int):
193194 space = self.space
195 num = space.int_w(w_int)
196 try:
197 ovfcheck(self.len * num)
198 except OverflowError:
199 raise MemoryError
194200 copied = W_Deque(space)
195201 copied.maxlen = self.maxlen
196 num = space.int_w(w_int)
197202
198203 for _ in range(num):
199204 copied.extend(self)
211216 if num <= 0:
212217 self.clear()
213218 return self
219 try:
220 ovfcheck(self.len * num)
221 except OverflowError:
222 raise MemoryError
214223 # use a copy to extend self
215224 copy = W_Deque(space)
216225 copy.maxlen = self.maxlen
371371 assert d == deque('a' * n)
372372 assert d.maxlen is None
373373
374 def test_deque_repeat_big(self):
375 import sys
376 from _collections import deque
377 d = deque([0])
378 d *= 2**8
379 if sys.maxsize <= 2147483647:
380 raises(MemoryError, d.__mul__, 2**24)
381 raises(MemoryError, d.__rmul__, 2**24)
382 raises(MemoryError, d.__imul__, 2**24)
383 else:
384 raises(MemoryError, d.__mul__, 2**56)
385 raises(MemoryError, d.__rmul__, 2**56)
386 raises(MemoryError, d.__imul__, 2**56)
387
374388 def test_deque_insert(self):
375389 from _collections import deque
376390 for i in range(0,11):
2121 assert d['x'] == 42
2222 d.update({'y': 2})
2323 assert d['y'] == 42
24
25 def test_reversed(self):
26 import sys
27 from _collections import OrderedDict
28
29 pairs = [('c', 1), ('b', 2), ('a', 3), ('d', 4), ('e', 5), ('f', 6)]
30 od = OrderedDict(pairs)
31 if '__pypy__' in sys.builtin_module_names:
32 # dict ordering is wrong when testing interpreted on top of CPython
33 pairs = list(dict(od).items())
34 assert list(reversed(od)) == [t[0] for t in reversed(pairs)]
35 assert list(reversed(od.keys())) == [t[0] for t in reversed(pairs)]
36 assert list(reversed(od.values())) == [t[1] for t in reversed(pairs)]
37 assert list(reversed(od.items())) == list(reversed(pairs))
00 from pypy.interpreter.mixedmodule import MixedModule
11
22 class Module(MixedModule):
3 "This module brigdes the cppyy frontend with its backend, through PyPy.\n\
3 "This module bridges the cppyy frontend with its backend, through PyPy.\n\
44 See http://cppyy.readthedocs.io/en/latest for full details."
55
66 interpleveldefs = {
77 '_resolve_name' : 'interp_cppyy.resolve_name',
88 '_scope_byname' : 'interp_cppyy.scope_byname',
9 '_is_static_data' : 'interp_cppyy.is_static_data',
910 '_is_template' : 'interp_cppyy.is_template',
1011 '_std_string_name' : 'interp_cppyy.std_string_name',
1112 '_set_class_generator' : 'interp_cppyy.set_class_generator',
1213 '_set_function_generator': 'interp_cppyy.set_function_generator',
1314 '_register_class' : 'interp_cppyy.register_class',
1415 '_get_nullptr' : 'interp_cppyy.get_nullptr',
15 'CPPInstanceBase' : 'interp_cppyy.W_CPPInstance',
16 'CPPInstance' : 'interp_cppyy.W_CPPInstance',
1617 'addressof' : 'interp_cppyy.addressof',
1718 '_bind_object' : 'interp_cppyy._bind_object',
1819 'bind_object' : 'interp_cppyy.bind_object',
1920 'move' : 'interp_cppyy.move',
21 '_pin_type' : 'interp_cppyy._pin_type',
2022 }
2123
2224 appleveldefs = {
23 '_init_pythonify' : 'pythonify._init_pythonify',
25 '_post_import_startup' : 'pythonify._post_import_startup',
26 'Template' : 'pythonify.CPPTemplate',
2427 'add_pythonization' : 'pythonify.add_pythonization',
25 'Template' : 'pythonify.CPPTemplate',
28 'remove_pythonization' : 'pythonify.remove_pythonization',
2629 }
2730
2831 def __init__(self, space, *args):
3336 # code generation is not, so give it a chance to run now
3437 from pypy.module._cppyy import capi
3538 capi.register_pythonizations(space)
36
37 def startup(self, space):
38 from pypy.module._cppyy import capi
39 capi.verify_backend(space) # may raise ImportError
40
41 space.call_method(self, '_init_pythonify')
1010 assert lltype.typeOf(ptr) == C_OBJECT
1111 address = rffi.cast(rffi.CCHARP, ptr)
1212 return rffi.cast(C_OBJECT, lltype.direct_ptradd(address, offset))
13
14 def exchange_address(ptr, cif_descr, index):
15 return rffi.ptradd(ptr, cif_descr.exchange_args[index])
00 import os
1
12 from rpython.rtyper.lltypesystem import rffi, lltype
23 from rpython.rlib.rarithmetic import intmask
34 from rpython.rlib import jit, jit_libffi, libffi, rdynload, objectmodel
45 from rpython.rlib.rarithmetic import r_singlefloat
56 from rpython.tool import leakfinder
67
7 from pypy.interpreter.gateway import interp2app
8 from pypy.interpreter.error import oefmt
9
8 from pypy.interpreter.error import OperationError, oefmt
9 from pypy.interpreter.argument import Arguments
10 from pypy.interpreter.gateway import interp2app, interpindirect2app
11 from pypy.interpreter.typedef import TypeDef
12 from pypy.objspace.std.iterobject import W_AbstractSeqIterObject
13
14 from pypy.module._rawffi.array import W_ArrayInstance
1015 from pypy.module._cffi_backend import ctypefunc, ctypeprim, cdataobj, misc
1116 from pypy.module._cffi_backend import newtype
1217 from pypy.module._cppyy import ffitypes
2227
2328 class _Arg: # poor man's union
2429 _immutable_ = True
25 def __init__(self, tc, h = 0, l = -1, s = '', p = rffi.cast(rffi.VOIDP, 0)):
30 def __init__(self, tc, h = 0, l = -1, d = -1., s = '', p = rffi.cast(rffi.VOIDP, 0)):
2631 self.tc = tc
2732 self._handle = h
2833 self._long = l
34 self._double = d
2935 self._string = s
3036 self._voidp = p
3137
3844 _immutable_ = True
3945 def __init__(self, val):
4046 _Arg.__init__(self, 'l', l = val)
47
48 class _ArgD(_Arg):
49 _immutable_ = True
50 def __init__(self, val):
51 _Arg.__init__(self, 'd', d = val)
4152
4253 class _ArgS(_Arg):
4354 _immutable_ = True
6879 space = self.space
6980 cif_descr = self.cif_descr
7081 size = cif_descr.exchange_size
71 raw_string = rffi.cast(rffi.CCHARP, 0) # only ever have one in the CAPI
82 raw_string1 = rffi.cast(rffi.CCHARP, 0)
83 raw_string2 = rffi.cast(rffi.CCHARP, 0) # have max two in any CAPI
7284 buffer = lltype.malloc(rffi.CCHARP.TO, size, flavor='raw')
7385 try:
7486 for i in range(len(args)):
8799 assert obj._voidp != rffi.cast(rffi.VOIDP, 0)
88100 data = rffi.cast(rffi.VOIDPP, data)
89101 data[0] = obj._voidp
90 else: # only other use is sring
102 elif obj.tc == 'd':
103 assert isinstance(argtype, ctypeprim.W_CTypePrimitiveFloat)
104 misc.write_raw_float_data(data, rffi.cast(rffi.DOUBLE, obj._double), argtype.size)
105 else: # only other use is string
91106 assert obj.tc == 's'
92107 n = len(obj._string)
93 assert raw_string == rffi.cast(rffi.CCHARP, 0)
94 # XXX could use rffi.get_nonmovingbuffer_final_null()
95 raw_string = rffi.str2charp(obj._string)
96108 data = rffi.cast(rffi.CCHARPP, data)
97 data[0] = raw_string
109 if raw_string1 == rffi.cast(rffi.CCHARP, 0):
110 # XXX could use rffi.get_nonmovingbuffer_final_null()
111 raw_string1 = rffi.str2charp(obj._string)
112 data[0] = raw_string1
113 else:
114 assert raw_string2 == rffi.cast(rffi.CCHARP, 0)
115 raw_string2 = rffi.str2charp(obj._string)
116 data[0] = raw_string2
98117
99118 jit_libffi.jit_ffi_call(cif_descr,
100119 rffi.cast(rffi.VOIDP, funcaddr),
105124 # immediate unwrapping, the round-trip is removed
106125 w_res = self.ctitem.copy_and_convert_to_object(resultdata)
107126 finally:
108 if raw_string != rffi.cast(rffi.CCHARP, 0):
109 rffi.free_charp(raw_string)
127 if raw_string1 != rffi.cast(rffi.CCHARP, 0):
128 rffi.free_charp(raw_string1)
129 if raw_string2 != rffi.cast(rffi.CCHARP, 0):
130 rffi.free_charp(raw_string2)
110131 lltype.free(buffer, flavor='raw')
111132 return w_res
112133
174195 'call_f' : ([c_method, c_object, c_int, c_voidp], c_float),
175196 'call_d' : ([c_method, c_object, c_int, c_voidp], c_double),
176197 'call_ld' : ([c_method, c_object, c_int, c_voidp], c_ldouble),
198 'call_nld' : ([c_method, c_object, c_int, c_voidp], c_double),
177199
178200 'call_r' : ([c_method, c_object, c_int, c_voidp], c_voidp),
179201 # call_s actually takes an size_t* as last parameter, but this will do
182204 'constructor' : ([c_method, c_object, c_int, c_voidp], c_object),
183205 'call_o' : ([c_method, c_object, c_int, c_voidp, c_type], c_object),
184206
185 'function_address_from_index' : ([c_scope, c_index], c_voidp), # TODO: verify
186 'function_address_from_method' : ([c_method], c_voidp), # id.
207 'function_address' : ([c_method], c_voidp), # TODO: verify
187208
188209 # handling of function argument buffer
189210 'allocate_function_args' : ([c_int], c_voidp),
206227 'num_bases' : ([c_type], c_int),
207228 'base_name' : ([c_type, c_int], c_ccharp),
208229 'is_subtype' : ([c_type, c_type], c_int),
230 'smartptr_info' : ([c_ccharp, c_voidp, c_voidp], c_int),
231 'add_smartptr_type' : ([c_ccharp], c_void),
209232
210233 'base_offset' : ([c_type, c_type, c_object, c_int], c_ptrdiff_t),
211234
213236 'num_methods' : ([c_scope], c_int),
214237 'method_indices_from_name' : ([c_scope, c_ccharp], c_index_array),
215238
216 'method_name' : ([c_scope, c_index], c_ccharp),
217 'method_mangled_name' : ([c_scope, c_index], c_ccharp),
218 'method_result_type' : ([c_scope, c_index], c_ccharp),
219 'method_num_args' : ([c_scope, c_index], c_int),
220 'method_req_args' : ([c_scope, c_index], c_int),
221 'method_arg_type' : ([c_scope, c_index, c_int], c_ccharp),
222 'method_arg_default' : ([c_scope, c_index, c_int], c_ccharp),
223 'method_signature' : ([c_scope, c_index, c_int], c_ccharp),
224 'method_prototype' : ([c_scope, c_index, c_int], c_ccharp),
239 'get_method' : ([c_scope, c_index], c_method),
240
241 'method_name' : ([c_method], c_ccharp),
242 'method_full_name' : ([c_method], c_ccharp),
243 'method_mangled_name' : ([c_method], c_ccharp),
244 'method_result_type' : ([c_method], c_ccharp),
245 'method_num_args' : ([c_method], c_int),
246 'method_req_args' : ([c_method], c_int),
247 'method_arg_type' : ([c_method, c_int], c_ccharp),
248 'method_arg_default' : ([c_method, c_int], c_ccharp),
249 'method_signature' : ([c_method, c_int], c_ccharp),
250 'method_prototype' : ([c_scope, c_method, c_int], c_ccharp),
225251 'is_const_method' : ([c_method], c_int),
226252
253 'get_num_templated_methods': ([c_scope], c_int),
254 'get_templated_method_name': ([c_scope, c_index], c_ccharp),
227255 'exists_method_template' : ([c_scope, c_ccharp], c_int),
228256 'method_is_template' : ([c_scope, c_index], c_int),
229 'method_num_template_args' : ([c_scope, c_index], c_int),
230 'method_template_arg_name' : ([c_scope, c_index, c_index], c_ccharp),
231
232 'get_method' : ([c_scope, c_index], c_method),
257 'get_method_template' : ([c_scope, c_ccharp, c_ccharp], c_method),
258
233259 'get_global_operator' : ([c_scope, c_scope, c_scope, c_ccharp], c_index),
234260
235261 # method properties
236 'is_public_method' : ([c_type, c_index], c_int),
237 'is_constructor' : ([c_type, c_index], c_int),
238 'is_destructor' : ([c_type, c_index], c_int),
239 'is_staticmethod' : ([c_type, c_index], c_int),
262 'is_public_method' : ([c_method], c_int),
263 'is_constructor' : ([c_method], c_int),
264 'is_destructor' : ([c_method], c_int),
265 'is_staticmethod' : ([c_method], c_int),
240266
241267 # data member reflection information
242268 'num_datamembers' : ([c_scope], c_int),
262288 'stdstring2charp' : ([c_object, c_voidp], c_ccharp),
263289 'stdstring2stdstring' : ([c_object], c_object),
264290
265 'stdvector_valuetype' : ([c_ccharp], c_ccharp),
266 'stdvector_valuesize' : ([c_ccharp], c_size_t),
267
291 'longdouble2double' : ([c_voidp], c_double),
292 'double2longdouble' : ([c_double, c_voidp], c_void),
293
294 'vectorbool_getitem' : ([c_object, c_int], c_int),
295 'vectorbool_setitem' : ([c_object, c_int, c_int], c_void),
268296 }
269297
270298 # size/offset are backend-specific but fixed after load
279307 dldflags = rdynload.RTLD_LOCAL | rdynload.RTLD_LAZY
280308 if os.environ.get('CPPYY_BACKEND_LIBRARY'):
281309 libname = os.environ['CPPYY_BACKEND_LIBRARY']
282 state.backend = W_Library(space, libname, dldflags)
310 state.backend = W_Library(space, space.newtext(libname), dldflags)
283311 else:
284312 # try usual lookups
285 state.backend = W_Library(space, backend_library, dldflags)
313 state.backend = W_Library(space, space.newtext(backend_library), dldflags)
286314
287315 if state.backend:
288316 # fix constants
307335 c_call = state.capi_calls[name]
308336 except KeyError:
309337 if state.backend is None:
310 load_backend(space)
338 verify_backend(space)
311339 iface = state.capi_call_ifaces[name]
312340 cfunc = W_RCTypeFunc(space, iface[0], iface[1], False)
313341 c_call = state.backend.load_function(cfunc, 'cppyy_'+name)
391419 return rffi.cast(rffi.DOUBLE, space.float_w(call_capi(space, 'call_d', args)))
392420 def c_call_ld(space, cppmethod, cppobject, nargs, cargs):
393421 args = [_ArgH(cppmethod), _ArgH(cppobject), _ArgL(nargs), _ArgP(cargs)]
394 return rffi.cast(rffi.LONGDOUBLE, space.float_w(call_capi(space, 'call_ld', args)))
422 #return rffi.cast(rffi.LONGDOUBLE, space.float_w(call_capi(space, 'call_ld', args)))
423 # call_nld narrows long double to double
424 return rffi.cast(rffi.DOUBLE, space.float_w(call_capi(space, 'call_nld', args)))
395425
396426 def c_call_r(space, cppmethod, cppobject, nargs, cargs):
397427 args = [_ArgH(cppmethod), _ArgH(cppobject), _ArgL(nargs), _ArgP(cargs)]
414444 args = [_ArgH(cppmethod), _ArgH(cppobject), _ArgL(nargs), _ArgP(cargs), _ArgH(cppclass.handle)]
415445 return _cdata_to_cobject(space, call_capi(space, 'call_o', args))
416446
417 def c_function_address_from_index(space, cppscope, index):
418 args = [_ArgH(cppscope.handle), _ArgL(index)]
447 def c_function_address(space, cppmethod):
419448 return rffi.cast(C_FUNC_PTR,
420 _cdata_to_ptr(space, call_capi(space, 'function_address_from_index', args)))
421 def c_function_address_from_method(space, cppmethod):
422 return rffi.cast(C_FUNC_PTR,
423 _cdata_to_ptr(space, call_capi(space, 'function_address_from_method', _ArgH(cppmethod))))
449 _cdata_to_ptr(space, call_capi(space, 'function_address', [_ArgH(cppmethod)])))
424450
425451 # handling of function argument buffer ---------------------------------------
426452 def c_allocate_function_args(space, size):
478504 if derived == base:
479505 return bool(1)
480506 return space.bool_w(call_capi(space, 'is_subtype', [_ArgH(derived.handle), _ArgH(base.handle)]))
507 def c_smartptr_info(space, name):
508 out_raw = lltype.malloc(rffi.ULONGP.TO, 1, flavor='raw', zero=True)
509 out_deref = lltype.malloc(rffi.ULONGP.TO, 1, flavor='raw', zero=True)
510 try:
511 args = [_ArgS(name),
512 _ArgP(rffi.cast(rffi.VOIDP, out_raw)), _ArgP(rffi.cast(rffi.VOIDP, out_deref))]
513 result = space.bool_w(call_capi(space, 'smartptr_info', args))
514 raw = rffi.cast(C_TYPE, out_raw[0])
515 deref = rffi.cast(C_METHOD, out_deref[0])
516 finally:
517 lltype.free(out_deref, flavor='raw')
518 lltype.free(out_raw, flavor='raw')
519 return (result, raw, deref)
520 def c_add_smartptr_type(space, name):
521 return space.bool_w(call_capi(space, 'add_smartptr_type', [_ArgS(name)]))
481522
482523 def _c_base_offset(space, derived_h, base_h, address, direction):
483524 args = [_ArgH(derived_h), _ArgH(base_h), _ArgH(address), _ArgL(direction)]
509550 c_free(space, rffi.cast(rffi.VOIDP, indices)) # c_free defined below
510551 return py_indices
511552
512 def c_method_name(space, cppscope, index):
553 def c_get_method(space, cppscope, index):
513554 args = [_ArgH(cppscope.handle), _ArgL(index)]
514 return charp2str_free(space, call_capi(space, 'method_name', args))
515 def c_method_result_type(space, cppscope, index):
555 return rffi.cast(C_METHOD, space.uint_w(call_capi(space, 'get_method', args)))
556
557 def c_method_name(space, cppmeth):
558 return charp2str_free(space, call_capi(space, 'method_name', [_ArgH(cppmeth)]))
559 def c_method_full_name(space, cppmeth):
560 return charp2str_free(space, call_capi(space, 'method_full_name', [_ArgH(cppmeth)]))
561 def c_method_mangled_name(space, cppmeth):
562 return charp2str_free(space, call_capi(space, 'method_mangled_name', [_ArgH(cppmeth)]))
563 def c_method_result_type(space, cppmeth):
564 return charp2str_free(space, call_capi(space, 'method_result_type', [_ArgH(cppmeth)]))
565 def c_method_num_args(space, cppmeth):
566 return space.int_w(call_capi(space, 'method_num_args', [_ArgH(cppmeth)]))
567 def c_method_req_args(space, cppmeth):
568 return space.int_w(call_capi(space, 'method_req_args', [_ArgH(cppmeth)]))
569 def c_method_arg_type(space, cppmeth, arg_index):
570 args = [_ArgH(cppmeth), _ArgL(arg_index)]
571 return charp2str_free(space, call_capi(space, 'method_arg_type', args))
572 def c_method_arg_default(space, cppmeth, arg_index):
573 args = [_ArgH(cppmeth), _ArgL(arg_index)]
574 return charp2str_free(space, call_capi(space, 'method_arg_default', args))
575 def c_method_signature(space, cppmeth, show_formalargs=True):
576 args = [_ArgH(cppmeth), _ArgL(show_formalargs)]
577 return charp2str_free(space, call_capi(space, 'method_signature', args))
578 def c_method_prototype(space, cppscope, cppmeth, show_formalargs=True):
579 args = [_ArgH(cppscope.handle), _ArgH(cppmeth), _ArgL(show_formalargs)]
580 return charp2str_free(space, call_capi(space, 'method_prototype', args))
581 def c_is_const_method(space, cppmeth):
582 return space.bool_w(call_capi(space, 'is_const_method', [_ArgH(cppmeth)]))
583
584 def c_get_num_templated_methods(space, cppscope):
585 return space.int_w(call_capi(space, 'method_is_template', [_ArgH(cppscope.handle)]))
586 def c_get_templated_method_name(space, cppscope, index):
516587 args = [_ArgH(cppscope.handle), _ArgL(index)]
517 return charp2str_free(space, call_capi(space, 'method_result_type', args))
518 def c_method_num_args(space, cppscope, index):
519 args = [_ArgH(cppscope.handle), _ArgL(index)]
520 return space.int_w(call_capi(space, 'method_num_args', args))
521 def c_method_req_args(space, cppscope, index):
522 args = [_ArgH(cppscope.handle), _ArgL(index)]
523 return space.int_w(call_capi(space, 'method_req_args', args))
524 def c_method_arg_type(space, cppscope, index, arg_index):
525 args = [_ArgH(cppscope.handle), _ArgL(index), _ArgL(arg_index)]
526 return charp2str_free(space, call_capi(space, 'method_arg_type', args))
527 def c_method_arg_default(space, cppscope, index, arg_index):
528 args = [_ArgH(cppscope.handle), _ArgL(index), _ArgL(arg_index)]
529 return charp2str_free(space, call_capi(space, 'method_arg_default', args))
530 def c_method_signature(space, cppscope, index, show_formalargs=True):
531 args = [_ArgH(cppscope.handle), _ArgL(index), _ArgL(show_formalargs)]
532 return charp2str_free(space, call_capi(space, 'method_signature', args))
533 def c_method_prototype(space, cppscope, index, show_formalargs=True):
534 args = [_ArgH(cppscope.handle), _ArgL(index), _ArgL(show_formalargs)]
535 return charp2str_free(space, call_capi(space, 'method_prototype', args))
536
588 return charp2str_free(space, call_capi(space, 'method_is_template', args))
537589 def c_exists_method_template(space, cppscope, name):
538590 args = [_ArgH(cppscope.handle), _ArgS(name)]
539591 return space.bool_w(call_capi(space, 'exists_method_template', args))
540592 def c_method_is_template(space, cppscope, index):
541593 args = [_ArgH(cppscope.handle), _ArgL(index)]
542594 return space.bool_w(call_capi(space, 'method_is_template', args))
543 def _c_method_num_template_args(space, cppscope, index):
544 args = [_ArgH(cppscope.handle), _ArgL(index)]
545 return space.int_w(call_capi(space, 'method_num_template_args', args))
546 def c_template_args(space, cppscope, index):
547 nargs = _c_method_num_template_args(space, cppscope, index)
548 arg1 = _ArgH(cppscope.handle)
549 arg2 = _ArgL(index)
550 args = [c_resolve_name(space, charp2str_free(space,
551 call_capi(space, 'method_template_arg_name', [arg1, arg2, _ArgL(iarg)]))
552 ) for iarg in range(nargs)]
553 return args
554
555 def c_get_method(space, cppscope, index):
556 args = [_ArgH(cppscope.handle), _ArgL(index)]
557 return rffi.cast(C_METHOD, space.uint_w(call_capi(space, 'get_method', args)))
595 def c_get_method_template(space, cppscope, name, proto):
596 args = [_ArgH(cppscope.handle), _ArgS(name), _ArgS(proto)]
597 return rffi.cast(C_METHOD, space.uint_w(call_capi(space, 'get_method_template', args)))
598
558599 def c_get_global_operator(space, nss, lc, rc, op):
559600 if nss is not None:
560601 args = [_ArgH(nss.handle), _ArgH(lc.handle), _ArgH(rc.handle), _ArgS(op)]
562603 return rffi.cast(WLAVC_INDEX, -1)
563604
564605 # method properties ----------------------------------------------------------
565 def c_is_public_method(space, cppclass, index):
566 args = [_ArgH(cppclass.handle), _ArgL(index)]
567 return space.bool_w(call_capi(space, 'is_public_method', args))
568 def c_is_constructor(space, cppclass, index):
569 args = [_ArgH(cppclass.handle), _ArgL(index)]
570 return space.bool_w(call_capi(space, 'is_constructor', args))
571 def c_is_destructor(space, cppclass, index):
572 args = [_ArgH(cppclass.handle), _ArgL(index)]
573 return space.bool_w(call_capi(space, 'is_destructor', args))
574 def c_is_staticmethod(space, cppclass, index):
575 args = [_ArgH(cppclass.handle), _ArgL(index)]
576 return space.bool_w(call_capi(space, 'is_staticmethod', args))
606 def c_is_public_method(space, cppmeth):
607 return space.bool_w(call_capi(space, 'is_public_method', [_ArgH(cppmeth)]))
608 def c_is_constructor(space, cppmeth):
609 return space.bool_w(call_capi(space, 'is_constructor', [_ArgH(cppmeth)]))
610 def c_is_destructor(space, cppmeth):
611 return space.bool_w(call_capi(space, 'is_destructor', [_ArgH(cppmeth)]))
612 def c_is_staticmethod(space, cppmeth):
613 return space.bool_w(call_capi(space, 'is_staticmethod', [_ArgH(cppmeth)]))
577614
578615 # data member reflection information -----------------------------------------
579616 def c_num_datamembers(space, cppscope):
607644 return space.bool_w(call_capi(space, 'is_enum_data', args))
608645 def c_get_dimension_size(space, cppscope, datamember_index, dim_idx):
609646 args = [_ArgH(cppscope.handle), _ArgL(datamember_index), _ArgL(dim_idx)]
610 return space.bool_w(call_capi(space, 'get_dimension_size', args))
647 return space.int_w(call_capi(space, 'get_dimension_size', args))
611648
612649 # misc helpers ---------------------------------------------------------------
613650 def c_strtoll(space, svalue):
638675 def c_stdstring2stdstring(space, cppobject):
639676 return _cdata_to_cobject(space, call_capi(space, 'stdstring2stdstring', [_ArgH(cppobject)]))
640677
641 def c_stdvector_valuetype(space, pystr):
642 return charp2str_free(space, call_capi(space, 'stdvector_valuetype', [_ArgS(pystr)]))
643
644 def c_stdvector_valuetype(space, pystr):
645 return charp2str_free(space, call_capi(space, 'stdvector_valuetype', [_ArgS(pystr)]))
646 def c_stdvector_valuesize(space, pystr):
647 return _cdata_to_size_t(space, call_capi(space, 'stdvector_valuesize', [_ArgS(pystr)]))
678 def c_longdouble2double(space, addr):
679 return space.float_w(call_capi(space, 'longdouble2double', [_ArgP(addr)]))
680 def c_double2longdouble(space, dval, addr):
681 call_capi(space, 'double2longdouble', [_ArgD(dval), _ArgP(addr)])
682
683 def c_vectorbool_getitem(space, vbool, idx):
684 return call_capi(space, 'vectorbool_getitem', [_ArgH(vbool), _ArgL(idx)])
685 def c_vectorbool_setitem(space, vbool, idx, value):
686 call_capi(space, 'vectorbool_setitem', [_ArgH(vbool), _ArgL(idx), _ArgL(value)])
648687
649688
650689 # TODO: factor these out ...
651690 # pythonizations
652691 def stdstring_c_str(space, w_self):
653692 """Return a python string taking into account \0"""
654
655693 from pypy.module._cppyy import interp_cppyy
656694 cppstr = space.interp_w(interp_cppyy.W_CPPInstance, w_self, can_be_None=False)
657695 return space.newtext(c_stdstring2charp(space, cppstr._rawobject))
696
697 def vbool_getindex(space, w_vbool, w_idx):
698 idx = space.getindex_w(w_idx, space.w_IndexError, "std::vector<bool> index")
699 sz = space.len_w(w_vbool)
700 if idx < 0: idx += sz
701 if idx < 0 or idx >= sz:
702 raise IndexError
703 return idx
704
705 def vectorbool_getitem(space, w_self, w_idx):
706 """Index a std::vector<bool>, return the value"""
707 from pypy.module._cppyy import interp_cppyy
708 vbool = space.interp_w(interp_cppyy.W_CPPInstance, w_self, can_be_None=False)
709 idx = vbool_getindex(space, w_self, w_idx)
710 item = c_vectorbool_getitem(space, vbool._rawobject, idx)
711 return space.newbool(space.is_true(item))
712
713 def vectorbool_setitem(space, w_self, w_idx, w_value):
714 """Index a std::vector<bool>, set the value"""
715 from pypy.module._cppyy import interp_cppyy
716 vbool = space.interp_w(interp_cppyy.W_CPPInstance, w_self, can_be_None=False)
717 idx = vbool_getindex(space, w_self, w_idx)
718 c_vectorbool_setitem(space, vbool._rawobject, idx, int(space.is_true(w_value)))
719
720 class W_STLVectorIter(W_AbstractSeqIterObject):
721 # w_seq and index are in base class
722 _immutable_fields_ = ['converter', 'data', 'len', 'stride']
723
724 def __init__(self, space, w_vector):
725 W_AbstractSeqIterObject.__init__(self, w_vector)
726 # TODO: this should live in rpythonize.py or something so that the
727 # imports can move to the top w/o getting circles
728 from pypy.module._cppyy import interp_cppyy
729 assert isinstance(w_vector, interp_cppyy.W_CPPInstance)
730 vector = space.interp_w(interp_cppyy.W_CPPInstance, w_vector)
731
732 v_type = c_resolve_name(space, vector.clsdecl.name+'::value_type')
733 v_size = c_size_of_type(space, v_type)
734
735 if not v_type or not v_size:
736 raise NotImplementedError # fallback on getitem
737
738 from pypy.module._cppyy import converter
739 self.converter = converter.get_converter(space, v_type, '')
740
741 # this 'data' is from the decl, so not the pythonized data from pythonify.py
742 w_arr = space.call_obj_args(vector.clsdecl.get_overload('data'), w_vector, Arguments(space, []))
743 arr = space.interp_w(W_ArrayInstance, w_arr, can_be_None=True)
744 if not arr:
745 raise OperationError(space.w_StopIteration, space.w_None)
746
747 self.data = rffi.cast(rffi.CCHARP, space.uint_w(arr.getbuffer(space)))
748 self.len = space.uint_w(space.call_obj_args(vector.clsdecl.get_overload('size'), w_vector, Arguments(space, [])))
749 self.stride = v_size
750
751 def descr_next(self, space):
752 if self.w_seq is None:
753 raise OperationError(space.w_StopIteration, space.w_None)
754 if self.len <= self.index:
755 self.w_seq = None
756 raise OperationError(space.w_StopIteration, space.w_None)
757 offset = lltype.direct_ptradd(self.data, rffi.cast(rffi.SIZE_T, self.index*self.stride))
758 w_item = self.converter.from_memory(space, space.w_None, rffi.cast(rffi.LONG, offset))
759 self.index += 1
760 return w_item
761
762 def stdvector_iter(space, w_self):
763 return W_STLVectorIter(space, w_self)
764
658765
659766 # setup pythonizations for later use at run-time
660767 _pythonizations = {}
666773 ### std::string
667774 stdstring_c_str,
668775
776 ### std::vector
777 stdvector_iter,
778
779 ### std::vector<bool>
780 vectorbool_getitem,
781 vectorbool_setitem,
669782 ]
670783
671784 for f in allfuncs:
675788 space.setattr(w_pycppclass, space.newtext(m1),
676789 space.getattr(w_pycppclass, space.newtext(m2)))
677790
678 def pythonize(space, name, w_pycppclass):
791 def pythonize(space, w_pycppclass, name):
679792 if name == "string":
680793 space.setattr(w_pycppclass, space.newtext("c_str"), _pythonizations["stdstring_c_str"])
681794 _method_alias(space, w_pycppclass, "_cppyy_as_builtin", "c_str")
682795 _method_alias(space, w_pycppclass, "__str__", "c_str")
796
797 if name.find("std::vector<bool", 0, 16) == 0:
798 space.setattr(w_pycppclass, space.newtext("__getitem__"), _pythonizations["vectorbool_getitem"])
799 space.setattr(w_pycppclass, space.newtext("__setitem__"), _pythonizations["vectorbool_setitem"])
800
801 elif name.find("std::vector", 0, 11) == 0:
802 space.setattr(w_pycppclass, space.newtext("__iter__"), _pythonizations["stdvector_iter"])
00 import sys
11
22 from pypy.interpreter.error import OperationError, oefmt
3
43 from rpython.rtyper.lltypesystem import rffi, lltype
54 from rpython.rlib.rarithmetic import r_singlefloat, r_longfloat
65 from rpython.rlib import rfloat, rawrefcount
7
86 from pypy.module._rawffi.interp_rawffi import letter2tp
9 from pypy.module._rawffi.array import W_Array, W_ArrayInstance
10
11 from pypy.module._cppyy import helper, capi, ffitypes
7 from pypy.module._rawffi.array import W_ArrayInstance
8 from pypy.module._cppyy import helper, capi, ffitypes, lowlevelviews
129
1310 # Converter objects are used to translate between RPython and C++. They are
1411 # defined by the type name for which they provide conversion. Uses are for
6764 pass
6865 # array type
6966 try:
67 if hasattr(space, "fake"):
68 raise NotImplementedError
7069 arr = space.interp_w(W_ArrayInstance, w_obj, can_be_None=True)
7170 if arr:
7271 return rffi.cast(rffi.VOIDP, space.uint_w(arr.getbuffer(space)))
7978
8079
8180 class TypeConverter(object):
82 _immutable_fields_ = ['cffi_name', 'uses_local', 'name']
81 _immutable_fields_ = ['cffi_name', 'name']
8382
8483 cffi_name = None
85 uses_local = False
8684 name = ""
8785
8886 def __init__(self, space, extra):
105103 from pypy.module._cppyy.interp_cppyy import FastCallNotPossible
106104 raise FastCallNotPossible
107105
108 def convert_argument(self, space, w_obj, address, call_local):
106 def convert_argument(self, space, w_obj, address):
109107 self._is_abstract(space)
110108
111 def convert_argument_libffi(self, space, w_obj, address, call_local):
109 def convert_argument_libffi(self, space, w_obj, address, scratch):
112110 from pypy.module._cppyy.interp_cppyy import FastCallNotPossible
113111 raise FastCallNotPossible
114112
116114 from pypy.module._cppyy.interp_cppyy import FastCallNotPossible
117115 raise FastCallNotPossible
118116
119 def from_memory(self, space, w_obj, w_pycppclass, offset):
117 def from_memory(self, space, w_obj, offset):
120118 self._is_abstract(space)
121119
122120 def to_memory(self, space, w_obj, w_value, offset):
123121 self._is_abstract(space)
124122
125 def finalize_call(self, space, w_obj, call_local):
123 def finalize_call(self, space, w_obj):
126124 pass
127125
128 def free_argument(self, space, arg, call_local):
126 def free_argument(self, space, arg):
129127 pass
130128
131
132 class ArrayCache(object):
133 def __init__(self, space):
134 self.space = space
135 def __getattr__(self, name):
136 if name.startswith('array_'):
137 typecode = name[len('array_'):]
138 arr = self.space.interp_w(W_Array, letter2tp(self.space, typecode))
139 setattr(self, name, arr)
140 return arr
141 raise AttributeError(name)
142
143 def _freeze_(self):
144 return True
145129
146130 class ArrayTypeConverterMixin(object):
147131 _mixin_ = True
157141 state = space.fromcache(ffitypes.State)
158142 return state.c_voidp
159143
160 def from_memory(self, space, w_obj, w_pycppclass, offset):
144 def from_memory(self, space, w_obj, offset):
161145 # read access, so no copy needed
162146 address_value = self._get_raw_address(space, w_obj, offset)
163147 address = rffi.cast(rffi.ULONG, address_value)
164 cache = space.fromcache(ArrayCache)
165 arr = getattr(cache, 'array_' + self.typecode)
166 return arr.fromaddress(space, address, self.size)
148 return lowlevelviews.W_LowLevelView(
149 space, letter2tp(space, self.typecode), self.size, address)
167150
168151 def to_memory(self, space, w_obj, w_value, offset):
169152 # copy the full array (uses byte copy for now)
185168 state = space.fromcache(ffitypes.State)
186169 return state.c_voidp
187170
188 def convert_argument(self, space, w_obj, address, call_local):
171 def convert_argument(self, space, w_obj, address):
189172 w_tc = space.findattr(w_obj, space.newtext('typecode'))
190173 if w_tc is not None and space.text_w(w_tc) != self.typecode:
191174 raise oefmt(space.w_TypeError,
200183 ba = rffi.cast(rffi.CCHARP, address)
201184 ba[capi.c_function_arg_typeoffset(space)] = 'o'
202185
203 def from_memory(self, space, w_obj, w_pycppclass, offset):
186 def from_memory(self, space, w_obj, offset):
204187 # read access, so no copy needed
205188 address_value = self._get_raw_address(space, w_obj, offset)
206189 address = rffi.cast(rffi.ULONGP, address_value)
207 cache = space.fromcache(ArrayCache)
208 arr = getattr(cache, 'array_' + self.typecode)
209 return arr.fromaddress(space, address[0], self.size)
190 return lowlevelviews.W_LowLevelView(
191 space, letter2tp(space, self.typecode), self.size, address[0])
210192
211193 def to_memory(self, space, w_obj, w_value, offset):
212194 # copy only the pointer value
213195 rawobject = get_rawobject_nonnull(space, w_obj)
214 byteptr = rffi.cast(rffi.CCHARPP, capi.direct_ptradd(rawobject, offset))
196 byteptr = rffi.cast(rffi.VOIDPP, capi.direct_ptradd(rawobject, offset))
215197 buf = space.getarg_w('s*', w_value)
216198 try:
217 byteptr[0] = buf.get_raw_address()
199 byteptr[0] = rffi.cast(rffi.VOIDP, buf.get_raw_address())
218200 except ValueError:
219201 raise oefmt(space.w_TypeError,
220202 "raw buffer interface not supported")
223205 class NumericTypeConverterMixin(object):
224206 _mixin_ = True
225207
226 def convert_argument_libffi(self, space, w_obj, address, call_local):
208 def convert_argument_libffi(self, space, w_obj, address, scratch):
227209 x = rffi.cast(self.c_ptrtype, address)
228210 x[0] = self._unwrap_object(space, w_obj)
229211
230212 def default_argument_libffi(self, space, address):
213 if not self.valid_default:
214 from pypy.module._cppyy.interp_cppyy import FastCallNotPossible
215 raise FastCallNotPossible
231216 x = rffi.cast(self.c_ptrtype, address)
232217 x[0] = self.default
233218
234 def from_memory(self, space, w_obj, w_pycppclass, offset):
219 def from_memory(self, space, w_obj, offset):
235220 address = self._get_raw_address(space, w_obj, offset)
236221 rffiptr = rffi.cast(self.c_ptrtype, address)
237222 return self._wrap_object(space, rffiptr[0])
241226 rffiptr = rffi.cast(self.c_ptrtype, address)
242227 rffiptr[0] = self._unwrap_object(space, w_value)
243228
244 class ConstRefNumericTypeConverterMixin(NumericTypeConverterMixin):
229 class ConstRefNumericTypeConverterMixin(object):
245230 _mixin_ = True
246 _immutable_fields_ = ['uses_local']
247
248 uses_local = True
249231
250232 def cffi_type(self, space):
251233 state = space.fromcache(ffitypes.State)
252234 return state.c_voidp
253235
254 def convert_argument_libffi(self, space, w_obj, address, call_local):
255 assert rffi.sizeof(self.c_type) <= 2*rffi.sizeof(rffi.VOIDP) # see interp_cppyy.py
236 def convert_argument_libffi(self, space, w_obj, address, scratch):
256237 obj = self._unwrap_object(space, w_obj)
257 typed_buf = rffi.cast(self.c_ptrtype, call_local)
238 typed_buf = rffi.cast(self.c_ptrtype, scratch)
258239 typed_buf[0] = obj
259240 x = rffi.cast(rffi.VOIDPP, address)
260 x[0] = call_local
241 x[0] = scratch
242
261243
262244 class IntTypeConverterMixin(NumericTypeConverterMixin):
263245 _mixin_ = True
264246
265 def convert_argument(self, space, w_obj, address, call_local):
247 def convert_argument(self, space, w_obj, address):
266248 x = rffi.cast(self.c_ptrtype, address)
267249 x[0] = self._unwrap_object(space, w_obj)
268250 ba = rffi.cast(rffi.CCHARP, address)
271253 class FloatTypeConverterMixin(NumericTypeConverterMixin):
272254 _mixin_ = True
273255
274 def convert_argument(self, space, w_obj, address, call_local):
256 def convert_argument(self, space, w_obj, address):
275257 x = rffi.cast(self.c_ptrtype, address)
276258 x[0] = self._unwrap_object(space, w_obj)
277259 ba = rffi.cast(rffi.CCHARP, address)
288270 state = space.fromcache(ffitypes.State)
289271 return state.c_void
290272
291 def convert_argument(self, space, w_obj, address, call_local):
273 def convert_argument(self, space, w_obj, address):
292274 self._is_abstract(space)
293275
294276
295277 class BoolConverter(ffitypes.typeid(bool), TypeConverter):
296 def convert_argument(self, space, w_obj, address, call_local):
278 def convert_argument(self, space, w_obj, address):
297279 x = rffi.cast(rffi.LONGP, address)
298280 x[0] = self._unwrap_object(space, w_obj)
299281 ba = rffi.cast(rffi.CCHARP, address)
300282 ba[capi.c_function_arg_typeoffset(space)] = 'b'
301283
302 def convert_argument_libffi(self, space, w_obj, address, call_local):
284 def convert_argument_libffi(self, space, w_obj, address, scratch):
303285 x = rffi.cast(rffi.LONGP, address)
304286 x[0] = self._unwrap_object(space, w_obj)
305287
306 def from_memory(self, space, w_obj, w_pycppclass, offset):
288 def from_memory(self, space, w_obj, offset):
307289 address = rffi.cast(rffi.CCHARP, self._get_raw_address(space, w_obj, offset))
308290 if address[0] == '\x01':
309291 return space.w_True
318300 address[0] = '\x00'
319301
320302 class CharConverter(ffitypes.typeid(rffi.CHAR), TypeConverter):
321 def convert_argument(self, space, w_obj, address, call_local):
303 def convert_argument(self, space, w_obj, address):
322304 x = rffi.cast(rffi.CCHARP, address)
323305 x[0] = self._unwrap_object(space, w_obj)
324306 ba = rffi.cast(rffi.CCHARP, address)
325307 ba[capi.c_function_arg_typeoffset(space)] = 'b'
326308
327 def convert_argument_libffi(self, space, w_obj, address, call_local):
309 def convert_argument_libffi(self, space, w_obj, address, scratch):
328310 x = rffi.cast(self.c_ptrtype, address)
329311 x[0] = self._unwrap_object(space, w_obj)
330312
331 def from_memory(self, space, w_obj, w_pycppclass, offset):
313 def from_memory(self, space, w_obj, offset):
332314 address = rffi.cast(rffi.CCHARP, self._get_raw_address(space, w_obj, offset))
333315 return space.newbytes(address[0])
334316
336318 address = rffi.cast(rffi.CCHARP, self._get_raw_address(space, w_obj, offset))
337319 address[0] = self._unwrap_object(space, w_value)
338320
321
322 class UCharConverter(ffitypes.typeid(rffi.UCHAR), CharConverter):
323 pass
324
339325 class FloatConverter(ffitypes.typeid(rffi.FLOAT), FloatTypeConverterMixin, TypeConverter):
340 _immutable_fields_ = ['default']
326 _immutable_fields_ = ['default', 'valid_default']
341327
342328 def __init__(self, space, default):
343 if default:
329 self.valid_default = False
330 try:
344331 fval = float(rfloat.rstring_to_float(default))
345 else:
332 self.valid_default = True
333 except Exception:
346334 fval = float(0.)
347 self.default = r_singlefloat(fval)
348
349 def from_memory(self, space, w_obj, w_pycppclass, offset):
335 self.default = rffi.cast(rffi.FLOAT, r_singlefloat(fval))
336
337 def from_memory(self, space, w_obj, offset):
350338 address = self._get_raw_address(space, w_obj, offset)
351339 rffiptr = rffi.cast(self.c_ptrtype, address)
352340 return self._wrap_object(space, rffiptr[0])
353341
354 class ConstFloatRefConverter(FloatConverter):
342 class ConstFloatRefConverter(ConstRefNumericTypeConverterMixin, FloatConverter):
355343 _immutable_fields_ = ['typecode']
356344 typecode = 'f'
357345
358 def cffi_type(self, space):
359 state = space.fromcache(ffitypes.State)
360 return state.c_voidp
361
362 def convert_argument_libffi(self, space, w_obj, address, call_local):
363 from pypy.module._cppyy.interp_cppyy import FastCallNotPossible
364 raise FastCallNotPossible
365
366346 class DoubleConverter(ffitypes.typeid(rffi.DOUBLE), FloatTypeConverterMixin, TypeConverter):
367 _immutable_fields_ = ['default']
347 _immutable_fields_ = ['default', 'valid_default']
368348
369349 def __init__(self, space, default):
370 if default:
350 self.valid_default = False
351 try:
371352 self.default = rffi.cast(self.c_type, rfloat.rstring_to_float(default))
372 else:
353 self.valid_default = True
354 except Exception:
373355 self.default = rffi.cast(self.c_type, 0.)
374356
375357 class ConstDoubleRefConverter(ConstRefNumericTypeConverterMixin, DoubleConverter):
376358 _immutable_fields_ = ['typecode']
377359 typecode = 'd'
378360
379 class LongDoubleConverter(ffitypes.typeid(rffi.LONGDOUBLE), FloatTypeConverterMixin, TypeConverter):
380 _immutable_fields_ = ['default']
361 class LongDoubleConverter(TypeConverter):
362 _immutable_fields_ = ['default', 'valid_default']
363 typecode = 'g'
381364
382365 def __init__(self, space, default):
383 if default:
384 fval = float(rfloat.rstring_to_float(default))
385 else:
386 fval = float(0.)
387 self.default = r_longfloat(fval)
366 self.valid_default = False
367 try:
368 # use float() instead of cast with r_longfloat
369 fval = rffi.cast(rffi.DOUBLE, rfloat.rstring_to_float(default))
370 self.valid_default = True
371 except Exception:
372 fval = rffi.cast(rffi.DOUBLE, 0.)
373 #self.default = r_longfloat(fval)
374 self.default = fval
375
376 def convert_argument(self, space, w_obj, address):
377 x = rffi.cast(rffi.VOIDP, address)
378 capi.c_double2longdouble(space, space.float_w(w_obj), x)
379 ba = rffi.cast(rffi.CCHARP, address)
380 ba[capi.c_function_arg_typeoffset(space)] = self.typecode
381
382 def convert_argument_libffi(self, space, w_obj, address, scratch):
383 x = rffi.cast(rffi.VOIDP, address)
384 capi.c_double2longdouble(space, space.float_w(w_obj), x)
385
386 def default_argument_libffi(self, space, address):
387 if not self.valid_default:
388 from pypy.module._cppyy.interp_cppyy import FastCallNotPossible
389 raise FastCallNotPossible
390 x = rffi.cast(rffi.VOIDP, address)
391 capi.c_double2longdouble(space, self.default, x)
392
393 def from_memory(self, space, w_obj, offset):
394 address = self._get_raw_address(space, w_obj, offset)
395 rffiptr = rffi.cast(rffi.VOIDP, address)
396 return space.newfloat(capi.c_longdouble2double(space, rffiptr))
397
398 def to_memory(self, space, w_obj, w_value, offset):
399 address = self._get_raw_address(space, w_obj, offset)
400 rffiptr = rffi.cast(rffi.VOIDP, address)
401 capi.c_double2longdouble(space, space.float_w(w_value), rffiptr)
388402
389403 class ConstLongDoubleRefConverter(ConstRefNumericTypeConverterMixin, LongDoubleConverter):
390404 _immutable_fields_ = ['typecode']
391405 typecode = 'g'
392406
407 def convert_argument_libffi(self, space, w_obj, address, scratch):
408 capi.c_double2longdouble(space, space.float_w(w_obj), rffi.cast(rffi.VOIDP, scratch))
409 x = rffi.cast(rffi.VOIDPP, address)
410 x[0] = scratch
411
393412
394413 class CStringConverter(TypeConverter):
395 def convert_argument(self, space, w_obj, address, call_local):
414 def convert_argument(self, space, w_obj, address):
396415 x = rffi.cast(rffi.LONGP, address)
397416 arg = space.text_w(w_obj)
398417 x[0] = rffi.cast(rffi.LONG, rffi.str2charp(arg))
399418 ba = rffi.cast(rffi.CCHARP, address)
400 ba[capi.c_function_arg_typeoffset(space)] = 'o'
401
402 def from_memory(self, space, w_obj, w_pycppclass, offset):
419 ba[capi.c_function_arg_typeoffset(space)] = 'p'
420
421 def from_memory(self, space, w_obj, offset):
403422 address = self._get_raw_address(space, w_obj, offset)
404423 charpptr = rffi.cast(rffi.CCHARPP, address)
405 return space.newbytes(rffi.charp2str(charpptr[0]))
406
407 def free_argument(self, space, arg, call_local):
424 return space.newtext(rffi.charp2str(charpptr[0]))
425
426 def free_argument(self, space, arg):
408427 lltype.free(rffi.cast(rffi.CCHARPP, arg)[0], flavor='raw')
409428
410429 class CStringConverterWithSize(CStringConverter):
413432 def __init__(self, space, extra):
414433 self.size = extra
415434
416 def from_memory(self, space, w_obj, w_pycppclass, offset):
435 def from_memory(self, space, w_obj, offset):
417436 address = self._get_raw_address(space, w_obj, offset)
418437 charpptr = rffi.cast(rffi.CCHARP, address)
419 strsize = self.size
420 if charpptr[self.size-1] == '\0':
421 strsize = self.size-1 # rffi will add \0 back
422 return space.newbytes(rffi.charpsize2str(charpptr, strsize))
438 if 0 <= self.size and self.size != 2**31-1: # cling's code for "unknown" (?)
439 strsize = self.size
440 if charpptr[self.size-1] == '\0':
441 strsize = self.size-1 # rffi will add \0 back
442 return space.newtext(rffi.charpsize2str(charpptr, strsize))
443 return space.newtext(rffi.charp2str(charpptr))
423444
424445
425446 class VoidPtrConverter(TypeConverter):
434455 state = space.fromcache(ffitypes.State)
435456 return state.c_voidp
436457
437 def convert_argument(self, space, w_obj, address, call_local):
458 def convert_argument(self, space, w_obj, address):
438459 x = rffi.cast(rffi.VOIDPP, address)
439460 x[0] = self._unwrap_object(space, w_obj)
440461 ba = rffi.cast(rffi.CCHARP, address)
441462 ba[capi.c_function_arg_typeoffset(space)] = 'o'
442463
443 def convert_argument_libffi(self, space, w_obj, address, call_local):
464 def convert_argument_libffi(self, space, w_obj, address, scratch):
444465 x = rffi.cast(rffi.VOIDPP, address)
445466 x[0] = self._unwrap_object(space, w_obj)
446467
447 def from_memory(self, space, w_obj, w_pycppclass, offset):
468 def from_memory(self, space, w_obj, offset):
448469 # returned as a long value for the address (INTPTR_T is not proper
449470 # per se, but rffi does not come with a PTRDIFF_T)
450471 address = self._get_raw_address(space, w_obj, offset)
451 ptrval = rffi.cast(rffi.ULONG, rffi.cast(rffi.VOIDPP, address)[0])
452 if ptrval == 0:
472 ptrval = rffi.cast(rffi.ULONGP, address)[0]
473 if ptrval == rffi.cast(rffi.ULONG, 0):
453474 from pypy.module._cppyy import interp_cppyy
454475 return interp_cppyy.get_nullptr(space)
455 arr = space.interp_w(W_Array, letter2tp(space, 'P'))
456 return arr.fromaddress(space, ptrval, sys.maxint)
476 shape = letter2tp(space, 'P')
477 return lowlevelviews.W_LowLevelView(space, shape, sys.maxint/shape.size, ptrval)
457478
458479 def to_memory(self, space, w_obj, w_value, offset):
459480 address = rffi.cast(rffi.VOIDPP, self._get_raw_address(space, w_obj, offset))
463484 address[0] = rffi.cast(rffi.VOIDP, self._unwrap_object(space, w_value))
464485
465486 class VoidPtrPtrConverter(TypeConverter):
466 _immutable_fields_ = ['uses_local', 'typecode']
467
468 uses_local = True
469 typecode = 'a'
470
471 def convert_argument(self, space, w_obj, address, call_local):
487 typecode = 'p'
488
489 def __init__(self, space, extra):
490 self.ref_buffer = lltype.nullptr(rffi.VOIDPP.TO)
491
492 def convert_argument(self, space, w_obj, address):
472493 x = rffi.cast(rffi.VOIDPP, address)
473 ba = rffi.cast(rffi.CCHARP, address)
474494 try:
475495 x[0] = get_rawbuffer(space, w_obj)
476496 except TypeError:
477 r = rffi.cast(rffi.VOIDPP, call_local)
478 r[0] = rffi.cast(rffi.VOIDP, get_rawobject(space, w_obj))
479 x[0] = rffi.cast(rffi.VOIDP, call_local)
497 ptr = rffi.cast(rffi.VOIDP, get_rawobject(space, w_obj))
498 self.ref_buffer = lltype.malloc(rffi.VOIDPP.TO, 1, flavor='raw')
499 self.ref_buffer[0] = ptr
500 x[0] = self.ref_buffer
501 ba = rffi.cast(rffi.CCHARP, address)
480502 ba[capi.c_function_arg_typeoffset(space)] = self.typecode
481503
482 def finalize_call(self, space, w_obj, call_local):
483 r = rffi.cast(rffi.VOIDPP, call_local)
484 try:
485 set_rawobject(space, w_obj, r[0])
486 except OperationError:
487 pass # no set on buffer/array/None
504 def finalize_call(self, space, w_obj):
505 if self.ref_buffer:
506 set_rawobject(space, w_obj, self.ref_buffer[0])
507
508 def free_argument(self, space, arg):
509 if self.ref_buffer:
510 lltype.free(self.ref_buffer, flavor='raw')
511 self.ref_buffer = lltype.nullptr(rffi.VOIDPP.TO)
488512
489513 class VoidPtrRefConverter(VoidPtrPtrConverter):
490 _immutable_fields_ = ['uses_local', 'typecode']
491 uses_local = True
514 _immutable_fields_ = ['typecode']
492515 typecode = 'V'
493516
494517 class InstanceRefConverter(TypeConverter):
495518 _immutable_fields_ = ['typecode', 'clsdecl']
496 typecode = 'V'
519 typecode = 'V'
497520
498521 def __init__(self, space, clsdecl):
499522 from pypy.module._cppyy.interp_cppyy import W_CPPClassDecl
503526 def _unwrap_object(self, space, w_obj):
504527 from pypy.module._cppyy.interp_cppyy import W_CPPInstance
505528 if isinstance(w_obj, W_CPPInstance):
506 from pypy.module._cppyy.interp_cppyy import INSTANCE_FLAGS_IS_R_VALUE
507 if w_obj.flags & INSTANCE_FLAGS_IS_R_VALUE:
529 from pypy.module._cppyy.interp_cppyy import INSTANCE_FLAGS_IS_RVALUE
530 if w_obj.rt_flags & INSTANCE_FLAGS_IS_RVALUE:
508531 # reject moves as all are explicit
509532 raise ValueError("lvalue expected")
510533 if capi.c_is_subtype(space, w_obj.clsdecl, self.clsdecl):
513536 obj_address = capi.direct_ptradd(rawobject, offset)
514537 return rffi.cast(capi.C_OBJECT, obj_address)
515538 raise oefmt(space.w_TypeError,
516 "cannot pass %T as %s", w_obj, self.clsdecl.name)
539 "cannot pass %T instance as %s", w_obj, self.clsdecl.name)
517540
518541 def cffi_type(self, space):
519542 state = space.fromcache(ffitypes.State)
520543 return state.c_voidp
521544
522 def convert_argument(self, space, w_obj, address, call_local):
545 def convert_argument(self, space, w_obj, address):
523546 x = rffi.cast(rffi.VOIDPP, address)
524547 x[0] = rffi.cast(rffi.VOIDP, self._unwrap_object(space, w_obj))
525548 address = rffi.cast(capi.C_OBJECT, address)
526549 ba = rffi.cast(rffi.CCHARP, address)
527550 ba[capi.c_function_arg_typeoffset(space)] = self.typecode
528551
529 def convert_argument_libffi(self, space, w_obj, address, call_local):
552 def convert_argument_libffi(self, space, w_obj, address, scratch):
530553 x = rffi.cast(rffi.VOIDPP, address)
531554 x[0] = rffi.cast(rffi.VOIDP, self._unwrap_object(space, w_obj))
532555
533556 class InstanceMoveConverter(InstanceRefConverter):
534557 def _unwrap_object(self, space, w_obj):
535558 # moving is same as by-ref, but have to check that move is allowed
536 from pypy.module._cppyy.interp_cppyy import W_CPPInstance, INSTANCE_FLAGS_IS_R_VALUE
537 if isinstance(w_obj, W_CPPInstance):
538 if w_obj.flags & INSTANCE_FLAGS_IS_R_VALUE:
539 w_obj.flags &= ~INSTANCE_FLAGS_IS_R_VALUE
540 return InstanceRefConverter._unwrap_object(self, space, w_obj)
559 from pypy.module._cppyy.interp_cppyy import W_CPPInstance, INSTANCE_FLAGS_IS_RVALUE
560 obj = space.interp_w(W_CPPInstance, w_obj)
561 if obj:
562 if obj.rt_flags & INSTANCE_FLAGS_IS_RVALUE:
563 obj.rt_flags &= ~INSTANCE_FLAGS_IS_RVALUE
564 try:
565 return InstanceRefConverter._unwrap_object(self, space, w_obj)
566 except Exception:
567 # TODO: if the method fails on some other converter, then the next
568 # overload can not be an rvalue anymore
569 obj.rt_flags |= INSTANCE_FLAGS_IS_RVALUE
570 raise
541571 raise oefmt(space.w_ValueError, "object is not an rvalue")
542572
543573
544574 class InstanceConverter(InstanceRefConverter):
545575
546 def convert_argument_libffi(self, space, w_obj, address, call_local):
576 def convert_argument_libffi(self, space, w_obj, address, scratch):
547577 from pypy.module._cppyy.interp_cppyy import FastCallNotPossible
548578 raise FastCallNotPossible # TODO: by-value is a jit_libffi special case
549579
550 def from_memory(self, space, w_obj, w_pycppclass, offset):
580 def from_memory(self, space, w_obj, offset):
551581 address = rffi.cast(capi.C_OBJECT, self._get_raw_address(space, w_obj, offset))
552582 from pypy.module._cppyy import interp_cppyy
553583 return interp_cppyy.wrap_cppinstance(space, address, self.clsdecl, do_cast=False)
555585 def to_memory(self, space, w_obj, w_value, offset):
556586 self._is_abstract(space)
557587
558
559588 class InstancePtrConverter(InstanceRefConverter):
560 typecode = 'o'
589 typecode = 'o'
561590
562591 def _unwrap_object(self, space, w_obj):
563592 try:
568597 return capi.C_NULL_OBJECT
569598 raise e
570599
571 def from_memory(self, space, w_obj, w_pycppclass, offset):
600 def from_memory(self, space, w_obj, offset):
572601 address = rffi.cast(capi.C_OBJECT, self._get_raw_address(space, w_obj, offset))
573602 from pypy.module._cppyy import interp_cppyy
574603 return interp_cppyy.wrap_cppinstance(space, address, self.clsdecl, do_cast=False)
575604
576 def to_memory(self, space, w_obj, w_value, offset):
577 address = rffi.cast(rffi.VOIDPP, self._get_raw_address(space, w_obj, offset))
578 address[0] = rffi.cast(rffi.VOIDP, self._unwrap_object(space, w_value))
579
580605 class InstancePtrPtrConverter(InstancePtrConverter):
581 _immutable_fields_ = ['uses_local']
582
583 uses_local = True
584
585 def convert_argument(self, space, w_obj, address, call_local):
586 r = rffi.cast(rffi.VOIDPP, call_local)
587 r[0] = rffi.cast(rffi.VOIDP, self._unwrap_object(space, w_obj))
606 typecode = 'o'
607
608 def __init__(self, space, extra):
609 InstancePtrConverter.__init__(self, space, extra)
610 self.ref_buffer = lltype.nullptr(rffi.VOIDPP.TO)
611
612 def convert_argument(self, space, w_obj, address):
588613 x = rffi.cast(rffi.VOIDPP, address)
589 x[0] = rffi.cast(rffi.VOIDP, call_local)
590 address = rffi.cast(capi.C_OBJECT, address)
591 ba = rffi.cast(rffi.CCHARP, address)
592 ba[capi.c_function_arg_typeoffset(space)] = 'o'
593
594 def convert_argument_libffi(self, space, w_obj, address, call_local):
614 ptr = rffi.cast(rffi.VOIDP, self._unwrap_object(space, w_obj))
615 self.ref_buffer = lltype.malloc(rffi.VOIDPP.TO, 1, flavor='raw')
616 self.ref_buffer[0] = ptr
617 x[0] = self.ref_buffer
618 ba = rffi.cast(rffi.CCHARP, address)
619 ba[capi.c_function_arg_typeoffset(space)] = self.typecode
620
621 def convert_argument_libffi(self, space, w_obj, address, scratch):
595622 # TODO: finalize_call not yet called for fast call (see interp_cppyy.py)
596623 from pypy.module._cppyy.interp_cppyy import FastCallNotPossible
597624 raise FastCallNotPossible
598625
599 def finalize_call(self, space, w_obj, call_local):
600 from pypy.module._cppyy.interp_cppyy import W_CPPInstance
601 assert isinstance(w_obj, W_CPPInstance)
602 r = rffi.cast(rffi.VOIDPP, call_local)
603 w_obj._rawobject = rffi.cast(capi.C_OBJECT, r[0])
604
605 def from_memory(self, space, w_obj, w_pycppclass, offset):
626 def from_memory(self, space, w_obj, offset):
606627 address = rffi.cast(capi.C_OBJECT, self._get_raw_address(space, w_obj, offset))
607628 from pypy.module._cppyy import interp_cppyy
608629 return interp_cppyy.wrap_cppinstance(
609630 space, address, self.clsdecl, do_cast=False, is_ref=True)
610631
632 def to_memory(self, space, w_obj, w_value, offset):
633 # the actual data member is of object* type, but we receive a pointer to that
634 # data member in order to modify its value, so by convention, the internal type
635 # used is object**
636 address = rffi.cast(rffi.VOIDPP, self._get_raw_address(space, w_obj, offset))
637 from pypy.module._cppyy.interp_cppyy import W_CPPInstance
638 cppinstance = space.interp_w(W_CPPInstance, w_value, can_be_None=True)
639 if cppinstance:
640 rawobject = cppinstance.get_rawobject()
641 offset = capi.c_base_offset(space, cppinstance.clsdecl, self.clsdecl, rawobject, 1)
642 obj_address = capi.direct_ptradd(rawobject, offset)
643 address[0] = rffi.cast(rffi.VOIDP, obj_address);
644 # register the value for potential recycling
645 from pypy.module._cppyy.interp_cppyy import memory_regulator
646 memory_regulator.register(cppinstance)
647 else:
648 raise oefmt(space.w_TypeError,
649 "cannot pass %T instance as %s", w_value, self.clsdecl.name)
650
651 def finalize_call(self, space, w_obj):
652 if self.ref_buffer:
653 set_rawobject(space, w_obj, self.ref_buffer[0])
654
655 def free_argument(self, space, arg):
656 if self.ref_buffer:
657 lltype.free(self.ref_buffer, flavor='raw')
658 self.ref_buffer = lltype.nullptr(rffi.VOIDPP.TO)
659
660 class InstanceArrayConverter(InstancePtrConverter):
661 _immutable_fields_ = ['size']
662
663 def __init__(self, space, clsdecl, array_size, dimensions):
664 InstancePtrConverter.__init__(self, space, clsdecl)
665 if array_size <= 0 or array_size == 2**31-1: # cling's code for "unknown" (?)
666 self.size = sys.maxint
667 else:
668 self.size = array_size
669 # peel one off as that should be the same as the array size
670 self.dimensions = dimensions[1:]
671
672 def from_memory(self, space, w_obj, offset):
673 address = rffi.cast(capi.C_OBJECT, self._get_raw_address(space, w_obj, offset))
674 return lowlevelviews.W_ArrayOfInstances(space, self.clsdecl, address, self.size, self.dimensions)
675
676 def to_memory(self, space, w_obj, w_value, offset):
677 self._is_abstract(space)
678
679
611680 class StdStringConverter(InstanceConverter):
612
613681 def __init__(self, space, extra):
614682 from pypy.module._cppyy import interp_cppyy
615683 cppclass = interp_cppyy.scope_byname(space, capi.std_string_name)
628696 address = rffi.cast(capi.C_OBJECT, self._get_raw_address(space, w_obj, offset))
629697 assign = self.clsdecl.get_overload("__assign__")
630698 from pypy.module._cppyy import interp_cppyy
631 assign.call(
632 interp_cppyy.wrap_cppinstance(space, address, self.clsdecl, do_cast=False), [w_value])
699 assign.call_impl(address, [w_value])
633700 except Exception:
634701 InstanceConverter.to_memory(self, space, w_obj, w_value, offset)
635702
636 def free_argument(self, space, arg, call_local):
703 def free_argument(self, space, arg):
637704 capi.c_destruct(space, self.clsdecl, rffi.cast(capi.C_OBJECT, rffi.cast(rffi.VOIDPP, arg)[0]))
705
706 class StdStringMoveConverter(StdStringConverter):
707 def _unwrap_object(self, space, w_obj):
708 # moving is same as by-ref, but have to check that move is allowed
709 moveit_reason = 3
710 from pypy.module._cppyy.interp_cppyy import W_CPPInstance, INSTANCE_FLAGS_IS_RVALUE
711 try:
712 obj = space.interp_w(W_CPPInstance, w_obj)
713 if obj and obj.rt_flags & INSTANCE_FLAGS_IS_RVALUE:
714 obj.rt_flags &= ~INSTANCE_FLAGS_IS_RVALUE
715 moveit_reason = 1
716 else:
717 moveit_reason = 0
718 except:
719 pass
720
721 if moveit_reason:
722 try:
723 return StdStringConverter._unwrap_object(self, space, w_obj)
724 except Exception:
725 if moveit_reason == 1:
726 # TODO: if the method fails on some other converter, then the next
727 # overload can not be an rvalue anymore
728 obj = space.interp_w(W_CPPInstance, w_obj)
729 obj.rt_flags |= INSTANCE_FLAGS_IS_RVALUE
730 raise
731
732 raise oefmt(space.w_ValueError, "object is not an rvalue")
638733
639734 class StdStringRefConverter(InstancePtrConverter):
640735 _immutable_fields_ = ['cppclass', 'typecode']
641
642736 typecode = 'V'
643737
644738 def __init__(self, space, extra):
652746 state = space.fromcache(ffitypes.State)
653747 return state.c_voidp
654748
655 def convert_argument(self, space, w_obj, address, call_local):
749 def convert_argument(self, space, w_obj, address):
656750 if hasattr(space, "fake"):
657751 raise NotImplementedError
658752 space.getbuiltinmodule("cpyext")
663757 ba = rffi.cast(rffi.CCHARP, address)
664758 ba[capi.c_function_arg_typeoffset(space)] = 'a'
665759
666 def convert_argument_libffi(self, space, w_obj, address, call_local):
760 def convert_argument_libffi(self, space, w_obj, address, scratch):
667761 # TODO: free_argument not yet called for fast call (see interp_cppyy.py)
668762 from pypy.module._cppyy.interp_cppyy import FastCallNotPossible
669763 raise FastCallNotPossible
677771 x = rffi.cast(rffi.VOIDPP, address)
678772 x[0] = rffi.cast(rffi.VOIDP, ref)"""
679773
680 def free_argument(self, space, arg, call_local):
774 def free_argument(self, space, arg):
681775 if hasattr(space, "fake"):
682776 raise NotImplementedError
683777 space.getbuiltinmodule("cpyext")
685779 decref(space, rffi.cast(PyObject, rffi.cast(rffi.VOIDPP, arg)[0]))
686780
687781
782 class FunctionPointerConverter(TypeConverter):
783 _immutable_fields_ = ['signature']
784
785 def __init__(self, space, signature):
786 self.signature = signature
787
788 def convert_argument(self, space, w_obj, address):
789 # TODO: atm, does not actually get an overload, but a staticmethod
790 from pypy.module._cppyy.interp_cppyy import W_CPPOverload
791 cppol = space.interp_w(W_CPPOverload, w_obj)
792
793 # find the function with matching signature
794 for i in range(len(cppol.functions)):
795 m = cppol.functions[i]
796 if m.signature(False) == self.signature:
797 x = rffi.cast(rffi.VOIDPP, address)
798 x[0] = rffi.cast(rffi.VOIDP, capi.c_function_address(space, m.cppmethod))
799 address = rffi.cast(capi.C_OBJECT, address)
800 ba = rffi.cast(rffi.CCHARP, address)
801 ba[capi.c_function_arg_typeoffset(space)] = 'p'
802 return
803
804 # lookup failed
805 raise oefmt(space.w_TypeError,
806 "no overload found matching %s", self.signature)
807
808
809 class SmartPtrConverter(TypeConverter):
810 _immutable_fields = ['typecode', 'smartdecl', 'rawdecl', 'deref']
811 typecode = 'V'
812
813 def __init__(self, space, smartdecl, raw, deref):
814 from pypy.module._cppyy.interp_cppyy import W_CPPClassDecl, get_pythonized_cppclass
815 self.smartdecl = smartdecl
816 w_raw = get_pythonized_cppclass(space, raw)
817 self.rawdecl = space.interp_w(W_CPPClassDecl,
818 space.findattr(w_raw, space.newtext("__cppdecl__")))
819 self.deref = deref
820
821 def _unwrap_object(self, space, w_obj):
822 from pypy.module._cppyy.interp_cppyy import W_CPPInstance
823 if isinstance(w_obj, W_CPPInstance):
824 # w_obj could carry a 'hidden' smart ptr or be one, cover both cases
825 have_match = False
826 if w_obj.smartdecl and capi.c_is_subtype(space, w_obj.smartdecl, self.smartdecl):
827 # hidden case, do not derefence when getting obj address
828 have_match = True
829 rawobject = w_obj._rawobject # TODO: this direct access if fugly
830 offset = capi.c_base_offset(space, w_obj.smartdecl, self.smartdecl, rawobject, 1)
831 elif capi.c_is_subtype(space, w_obj.clsdecl, self.smartdecl):
832 # exposed smart pointer
833 have_match = True
834 rawobject = w_obj.get_rawobject()
835 offset = capi.c_base_offset(space, w_obj.clsdecl, self.smartdecl, rawobject, 1)
836 if have_match:
837 obj_address = capi.direct_ptradd(rawobject, offset)
838 return rffi.cast(capi.C_OBJECT, obj_address)
839
840 raise oefmt(space.w_TypeError,
841 "cannot pass %T instance as %s", w_obj, self.rawdecl.name)
842
843 def convert_argument(self, space, w_obj, address):
844 x = rffi.cast(rffi.VOIDPP, address)
845 x[0] = rffi.cast(rffi.VOIDP, self._unwrap_object(space, w_obj))
846 address = rffi.cast(capi.C_OBJECT, address)
847 ba = rffi.cast(rffi.CCHARP, address)
848 ba[capi.c_function_arg_typeoffset(space)] = self.typecode
849
850 def from_memory(self, space, w_obj, offset):
851 address = rffi.cast(capi.C_OBJECT, self._get_raw_address(space, w_obj, offset))
852 from pypy.module._cppyy import interp_cppyy
853 return interp_cppyy.wrap_cppinstance(space, address,
854 self.rawdecl, smartdecl=self.smartdecl, deref=self.deref, do_cast=False)
855
856 class SmartPtrPtrConverter(SmartPtrConverter):
857 typecode = 'o'
858
859 def from_memory(self, space, w_obj, offset):
860 self._is_abstract(space)
861
862 def to_memory(self, space, w_obj, w_value, offset):
863 self._is_abstract(space)
864
865
866 class SmartPtrRefConverter(SmartPtrPtrConverter):
867 typecode = 'V'
868
869
688870 class MacroConverter(TypeConverter):
689 def from_memory(self, space, w_obj, w_pycppclass, offset):
871 def from_memory(self, space, w_obj, offset):
690872 # TODO: get the actual type info from somewhere ...
691873 address = self._get_raw_address(space, w_obj, offset)
692874 longptr = rffi.cast(rffi.LONGP, address)
700882 # 1) full, exact match
701883 # 1a) const-removed match
702884 # 2) match of decorated, unqualified type
703 # 3) accept ref as pointer (for the stubs, const& can be
704 # by value, but that does not work for the ffi path)
705 # 4) generalized cases (covers basically all user classes)
706 # 5) void* or void converter (which fails on use)
885 # 3) generalized cases (covers basically all user classes)
886 # 3a) smart pointers
887 # 4) void* or void converter (which fails on use)
707888
708889 name = capi.c_resolve_name(space, _name)
709890
710 # 1) full, exact match
891 # full, exact match
711892 try:
712893 return _converters[name](space, default)
713894 except KeyError:
714895 pass
715896
716 # 1a) const-removed match
897 # const-removed match
717898 try:
718899 return _converters[helper.remove_const(name)](space, default)
719900 except KeyError:
720901 pass
721902
722 # 2) match of decorated, unqualified type
723 compound = helper.compound(name)
903 # match of decorated, unqualified type
904 cpd = helper.compound(name)
724905 clean_name = capi.c_resolve_name(space, helper.clean_type(name))
725906 try:
726 # array_index may be negative to indicate no size or no size found
727 array_size = helper.array_size(_name) # uses original arg
728 return _a_converters[clean_name+compound](space, array_size)
907 return _converters[clean_name+cpd](space, default)
729908 except KeyError:
730909 pass
731910
732 # 3) TODO: accept ref as pointer
733
734 # 4) generalized cases (covers basically all user classes)
911 # arrays (array_size may be negative, meaning: no size or no size found)
912 array_size = -1
913 if cpd == "[]":
914 array_size = helper.array_size(_name) # uses original arg
915 elif cpd == '*' and ':' in default:
916 # this happens for multi-dimensional arrays: those are described as pointers
917 cpd = "[]"
918 splitpos = default.find(':')
919 if 0 < splitpos: # always true, but needed for annotator
920 array_size = int(default[:splitpos])
921
922 try:
923 # TODO: using clean_name here drops const (e.g. const char[] will
924 # never be seen this way)
925 return _a_converters[clean_name+cpd](space, array_size)
926 except KeyError:
927 pass
928
929 # generalized cases (covers basically all user classes)
735930 from pypy.module._cppyy import interp_cppyy
736931 scope_decl = interp_cppyy.scope_byname(space, clean_name)
737932 if scope_decl:
738 # type check for the benefit of the annotator
739933 from pypy.module._cppyy.interp_cppyy import W_CPPClassDecl
740934 clsdecl = space.interp_w(W_CPPClassDecl, scope_decl, can_be_None=False)
741 if compound == "*":
935
936 # check smart pointer type
937 check_smart = capi.c_smartptr_info(space, clean_name)
938 if check_smart[0]:
939 if cpd == '':
940 return SmartPtrConverter(space, clsdecl, check_smart[1], check_smart[2])
941 elif cpd == '*':
942 return SmartPtrPtrConverter(space, clsdecl, check_smart[1], check_smart[2])
943 elif cpd == '&':
944 return SmartPtrRefConverter(space, clsdecl, check_smart[1], check_smart[2])
945 # fall through: can still return smart pointer in non-smart way
946
947 # type check for the benefit of the annotator
948 if cpd == "*":
742949 return InstancePtrConverter(space, clsdecl)
743 elif compound == "&":
950 elif cpd == "&":
744951 return InstanceRefConverter(space, clsdecl)
745 elif compound == "&&":
952 elif cpd == "&&":
746953 return InstanceMoveConverter(space, clsdecl)
747 elif compound == "**":
954 elif cpd in ["**", "*[]", "&*"]:
748955 return InstancePtrPtrConverter(space, clsdecl)
749 elif compound == "":
956 elif cpd == "[]" and array_size > 0:
957 # default encodes the dimensions
958 dims = default.split(':')
959 return InstanceArrayConverter(space, clsdecl, array_size, dims)
960 elif cpd == "":
750961 return InstanceConverter(space, clsdecl)
751
752 # 5) void* or void converter (which fails on use)
753 if 0 <= compound.find('*'):
962 elif "(anonymous)" in name:
963 # special case: enum w/o a type name
964 return _converters["internal_enum_type_t"](space, default)
965 elif "(*)" in name or "::*)" in name:
966 # function pointer
967 pos = name.find("*)")
968 if pos > 0:
969 return FunctionPointerConverter(space, name[pos+2:])
970
971 # void* or void converter (which fails on use)
972 if 0 <= cpd.find('*'):
754973 return VoidPtrConverter(space, default) # "user knows best"
755974
756975 # return a void converter here, so that the class can be build even
760979
761980 _converters["bool"] = BoolConverter
762981 _converters["char"] = CharConverter
982 _converters["unsigned char"] = UCharConverter
763983 _converters["float"] = FloatConverter
764984 _converters["const float&"] = ConstFloatRefConverter
765985 _converters["double"] = DoubleConverter
766986 _converters["const double&"] = ConstDoubleRefConverter
767 #_converters["long double"] = LongDoubleConverter
768 #_converters["const long double&"] = ConstLongDoubleRefConverter
987 _converters["long double"] = LongDoubleConverter
988 _converters["const long double&"] = ConstLongDoubleRefConverter
769989 _converters["const char*"] = CStringConverter
770990 _converters["void*"] = VoidPtrConverter
771991 _converters["void**"] = VoidPtrPtrConverter
775995 _converters["std::basic_string<char>"] = StdStringConverter
776996 _converters["const std::basic_string<char>&"] = StdStringConverter # TODO: shouldn't copy
777997 _converters["std::basic_string<char>&"] = StdStringRefConverter
998 _converters["std::basic_string<char>&&"] = StdStringMoveConverter
778999
7791000 _converters["PyObject*"] = PyObjectConverter
7801001
7981019 _immutable_ = True
7991020 typecode = c_tc
8001021 def __init__(self, space, default):
801 self.default = rffi.cast(self.c_type, capi.c_strtoll(space, default))
1022 self.valid_default = False
1023 try:
1024 self.default = rffi.cast(self.c_type, capi.c_strtoll(space, default))
1025 self.valid_default = True
1026 except Exception:
1027 self.default = rffi.cast(self.c_type, 0)
8021028 class ConstRefConverter(ConstRefNumericTypeConverterMixin, BasicConverter):
8031029 _immutable_ = True
8041030 for name in names:
8151041 _immutable_ = True
8161042 typecode = c_tc
8171043 def __init__(self, space, default):
818 self.default = rffi.cast(self.c_type, capi.c_strtoll(space, default))
1044 self.valid_default = False
1045 try:
1046 self.default = rffi.cast(self.c_type, capi.c_strtoll(space, default))
1047 self.valid_default = True
1048 except Exception:
1049 self.default = rffi.cast(self.c_type, 0)
8191050 class ConstRefConverter(ConstRefNumericTypeConverterMixin, BasicConverter):
8201051 _immutable_ = True
8211052 for name in names:
8351066 _immutable_ = True
8361067 typecode = c_tc
8371068 def __init__(self, space, default):
838 self.default = rffi.cast(self.c_type, capi.c_strtoull(space, default))
1069 self.valid_default = False
1070 try:
1071 self.default = rffi.cast(self.c_type, capi.c_strtoull(space, default))
1072 self.valid_default = True
1073 except Exception:
1074 self.default = rffi.cast(self.c_type, 0)
8391075 class ConstRefConverter(ConstRefNumericTypeConverterMixin, BasicConverter):
8401076 _immutable_ = True
8411077 for name in names:
8491085 "NOT_RPYTHON"
8501086 array_info = (
8511087 ('b', rffi.sizeof(rffi.UCHAR), ("bool",)), # is debatable, but works ...
1088 ('B', rffi.sizeof(rffi.UCHAR), ("unsigned char",)),
8521089 ('h', rffi.sizeof(rffi.SHORT), ("short int", "short")),
8531090 ('H', rffi.sizeof(rffi.USHORT), ("unsigned short int", "unsigned short")),
8541091 ('i', rffi.sizeof(rffi.INT), ("int",)),
8641101
8651102 for tcode, tsize, names in array_info:
8661103 class ArrayConverter(ArrayTypeConverterMixin, TypeConverter):
1104 _immutable_fields_ = ['typecode', 'typesize']
8671105 typecode = tcode
8681106 typesize = tsize
8691107 class PtrConverter(PtrTypeConverterMixin, TypeConverter):
1108 _immutable_fields_ = ['typecode', 'typesize']
8701109 typecode = tcode
8711110 typesize = tsize
8721111 for name in names:
8751114
8761115 # special case, const char* w/ size and w/o '\0'
8771116 _a_converters["const char[]"] = CStringConverterWithSize
1117 _a_converters["char[]"] = _a_converters["const char[]"] # debatable
8781118
8791119 _build_array_converters()
8801120
8821122 def _add_aliased_converters():
8831123 "NOT_RPYTHON"
8841124 aliases = (
885 ("char", "unsigned char"), # TODO: check
8861125 ("char", "signed char"), # TODO: check
8871126 ("const char*", "char*"),
8881127
8891128 ("std::basic_string<char>", "string"),
8901129 ("const std::basic_string<char>&", "const string&"),
8911130 ("std::basic_string<char>&", "string&"),
1131 ("std::basic_string<char>&&", "string&&"),
8921132
8931133 ("PyObject*", "_object*"),
8941134 )
00 import sys
11
22 from pypy.interpreter.error import oefmt
3
43 from rpython.rtyper.lltypesystem import rffi, lltype
54 from rpython.rlib import jit_libffi
6
7 from pypy.module._rawffi.interp_rawffi import unpack_simple_shape
8 from pypy.module._rawffi.array import W_Array, W_ArrayInstance
9
10 from pypy.module._cppyy import helper, capi, ffitypes
5 from pypy.module._rawffi.interp_rawffi import letter2tp
6 from pypy.module._cppyy import helper, capi, ffitypes, lowlevelviews
117
128 # Executor objects are used to dispatch C++ methods. They are defined by their
139 # return type only: arguments are converted by Converter objects, and Executors
2521
2622 NULL = lltype.nullptr(jit_libffi.FFI_TYPE_P.TO)
2723
28 class FunctionExecutor(object):
24 class Executor(object):
2925 def __init__(self, space, extra):
3026 pass
3127
4238 raise FastCallNotPossible
4339
4440
45 class PtrTypeExecutor(FunctionExecutor):
41 class PtrTypeExecutor(Executor):
4642 _immutable_fields_ = ['typecode']
4743 typecode = 'P'
4844
5551 raise NotImplementedError
5652 lresult = capi.c_call_l(space, cppmethod, cppthis, num_args, args)
5753 ptrval = rffi.cast(rffi.ULONG, lresult)
58 arr = space.interp_w(W_Array, unpack_simple_shape(space, space.newtext(self.typecode)))
59 if ptrval == 0:
54 if ptrval == rffi.cast(rffi.ULONG, 0):
6055 from pypy.module._cppyy import interp_cppyy
6156 return interp_cppyy.get_nullptr(space)
62 return arr.fromaddress(space, ptrval, sys.maxint)
63
64
65 class VoidExecutor(FunctionExecutor):
57 shape = letter2tp(space, self.typecode)
58 return lowlevelviews.W_LowLevelView(space, shape, sys.maxint/shape.size, ptrval)
59
60
61 class VoidExecutor(Executor):
6662 def cffi_type(self, space):
6763 state = space.fromcache(ffitypes.State)
6864 return state.c_void
7975 class NumericExecutorMixin(object):
8076 _mixin_ = True
8177
82 #def _wrap_object(self, space, obj):
83 # return getattr(space, self.wrapper)(obj)
84
8578 def execute(self, space, cppmethod, cppthis, num_args, args):
8679 result = self.c_stubcall(space, cppmethod, cppthis, num_args, args)
8780 return self._wrap_object(space, rffi.cast(self.c_type, result))
9588 _mixin_ = True
9689
9790 def __init__(self, space, extra):
98 FunctionExecutor.__init__(self, space, extra)
91 Executor.__init__(self, space, extra)
9992 self.do_assign = False
100 self.item = rffi.cast(self.c_type, 0)
93 self.w_item = space.w_None
10194
10295 def set_item(self, space, w_item):
103 self.item = self._unwrap_object(space, w_item)
96 self.w_item = w_item
10497 self.do_assign = True
105
106 #def _wrap_object(self, space, obj):
107 # return getattr(space, self.wrapper)(rffi.cast(self.c_type, obj))
10898
10999 def _wrap_reference(self, space, rffiptr):
110100 if self.do_assign:
111 rffiptr[0] = self.item
112 self.do_assign = False
101 rffiptr[0] = rffi.cast(self.c_type, self._unwrap_object(space, self.w_item))
102 self.do_assign = False
113103 return self._wrap_object(space, rffiptr[0]) # all paths, for rtyper
114104
115105 def execute(self, space, cppmethod, cppthis, num_args, args):
122112 return self._wrap_reference(space,
123113 rffi.cast(self.c_ptrtype, rffi.cast(rffi.VOIDPP, result)[0]))
124114
125
126 class CStringExecutor(FunctionExecutor):
127
115 class LongDoubleExecutorMixin(object):
116 # Note: not really supported, but returns normal double
117 _mixin_ = True
118
119 def execute(self, space, cppmethod, cppthis, num_args, args):
120 result = self.c_stubcall(space, cppmethod, cppthis, num_args, args)
121 return space.newfloat(result)
122
123 def execute_libffi(self, space, cif_descr, funcaddr, buffer):
124 from pypy.module._cppyy.interp_cppyy import FastCallNotPossible
125 raise FastCallNotPossible
126
127 class LongDoubleExecutor(ffitypes.typeid(rffi.LONGDOUBLE), LongDoubleExecutorMixin, Executor):
128 _immutable_ = True
129 c_stubcall = staticmethod(capi.c_call_ld)
130
131 class LongDoubleRefExecutorMixin(NumericRefExecutorMixin):
132 # Note: not really supported, but returns normal double
133 _mixin_ = True
134
135 def _wrap_reference(self, space, rffiptr):
136 if self.do_assign:
137 capi.c_double2longdouble(space, space.float_w(self.w_item), rffiptr)
138 self.do_assign = False
139 return self.w_item
140 return space.newfloat(capi.c_longdouble2double(space, rffiptr))
141
142 def execute(self, space, cppmethod, cppthis, num_args, args):
143 result = capi.c_call_r(space, cppmethod, cppthis, num_args, args)
144 return self._wrap_reference(space, rffi.cast(self.c_ptrtype, result))
145
146 def execute_libffi(self, space, cif_descr, funcaddr, buffer):
147 jit_libffi.jit_ffi_call(cif_descr, funcaddr, buffer)
148 result = rffi.ptradd(buffer, cif_descr.exchange_result)
149 return self._wrap_reference(space,
150 rffi.cast(self.c_ptrtype, rffi.cast(rffi.VOIDPP, result)[0]))
151
152 class LongDoubleRefExecutor(ffitypes.typeid(rffi.LONGDOUBLE), LongDoubleRefExecutorMixin, Executor):
153 def cffi_type(self, space):
154 state = space.fromcache(ffitypes.State)
155 return state.c_voidp
156
157
158 class CStringExecutor(Executor):
128159 def execute(self, space, cppmethod, cppthis, num_args, args):
129160 lresult = capi.c_call_l(space, cppmethod, cppthis, num_args, args)
130161 ccpresult = rffi.cast(rffi.CCHARP, lresult)
138169 return space.newtext(result)
139170
140171
141 class ConstructorExecutor(FunctionExecutor):
142
172 class ConstructorExecutor(Executor):
143173 def execute(self, space, cppmethod, cpptype, num_args, args):
144174 from pypy.module._cppyy import interp_cppyy
145175 newthis = capi.c_constructor(space, cppmethod, cpptype, num_args, args)
147177 return space.newlong(rffi.cast(rffi.LONG, newthis)) # really want ptrdiff_t here
148178
149179
150 class InstancePtrExecutor(FunctionExecutor):
151 _immutable_fields_ = ['cppclass']
152
153 def __init__(self, space, cppclass):
154 FunctionExecutor.__init__(self, space, cppclass)
155 self.cppclass = cppclass
180 class InstanceExecutor(Executor):
181 # For return of a C++ instance by pointer: MyClass* func()
182 _immutable_fields_ = ['clsdecl']
183
184 def __init__(self, space, clsdecl):
185 Executor.__init__(self, space, clsdecl)
186 self.clsdecl = clsdecl
187
188 def _wrap_result(self, space, obj):
189 from pypy.module._cppyy import interp_cppyy
190 return interp_cppyy.wrap_cppinstance(space,
191 obj, self.clsdecl, do_cast=False, python_owns=True, fresh=True)
192
193 def execute(self, space, cppmethod, cppthis, num_args, args):
194 oresult = capi.c_call_o(space, cppmethod, cppthis, num_args, args, self.clsdecl)
195 return self._wrap_result(space, rffi.cast(capi.C_OBJECT, oresult))
196
197
198 class InstancePtrExecutor(InstanceExecutor):
199 # For return of a C++ instance by pointer: MyClass* func()
156200
157201 def cffi_type(self, space):
158202 state = space.fromcache(ffitypes.State)
159203 return state.c_voidp
160204
161 def execute(self, space, cppmethod, cppthis, num_args, args):
162 from pypy.module._cppyy import interp_cppyy
163 long_result = capi.c_call_l(space, cppmethod, cppthis, num_args, args)
164 ptr_result = rffi.cast(capi.C_OBJECT, long_result)
165 pyres = interp_cppyy.wrap_cppinstance(space, ptr_result, self.cppclass)
166 return pyres
167
168 def execute_libffi(self, space, cif_descr, funcaddr, buffer):
169 jit_libffi.jit_ffi_call(cif_descr, funcaddr, buffer)
170 result = rffi.ptradd(buffer, cif_descr.exchange_result)
171 from pypy.module._cppyy import interp_cppyy
172 ptr_result = rffi.cast(capi.C_OBJECT, rffi.cast(rffi.VOIDPP, result)[0])
173 return interp_cppyy.wrap_cppinstance(space, ptr_result, self.cppclass)
205 def _wrap_result(self, space, obj):
206 from pypy.module._cppyy import interp_cppyy
207 return interp_cppyy.wrap_cppinstance(space, obj, self.clsdecl)
208
209 def execute(self, space, cppmethod, cppthis, num_args, args):
210 lresult = capi.c_call_l(space, cppmethod, cppthis, num_args, args)
211 return self._wrap_result(space, rffi.cast(capi.C_OBJECT, lresult))
212
213 def execute_libffi(self, space, cif_descr, funcaddr, buffer):
214 jit_libffi.jit_ffi_call(cif_descr, funcaddr, buffer)
215 presult = rffi.ptradd(buffer, cif_descr.exchange_result)
216 obj = rffi.cast(capi.C_OBJECT, rffi.cast(rffi.VOIDPP, presult)[0])
217 return self._wrap_result(space, obj)
174218
175219 class InstancePtrPtrExecutor(InstancePtrExecutor):
176
177 def execute(self, space, cppmethod, cppthis, num_args, args):
178 from pypy.module._cppyy import interp_cppyy
179 voidp_result = capi.c_call_r(space, cppmethod, cppthis, num_args, args)
180 ref_address = rffi.cast(rffi.VOIDPP, voidp_result)
181 ptr_result = rffi.cast(capi.C_OBJECT, ref_address[0])
182 return interp_cppyy.wrap_cppinstance(space, ptr_result, self.cppclass)
220 # For return of a C++ instance by ptr-to-ptr or ptr-to-ref: MyClass*& func()
221
222 def execute(self, space, cppmethod, cppthis, num_args, args):
223 presult = capi.c_call_r(space, cppmethod, cppthis, num_args, args)
224 ref = rffi.cast(rffi.VOIDPP, presult)
225 return self._wrap_result(space, rffi.cast(capi.C_OBJECT, ref[0]))
183226
184227 def execute_libffi(self, space, cif_descr, funcaddr, buffer):
185228 from pypy.module._cppyy.interp_cppyy import FastCallNotPossible
186229 raise FastCallNotPossible
187230
188 class InstanceExecutor(InstancePtrExecutor):
189
190 def execute(self, space, cppmethod, cppthis, num_args, args):
191 from pypy.module._cppyy import interp_cppyy
192 long_result = capi.c_call_o(space, cppmethod, cppthis, num_args, args, self.cppclass)
193 ptr_result = rffi.cast(capi.C_OBJECT, long_result)
194 return interp_cppyy.wrap_cppinstance(space, ptr_result, self.cppclass,
195 do_cast=False, python_owns=True, fresh=True)
196
197 def execute_libffi(self, space, cif_descr, funcaddr, buffer):
198 from pypy.module._cppyy.interp_cppyy import FastCallNotPossible
199 raise FastCallNotPossible
200
201231
202232 class StdStringExecutor(InstancePtrExecutor):
203
204233 def execute(self, space, cppmethod, cppthis, num_args, args):
205234 cstr, cstr_len = capi.c_call_s(space, cppmethod, cppthis, num_args, args)
206235 pystr = rffi.charpsize2str(cstr, cstr_len)
207236 capi.c_free(space, rffi.cast(rffi.VOIDP, cstr))
208 return space.newbytes(pystr)
237 return space.newbytes(pystr)
209238
210239 def execute_libffi(self, space, cif_descr, funcaddr, buffer):
211240 from pypy.module._cppyy.interp_cppyy import FastCallNotPossible
212241 raise FastCallNotPossible
213242
214243 class StdStringRefExecutor(InstancePtrExecutor):
215
216 def __init__(self, space, cppclass):
217 from pypy.module._cppyy import interp_cppyy
218 cppclass = interp_cppyy.scope_byname(space, capi.std_string_name)
219 InstancePtrExecutor.__init__(self, space, cppclass)
244 def __init__(self, space, clsdecl):
245 from pypy.module._cppyy import interp_cppyy
246 clsdecl = interp_cppyy.scope_byname(space, capi.std_string_name)
247 InstancePtrExecutor.__init__(self, space, clsdecl)
220248
221249
222250 class PyObjectExecutor(PtrTypeExecutor):
223
224251 def wrap_result(self, space, lresult):
225252 space.getbuiltinmodule("cpyext")
226253 from pypy.module.cpyext.pyobject import PyObject, from_ref, make_ref, decref
242269 jit_libffi.jit_ffi_call(cif_descr, funcaddr, buffer)
243270 result = rffi.ptradd(buffer, cif_descr.exchange_result)
244271 return self.wrap_result(space, rffi.cast(rffi.LONGP, result)[0])
272
273
274 class SmartPointerExecutor(InstanceExecutor):
275 _immutable_fields_ = ['smartdecl', 'deref']
276
277 def __init__(self, space, smartdecl, raw, deref):
278 from pypy.module._cppyy.interp_cppyy import W_CPPClassDecl, get_pythonized_cppclass
279 w_raw = get_pythonized_cppclass(space, raw)
280 rawdecl = space.interp_w(W_CPPClassDecl, space.findattr(w_raw, space.newtext("__cppdecl__")))
281 InstanceExecutor.__init__(self, space, rawdecl)
282 self.smartdecl = smartdecl
283 self.deref = deref
284
285 def _wrap_result(self, space, obj):
286 from pypy.module._cppyy import interp_cppyy
287 return interp_cppyy.wrap_cppinstance(space, obj, self.clsdecl,
288 self.smartdecl, self.deref, do_cast=False, python_owns=True, fresh=True)
289
290 class SmartPointerPtrExecutor(InstancePtrExecutor):
291 _immutable_fields_ = ['smartdecl', 'deref']
292
293 def __init__(self, space, smartdecl, raw, deref):
294 # TODO: share this with SmartPointerExecutor through in mixin
295 from pypy.module._cppyy.interp_cppyy import W_CPPClassDecl, get_pythonized_cppclass
296 w_raw = get_pythonized_cppclass(space, raw)
297 rawdecl = space.interp_w(W_CPPClassDecl, space.findattr(w_raw, space.newtext("__cppdecl__")))
298 InstancePtrExecutor.__init__(self, space, rawdecl)
299 self.smartdecl = smartdecl
300 self.deref = deref
301
302 def _wrap_result(self, space, obj):
303 from pypy.module._cppyy import interp_cppyy
304 # TODO: this is a pointer to a smart pointer, take ownership on the smart one?
305 return interp_cppyy.wrap_cppinstance(space, obj, self.clsdecl,
306 self.smartdecl, self.deref, do_cast=False)
245307
246308
247309 _executors = {}
256318
257319 name = capi.c_resolve_name(space, name)
258320
259 # 1) full, qualified match
321 # full, qualified match
260322 try:
261323 return _executors[name](space, None)
262324 except KeyError:
265327 compound = helper.compound(name)
266328 clean_name = capi.c_resolve_name(space, helper.clean_type(name))
267329
268 # 1a) clean lookup
330 # clean lookup
269331 try:
270332 return _executors[clean_name+compound](space, None)
271333 except KeyError:
272334 pass
273335
274 # 2) drop '&': by-ref is pretty much the same as by-value, python-wise
336 # drop '&': by-ref is pretty much the same as by-value, python-wise
275337 if compound and compound[len(compound)-1] == '&':
276338 # TODO: this does not actually work with Reflex (?)
277339 try:
279341 except KeyError:
280342 pass
281343
282 # 3) types/classes, either by ref/ptr or by value
344 # types/classes, either by ref/ptr or by value
283345 from pypy.module._cppyy import interp_cppyy
284346 cppclass = interp_cppyy.scope_byname(space, clean_name)
285347 if cppclass:
286348 # type check for the benefit of the annotator
287349 from pypy.module._cppyy.interp_cppyy import W_CPPClassDecl
288 cppclass = space.interp_w(W_CPPClassDecl, cppclass, can_be_None=False)
350 clsdecl = space.interp_w(W_CPPClassDecl, cppclass, can_be_None=False)
351
352 # check smart pointer type
353 check_smart = capi.c_smartptr_info(space, clean_name)
354 if check_smart[0]:
355 if compound == '':
356 return SmartPointerExecutor(space, clsdecl, check_smart[1], check_smart[2])
357 elif compound == '*' or compound == '&':
358 return SmartPointerPtrExecutor(space, clsdecl, check_smart[1], check_smart[2])
359 # fall through: can still return smart pointer in non-smart way
360
289361 if compound == '':
290 return InstanceExecutor(space, cppclass)
362 return InstanceExecutor(space, clsdecl)
291363 elif compound == '*' or compound == '&':
292 return InstancePtrExecutor(space, cppclass)
364 return InstancePtrExecutor(space, clsdecl)
293365 elif compound == '**' or compound == '*&':
294 return InstancePtrPtrExecutor(space, cppclass)
366 return InstancePtrPtrExecutor(space, clsdecl)
367 elif "(anonymous)" in name:
368 # special case: enum w/o a type name
369 return _executors["internal_enum_type_t"](space, None)
295370
296371 # 4) additional special cases
297372 if compound == '*':
298373 return _executors['void*'](space, None) # allow at least passing of the pointer
299374
300375 # currently used until proper lazy instantiation available in interp_cppyy
301 return FunctionExecutor(space, None)
376 return Executor(space, None)
302377
303378
304379 _executors["void"] = VoidExecutor
305380 _executors["void*"] = PtrTypeExecutor
306381 _executors["const char*"] = CStringExecutor
382
383 # long double not really supported: narrows to double
384 _executors["long double"] = LongDoubleExecutor
385 _executors["long double&"] = LongDoubleRefExecutor
307386
308387 # special cases (note: 'string' aliases added below)
309388 _executors["constructor"] = ConstructorExecutor
334413 )
335414
336415 for c_type, stub, names in type_info:
337 class BasicExecutor(ffitypes.typeid(c_type), NumericExecutorMixin, FunctionExecutor):
416 class BasicExecutor(ffitypes.typeid(c_type), NumericExecutorMixin, Executor):
338417 _immutable_ = True
339418 c_stubcall = staticmethod(stub)
340 class BasicRefExecutor(ffitypes.typeid(c_type), NumericRefExecutorMixin, FunctionExecutor):
419 class BasicRefExecutor(ffitypes.typeid(c_type), NumericRefExecutorMixin, Executor):
341420 def cffi_type(self, space):
342421 state = space.fromcache(ffitypes.State)
343422 return state.c_voidp
7373 # allow int to pass to char and make sure that str is of length 1
7474 if space.isinstance_w(w_value, space.w_int):
7575 ival = space.c_int_w(w_value)
76 if ival < -128 or 127 < ival:
77 raise oefmt(space.w_ValueError, "char arg not in range(-128,128)")
78
79 value = rffi.cast(rffi.CHAR, space.c_int_w(w_value))
80 else:
81 if space.isinstance_w(w_value, space.w_text):
82 value = space.text_w(w_value)
83 else:
84 value = space.bytes_w(w_value)
85 if len(value) != 1:
86 raise oefmt(space.w_ValueError,
87 "char expected, got string of size %d", len(value))
88
89 value = rffi.cast(rffi.CHAR, value[0])
90 return value # turn it into a "char" to the annotator
91
92 def cffi_type(self, space):
93 state = space.fromcache(State)
94 return state.c_char
95
96 class UCharTypeMixin(object):
97 _mixin_ = True
98 _immutable_fields_ = ['c_type', 'c_ptrtype']
99
100 c_type = rffi.UCHAR
101 c_ptrtype = rffi.CCHARP # there's no such thing as rffi.UCHARP
102
103 def _wrap_object(self, space, obj):
104 return space.newbytes(obj)
105
106 def _unwrap_object(self, space, w_value):
107 # allow int to pass to char and make sure that str is of length 1
108 if space.isinstance_w(w_value, space.w_int):
109 ival = space.c_int_w(w_value)
76110 if ival < 0 or 256 <= ival:
77111 raise oefmt(space.w_ValueError, "char arg not in range(256)")
78112
79113 value = rffi.cast(rffi.CHAR, space.c_int_w(w_value))
80 elif space.isinstance_w(w_value, space.w_text):
81 value = space.text_w(w_value)
82114 else:
83 value = space.bytes_w(w_value)
84
85 if len(value) != 1:
86 raise oefmt(space.w_ValueError,
87 "char expected, got string of size %d", len(value))
88 value = rffi.cast(rffi.CHAR, value[0])
89
115 if space.isinstance_w(w_value, space.w_text):
116 value = space.text_w(w_value)
117 else:
118 value = space.bytes_w(w_value)
119 if len(value) != 1:
120 raise oefmt(space.w_ValueError,
121 "unsigned char expected, got string of size %d", len(value))
122
123 value = rffi.cast(rffi.CHAR, value[0])
90124 return value # turn it into a "char" to the annotator
91125
92126 def cffi_type(self, space):
261295 _immutable_fields_ = ['c_type', 'c_ptrtype', 'typecode']
262296
263297 c_type = rffi.LONGDOUBLE
264 c_ptrtype = rffi.LONGDOUBLEP
298 # c_ptrtype = rffi.LONGDOUBLEP # useless type at this point
299 c_ptrtype = rffi.VOIDP
265300 typecode = 'g'
266301
267302 # long double is not really supported ...
269304 return r_longfloat(space.float_w(w_obj))
270305
271306 def _wrap_object(self, space, obj):
272 return space.wrap(obj)
307 return space.newfloat(obj)
273308
274309 def cffi_type(self, space):
275310 state = space.fromcache(State)
279314 "NOT_RPYTHON"
280315 if c_type == bool: return BoolTypeMixin
281316 if c_type == rffi.CHAR: return CharTypeMixin
317 if c_type == rffi.UCHAR: return UCharTypeMixin
282318 if c_type == rffi.SHORT: return ShortTypeMixin
283319 if c_type == rffi.USHORT: return UShortTypeMixin
284320 if c_type == rffi.INT: return IntTypeMixin
0 import sys
01 from rpython.rlib import rstring
12
23
115116 # TODO: perhaps absorb or "pythonify" these operators?
116117 return cppname
117118
119 CPPYY__div__ = "__div__"
120 CPPYY__idiv__ = "__idiv__"
121 CPPYY__long__ = "__long__"
122 CPPYY__bool__ = "__nonzero__"
123
118124 # _operator_mappings["[]"] = "__setitem__" # depends on return type
119125 # _operator_mappings["+"] = "__add__" # depends on # of args (see __pos__)
120126 # _operator_mappings["-"] = "__sub__" # id. (eq. __neg__)
122128
123129 # _operator_mappings["[]"] = "__getitem__" # depends on return type
124130 _operator_mappings["()"] = "__call__"
125 _operator_mappings["/"] = "__div__" # __truediv__ in p3
131 _operator_mappings["/"] = CPPYY__div__
126132 _operator_mappings["%"] = "__mod__"
127133 _operator_mappings["**"] = "__pow__" # not C++
128134 _operator_mappings["<<"] = "__lshift__"
135141 _operator_mappings["+="] = "__iadd__"
136142 _operator_mappings["-="] = "__isub__"
137143 _operator_mappings["*="] = "__imul__"
138 _operator_mappings["/="] = "__idiv__" # __itruediv__ in p3
144 _operator_mappings["/="] = CPPYY__idiv__
139145 _operator_mappings["%="] = "__imod__"
140146 _operator_mappings["**="] = "__ipow__"
141147 _operator_mappings["<<="] = "__ilshift__"
153159 # the following type mappings are "exact"
154160 _operator_mappings["const char*"] = "__str__"
155161 _operator_mappings["int"] = "__int__"
156 _operator_mappings["long"] = "__long__" # __int__ in p3
162 _operator_mappings["long"] = CPPYY__long__
157163 _operator_mappings["double"] = "__float__"
158164
159165 # the following type mappings are "okay"; the assumption is that they
162168 _operator_mappings["char*"] = "__str__"
163169 _operator_mappings["short"] = "__int__"
164170 _operator_mappings["unsigned short"] = "__int__"
165 _operator_mappings["unsigned int"] = "__long__" # __int__ in p3
166 _operator_mappings["unsigned long"] = "__long__" # id.
167 _operator_mappings["long long"] = "__long__" # id.
168 _operator_mappings["unsigned long long"] = "__long__" # id.
171 _operator_mappings["unsigned int"] = CPPYY__long__
172 _operator_mappings["unsigned long"] = CPPYY__long__
173 _operator_mappings["long long"] = CPPYY__long__
174 _operator_mappings["unsigned long long"] = CPPYY__long__
169175 _operator_mappings["float"] = "__float__"
170176
171 _operator_mappings["bool"] = "__nonzero__" # __bool__ in p3
177 _operator_mappings["bool"] = CPPYY__bool__
172178
173179 # the following are not python, but useful to expose
174180 _operator_mappings["->"] = "__follow__"
6262 double cppyy_call_d(cppyy_method_t method, cppyy_object_t self, int nargs, void* args);
6363 RPY_EXTERN
6464 long double cppyy_call_ld(cppyy_method_t method, cppyy_object_t self, int nargs, void* args);
65 RPY_EXTERN
66 double cppyy_call_nld(cppyy_method_t method, cppyy_object_t self, int nargs, void* args);
6567
6668 RPY_EXTERN
6769 void* cppyy_call_r(cppyy_method_t method, cppyy_object_t self, int nargs, void* args);
7577 cppyy_object_t cppyy_call_o(cppyy_method_t method, cppyy_object_t self, int nargs, void* args, cppyy_type_t result_type);
7678
7779 RPY_EXTERN
78 cppyy_funcaddr_t cppyy_function_address_from_index(cppyy_scope_t scope, cppyy_index_t idx);
79 RPY_EXTERN
80 cppyy_funcaddr_t cppyy_function_address_from_method(cppyy_method_t method);
80 cppyy_funcaddr_t cppyy_function_address(cppyy_method_t method);
8181
8282 /* handling of function argument buffer ----------------------------------- */
8383 RPY_EXTERN
131131 cppyy_index_t* cppyy_method_indices_from_name(cppyy_scope_t scope, const char* name);
132132
133133 RPY_EXTERN
134 char* cppyy_method_name(cppyy_scope_t scope, cppyy_index_t idx);
135 RPY_EXTERN
136 char* cppyy_method_mangled_name(cppyy_scope_t scope, cppyy_index_t idx);
137 RPY_EXTERN
138 char* cppyy_method_result_type(cppyy_scope_t scope, cppyy_index_t idx);
139 RPY_EXTERN
140 int cppyy_method_num_args(cppyy_scope_t scope, cppyy_index_t idx);
141 RPY_EXTERN
142 int cppyy_method_req_args(cppyy_scope_t scope, cppyy_index_t idx);
143 RPY_EXTERN
144 char* cppyy_method_arg_type(cppyy_scope_t scope, cppyy_index_t idx, int arg_index);
145 RPY_EXTERN
146 char* cppyy_method_arg_default(cppyy_scope_t scope, cppyy_index_t idx, int arg_index);
147 RPY_EXTERN
148 char* cppyy_method_signature(cppyy_scope_t scope, cppyy_index_t idx, int show_formalargs);
149 RPY_EXTERN
150 char* cppyy_method_prototype(cppyy_scope_t scope, cppyy_index_t idx, int show_formalargs);
134 cppyy_method_t cppyy_get_method(cppyy_scope_t scope, cppyy_index_t idx);
135
136 RPY_EXTERN
137 char* cppyy_method_name(cppyy_method_t);
138 RPY_EXTERN
139 char* cppyy_method_full_name(cppyy_method_t);
140 RPY_EXTERN
141 char* cppyy_method_mangled_name(cppyy_method_t);
142 RPY_EXTERN
143 char* cppyy_method_result_type(cppyy_method_t);
144 RPY_EXTERN
145 int cppyy_method_num_args(cppyy_method_t);
146 RPY_EXTERN
147 int cppyy_method_req_args(cppyy_method_t);
148 RPY_EXTERN
149 char* cppyy_method_arg_type(cppyy_method_t, int arg_index);
150 RPY_EXTERN
151 char* cppyy_method_arg_default(cppyy_method_t, int arg_index);
152 RPY_EXTERN
153 char* cppyy_method_signature(cppyy_method_t, int show_formalargs);
154 RPY_EXTERN
155 char* cppyy_method_prototype(cppyy_scope_t scope, cppyy_method_t, int show_formalargs);
151156 RPY_EXTERN
152157 int cppyy_is_const_method(cppyy_method_t);
153158
154159 RPY_EXTERN
160 int get_num_templated_methods(cppyy_scope_t scope);
161 RPY_EXTERN
162 char* get_templated_method_name(cppyy_scope_t scope, cppyy_index_t imeth);
163 RPY_EXTERN
155164 int cppyy_exists_method_template(cppyy_scope_t scope, const char* name);
156165 RPY_EXTERN
157166 int cppyy_method_is_template(cppyy_scope_t scope, cppyy_index_t idx);
158167 RPY_EXTERN
159 int cppyy_method_num_template_args(cppyy_scope_t scope, cppyy_index_t idx);
160 RPY_EXTERN
161 char* cppyy_method_template_arg_name(cppyy_scope_t scope, cppyy_index_t idx, cppyy_index_t iarg);
162
163 RPY_EXTERN
164 cppyy_method_t cppyy_get_method(cppyy_scope_t scope, cppyy_index_t idx);
168 cppyy_method_t cppyy_get_method_template(cppyy_scope_t scope, const char* name, const char* proto);
169
165170 RPY_EXTERN
166171 cppyy_index_t cppyy_get_global_operator(
167172 cppyy_scope_t scope, cppyy_scope_t lc, cppyy_scope_t rc, const char* op);
168173
169174 /* method properties ------------------------------------------------------ */
170175 RPY_EXTERN
171 int cppyy_is_publicmethod(cppyy_type_t type, cppyy_index_t idx);
172 RPY_EXTERN
173 int cppyy_is_constructor(cppyy_type_t type, cppyy_index_t idx);
174 RPY_EXTERN
175 int cppyy_is_destructor(cppyy_type_t type, cppyy_index_t idx);
176 RPY_EXTERN
177 int cppyy_is_staticmethod(cppyy_type_t type, cppyy_index_t idx);
176 int cppyy_is_publicmethod(cppyy_method_t);
177 RPY_EXTERN
178 int cppyy_is_constructor(cppyy_method_t);
179 RPY_EXTERN
180 int cppyy_is_destructor(cppyy_method_t);
181 RPY_EXTERN
182 int cppyy_is_staticmethod(cppyy_method_t);
178183
179184 /* data member reflection information ------------------------------------- */
180185 RPY_EXTERN
216221 cppyy_object_t cppyy_stdstring2stdstring(cppyy_object_t ptr);
217222
218223 RPY_EXTERN
219 const char* cppyy_stdvector_valuetype(const char* clname);
220 RPY_EXTERN
221 size_t cppyy_stdvector_valuesize(const char* clname);
224 double cppyy_longdouble2double(void*);
225 RPY_EXTERN
226 void cppyy_double2longdouble(double, void*);
227
228 RPY_EXTERN
229 int cppyy_vectorbool_getitem(cppyy_object_t ptr, int idx);
230 RPY_EXTERN
231 void cppyy_vectorbool_setitem(cppyy_object_t ptr, int idx, int value);
222232
223233 #ifdef __cplusplus
224234 }
00 import pypy.module._cppyy.capi as capi
11
22 from pypy.interpreter.error import OperationError, oefmt
3 from pypy.interpreter.function import Method
4 from pypy.interpreter.argument import Arguments
5 from pypy.interpreter.typedef import interp_attrproperty_w, descr_generic_ne, make_weakref_descr
36 from pypy.interpreter.gateway import interp2app, unwrap_spec
47 from pypy.interpreter.typedef import TypeDef, GetSetProperty, interp_attrproperty
58 from pypy.interpreter.baseobjspace import W_Root
1316 from pypy.module._cffi_backend import ctypefunc
1417 from pypy.module._cppyy import converter, executor, ffitypes, helper
1518
19 CLASS_FLAGS_IS_PINNED = 0x0001
1620
1721 INSTANCE_FLAGS_PYTHON_OWNS = 0x0001
1822 INSTANCE_FLAGS_IS_REF = 0x0002
19 INSTANCE_FLAGS_IS_R_VALUE = 0x0004
23 INSTANCE_FLAGS_IS_RVALUE = 0x0004
2024
2125 OVERLOAD_FLAGS_USE_FFI = 0x0001
26 OVERLOAD_FLAGS_CREATES = 0x0002
27
28 FUNCTION_IS_GLOBAL = 0x0001
29 FUNCTION_IS_STATIC = 0x0001
30 FUNCTION_IS_METHOD = 0x0002
31 FUNCTION_IS_CONSTRUCTOR = 0x0004
32 FUNCTION_IS_TEMPLATE = 0x0008
33 FUNCTION_IS_SETITEM = 0x0010
2234
2335
2436 class FastCallNotPossible(Exception):
2941 'void**' : 100,
3042 'float' : 30,
3143 'double' : 10,
44 'bool' : 1,
3245 'const string&' : 1, } # solves a specific string ctor overload
3346
3447 from rpython.rlib.listsort import make_timsort_class
99112 state.cppscope_cache[final_scoped_name] = cppscope
100113
101114 if not isns:
102 # build methods/data; TODO: also defer this for classes (a functional __dir__
115 # build overloads/data; TODO: also defer this for classes (a functional __dir__
103116 # and instrospection for help() is enough and allows more lazy loading)
104 cppscope._build_methods()
117 cppscope._build_overloads()
105118 cppscope._find_datamembers()
106119
107120 return cppscope
127140
128141 def register_class(space, w_pycppclass):
129142 w_cppclass = space.findattr(w_pycppclass, space.newtext("__cppdecl__"))
130 cppclass = space.interp_w(W_CPPClassDecl, w_cppclass, can_be_None=False)
143 cppclass = space.interp_w(W_CPPClassDecl, w_cppclass)
131144 # add back-end specific method pythonizations (doing this on the wrapped
132145 # class allows simple aliasing of methods)
133 capi.pythonize(space, cppclass.name, w_pycppclass)
146 capi.pythonize(space, w_pycppclass, cppclass.name)
134147 state = space.fromcache(State)
135148 state.cppclass_registry[rffi.cast(rffi.LONG, cppclass.handle)] = w_pycppclass
136149
147160 )
148161 W_CPPLibrary.typedef.acceptable_as_base_class = True
149162
163
164 #-----
165 # Classes involved with methods and functions come at two levels:
166 # - overloads: user-facing collections of overloaded functions
167 # - wrappers: internal holders of the individual C++ methods
168 #
169 # W_CPPOverload: instance methods (base class)
170 # W_CPPConstructorOverload: constructors
171 # W_CPPAbstractCtorOverload: to provent instantiation of abstract classes
172 # W_CPPStaticOverload: free and static functions
173 # W_CPPTemplateOverload: templated methods
174 # W_CPPTemplateStaticOverload: templated free and static functions
175 #
176 # CPPMethod: a single function or method (base class)
177 # CPPSetItem: specialization for Python's __setitem__
178 #
179 # MethodWithProps: python instancemethod that forwards properties
180 #
181 # All methods/functions derive from CPPMethod and are collected as overload
182 # candidates in user-facing overload classes. Templated methods are a two-step
183 # process, where first the template is instantiated (or selected if already
184 # available), which returns a callable object that is the actual bound method.
150185
151186 class CPPMethod(object):
152187 """Dispatcher of methods. Checks the arguments, find the corresponding FFI
154189 also takes care of offset casting and recycling of known objects through
155190 the memory_regulator."""
156191
157 _attrs_ = ['space', 'scope', 'index', 'cppmethod', 'arg_defs', 'args_required',
158 'converters', 'executor', '_funcaddr', 'cif_descr', 'uses_local']
159 _immutable_ = True
160
161 def __init__(self, space, declaring_scope, method_index, arg_defs, args_required):
192 _attrs_ = ['space', 'scope', 'cppmethod', 'arg_defs', 'args_required',
193 'converters', 'executor', '_funcaddr', 'cif_descr']
194 _immutable_fields_ = ['scope', 'cppmethod', 'arg_defs', 'args_required',
195 'converters', 'executor', '_funcaddr', 'cif_descr']
196
197 def __init__(self, space, decl_scope, cppmethod, arg_defs, args_required):
162198 self.space = space
163 self.scope = declaring_scope
164 self.index = method_index
165 self.cppmethod = capi.c_get_method(self.space, self.scope, method_index)
199 self.scope = decl_scope
200 self.cppmethod = cppmethod
166201 self.arg_defs = arg_defs
167202 self.args_required = args_required
168203
172207 self.executor = None
173208 self.cif_descr = lltype.nullptr(jit_libffi.CIF_DESCRIPTION)
174209 self._funcaddr = lltype.nullptr(capi.C_FUNC_PTR.TO)
175 self.uses_local = False
176
177 @staticmethod
178 def unpack_cppthis(space, w_cppinstance, declaring_scope):
179 cppinstance = space.interp_w(W_CPPInstance, w_cppinstance, can_be_None=False)
180 cppinstance._nullcheck()
181 return cppinstance.get_cppthis(declaring_scope)
182
183 def _address_from_local_buffer(self, call_local, idx):
184 if not call_local:
185 return call_local
186 stride = 2*rffi.sizeof(rffi.VOIDP)
187 loc_idx = lltype.direct_ptradd(rffi.cast(rffi.CCHARP, call_local), idx*stride)
188 return rffi.cast(rffi.VOIDP, loc_idx)
189210
190211 @jit.unroll_safe
191212 def call(self, cppthis, args_w, useffi):
208229 if self.converters is None:
209230 try:
210231 self._setup(cppthis)
211 except Exception:
212 pass
213
214 # some calls, e.g. for ptr-ptr or reference need a local array to store data for
215 # the duration of the call
216 if self.uses_local:
217 call_local = lltype.malloc(rffi.VOIDP.TO, 2*len(args_w), flavor='raw')
218 else:
219 call_local = lltype.nullptr(rffi.VOIDP.TO)
220
232 except Exception as e:
233 if self.converters is None:
234 raise oefmt(self.space.w_SystemError,
235 "unable to initialize converters (%s)", str(e))
236
237 # attempt to call directly through ffi chain
238 if useffi and self._funcaddr:
239 try:
240 return self.do_fast_call(cppthis, args_w)
241 except FastCallNotPossible:
242 pass # can happen if converters or executor does not implement ffi
243
244 # ffi chain must have failed; using stub functions instead
245 args, stat = self.prepare_arguments(args_w)
221246 try:
222 # attempt to call directly through ffi chain
223 if useffi and self._funcaddr:
224 try:
225 return self.do_fast_call(cppthis, args_w, call_local)
226 except FastCallNotPossible:
227 pass # can happen if converters or executor does not implement ffi
228
229 # ffi chain must have failed; using stub functions instead
230 args, stat = self.prepare_arguments(args_w, call_local)
231 try:
232 result = self.executor.execute(
233 self.space, self.cppmethod, cppthis, len(args_w), args)
234 if stat[0] != rffi.cast(rffi.ULONG, 0):
235 what = rffi.cast(rffi.CCHARP, stat[1])
236 pywhat = rffi.charp2str(what)
237 capi.c_free(self.space, rffi.cast(rffi.VOIDP, what))
238 raise OperationError(self.space.w_Exception, self.space.newtext(pywhat))
239 return result
240 finally:
241 self.finalize_call(args, args_w, call_local)
247 result = self.executor.execute(
248 self.space, self.cppmethod, cppthis, len(args_w), args)
249 if stat[0] != rffi.cast(rffi.ULONG, 0):
250 what = rffi.cast(rffi.CCHARP, stat[1])
251 pywhat = rffi.charp2str(what)
252 capi.c_free(self.space, rffi.cast(rffi.VOIDP, what))
253 raise OperationError(self.space.w_Exception, self.space.newtext(pywhat))
254 return result
242255 finally:
243 if call_local:
244 lltype.free(call_local, flavor='raw')
256 self.finalize_call(args, args_w)
245257
246258 @jit.unroll_safe
247 def do_fast_call(self, cppthis, args_w, call_local):
259 def do_fast_call(self, cppthis, args_w):
248260 if self.cif_descr == lltype.nullptr(jit_libffi.CIF_DESCRIPTION):
249261 raise FastCallNotPossible
262 jit.promote(self)
250263 cif_descr = self.cif_descr
251 buffer = lltype.malloc(rffi.CCHARP.TO, cif_descr.exchange_size, flavor='raw')
264 # add extra space for const-ref support (see converter.py)
265 buffer = lltype.malloc(rffi.CCHARP.TO,
266 cif_descr.exchange_size+len(self.arg_defs)*rffi.sizeof(rffi.DOUBLE), flavor='raw')
267 thisoff = 0
252268 try:
253 # this pointer
254 data = capi.exchange_address(buffer, cif_descr, 0)
255 x = rffi.cast(rffi.LONGP, data) # LONGP needed for test_zjit.py
256 x[0] = rffi.cast(rffi.LONG, cppthis)
257
258 # other arguments and defaults
259 i = len(self.arg_defs) + 1
269 if cppthis:
270 # this pointer
271 data = rffi.ptradd(buffer, cif_descr.exchange_args[0])
272 x = rffi.cast(rffi.LONGP, data) # LONGP needed for test_zjit.py
273 x[0] = rffi.cast(rffi.LONG, cppthis)
274 thisoff = 1
275
276 # actual provided arguments
277 i = -1 # needed if all arguments are defaults
260278 for i in range(len(args_w)):
261279 conv = self.converters[i]
262 w_arg = args_w[i]
263 data = capi.exchange_address(buffer, cif_descr, i+1)
264 conv.convert_argument_libffi(self.space, w_arg, data, call_local)
280 data = rffi.ptradd(buffer, cif_descr.exchange_args[i+thisoff])
281 scratch = rffi.ptradd(buffer, cif_descr.exchange_size+i*rffi.sizeof(rffi.DOUBLE))
282 conv.convert_argument_libffi(self.space, args_w[i], data, scratch)
283 # drop in defaults for the rest
265284 for j in range(i+1, len(self.arg_defs)):
266285 conv = self.converters[j]
267 data = capi.exchange_address(buffer, cif_descr, j+1)
286 data = rffi.ptradd(buffer, cif_descr.exchange_args[j+thisoff])
268287 conv.default_argument_libffi(self.space, data)
269288
270289 assert self._funcaddr
276295 return w_res
277296
278297 # from ctypefunc; have my own version for annotater purposes and to disable
279 # memory tracking (method live time is longer than the tests)
298 # memory tracking (method life time is longer than the tests)
280299 @jit.dont_look_inside
281300 def _rawallocate(self, builder):
282301 builder.space = self.space
289308 # allocate the buffer
290309 if we_are_translated():
291310 rawmem = lltype.malloc(rffi.CCHARP.TO, builder.nb_bytes,
292 flavor='raw', track_allocation=False)
311 flavor='raw')
293312 rawmem = rffi.cast(jit_libffi.CIF_DESCRIPTION_P, rawmem)
294313 else:
295314 # gross overestimation of the length below, but too bad
321340 self.converters = [converter.get_converter(self.space, arg_type, arg_dflt)
322341 for arg_type, arg_dflt in self.arg_defs]
323342 self.executor = executor.get_executor(
324 self.space, capi.c_method_result_type(self.space, self.scope, self.index))
325
326 for conv in self.converters:
327 if conv.uses_local:
328 self.uses_local = True
329 break
343 self.space, capi.c_method_result_type(self.space, self.cppmethod))
330344
331345 # Each CPPMethod corresponds one-to-one to a C++ equivalent and cppthis
332346 # has been offset to the matching class. Hence, the libffi pointer is
333347 # uniquely defined and needs to be setup only once.
334 funcaddr = capi.c_function_address_from_index(self.space, self.scope, self.index)
335 if funcaddr and cppthis: # methods only for now
348 funcaddr = capi.c_function_address(self.space, self.cppmethod)
349 if funcaddr:
336350 state = self.space.fromcache(ffitypes.State)
337351
338 # argument type specification (incl. cppthis)
352 # argument type specification (incl. cppthis if applicable)
339353 fargs = []
340354 try:
341 fargs.append(state.c_voidp)
355 if cppthis: fargs.append(state.c_voidp)
342356 for i, conv in enumerate(self.converters):
343357 fargs.append(conv.cffi_type(self.space))
344358 fresult = self.executor.cffi_type(self.space)
363377 self._funcaddr = funcaddr
364378
365379 @jit.unroll_safe
366 def prepare_arguments(self, args_w, call_local):
380 def prepare_arguments(self, args_w):
367381 args = capi.c_allocate_function_args(self.space, len(args_w))
368382 stride = capi.c_function_arg_sizeof(self.space)
369383 for i in range(len(args_w)):
371385 w_arg = args_w[i]
372386 try:
373387 arg_i = lltype.direct_ptradd(rffi.cast(rffi.CCHARP, args), i*stride)
374 loc_i = self._address_from_local_buffer(call_local, i)
375 conv.convert_argument(self.space, w_arg, rffi.cast(capi.C_OBJECT, arg_i), loc_i)
388 conv.convert_argument(self.space, w_arg, rffi.cast(capi.C_OBJECT, arg_i))
376389 except:
377390 # fun :-(
378391 for j in range(i):
379392 conv = self.converters[j]
380393 arg_j = lltype.direct_ptradd(rffi.cast(rffi.CCHARP, args), j*stride)
381 loc_j = self._address_from_local_buffer(call_local, j)
382 conv.free_argument(self.space, rffi.cast(capi.C_OBJECT, arg_j), loc_j)
394 conv.free_argument(self.space, rffi.cast(capi.C_OBJECT, arg_j))
383395 capi.c_deallocate_function_args(self.space, args)
384396 raise
385397 stat = rffi.cast(rffi.ULONGP,
388400 return args, stat
389401
390402 @jit.unroll_safe
391 def finalize_call(self, args, args_w, call_local):
403 def finalize_call(self, args, args_w):
392404 stride = capi.c_function_arg_sizeof(self.space)
393405 for i in range(len(args_w)):
394406 conv = self.converters[i]
395407 arg_i = lltype.direct_ptradd(rffi.cast(rffi.CCHARP, args), i*stride)
396 loc_i = self._address_from_local_buffer(call_local, i)
397 conv.finalize_call(self.space, args_w[i], loc_i)
398 conv.free_argument(self.space, rffi.cast(capi.C_OBJECT, arg_i), loc_i)
408 conv.finalize_call(self.space, args_w[i])
409 conv.free_argument(self.space, rffi.cast(capi.C_OBJECT, arg_i))
399410 capi.c_deallocate_function_args(self.space, args)
400411
401412 def signature(self, show_formalargs=True):
402 return capi.c_method_signature(self.space, self.scope, self.index, show_formalargs)
413 return capi.c_method_signature(self.space, self.cppmethod, show_formalargs)
403414
404415 def prototype(self, show_formalargs=True):
405 return capi.c_method_prototype(self.space, self.scope, self.index, show_formalargs)
416 return capi.c_method_prototype(self.space, self.scope, self.cppmethod, show_formalargs)
406417
407418 def priority(self):
408419 total_arg_priority = 0
409 for p in [priority.get(arg_type, 0) for arg_type, arg_dflt in self.arg_defs]:
410 total_arg_priority += p
420 for arg_type, arg_dflt in self.arg_defs:
421 total_arg_priority += priority.get(arg_type, 0)
422 if '&&' in arg_type:
423 total_arg_priority += 100
411424 return total_arg_priority
412425
413426 @rgc.must_be_light_finalizer
414427 def __del__(self):
415 if self.cif_descr:
416 lltype.free(self.cif_descr, flavor='raw')
428 try:
429 if self.cif_descr:
430 lltype.free(self.cif_descr, flavor='raw')
431 except Exception: # TODO: happens for templates, why?
432 pass
417433
418434 def __repr__(self):
419435 return "CPPMethod: %s" % self.prototype()
422438 assert 0, "you should never have a pre-built instance of this!"
423439
424440
425 class CPPFunction(CPPMethod):
426 """Global (namespaced) function dispatcher."""
427
428 _immutable_ = True
429
430 @staticmethod
431 def unpack_cppthis(space, w_cppinstance, declaring_scope):
432 return capi.C_NULL_OBJECT
433
434 def __repr__(self):
435 return "CPPFunction: %s" % self.prototype()
436
437
438 class CPPTemplatedCall(CPPMethod):
439 """Method dispatcher that first resolves the template instance."""
440
441 _attrs_ = ['space', 'templ_args']
442 _immutable_ = True
443
444 def __init__(self, space, templ_args, declaring_scope, method_index, arg_defs, args_required):
445 self.space = space
446 self.templ_args = templ_args
447 # TODO: might have to specialize for CPPTemplatedCall on CPPMethod/CPPFunction here
448 CPPMethod.__init__(self, space, declaring_scope, method_index, arg_defs, args_required)
449
450 def call(self, cppthis, args_w, useffi):
451 assert lltype.typeOf(cppthis) == capi.C_OBJECT
452 for i in range(len(args_w)):
453 try:
454 s = self.space.text_w(args_w[i])
455 except OperationError:
456 s = self.space.text_w(self.space.getattr(args_w[i], self.space.newtext('__name__')))
457 s = capi.c_resolve_name(self.space, s)
458 if s != self.templ_args[i]:
459 raise oefmt(self.space.w_TypeError,
460 "non-matching template (got %s where %s expected)",
461 s, self.templ_args[i])
462 return W_CPPBoundMethod(cppthis, self, useffi)
463
464 def bound_call(self, cppthis, args_w, useffi):
465 return CPPMethod.call(self, cppthis, args_w, useffi)
466
467 def __repr__(self):
468 return "CPPTemplatedCall: %s" % self.prototype()
469
470
471 class CPPConstructor(CPPMethod):
472 """Method dispatcher that constructs new objects. This method can not have
473 a fast path, as the allocation of the object is currently left to the
474 reflection layer only, since the C++ class may have an overloaded operator
475 new, disallowing malloc here."""
476
477 _immutable_ = True
478
479 @staticmethod
480 def unpack_cppthis(space, w_cppinstance, declaring_scope):
481 return rffi.cast(capi.C_OBJECT, declaring_scope.handle)
482
483 def call(self, cppthis, args_w, useffi):
484 # Note: this does not return a wrapped instance, just a pointer to the
485 # new instance; the overload must still wrap it before returning. Also,
486 # cppthis is declaring_scope.handle (as per unpack_cppthis(), above).
487 return CPPMethod.call(self, cppthis, args_w, useffi)
488
489 def __repr__(self):
490 return "CPPConstructor: %s" % self.prototype()
491
492
493441 class CPPSetItem(CPPMethod):
494442 """Method dispatcher specific to Python's __setitem__ mapped onto C++'s
495 operator[](int). The former function takes an extra argument to assign to
443 operator[](T). The former function takes an extra argument to assign to
496444 the return type of the latter."""
497445
498 _immutable_ = True
446 _attrs_ = []
499447
500448 def call(self, cppthis, args_w, useffi):
501449 end = len(args_w)-1
508456 CPPMethod.call(self, cppthis, args_w, useffi)
509457
510458
459 # CPPOverloads have settable flags that control memory and ffi behavior. These flags
460 # need forwarding, which the normal instancemethod does not provide, hence this
461 # derived class.
462 class MethodWithProps(Method):
463 # set life management of result from the call
464 def fget_creates(self, space):
465 f = space.interp_w(W_CPPOverload, self.w_function)
466 return f.fget_creates(space)
467
468 @unwrap_spec(value=bool)
469 def fset_creates(self, space, value):
470 f = space.interp_w(W_CPPOverload, self.w_function)
471 f.fset_creates(space, value)
472
473 # set ownership policy of arguments (not yet implemented)
474 def fget_mempolicy(self, space):
475 f = space.interp_w(W_CPPOverload, self.w_function)
476 return f.fget_mempolicy(space)
477
478 @unwrap_spec(value=int)
479 def fset_mempolicy(self, space, value):
480 f = space.interp_w(W_CPPOverload, self.w_function)
481 f.fset_mempolicy(space, value)
482
483 # set to release the gil during call (not yet implemented)
484 def fget_release_gil(self, space):
485 f = space.interp_w(W_CPPOverload, self.w_function)
486 return f.fget_release_gil(space)
487
488 @unwrap_spec(value=bool)
489 def fset_release_gil(self, space, value):
490 f = space.interp_w(W_CPPOverload, self.w_function)
491 f.fset_release_gil(space, value)
492
493 # allow user to determine ffi use rules per overload
494 def fget_useffi(self, space):
495 f = space.interp_w(W_CPPOverload, self.w_function)
496 return f.fget_useffi(space)
497
498 @unwrap_spec(value=bool)
499 def fset_useffi(self, space, value):
500 f = space.interp_w(W_CPPOverload, self.w_function)
501 f.fset_useffi(space, value)
502
503 MethodWithProps.typedef = TypeDef(
504 "cpp_instancemethod",
505 __doc__ = """cpp_instancemethod(function, instance, class)
506
507 Create an instance method object.""",
508 __new__ = interp2app(MethodWithProps.descr_method__new__.im_func),
509 __call__ = interp2app(MethodWithProps.descr_method_call),
510 __get__ = interp2app(MethodWithProps.descr_method_get),
511 __func__ = interp_attrproperty_w('w_function', cls=MethodWithProps),
512 __self__ = interp_attrproperty_w('w_instance', cls=MethodWithProps),
513 __getattribute__ = interp2app(MethodWithProps.descr_method_getattribute),
514 __eq__ = interp2app(MethodWithProps.descr_method_eq),
515 __ne__ = descr_generic_ne,
516 __hash__ = interp2app(MethodWithProps.descr_method_hash),
517 __repr__ = interp2app(MethodWithProps.descr_method_repr),
518 __reduce__ = interp2app(MethodWithProps.descr_method__reduce__),
519 __weakref__ = make_weakref_descr(MethodWithProps),
520 __creates__ = GetSetProperty(MethodWithProps.fget_creates, MethodWithProps.fset_creates),
521 __mempolicy__ = GetSetProperty(MethodWithProps.fget_mempolicy, MethodWithProps.fset_mempolicy),
522 __release_gil__ = GetSetProperty(MethodWithProps.fget_release_gil, MethodWithProps.fset_release_gil),
523 __useffi__ = GetSetProperty(MethodWithProps.fget_useffi, MethodWithProps.fset_useffi),
524 )
525 MethodWithProps.typedef.acceptable_as_base_class = False
526
527
511528 class W_CPPOverload(W_Root):
512 """Dispatcher that is actually available at the app-level: it is a
513 collection of (possibly) overloaded methods or functions. It calls these
514 in order and deals with error handling and reporting."""
529 """App-level dispatcher: controls a collection of (potentially) overloaded methods
530 or functions. Calls these in order and deals with error handling and reporting."""
515531
516532 _attrs_ = ['space', 'scope', 'functions', 'flags']
517533 _immutable_fields_ = ['scope', 'functions[*]']
518534
519 def __init__(self, space, declaring_scope, functions):
520 self.space = space
521 self.scope = declaring_scope
522 assert len(functions)
535 def __init__(self, space, decl_scope, funcs, flags = OVERLOAD_FLAGS_USE_FFI):
536 self.space = space
537 self.scope = decl_scope
523538 from rpython.rlib import debug
524 self.functions = debug.make_sure_not_resized(functions)
525 self.flags = 0
526 self.flags |= OVERLOAD_FLAGS_USE_FFI
527
528 # allow user to determine ffi use rules per overload
529 def fget_useffi(self, space):
530 return space.newbool(bool(self.flags & OVERLOAD_FLAGS_USE_FFI))
531
532 @unwrap_spec(value=bool)
533 def fset_useffi(self, space, value):
534 if space.is_true(value):
535 self.flags |= OVERLOAD_FLAGS_USE_FFI
539 self.functions = debug.make_sure_not_resized(funcs)
540 self.flags = flags
541
542 def descr_get(self, w_obj, w_cls=None):
543 """functionobject.__get__(obj[, type]) -> method"""
544 # TODO: check validity of w_cls if given
545 # TODO: this does not work for Python 3, which does not have
546 # unbound methods (probably no common code possible, see also
547 # pypy/interpreter/function.py)
548 space = self.space
549 asking_for_bound = (space.is_none(w_cls) or
550 not space.is_w(w_obj, space.w_None) or
551 space.is_w(w_cls, space.type(space.w_None)))
552 if asking_for_bound:
553 return MethodWithProps(space, self, w_obj)
536554 else:
537 self.flags &= ~OVERLOAD_FLAGS_USE_FFI
538
539 @jit.elidable_promote()
540 def is_static(self):
541 if isinstance(self.functions[0], CPPFunction):
542 return self.space.w_True
543 return self.space.w_False
555 return self # unbound methods don't exist in Python 3
556
557 @unwrap_spec(args_w='args_w')
558 def call_args(self, args_w):
559 jit.promote(self)
560 w_this = args_w[0]
561 cppinstance = self.space.interp_w(W_CPPInstance, w_this)
562 cppinstance._nullcheck()
563 if not capi.c_is_subtype(self.space, cppinstance.clsdecl, self.scope):
564 raise oefmt(self.space.w_TypeError,
565 "cannot pass %T instance as %s", w_this, self.scope.name)
566 return self.call_impl(cppinstance.get_cppthis(self.scope), args_w[1:])
544567
545568 @jit.unroll_safe
546 @unwrap_spec(args_w='args_w')
547 def call(self, w_cppinstance, args_w):
548 # instance handling is specific to the function type only, so take it out
549 # of the loop over function overloads
550 cppthis = self.functions[0].unpack_cppthis(
551 self.space, w_cppinstance, self.functions[0].scope)
569 def call_impl(self, cppthis, args_w):
552570 assert lltype.typeOf(cppthis) == capi.C_OBJECT
553571
554572 # The following code tries out each of the functions in order. If
565583 for i in range(len(self.functions)):
566584 cppyyfunc = self.functions[i]
567585 try:
568 return cppyyfunc.call(cppthis, args_w, self.flags & OVERLOAD_FLAGS_USE_FFI)
586 w_result = cppyyfunc.call(cppthis, args_w, self.flags & OVERLOAD_FLAGS_USE_FFI)
587 if self.flags & OVERLOAD_FLAGS_CREATES:
588 if isinstance(w_result, W_CPPInstance):
589 cppinstance = self.space.interp_w(W_CPPInstance, w_result)
590 cppinstance.fset_python_owns(self.space, self.space.w_True)
591 return w_result
569592 except Exception:
570593 pass
571594
578601 for i in range(len(self.functions)):
579602 cppyyfunc = self.functions[i]
580603 try:
604 # no need to set ownership on the return value, as none of the methods execute
581605 return cppyyfunc.call(cppthis, args_w, self.flags & OVERLOAD_FLAGS_USE_FFI)
582606 except OperationError as e:
583607 # special case if there's just one function, to prevent clogging the error message
606630 sig += '\n'+self.functions[i].prototype()
607631 return self.space.newtext(sig)
608632
633 @unwrap_spec(signature='text')
634 def mp_overload(self, signature):
635 sig = '(%s)' % signature
636 for f in self.functions:
637 if f.signature(False) == sig:
638 if isinstance(self, W_CPPStaticOverload):
639 return W_CPPStaticOverload(self.space, self.scope, [f])
640 return W_CPPOverload(self.space, self.scope, [f])
641 raise oefmt(self.space.w_LookupError, "signature '%s' not found", signature)
642
643 # set life management of result from the call
644 def fget_creates(self, space):
645 return space.newbool(bool(self.flags & OVERLOAD_FLAGS_CREATES))
646
647 @unwrap_spec(value=bool)
648 def fset_creates(self, space, value):
649 if space.is_true(value):
650 self.flags |= OVERLOAD_FLAGS_CREATES
651 else:
652 self.flags &= ~OVERLOAD_FLAGS_CREATES
653
654 # set ownership policy of arguments (not yet implemented)
655 def fget_mempolicy(self, space):
656 return space.newint(0)
657
658 @unwrap_spec(value=int)
659 def fset_mempolicy(self, space, value):
660 pass
661
662 # set to release the gil during call (not yet implemented)
663 def fget_release_gil(self, space):
664 return space.newbool(True)
665
666 @unwrap_spec(value=bool)
667 def fset_release_gil(self, space, value):
668 pass
669
670 # allow user to determine ffi use rules per overload
671 def fget_useffi(self, space):
672 return space.newbool(bool(self.flags & OVERLOAD_FLAGS_USE_FFI))
673
674 @unwrap_spec(value=bool)
675 def fset_useffi(self, space, value):
676 if space.is_true(value):
677 self.flags |= OVERLOAD_FLAGS_USE_FFI
678 else:
679 self.flags &= ~OVERLOAD_FLAGS_USE_FFI
680
681 def fget_doc(self, space):
682 return self.prototype()
683
684 def getname(self, space):
685 # for the benefit of Method/instancemethod
686 return capi.c_method_name(space, self.functions[0].cppmethod).decode('latin-1')
687
609688 def __repr__(self):
610689 return "W_CPPOverload(%s)" % [f.prototype() for f in self.functions]
611690
612691 W_CPPOverload.typedef = TypeDef(
613692 'CPPOverload',
614 is_static = interp2app(W_CPPOverload.is_static),
615 call = interp2app(W_CPPOverload.call),
616 __useffi__ = GetSetProperty(W_CPPOverload.fget_useffi, W_CPPOverload.fset_useffi),
617 prototype = interp2app(W_CPPOverload.prototype),
693 __get__ = interp2app(W_CPPOverload.descr_get),
694 __call__ = interp2app(W_CPPOverload.call_args),
695 __creates__ = GetSetProperty(W_CPPOverload.fget_creates, W_CPPOverload.fset_creates),
696 __mempolicy__ = GetSetProperty(W_CPPOverload.fget_mempolicy, W_CPPOverload.fset_mempolicy),
697 __release_gil__ = GetSetProperty(W_CPPOverload.fget_release_gil, W_CPPOverload.fset_release_gil),
698 __useffi__ = GetSetProperty(W_CPPOverload.fget_useffi, W_CPPOverload.fset_useffi),
699 __overload__ = interp2app(W_CPPOverload.mp_overload),
700 __doc__ = GetSetProperty(W_CPPOverload.fget_doc)
618701 )
619702
620703
704 # overload collection of static (class and free) functions; these differ
705 # from methods only in the handling of 'cppthis'
706 class W_CPPStaticOverload(W_CPPOverload):
707 _attrs_ = []
708
709 def descr_get(self, w_obj, w_cls=None):
710 if isinstance(w_obj, W_CPPInstance):
711 # two possibilities: this is a static function called on an
712 # instance and w_this must not be set, or a free function rebound
713 # onto a class and w_this should be set
714 cppinstance = self.space.interp_w(W_CPPInstance, w_obj)
715 if cppinstance.clsdecl.handle != self.scope.handle:
716 return MethodWithProps(self.space, self, w_obj) # bound
717 return self # unbound
718
719 @unwrap_spec(args_w='args_w')
720 def call_args(self, args_w):
721 jit.promote(self)
722 return self.call_impl(capi.C_NULL_OBJECT, args_w)
723
724 def __repr__(self):
725 return "W_CPPStaticOverload(%s)" % [f.prototype() for f in self.functions]
726
727 W_CPPStaticOverload.typedef = TypeDef(
728 'CPPStaticOverload',
729 __get__ = interp2app(W_CPPStaticOverload.descr_get),
730 __call__ = interp2app(W_CPPStaticOverload.call_args),
731 __creates__ = GetSetProperty(W_CPPStaticOverload.fget_creates, W_CPPStaticOverload.fset_creates),
732 __mempolicy__ = GetSetProperty(W_CPPStaticOverload.fget_mempolicy, W_CPPStaticOverload.fset_mempolicy),
733 __release_gil__ = GetSetProperty(W_CPPStaticOverload.fget_release_gil, W_CPPStaticOverload.fset_release_gil),
734 __useffi__ = GetSetProperty(W_CPPStaticOverload.fget_useffi, W_CPPStaticOverload.fset_useffi),
735 __overload__ = interp2app(W_CPPStaticOverload.mp_overload),
736 __doc__ = GetSetProperty(W_CPPStaticOverload.fget_doc)
737 )
738
739
621740 class W_CPPConstructorOverload(W_CPPOverload):
622 @jit.elidable_promote()
623 def is_static(self):
624 return self.space.w_False
625
626 @jit.elidable_promote()
627 def unpack_cppthis(self, w_cppinstance):
628 return rffi.cast(capi.C_OBJECT, self.scope.handle)
629
630 @jit.unroll_safe
741 _attrs_ = []
742
743 def __init__(self, space, decl_scope, funcs, flags = OVERLOAD_FLAGS_USE_FFI):
744 W_CPPOverload.__init__(self, space, decl_scope, funcs, flags)
745 self.flags &= ~OVERLOAD_FLAGS_USE_FFI
746
631747 @unwrap_spec(args_w='args_w')
632 def call(self, w_cppinstance, args_w):
633 # TODO: factor out the following:
634 if capi.c_is_abstract(self.space, self.scope.handle):
635 raise oefmt(self.space.w_TypeError,
636 "cannot instantiate abstract class '%s'",
637 self.scope.name)
638 w_result = W_CPPOverload.call(self, w_cppinstance, args_w)
748 def call_args(self, args_w):
749 jit.promote(self)
750 cppinstance = self.space.interp_w(W_CPPInstance, args_w[0])
751 w_result = self.call_impl(rffi.cast(capi.C_OBJECT, self.scope.handle), args_w[1:])
639752 newthis = rffi.cast(capi.C_OBJECT, self.space.uint_w(w_result))
640 cppinstance = self.space.interp_w(W_CPPInstance, w_cppinstance, can_be_None=True)
641753 if cppinstance is not None:
642754 cppinstance._rawobject = newthis
643755 memory_regulator.register(cppinstance)
647759
648760 W_CPPConstructorOverload.typedef = TypeDef(
649761 'CPPConstructorOverload',
650 is_static = interp2app(W_CPPConstructorOverload.is_static),
651 call = interp2app(W_CPPConstructorOverload.call),
652 prototype = interp2app(W_CPPConstructorOverload.prototype),
762 __get__ = interp2app(W_CPPConstructorOverload.descr_get),
763 __call__ = interp2app(W_CPPConstructorOverload.call_args),
764 __overload__ = interp2app(W_CPPConstructorOverload.mp_overload),
765 __doc__ = GetSetProperty(W_CPPConstructorOverload.fget_doc)
653766 )
654767
655
656 class W_CPPTemplateOverload(W_CPPOverload):
768 class W_CPPAbstractCtorOverload(W_CPPOverload):
769 _attrs_ = []
770
657771 @unwrap_spec(args_w='args_w')
658 def __getitem__(self, args_w):
659 pass
772 def call_args(self, args_w):
773 raise oefmt(self.space.w_TypeError,
774 "cannot instantiate abstract class '%s'", self.scope.name)
775
776 def __repr__(self):
777 return "W_CPPAbstractCtorOverload"
778
779 W_CPPAbstractCtorOverload.typedef = TypeDef(
780 'CPPAbstractCtorOverload',
781 __get__ = interp2app(W_CPPAbstractCtorOverload.descr_get),
782 __call__ = interp2app(W_CPPAbstractCtorOverload.call_args),
783 )
784
785
786 class TemplateOverloadMixin(object):
787 """Mixin to instantiate templated methods/functions."""
788
789 _attrs_ = ['tmpl_args_w']
790 _mixin_ = True
791
792 def construct_template_args(self, w_tpArgs, args_w = None):
793 space = self.space
794 tmpl_args = ''
795 for i in range(space.len_w(w_tpArgs)):
796 w_tp = space.getitem(w_tpArgs, space.newint(i))
797 if space.isinstance_w(w_tp, space.w_text):
798 s = space.text_w(w_tp) # string describing type
799 elif space.isinstance_w(w_tp, space.w_type):
800 try:
801 # cppyy bound types
802 s = space.text_w(space.getattr(w_tp, space.newtext('__cppname__')))
803 if args_w:
804 # try to specialize the type match for the given object
805 cppinstance = self.space.interp_w(W_CPPInstance, args_w[i])
806 if cppinstance.rt_flags & INSTANCE_FLAGS_IS_RVALUE:
807 sugar = "&&"
808 elif cppinstance.flags & INSTANCE_FLAGS_IS_REF:
809 sugar = "*"
810 else:
811 sugar = "&"
812 s += sugar
813 except OperationError:
814 # generic python types
815 s = space.text_w(space.getattr(w_tp, space.newtext('__name__')))
816 else:
817 # builtin types etc.
818 s = space.text_w(space.str(w_tp))
819 # map python types -> C++ types
820 if s == 'str': s = 'std::string'
821 if i != 0: tmpl_args += ', '
822 tmpl_args += s
823 return tmpl_args
824
825 def find_method_template(self, name, proto = ''):
826 # find/instantiate new callable function
827 space = self.space
828 cppmeth = capi.c_get_method_template(space, self.scope, name, proto)
829 if not cppmeth:
830 raise oefmt(self.space.w_AttributeError,
831 "scope '%s' has no function %s", self.scope.name, name)
832
833 funcs = []
834 ftype = self.scope._make_cppfunction(name, cppmeth, funcs)
835 if ftype & FUNCTION_IS_STATIC:
836 cppol = W_CPPStaticOverload(space, self.scope, funcs[:], self.flags)
837 else:
838 cppol = W_CPPOverload(space, self.scope, funcs[:], self.flags)
839 return cppol
840
841 def instantiate_and_call(self, name, args_w):
842 method = None
843 try:
844 # existing cached instantiations
845 if name[-1] == '>': # only accept full templated name, to ensure explicit
846 method = self.master.overloads[name]
847 else:
848 # try to match with run-time instantiations
849 # TODO: logically, this could be used, but in practice, it's proving too
850 # greedy ... maybe as a last resort?
851 #for cppol in self.master.overloads.values():
852 # try:
853 # if not self.space.is_w(self.w_this, self.space.w_None):
854 # return self.space.call_obj_args(cppol, self.w_this, Arguments(self.space, args_w))
855 # return self.space.call_args(cppol, Arguments(self.space, args_w))
856 # except Exception:
857 # pass # completely ignore for now; have to see whether errors become confusing
858 raise TypeError("pre-existing overloads failed")
859 except (KeyError, TypeError):
860 # if not known, try to deduce from argument types
861 w_types = self.space.newtuple([self.space.type(obj_w) for obj_w in args_w])
862 proto = self.construct_template_args(w_types, args_w)
863 method = self.find_method_template(name, proto)
864
865 # only cache result if the name retains the full template
866 # TODO: the problem is in part that c_method_full_name returns incorrect names,
867 # e.g. when default template arguments are involved, so for now use 'name' if it
868 # has the full templated name
869 if name[-1] == '>':
870 fullname = name
871 else:
872 fullname = capi.c_method_full_name(self.space, method.functions[0].cppmethod)
873 try:
874 existing = self.master.overloads[fullname]
875 allf = existing.functions + method.functions
876 if isinstance(existing, W_CPPStaticOverload):
877 cppol = W_CPPStaticOverload(self.space, self.scope, allf, self.flags)
878 else:
879 cppol = W_CPPOverload(self.space, self.scope, allf, self.flags)
880 self.master.overloads[fullname] = cppol
881 except KeyError:
882 self.master.overloads[fullname] = method
883
884 if method is not None:
885 if not self.space.is_w(self.w_this, self.space.w_None):
886 return self.space.call_obj_args(method, self.w_this, Arguments(self.space, args_w))
887 return self.space.call_args(method, Arguments(self.space, args_w))
888
889 def getitem_impl(self, name, args_w):
890 space = self.space
891
892 if space.isinstance_w(args_w[0], space.w_tuple):
893 w_args = args_w[0]
894 else:
895 w_args = space.newtuple(args_w)
896
897 tmpl_args = self.construct_template_args(w_args)
898 fullname = name+'<'+tmpl_args+'>'
899 try:
900 method = self.master.overloads[fullname]
901 except KeyError as e:
902 # defer instantiation until arguments are known
903 return self.clone(tmpl_args)
904
905 return method.descr_get(self.w_this, None)
906
907
908 class W_CPPTemplateOverload(W_CPPOverload, TemplateOverloadMixin):
909 """App-level dispatcher to allow both lookup/instantiation of templated methods and
910 dispatch among overloads between templated and non-templated method."""
911
912 _attrs_ = ['name', 'tmpl_args', 'overloads', 'master', 'w_this']
913 _immutable_fields_ = ['name', 'tmpl_args']
914
915 def __init__(self, space, name, tmpl_args, decl_scope, functions, flags = OVERLOAD_FLAGS_USE_FFI):
916 W_CPPOverload.__init__(self, space, decl_scope, functions, flags)
917 self.name = name
918 self.tmpl_args = tmpl_args
919 self.overloads = {}
920 self.master = self
921 self.w_this = space.w_None
922
923 def clone(self, tmpl_args):
924 other = W_CPPTemplateOverload(self.space, self.name, tmpl_args, self.scope, self.functions, self.flags)
925 other.overloads = self.overloads
926 other.master = self.master
927 other.w_this = self.w_this
928 return other
929
930 def descr_get(self, w_cppinstance, w_cls=None):
931 # TODO: don't return copy, but bind in an external object (like W_CPPOverload)
932 if self.space.is_w(w_cppinstance, self.space.w_None):
933 return self # unbound, so no new instance needed
934 cppol = W_CPPTemplateOverload(self.space, self.name, self.tmpl_args, self.scope, self.functions, self.flags)
935 cppol.w_this = w_cppinstance
936 cppol.master = self.master
937 return cppol # bound
938
939 @unwrap_spec(args_w='args_w')
940 def call_args(self, args_w):
941 # direct call: either pick non-templated overload or attempt to deduce
942 # the template instantiation from the argument types
943
944 # do explicit lookup with tmpl_args if given
945 try:
946 fullname = self.name
947 if self.tmpl_args is not None:
948 fullname = fullname+'<'+self.tmpl_args+'>'
949 return self.instantiate_and_call(fullname, args_w)
950 except Exception:
951 pass
952
953 # otherwise, try existing overloads or compile-time instantiations
954 # TODO: consolidate errors
955 return W_CPPOverload.call_args(self, [self.w_this]+args_w)
956
957 @unwrap_spec(args_w='args_w')
958 def getitem(self, args_w):
959 return self.getitem_impl(self.name, args_w)
960
961 def getname(self, space):
962 return self.name.decode('latin-1')
660963
661964 def __repr__(self):
662965 return "W_CPPTemplateOverload(%s)" % [f.prototype() for f in self.functions]
663966
664967 W_CPPTemplateOverload.typedef = TypeDef(
665968 'CPPTemplateOverload',
666 __getitem__ = interp2app(W_CPPTemplateOverload.call),
969 __get__ = interp2app(W_CPPTemplateOverload.descr_get),
970 __getitem__ = interp2app(W_CPPTemplateOverload.getitem),
971 __call__ = interp2app(W_CPPTemplateOverload.call_args),
972 __creates__ = GetSetProperty(W_CPPTemplateOverload.fget_creates, W_CPPTemplateOverload.fset_creates),
973 __mempolicy__ = GetSetProperty(W_CPPTemplateOverload.fget_mempolicy, W_CPPTemplateOverload.fset_mempolicy),
974 __release_gil__ = GetSetProperty(W_CPPTemplateOverload.fget_release_gil, W_CPPTemplateOverload.fset_release_gil),
975 __useffi__ = GetSetProperty(W_CPPTemplateOverload.fget_useffi, W_CPPTemplateOverload.fset_useffi),
976 __doc__ = GetSetProperty(W_CPPTemplateOverload.fget_doc)
667977 )
668978
669
670 class W_CPPBoundMethod(W_Root):
671 _attrs_ = ['cppthis', 'method', 'useffi']
672
673 def __init__(self, cppthis, method, useffi):
674 self.cppthis = cppthis
675 self.method = method
676 self.useffi = useffi
677
678 def __call__(self, args_w):
679 return self.method.bound_call(self.cppthis, args_w, self.useffi)
979 class W_CPPTemplateStaticOverload(W_CPPStaticOverload, TemplateOverloadMixin):
980 """App-level dispatcher to allow both lookup/instantiation of templated methods and
981 dispatch among overloads between templated and non-templated method."""
982
983 _attrs_ = ['name', 'tmpl_args', 'overloads', 'master', 'w_this']
984 _immutable_fields_ = ['name', 'tmpl_args']
985
986 def __init__(self, space, name, tmpl_args, decl_scope, funcs, flags = OVERLOAD_FLAGS_USE_FFI):
987 W_CPPStaticOverload.__init__(self, space, decl_scope, funcs, flags)
988 self.name = name
989 self.tmpl_args = tmpl_args
990 self.overloads = {}
991 self.master = self
992 self.w_this = space.w_None
993
994 def clone(self, tmpl_args):
995 other = W_CPPTemplateStaticOverload(self.space, self.name, tmpl_args, self.scope, self.functions, self.flags)
996 other.overloads = self.overloads
997 other.master = self.master
998 other.w_this = self.w_this
999 return other
1000
1001 def descr_get(self, w_cppinstance, w_cls=None):
1002 # TODO: don't return copy, but bind in an external object (like W_CPPOverload)
1003 if isinstance(w_cppinstance, W_CPPInstance):
1004 cppinstance = self.space.interp_w(W_CPPInstance, w_cppinstance)
1005 if cppinstance.clsdecl.handle != self.scope.handle:
1006 cppol = W_CPPTemplateStaticOverload(self.space, self.name, self.tmpl_args, self.scope, self.functions, self.flags)
1007 cppol.w_this = w_cppinstance
1008 cppol.master = self.master
1009 return cppol # bound
1010 return self # unbound
1011
1012 @unwrap_spec(args_w='args_w')
1013 def call_args(self, args_w):
1014 # direct call: either pick non-templated overload or attempt to deduce
1015 # the template instantiation from the argument types
1016 # TODO: refactor with W_CPPTemplateOverload
1017
1018 # do explicit lookup with tmpl_args if given
1019 try:
1020 fullname = self.name
1021 if self.tmpl_args is not None:
1022 fullname = fullname+'<'+self.tmpl_args+'>'
1023 return self.instantiate_and_call(fullname, args_w)
1024 except Exception:
1025 pass
1026
1027 # otherwise, try existing overloads or compile-time instantiations
1028 # TODO: consolidate errors
1029 return W_CPPStaticOverload.call_args(self, args_w)
1030
1031 @unwrap_spec(args_w='args_w')
1032 def getitem(self, args_w):
1033 return self.getitem_impl(self.name, args_w)
1034
1035 def getname(self, space):
1036 return self.name.decode('latin-1')
6801037
6811038 def __repr__(self):
682 return "W_CPPBoundMethod(%s)" % self.method.prototype()
683
684 W_CPPBoundMethod.typedef = TypeDef(
685 'CPPBoundMethod',
686 __call__ = interp2app(W_CPPBoundMethod.__call__),
1039 return "W_CPPTemplateStaticOverload(%s)" % [f.prototype() for f in self.functions]
1040
1041 W_CPPTemplateStaticOverload.typedef = TypeDef(
1042 'CPPTemplateStaticOverload',
1043 __get__ = interp2app(W_CPPTemplateStaticOverload.descr_get),
1044 __getitem__ = interp2app(W_CPPTemplateStaticOverload.getitem),
1045 __call__ = interp2app(W_CPPTemplateStaticOverload.call_args),
1046 __creates__ = GetSetProperty(W_CPPTemplateStaticOverload.fget_creates,
1047 W_CPPTemplateStaticOverload.fset_creates),
1048 __mempolicy__ = GetSetProperty(W_CPPTemplateStaticOverload.fget_mempolicy,
1049 W_CPPTemplateStaticOverload.fset_mempolicy),
1050 __release_gil__ = GetSetProperty(W_CPPTemplateStaticOverload.fget_release_gil,
1051 W_CPPTemplateStaticOverload.fset_release_gil),
1052 __useffi__ = GetSetProperty(W_CPPTemplateStaticOverload.fget_useffi,
1053 W_CPPTemplateStaticOverload.fset_useffi),
1054 __doc__ = GetSetProperty(W_CPPTemplateStaticOverload.fget_doc)
6871055 )
6881056
1057
1058 #-----
1059 # Classes for data members:
1060 #
1061 # W_CPPDataMember: instance data members
1062 # W_CPPConstDataMember: specialization for const data members
1063 # W_CPPStaticData: class-level and global/static data
1064 # W_CPPConstStaticData: specialization for const global/static data
1065 #
1066 # Data is represented by an offset which is either a global pointer (static data)
1067 # or an offset from the start of an instance (data members). The "const"
1068 # specializations raise when attempting to set their value.
6891069
6901070 class W_CPPDataMember(W_Root):
6911071 _attrs_ = ['space', 'scope', 'converter', 'offset']
6921072 _immutable_fields = ['scope', 'converter', 'offset']
6931073
694 def __init__(self, space, declaring_scope, type_name, offset):
1074 def __init__(self, space, decl_scope, type_name, dimensions, offset):
6951075 self.space = space
696 self.scope = declaring_scope
697 self.converter = converter.get_converter(self.space, type_name, '')
698 self.offset = offset
699
700 def is_static(self):
701 return self.space.w_False
1076 self.scope = decl_scope
1077 self.converter = converter.get_converter(self.space, type_name, dimensions)
1078 self.offset = rffi.cast(rffi.LONG, offset)
7021079
7031080 def _get_offset(self, cppinstance):
7041081 if cppinstance:
1082 assert isinstance(cppinstance.clsdecl, W_CPPClassDecl)
7051083 assert lltype.typeOf(cppinstance.clsdecl.handle) == lltype.typeOf(self.scope.handle)
7061084 offset = self.offset + cppinstance.clsdecl.get_base_offset(cppinstance, self.scope)
7071085 else:
7141092 raise oefmt(self.space.w_AttributeError,
7151093 "attribute access requires an instance")
7161094 offset = self._get_offset(cppinstance)
717 return self.converter.from_memory(self.space, w_cppinstance, w_pycppclass, offset)
1095 return self.converter.from_memory(self.space, w_cppinstance, offset)
7181096
7191097 def set(self, w_cppinstance, w_value):
7201098 cppinstance = self.space.interp_w(W_CPPInstance, w_cppinstance, can_be_None=True)
7271105
7281106 W_CPPDataMember.typedef = TypeDef(
7291107 'CPPDataMember',
730 is_static = interp2app(W_CPPDataMember.is_static),
7311108 __get__ = interp2app(W_CPPDataMember.get),
7321109 __set__ = interp2app(W_CPPDataMember.set),
7331110 )
7341111 W_CPPDataMember.typedef.acceptable_as_base_class = False
7351112
1113
1114 class W_CPPConstDataMember(W_CPPDataMember):
1115 def set(self, w_cppinstance, w_value):
1116 raise oefmt(self.space.w_TypeError, "assignment to const data not allowed")
1117
1118 W_CPPConstDataMember.typedef = TypeDef(
1119 'CPPConstDataMember',
1120 __get__ = interp2app(W_CPPDataMember.get),
1121 __set__ = interp2app(W_CPPConstDataMember.set),
1122 )
1123 W_CPPConstDataMember.typedef.acceptable_as_base_class = False
1124
1125
7361126 class W_CPPStaticData(W_CPPDataMember):
737 def is_static(self):
738 return self.space.w_True
739
7401127 @jit.elidable_promote()
7411128 def _get_offset(self, cppinstance):
7421129 return self.offset
7431130
7441131 def get(self, w_cppinstance, w_pycppclass):
745 return self.converter.from_memory(self.space, self.space.w_None, w_pycppclass, self.offset)
1132 return self.converter.from_memory(self.space, self.space.w_None, self.offset)
7461133
7471134 def set(self, w_cppinstance, w_value):
7481135 self.converter.to_memory(self.space, self.space.w_None, w_value, self.offset)
7501137
7511138 W_CPPStaticData.typedef = TypeDef(
7521139 'CPPStaticData',
753 is_static = interp2app(W_CPPStaticData.is_static),
7541140 __get__ = interp2app(W_CPPStaticData.get),
7551141 __set__ = interp2app(W_CPPStaticData.set),
7561142 )
7571143 W_CPPStaticData.typedef.acceptable_as_base_class = False
7581144
759 def is_static(space, w_obj):
1145
1146 class W_CPPConstStaticData(W_CPPStaticData):
1147 def set(self, w_cppinstance, w_value):
1148 raise oefmt(self.space.w_TypeError, "assignment to const data not allowed")
1149
1150 W_CPPConstStaticData.typedef = TypeDef(
1151 'CPPConstStaticData',
1152 __get__ = interp2app(W_CPPConstStaticData.get),
1153 __set__ = interp2app(W_CPPConstStaticData.set),
1154 )
1155 W_CPPConstStaticData.typedef.acceptable_as_base_class = False
1156
1157
1158 def is_static_data(space, w_obj):
7601159 try:
761 space.interp_w(W_CPPStaticData, w_obj, can_be_None=False)
1160 space.interp_w(W_CPPStaticData, w_obj)
7621161 return space.w_True
7631162 except Exception:
7641163 return space.w_False
7651164
1165 #-----
1166 # Classes for data members:
1167 #
1168 # W_CPPScopeDecl : scope base class
1169 # W_CPPNamespaceDecl : namespace scope
1170 # W_CPPClassDecl : class scope
1171 #
1172 # Namespaces and classes mainly differ in lookups of methods. Whereas classes
1173 # can grown templated methods, namespaces are wide open to any additions. Such
1174 # lookups are triggered from get_scoped_pycppitem (in pythonify.py). Further
1175 # specialization is done on the type of data/methods that each can have.
1176
7661177 class W_CPPScopeDecl(W_Root):
767 _attrs_ = ['space', 'handle', 'name', 'methods', 'datamembers']
1178 _attrs_ = ['space', 'handle', 'flags', 'name', 'overloads', 'datamembers']
7681179 _immutable_fields_ = ['handle', 'name']
7691180
7701181 def __init__(self, space, opaque_handle, final_scoped_name):
7711182 self.space = space
772 self.name = final_scoped_name
7731183 assert lltype.typeOf(opaque_handle) == capi.C_SCOPE
7741184 self.handle = opaque_handle
775 self.methods = {}
776 # Do not call "self._build_methods()" here, so that a distinction can
1185 self.flags = 0
1186 self.name = final_scoped_name
1187 self.overloads = {}
1188 # Do not call "self._build_overloadss()" here, so that a distinction can
7771189 # be made between testing for existence (i.e. existence in the cache
7781190 # of classes) and actual use. Point being that a class can use itself,
7791191 # e.g. as a return type or an argument to one of its methods.
7801192
7811193 self.datamembers = {}
782 # Idem as for self.methods: a type could hold itself by pointer.
1194 # Idem as for self.overloads: a type could hold itself by pointer.
7831195
7841196 def get_method_names(self):
785 return self.space.newlist([self.space.newtext(name) for name in self.methods])
1197 return self.space.newlist([self.space.newtext(name) for name in self.overloads])
7861198
7871199 @unwrap_spec(name='text')
7881200 def get_overload(self, name):
7891201 try:
790 return self.methods[name]
1202 return self.overloads[name]
7911203 except KeyError:
7921204 pass
793 new_method = self.find_overload(name)
794 self.methods[name] = new_method
795 return new_method
1205 new_ol = self.find_overload(name)
1206 self.overloads[name] = new_ol
1207 return new_ol
7961208
7971209 def get_datamember_names(self):
7981210 return self.space.newlist([self.space.newtext(name) for name in self.datamembers])
8071219 self.datamembers[name] = new_dm
8081220 return new_dm
8091221
1222 @unwrap_spec(name='text')
1223 def has_enum(self, name):
1224 if capi.c_is_enum(self.space, self.name+'::'+name):
1225 return self.space.w_True
1226 return self.space.w_False
1227
1228 def _encode_dm_dimensions(self, idata):
1229 # encode dimensions (TODO: this is ugly, but here's where the info is)
1230 dims = []
1231 sz = capi.c_get_dimension_size(self.space, self, idata, len(dims))
1232 while 0 < sz:
1233 dims.append(str(sz))
1234 sz = capi.c_get_dimension_size(self.space, self, idata, len(dims))
1235 return ':'.join(dims)
1236
8101237 @unwrap_spec(name='text', signature='text')
8111238 def scope__dispatch__(self, name, signature):
8121239 overload = self.get_overload(name)
8131240 sig = '(%s)' % signature
8141241 for f in overload.functions:
8151242 if f.signature(False) == sig:
1243 if isinstance(overload, W_CPPStaticOverload):
1244 return W_CPPStaticOverload(self.space, self, [f])
8161245 return W_CPPOverload(self.space, self, [f])
8171246 raise oefmt(self.space.w_LookupError, "no overload matches signature")
8181247
8281257 # classes for inheritance. Both are python classes, though, and refactoring
8291258 # may be in order at some point.
8301259 class W_CPPNamespaceDecl(W_CPPScopeDecl):
831 _attrs_ = ['space', 'handle', 'name', 'methods', 'datamembers']
1260 _attrs_ = ['space', 'handle', 'name', 'overloads', 'datamembers']
8321261 _immutable_fields_ = ['handle', 'name']
8331262
834 def _make_cppfunction(self, pyname, index):
835 num_args = capi.c_method_num_args(self.space, self, index)
836 args_required = capi.c_method_req_args(self.space, self, index)
1263 def _make_cppfunction(self, pyname, cppmeth, funcs):
1264 num_args = capi.c_method_num_args(self.space, cppmeth)
1265 args_required = capi.c_method_req_args(self.space, cppmeth)
8371266 arg_defs = []
8381267 for i in range(num_args):
839 arg_type = capi.c_method_arg_type(self.space, self, index, i)
840 arg_dflt = capi.c_method_arg_default(self.space, self, index, i)
1268 arg_type = capi.c_method_arg_type(self.space, cppmeth, i)
1269 arg_dflt = capi.c_method_arg_default(self.space, cppmeth, i)
8411270 arg_defs.append((arg_type, arg_dflt))
842 return CPPFunction(self.space, self, index, arg_defs, args_required)
1271 funcs.append(CPPMethod(self.space, self, cppmeth, arg_defs, args_required))
1272 return FUNCTION_IS_GLOBAL
8431273
8441274 def _make_datamember(self, dm_name, dm_idx):
8451275 type_name = capi.c_datamember_type(self.space, self, dm_idx)
1276 if capi.c_is_enum_data(self.space, self, dm_idx):
1277 type_name = capi.c_resolve_enum(self.space, type_name)
8461278 offset = capi.c_datamember_offset(self.space, self, dm_idx)
8471279 if offset == -1:
8481280 raise self.missing_attribute_error(dm_name)
849 datamember = W_CPPStaticData(self.space, self, type_name, offset)
1281 dims = self._encode_dm_dimensions(dm_idx)
1282 if capi.c_is_const_data(self.space, self, dm_idx):
1283 datamember = W_CPPConstStaticData(self.space, self, type_name, dims, offset)
1284 else:
1285 datamember = W_CPPStaticData(self.space, self, type_name, dims, offset)
8501286 self.datamembers[dm_name] = datamember
8511287 return datamember
8521288
8531289 def find_overload(self, meth_name):
8541290 indices = capi.c_method_indices_from_name(self.space, self, meth_name)
855 if not indices:
856 raise self.missing_attribute_error(meth_name)
857 cppfunctions = []
858 for meth_idx in indices:
859 f = self._make_cppfunction(meth_name, meth_idx)
860 cppfunctions.append(f)
861 overload = W_CPPOverload(self.space, self, cppfunctions)
862 return overload
1291 if indices:
1292 cppfunctions, ftype = [], 0
1293 templated = False
1294 for idx in indices:
1295 cppmeth = capi.c_get_method(self.space, self, idx)
1296 ftype |= self._make_cppfunction(meth_name, cppmeth, cppfunctions)
1297 if capi.c_method_is_template(self.space, self, idx):
1298 templated = True
1299 if templated:
1300 return W_CPPTemplateStaticOverload(self.space, meth_name, None, self, cppfunctions[:])
1301 return W_CPPStaticOverload(self.space, self, cppfunctions[:])
1302 elif capi.c_exists_method_template(self.space, self, meth_name):
1303 return W_CPPTemplateStaticOverload(self.space, meth_name, None, self, [])
1304 raise self.missing_attribute_error(meth_name)
8631305
8641306 def find_datamember(self, dm_name):
8651307 dm_idx = capi.c_datamember_index(self.space, self, dm_name)
8901332 get_datamember_names = interp2app(W_CPPNamespaceDecl.get_datamember_names),
8911333 get_datamember = interp2app(W_CPPNamespaceDecl.get_datamember),
8921334 is_namespace = interp2app(W_CPPNamespaceDecl.is_namespace),
1335 has_enum = interp2app(W_CPPNamespaceDecl.has_enum),
8931336 __cppname__ = interp_attrproperty('name', W_CPPNamespaceDecl, wrapfn="newtext"),
8941337 __dispatch__ = interp2app(W_CPPNamespaceDecl.scope__dispatch__),
8951338 __dir__ = interp2app(W_CPPNamespaceDecl.ns__dir__),
8981341
8991342
9001343 class W_CPPClassDecl(W_CPPScopeDecl):
901 _attrs_ = ['space', 'handle', 'name', 'methods', 'datamembers']
902 _immutable_fields_ = ['handle', 'name', 'methods[*]', 'datamembers[*]']
903
904 def _build_methods(self):
905 assert len(self.methods) == 0
906 methods_temp = {}
1344 _attrs_ = ['space', 'handle', 'name', 'overloads', 'datamembers', 'cppobjects']
1345 _immutable_fields_ = ['handle', 'name', 'overloads[*]', 'datamembers[*]']
1346
1347 def __init__(self, space, opaque_handle, final_scoped_name):
1348 W_CPPScopeDecl.__init__(self, space, opaque_handle, final_scoped_name)
1349 self.cppobjects = rweakref.RWeakValueDictionary(int, W_CPPInstance)
1350
1351 def _build_overloads(self):
1352 assert len(self.overloads) == 0
1353 methods_tmp = {}; ftype_tmp = {}
9071354 for idx in range(capi.c_num_methods(self.space, self)):
908 if capi.c_is_constructor(self.space, self, idx):
1355 cppmeth = capi.c_get_method(self.space, self, idx)
1356 if capi.c_is_constructor(self.space, cppmeth):
9091357 pyname = '__init__'
9101358 else:
9111359 pyname = helper.map_operator_name(self.space,
912 capi.c_method_name(self.space, self, idx),
913 capi.c_method_num_args(self.space, self, idx),
914 capi.c_method_result_type(self.space, self, idx))
915 cppmethod = self._make_cppfunction(pyname, idx)
916 methods_temp.setdefault(pyname, []).append(cppmethod)
1360 capi.c_method_name(self.space, cppmeth),
1361 capi.c_method_num_args(self.space, cppmeth),
1362 capi.c_method_result_type(self.space, cppmeth))
1363 try:
1364 methods = methods_tmp[pyname]
1365 except KeyError:
1366 methods_tmp[pyname] = []; ftype_tmp[pyname] = 0
1367 methods = methods_tmp[pyname]
1368 ftype_tmp[pyname] |= self._make_cppfunction(pyname, cppmeth, methods)
1369 if capi.c_method_is_template(self.space, self, idx):
1370 ftype_tmp[pyname] |= FUNCTION_IS_TEMPLATE
9171371 # the following covers the case where the only kind of operator[](idx)
9181372 # returns are the ones that produce non-const references; these can be
9191373 # used for __getitem__ just as much as for __setitem__, though
920 if not "__getitem__" in methods_temp:
1374 if not "__getitem__" in methods_tmp:
9211375 try:
922 for m in methods_temp["__setitem__"]:
923 cppmethod = self._make_cppfunction("__getitem__", m.index)
924 methods_temp.setdefault("__getitem__", []).append(cppmethod)
1376 si_methods = methods_tmp["__setitem__"]
1377 gi_methods = []; ftype = 0
1378 for m in si_methods:
1379 ftype |= self._make_cppfunction("__getitem__", m.cppmethod, gi_methods)
1380 methods_tmp["__getitem__"] = gi_methods; ftype_tmp["__getitem__"] = ftype
9251381 except KeyError:
9261382 pass # just means there's no __setitem__ either
9271383
928 # create the overload methods from the method sets
929 for pyname, methods in methods_temp.iteritems():
1384 # create the overloads from the method sets
1385 for pyname, methods in methods_tmp.iteritems():
1386 ftype = ftype_tmp[pyname]
9301387 CPPMethodSort(methods).sort()
931 if pyname == '__init__':
932 overload = W_CPPConstructorOverload(self.space, self, methods[:])
1388 if ftype & FUNCTION_IS_CONSTRUCTOR:
1389 if capi.c_is_abstract(self.space, self.handle):
1390 overload = W_CPPAbstractCtorOverload(self.space, self, methods[:])
1391 else:
1392 overload = W_CPPConstructorOverload(self.space, self, methods[:])
1393 elif ftype & FUNCTION_IS_STATIC:
1394 if ftype & FUNCTION_IS_TEMPLATE:
1395 cppname = capi.c_method_name(self.space, methods[0].cppmethod)
1396 overload = W_CPPTemplateStaticOverload(self.space, cppname, None, self, methods[:])
1397 else:
1398 overload = W_CPPStaticOverload(self.space, self, methods[:])
1399 elif ftype & FUNCTION_IS_TEMPLATE:
1400 cppname = capi.c_method_name(self.space, methods[0].cppmethod)
1401 overload = W_CPPTemplateOverload(self.space, cppname, None, self, methods[:])
9331402 else:
9341403 overload = W_CPPOverload(self.space, self, methods[:])
935 self.methods[pyname] = overload
936
937 def _make_cppfunction(self, pyname, index):
938 num_args = capi.c_method_num_args(self.space, self, index)
939 args_required = capi.c_method_req_args(self.space, self, index)
1404 self.overloads[pyname] = overload
1405
1406 def _make_cppfunction(self, pyname, cppmeth, funcs):
1407 num_args = capi.c_method_num_args(self.space, cppmeth)
1408 args_required = capi.c_method_req_args(self.space, cppmeth)
9401409 arg_defs = []
9411410 for i in range(num_args):
942 arg_type = capi.c_method_arg_type(self.space, self, index, i)
943 arg_dflt = capi.c_method_arg_default(self.space, self, index, i)
1411 arg_type = capi.c_method_arg_type(self.space, cppmeth, i)
1412 arg_dflt = capi.c_method_arg_default(self.space, cppmeth, i)
9441413 arg_defs.append((arg_type, arg_dflt))
945 if capi.c_is_constructor(self.space, self, index):
946 cppfunction = CPPConstructor(self.space, self, index, arg_defs, args_required)
947 elif capi.c_method_is_template(self.space, self, index):
948 templ_args = capi.c_template_args(self.space, self, index)
949 cppfunction = CPPTemplatedCall(self.space, templ_args, self, index, arg_defs, args_required)
950 elif capi.c_is_staticmethod(self.space, self, index):
951 cppfunction = CPPFunction(self.space, self, index, arg_defs, args_required)
952 elif pyname == "__setitem__":
953 cppfunction = CPPSetItem(self.space, self, index, arg_defs, args_required)
1414 ftype = 0
1415 if pyname == "__setitem__":
1416 cppfunction = CPPSetItem(self.space, self, cppmeth, arg_defs, args_required)
1417 ftype = FUNCTION_IS_SETITEM
9541418 else:
955 cppfunction = CPPMethod(self.space, self, index, arg_defs, args_required)
956 return cppfunction
1419 cppfunction = CPPMethod(self.space, self, cppmeth, arg_defs, args_required)
1420 if capi.c_is_constructor(self.space, cppmeth):
1421 ftype = FUNCTION_IS_CONSTRUCTOR
1422 elif capi.c_is_staticmethod(self.space, cppmeth):
1423 ftype = FUNCTION_IS_STATIC
1424 else:
1425 ftype = FUNCTION_IS_METHOD
1426 funcs.append(cppfunction)
1427 return ftype
9571428
9581429 def _find_datamembers(self):
9591430 num_datamembers = capi.c_num_datamembers(self.space, self)
9661437 if offset == -1:
9671438 continue # dictionary problem; raises AttributeError on use
9681439 is_static = bool(capi.c_is_staticdata(self.space, self, i))
969 if is_static:
970 datamember = W_CPPStaticData(self.space, self, type_name, offset)
1440 is_const = bool(capi.c_is_const_data(self.space, self, i))
1441 dims = self._encode_dm_dimensions(i)
1442 if is_static and is_const:
1443 datamember = W_CPPConstStaticData(self.space, self, type_name, dims, offset)
1444 elif is_static:
1445 datamember = W_CPPStaticData(self.space, self, type_name, dims, offset)
1446 elif is_const:
1447 datamember = W_CPPConstDataMember(self.space, self, type_name, dims, offset)
9711448 else:
972 datamember = W_CPPDataMember(self.space, self, type_name, offset)
1449 datamember = W_CPPDataMember(self.space, self, type_name, dims, offset)
9731450 self.datamembers[datamember_name] = datamember
9741451
975 def find_overload(self, name):
976 raise self.missing_attribute_error(name)
1452 def find_overload(self, meth_name):
1453 raise self.missing_attribute_error(meth_name)
9771454
9781455 def find_datamember(self, name):
9791456 raise self.missing_attribute_error(name)
9801457
9811458 def get_base_offset(self, cppinstance, calling_scope):
1459 assert isinstance(cppinstance.clsdecl, W_CPPClassDecl)
9821460 assert self == cppinstance.clsdecl
9831461 return 0
9841462
9851463 def get_cppthis(self, cppinstance, calling_scope):
1464 assert isinstance(cppinstance.clsdecl, W_CPPClassDecl)
9861465 assert self == cppinstance.clsdecl
9871466 return cppinstance.get_rawobject()
9881467
10101489 get_datamember_names = interp2app(W_CPPClassDecl.get_datamember_names),
10111490 get_datamember = interp2app(W_CPPClassDecl.get_datamember),
10121491 is_namespace = interp2app(W_CPPClassDecl.is_namespace),
1492 has_enum = interp2app(W_CPPClassDecl.has_enum),
10131493 __cppname__ = interp_attrproperty('name', W_CPPClassDecl, wrapfn="newtext"),
10141494 __dispatch__ = interp2app(W_CPPClassDecl.scope__dispatch__)
10151495 )
10181498
10191499 class W_CPPComplexClassDecl(W_CPPClassDecl):
10201500 def get_base_offset(self, cppinstance, calling_scope):
1501 assert isinstance(cppinstance.clsdecl, W_CPPComplexClassDecl)
10211502 assert self == cppinstance.clsdecl
10221503 offset = capi.c_base_offset(self.space,
1023 self, calling_scope, cppinstance.get_rawobject(), 1)
1504 self, calling_scope, cppinstance.get_rawobject(), 1)
10241505 return offset
10251506
10261507 def get_cppthis(self, cppinstance, calling_scope):
1508 assert isinstance(cppinstance.clsdecl, W_CPPComplexClassDecl)
10271509 assert self == cppinstance.clsdecl
10281510 offset = self.get_base_offset(cppinstance, calling_scope)
10291511 return capi.direct_ptradd(cppinstance.get_rawobject(), offset)
10431525
10441526
10451527 class W_CPPInstance(W_Root):
1046 _attrs_ = ['space', 'clsdecl', '_rawobject', 'flags',
1528 _attrs_ = ['space', 'clsdecl', '_rawobject', 'smartdecl', 'deref', 'flags', 'rt_flags',
10471529 'finalizer_registered']
1048 _immutable_fields_ = ['clsdecl']
1530 _immutable_fields_ = ['clsdecl', 'smartdecl', 'deref', 'flags']
10491531
10501532 finalizer_registered = False
10511533
1052 def __init__(self, space, decl, rawobject, isref, python_owns):
1534 def __init__(self, space, decl, rawobject, isref, python_owns,
1535 smartdecl=None, deref=rffi.cast(capi.C_METHOD, 0)):
10531536 self.space = space
10541537 self.clsdecl = decl
1538 assert isinstance(self.clsdecl, W_CPPClassDecl)
10551539 assert lltype.typeOf(rawobject) == capi.C_OBJECT
10561540 assert not isref or rawobject
10571541 self._rawobject = rawobject
10581542 assert not isref or not python_owns
10591543 self.flags = 0
1060 if isref:
1544 if isref or (smartdecl and deref):
10611545 self.flags |= INSTANCE_FLAGS_IS_REF
1546 self.rt_flags = 0
10621547 if python_owns:
1063 self.flags |= INSTANCE_FLAGS_PYTHON_OWNS
1548 self.rt_flags |= INSTANCE_FLAGS_PYTHON_OWNS
10641549 self._opt_register_finalizer()
1550 self.smartdecl = smartdecl
1551 self.deref = deref
10651552
10661553 def _opt_register_finalizer(self):
10671554 if not self.finalizer_registered and not hasattr(self.space, "fake"):
1068 assert self.flags & INSTANCE_FLAGS_PYTHON_OWNS
1555 assert self.rt_flags & INSTANCE_FLAGS_PYTHON_OWNS
10691556 self.register_finalizer(self.space)
10701557 self.finalizer_registered = True
10711558
10771564
10781565 # allow user to determine ownership rules on a per object level
10791566 def fget_python_owns(self, space):
1080 return space.newbool(bool(self.flags & INSTANCE_FLAGS_PYTHON_OWNS))
1567 return space.newbool(bool(self.rt_flags & INSTANCE_FLAGS_PYTHON_OWNS))
10811568
10821569 @unwrap_spec(value=bool)
10831570 def fset_python_owns(self, space, value):
10841571 if space.is_true(value):
1085 self.flags |= INSTANCE_FLAGS_PYTHON_OWNS
1572 self.rt_flags |= INSTANCE_FLAGS_PYTHON_OWNS
10861573 self._opt_register_finalizer()
10871574 else:
1088 self.flags &= ~INSTANCE_FLAGS_PYTHON_OWNS
1575 self.rt_flags &= ~INSTANCE_FLAGS_PYTHON_OWNS
10891576
10901577 def get_cppthis(self, calling_scope):
1578 assert isinstance(self.clsdecl, W_CPPClassDecl)
10911579 return self.clsdecl.get_cppthis(self, calling_scope)
10921580
10931581 def get_rawobject(self):
10941582 if not (self.flags & INSTANCE_FLAGS_IS_REF):
10951583 return self._rawobject
1584 elif self.smartdecl and self.deref:
1585 args = capi.c_allocate_function_args(self.space, 0)
1586 rawptr = capi.c_call_l(self.space, self.deref, self._rawobject, 0, args)
1587 capi.c_deallocate_function_args(self.space, args)
1588 return rffi.cast(capi.C_OBJECT, rawptr)
10961589 else:
10971590 ptrptr = rffi.cast(rffi.VOIDPP, self._rawobject)
10981591 return rffi.cast(capi.C_OBJECT, ptrptr[0])
11231616 # scopes of the argument classes (TODO: implement that last option)
11241617 try:
11251618 # TODO: expecting w_other to be an W_CPPInstance is too limiting
1126 other = self.space.interp_w(W_CPPInstance, w_other, can_be_None=False)
1619 other = self.space.interp_w(W_CPPInstance, w_other)
11271620 for name in ["", "__gnu_cxx", "__1"]:
11281621 nss = scope_byname(self.space, name)
11291622 meth_idx = capi.c_get_global_operator(
11301623 self.space, nss, self.clsdecl, other.clsdecl, "operator==")
11311624 if meth_idx != -1:
1132 f = nss._make_cppfunction("operator==", meth_idx)
1133 ol = W_CPPOverload(self.space, nss, [f])
1625 funcs = []
1626 cppmeth = capi.c_get_method(self.space, nss, meth_idx)
1627 nss._make_cppfunction("operator==", cppmeth, funcs)
1628 ol = W_CPPStaticOverload(self.space, nss, funcs[:])
11341629 # TODO: cache this operator (not done yet, as the above does not
11351630 # select all overloads)
1136 return ol.call(self, [self, w_other])
1631 return ol.call_args([self, w_other])
11371632 except OperationError as e:
11381633 if not e.match(self.space, self.space.w_TypeError):
11391634 raise
11451640
11461641 # fallback 2: direct pointer comparison (the class comparison is needed since
11471642 # the first data member in a struct and the struct have the same address)
1148 other = self.space.interp_w(W_CPPInstance, w_other, can_be_None=False) # TODO: factor out
1643 other = self.space.interp_w(W_CPPInstance, w_other) # TODO: factor out
11491644 iseq = (self._rawobject == other._rawobject) and (self.clsdecl == other.clsdecl)
11501645 return self.space.newbool(iseq)
11511646
11661661 "'%s' has no length", self.clsdecl.name)
11671662
11681663 def instance__cmp__(self, w_other):
1169 w_as_builtin = self._get_as_builtin()
1170 if w_as_builtin is not None:
1171 return self.space.cmp(w_as_builtin, w_other)
1664 from pypy.module.sys.version import CPYTHON_VERSION
1665 if CPYTHON_VERSION[0] != 3:
1666 w_as_builtin = self._get_as_builtin()
1667 if w_as_builtin is not None:
1668 return self.space.cmp(w_as_builtin, w_other)
11721669 raise oefmt(self.space.w_AttributeError,
11731670 "'%s' has no attribute __cmp__", self.clsdecl.name)
11741671
11791676 return self.space.newtext("<%s object at 0x%x>" %
11801677 (self.clsdecl.name, rffi.cast(rffi.ULONG, self.get_rawobject())))
11811678
1679 def smartptr(self):
1680 if self._rawobject and self.smartdecl:
1681 return wrap_cppinstance(self.space, self._rawobject, self.smartdecl, do_cast=False)
1682
11821683 def destruct(self):
1183 if self._rawobject and not (self.flags & INSTANCE_FLAGS_IS_REF):
1684 if self._rawobject:
1685 assert isinstance(self.clsdecl, W_CPPClassDecl)
1686 if self.smartdecl and self.deref:
1687 klass = self.smartdecl
1688 elif not (self.flags & INSTANCE_FLAGS_IS_REF):
1689 klass = self.clsdecl
1690 else:
1691 return
11841692 memory_regulator.unregister(self)
1185 capi.c_destruct(self.space, self.clsdecl, self._rawobject)
1693 capi.c_destruct(self.space, klass, self._rawobject)
11861694 self._rawobject = capi.C_NULL_OBJECT
11871695
11881696 def _finalize_(self):
1189 if self.flags & INSTANCE_FLAGS_PYTHON_OWNS:
1697 if self.rt_flags & INSTANCE_FLAGS_PYTHON_OWNS:
11901698 self.destruct()
11911699
11921700 W_CPPInstance.typedef = TypeDef(
11951703 __init__ = interp2app(W_CPPInstance.instance__init__),
11961704 __eq__ = interp2app(W_CPPInstance.instance__eq__),
11971705 __ne__ = interp2app(W_CPPInstance.instance__ne__),
1706 # should be based on python version, but syntax is simpler this way
11981707 __nonzero__ = interp2app(W_CPPInstance.instance__nonzero__),
1708 __bool__ = interp2app(W_CPPInstance.instance__nonzero__),
11991709 __len__ = interp2app(W_CPPInstance.instance__len__),
12001710 __cmp__ = interp2app(W_CPPInstance.instance__cmp__),
12011711 __repr__ = interp2app(W_CPPInstance.instance__repr__),
1712 __smartptr__ = interp2app(W_CPPInstance.smartptr),
12021713 __destruct__ = interp2app(W_CPPInstance.destruct),
12031714 )
12041715 W_CPPInstance.typedef.acceptable_as_base_class = True
12051716
12061717
12071718 class MemoryRegulator:
1208 # TODO: (?) An object address is not unique if e.g. the class has a
1209 # public data member of class type at the start of its definition and
1210 # has no virtual functions. A _key class that hashes on address and
1211 # type would be better, but my attempt failed in the rtyper, claiming
1212 # a call on None ("None()") and needed a default ctor. (??)
1213 # Note that for now, the associated test carries an m_padding to make
1214 # a difference in the addresses.
1215 def __init__(self):
1216 self.objects = rweakref.RWeakValueDictionary(int, W_CPPInstance)
1217
1218 def register(self, obj):
1719 _immutable_ = True
1720
1721 @staticmethod
1722 def register(obj):
12191723 if not obj._rawobject:
12201724 return
1221 int_address = int(rffi.cast(rffi.LONG, obj._rawobject))
1222 self.objects.set(int_address, obj)
1223
1224 def unregister(self, obj):
1725 addr_as_int = int(rffi.cast(rffi.LONG, obj.get_rawobject()))
1726 clsdecl = obj.clsdecl
1727 assert isinstance(clsdecl, W_CPPClassDecl)
1728 clsdecl.cppobjects.set(addr_as_int, obj)
1729
1730 @staticmethod
1731 def unregister(obj):
12251732 if not obj._rawobject:
12261733 return
1227 int_address = int(rffi.cast(rffi.LONG, obj._rawobject))
1228 self.objects.set(int_address, None)
1229
1230 def retrieve(self, address):
1231 int_address = int(rffi.cast(rffi.LONG, address))
1232 return self.objects.get(int_address)
1734 addr_as_int = int(rffi.cast(rffi.LONG, obj.get_rawobject()))
1735 clsdecl = obj.clsdecl
1736 assert isinstance(clsdecl, W_CPPClassDecl)
1737 clsdecl.cppobjects.set(addr_as_int, None) # actually deletes (pops)
1738
1739 @staticmethod
1740 def retrieve(clsdecl, address):
1741 if not address:
1742 return None
1743 addr_as_int = int(rffi.cast(rffi.LONG, address))
1744 assert isinstance(clsdecl, W_CPPClassDecl)
1745 return clsdecl.cppobjects.get(addr_as_int)
12331746
12341747 memory_regulator = MemoryRegulator()
12351748
12491762 return space.call_function(state.w_fngen_callback, w_callable, space.newint(npar))
12501763
12511764 def wrap_cppinstance(space, rawobject, clsdecl,
1765 smartdecl=None, deref=rffi.cast(capi.C_METHOD, 0),
12521766 do_cast=True, python_owns=False, is_ref=False, fresh=False):
12531767 rawobject = rffi.cast(capi.C_OBJECT, rawobject)
12541768
12551769 # cast to actual if requested and possible
12561770 w_pycppclass = None
1257 if do_cast and rawobject:
1771 if do_cast and rawobject and not (clsdecl.flags & CLASS_FLAGS_IS_PINNED):
12581772 actual = capi.c_actual_class(space, clsdecl, rawobject)
12591773 if actual != clsdecl.handle:
12601774 try:
12621776 offset = capi.c_base_offset1(space, actual, clsdecl, rawobject, -1)
12631777 rawobject = capi.direct_ptradd(rawobject, offset)
12641778 w_cppdecl = space.findattr(w_pycppclass, space.newtext("__cppdecl__"))
1265 clsdecl = space.interp_w(W_CPPClassDecl, w_cppdecl, can_be_None=False)
1779 clsdecl = space.interp_w(W_CPPClassDecl, w_cppdecl)
12661780 except Exception:
12671781 # failed to locate/build the derived class, so stick to the base (note
12681782 # that only get_pythonized_cppclass is expected to raise, so none of
12741788
12751789 # try to recycle existing object if this one is not newly created
12761790 if not fresh and rawobject:
1277 obj = memory_regulator.retrieve(rawobject)
1278 if obj is not None and obj.clsdecl is clsdecl:
1791 address = rawobject
1792 if is_ref:
1793 address = rffi.cast(capi.C_OBJECT, rffi.cast(rffi.VOIDPP, address)[0])
1794 obj = memory_regulator.retrieve(clsdecl, address)
1795 if obj is not None:
12791796 return obj
12801797
12811798 # fresh creation
12821799 w_cppinstance = space.allocate_instance(W_CPPInstance, w_pycppclass)
1283 cppinstance = space.interp_w(W_CPPInstance, w_cppinstance, can_be_None=False)
1284 cppinstance.__init__(space, clsdecl, rawobject, is_ref, python_owns)
1800 cppinstance = space.interp_w(W_CPPInstance, w_cppinstance)
1801 cppinstance.__init__(space, clsdecl, rawobject, is_ref, python_owns, smartdecl, deref)
12851802 memory_regulator.register(cppinstance)
12861803 return w_cppinstance
12871804
13081825 except Exception:
13091826 # accept integer value as address
13101827 rawobject = rffi.cast(capi.C_OBJECT, space.uint_w(w_obj))
1311 decl = space.interp_w(W_CPPClassDecl, w_clsdecl, can_be_None=False)
1828 decl = space.interp_w(W_CPPClassDecl, w_clsdecl)
13121829 return wrap_cppinstance(space, rawobject, decl, python_owns=owns, do_cast=cast)
13131830
13141831 @unwrap_spec(owns=bool, cast=bool)
13241841
13251842 def move(space, w_obj):
13261843 """Casts the given instance into an C++-style rvalue."""
1327 obj = space.interp_w(W_CPPInstance, w_obj, can_be_None=True)
1844 obj = space.interp_w(W_CPPInstance, w_obj)
13281845 if obj:
1329 obj.flags |= INSTANCE_FLAGS_IS_R_VALUE
1846 obj.rt_flags |= INSTANCE_FLAGS_IS_RVALUE
13301847 return w_obj
1848
1849
1850 # pythonization interface ---------------------------------------------------
1851
1852 # do not auto-cast to given type
1853 @unwrap_spec(w_pycppclass=W_Root)
1854 def _pin_type(space, w_pycppclass):
1855 w_clsdecl = space.findattr(w_pycppclass, space.newtext("__cppdecl__"))
1856 decl = space.interp_w(W_CPPClassDecl, w_clsdecl)
1857 decl.flags |= CLASS_FLAGS_IS_PINNED
0 # Naked C++ pointers carry no useful size or layout information, but often
1 # such information is externnally available. Low level views are arrays with
2 # a few more methods allowing such information to be set. Afterwards, it is
3 # simple to pass these views on to e.g. numpy (w/o the need to copy).
4
5 from pypy.interpreter.error import OperationError, oefmt
6 from pypy.interpreter.gateway import interp2app, unwrap_spec
7 from pypy.interpreter.typedef import TypeDef, GetSetProperty, interp_attrproperty_w
8 from pypy.interpreter.baseobjspace import W_Root
9
10 from rpython.rtyper.lltypesystem import rffi
11 from rpython.rlib.rarithmetic import intmask
12
13 from pypy.module._rawffi.array import W_ArrayInstance
14 from pypy.module._rawffi.interp_rawffi import segfault_exception
15 from pypy.module._cppyy import capi
16
17
18 class W_LowLevelView(W_ArrayInstance):
19 def __init__(self, space, shape, length, address):
20 assert address # if not address, base class will allocate memory
21 W_ArrayInstance.__init__(self, space, shape, length, address)
22
23 @unwrap_spec(args_w='args_w')
24 def reshape(self, space, args_w):
25 # llviews are only created from non-zero addresses, so we only need
26 # to adjust length and shape
27
28 nargs = len(args_w)
29 if nargs == 0:
30 raise oefmt(space.w_TypeError, "reshape expects a tuple argument")
31
32 newshape_w = args_w
33 if nargs != 1 or not space.isinstance_w(args_w[0], space.w_tuple) or \
34 not space.len_w(args_w[0]) == 1:
35 raise oefmt(space.w_TypeError,
36 "tuple object of length 1 expected, received %T", args_w[0])
37
38 w_shape = args_w[0]
39
40 # shape in W_ArrayInstance-speak is somewhat different from what
41 # e.g. numpy thinks of it: self.shape contains the info (itemcode,
42 # size, etc.) of a single entry; length is user-facing shape
43 self.length = space.int_w(space.getitem(w_shape, space.newint(0)))
44
45
46 W_LowLevelView.typedef = TypeDef(
47 'LowLevelView',
48 __repr__ = interp2app(W_LowLevelView.descr_repr),
49 __setitem__ = interp2app(W_LowLevelView.descr_setitem),
50 __getitem__ = interp2app(W_LowLevelView.descr_getitem),
51 __len__ = interp2app(W_LowLevelView.getlength),
52 buffer = GetSetProperty(W_LowLevelView.getbuffer),
53 shape = interp_attrproperty_w('shape', W_LowLevelView),
54 free = interp2app(W_LowLevelView.free),
55 byptr = interp2app(W_LowLevelView.byptr),
56 itemaddress = interp2app(W_LowLevelView.descr_itemaddress),
57 reshape = interp2app(W_LowLevelView.reshape),
58 )
59 W_LowLevelView.typedef.acceptable_as_base_class = False
60
61
62 class W_ArrayOfInstances(W_Root):
63 _attrs_ = ['converter', 'baseaddress', 'clssize', 'length']
64 _immutable_fields_ = ['converter', 'baseaddress', 'clssize']
65
66 def __init__(self, space, clsdecl, address, length, dimensions):
67 from pypy.module._cppyy import converter
68 name = clsdecl.name
69 self.clssize = int(intmask(capi.c_size_of_klass(space, clsdecl)))
70 if dimensions:
71 name = name + '[' + dimensions[0] + ']'
72 for num in dimensions:
73 self.clssize *= int(num)
74 dimensions = ':'.join(dimensions)
75 self.converter = converter.get_converter(space, name, dimensions)
76 self.baseaddress = address
77 self.length = length
78
79 @unwrap_spec(idx=int)
80 def getitem(self, space, idx):
81 if not self.baseaddress:
82 raise segfault_exception(space, "accessing elements of freed array")
83 if idx >= self.length or idx < 0:
84 raise OperationError(space.w_IndexError, space.w_None)
85 itemaddress = rffi.cast(rffi.LONG, self.baseaddress)+idx*self.clssize
86 return self.converter.from_memory(space, space.w_None, itemaddress)
87
88 def getlength(self, space):
89 return space.newint(self.length)
90
91 def setlength(self, space, w_length):
92 self.length = space.int_w(w_length)
93
94 W_ArrayOfInstances.typedef = TypeDef(
95 'ArrayOfInstances',
96 __getitem__ = interp2app(W_ArrayOfInstances.getitem),
97 __len__ = interp2app(W_ArrayOfInstances.getlength),
98 size = GetSetProperty(W_ArrayOfInstances.getlength, W_ArrayOfInstances.setlength),
99 )
100 W_ArrayOfInstances.typedef.acceptable_as_base_class = False
00 # NOT_RPYTHON
1 # do not load _cppyy here, see _init_pythonify()
2 import types
1 # do not load _cppyy here, see _post_import_startup()
32 import sys
43
5
6 # Metaclasses are needed to store C++ static data members as properties. Since
7 # the interp-level does not support metaclasses, they are created at app-level.
8 # These are the metaclass base classes:
9 class CPPScope(type):
4 class _C:
5 def _m(self): pass
6 MethodType = type(_C()._m)
7
8 # Metaclasses are needed to store C++ static data members as properties and to
9 # provide Python language features such as a customized __dir__ for namespaces
10 # and __getattr__ for both. These features are used for lazy lookup/creation.
11 # Since the interp-level does not support metaclasses, this is all done at the
12 # app-level.
13 #
14 # C++ namespaces: are represented as Python classes, with CPPNamespace as the
15 # base class, which is at the moment just a label, and CPPNamespaceMeta as
16 # the base class of their invididualized meta class.
17 #
18 # C++ classes: are represented as Python classes, with CPPClass as the base
19 # class, which is a subclass of the interp-level CPPInstance. The former
20 # sets up the Python-class behavior for bound classes, the latter adds the
21 # bound object behavior that lives at the class level.
22
23 class CPPScopeMeta(type):
1024 def __getattr__(self, name):
1125 try:
1226 return get_scoped_pycppitem(self, name) # will cache on self
1428 raise AttributeError("%s object has no attribute '%s' (details: %s)" %
1529 (self, name, str(e)))
1630
17 class CPPMetaNamespace(CPPScope):
31 class CPPNamespaceMeta(CPPScopeMeta):
1832 def __dir__(self):
19 return self.__cppdecl__.__dir__()
20
21 class CPPClass(CPPScope):
33 # For Py3: can actually call base class __dir__ (lives in type)
34 values = set(self.__dict__.keys())
35 values.update(object.__dict__.keys())
36 values.update(type(self).__dict__.keys())
37
38 # add C++ entities
39 values.update(self.__cppdecl__.__dir__())
40 return list(values)
41
42 class CPPClassMeta(CPPScopeMeta):
2243 pass
2344
24 # namespace base class (class base class defined in _init_pythonify)
25 class CPPNamespace(object):
26 __metatype__ = CPPMetaNamespace
27
28
45 # from six.py ---
46 # Copyright (c) 2010-2017 Benjamin Peterson
47 #
48 # Permission is hereby granted, free of charge, to any person obtaining a copy
49 # of this software and associated documentation files (the "Software"), to deal
50 # in the Software without restriction, including without limitation the rights
51 # to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
52 # copies of the Software, and to permit persons to whom the Software is
53 # furnished to do so, subject to the following conditions:
54 #
55 # The above copyright notice and this permission notice shall be included in all
56 # copies or substantial portions of the Software.
57 #
58 # THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
59 # IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
60 # FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
61 # AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
62 # LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
63 # OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
64 # SOFTWARE.
65
66 def with_metaclass(meta, *bases):
67 """Create a base class with a metaclass."""
68 # This requires a bit of explanation: the basic idea is to make a dummy
69 # metaclass for one level of class instantiation that replaces itself with
70 # the actual metaclass.
71 class metaclass(type):
72
73 def __new__(cls, name, this_bases, d):
74 return meta(name, bases, d)
75
76 @classmethod
77 def __prepare__(cls, name, this_bases):
78 return meta.__prepare__(name, bases)
79 return type.__new__(metaclass, 'temporary_class', (), {})
80 # --- end from six.py
81
82 # C++ namespace base class (the C++ class base class defined in _post_import_startup)
83 class CPPNamespace(with_metaclass(CPPNamespaceMeta, object)):
84 def __init__(self):
85 raise TypeError("cannot instantiate namespace '%s'", self.__cppname__)
86
87
88 # TODO: this can be moved to the interp level (and share template argument
89 # construction with function templates there)
2990 class CPPTemplate(object):
3091 def __init__(self, name, scope=None):
3192 self._name = name
3596 self._scope = scope
3697
3798 def _arg_to_str(self, arg):
38 try:
39 arg = arg.__cppname__
40 except AttributeError:
41 if arg == str:
42 import _cppyy
43 arg = _cppyy._std_string_name()
44 elif type(arg) != str:
45 arg = arg.__name__
46 return arg
99 # arguments are strings representing types, types, or builtins
100 if type(arg) == str:
101 return arg # string describing type
102 elif hasattr(arg, '__cppname__'):
103 return arg.__cppname__ # C++ bound type
104 elif arg == str:
105 import _cppyy
106 return _cppyy._std_string_name() # special case pystr -> C++ string
107 elif isinstance(arg, type): # builtin types
108 return arg.__name__
109 return str(arg) # builtin values
47110
48111 def __call__(self, *args):
49112 fullname = ''.join(
50113 [self._name, '<', ','.join(map(self._arg_to_str, args))])
51 if fullname[-1] == '>':
52 fullname += ' >'
53 else:
54 fullname += '>'
55 return getattr(self._scope, fullname)
114 fullname += '>'
115 try:
116 return self._scope.__dict__[fullname]
117 except KeyError:
118 pass
119 result = get_scoped_pycppitem(self._scope, fullname, True)
120 if not result:
121 raise TypeError("%s does not exist" % fullname)
122 return result
56123
57124 def __getitem__(self, *args):
58125 if args and type(args[0]) == tuple:
111178 return scope.__module__ + '.' + scope.__name__
112179 return 'cppyy'
113180
114 def make_static_function(func_name, cppol):
115 def function(*args):
116 return cppol.call(None, *args)
117 function.__name__ = func_name
118 function.__doc__ = cppol.prototype()
119 return staticmethod(function)
120
121
122181 def make_cppnamespace(scope, name, decl):
123182 # build up a representation of a C++ namespace (namespaces are classes)
124183
125184 # create a metaclass to allow properties (for static data write access)
126185 import _cppyy
127 ns_meta = type(name+'_meta', (CPPMetaNamespace,), {})
186 ns_meta = type(CPPNamespace)(name+'_meta', (CPPNamespaceMeta,), {})
128187
129188 # create the python-side C++ namespace representation, cache in scope if given
130189 d = {"__cppdecl__" : decl,
146205 bases.remove(b1) # removes lateral class
147206 break
148207 return tuple(bases)
149
150208
151209 def make_new(decl):
152210 def __new__(cls, *args):
160218 return instance
161219 return __new__
162220
163 def make_method(meth_name, cppol):
164 def method(self, *args):
165 return cppol.call(self, *args)
166 method.__name__ = meth_name
167 method.__doc__ = cppol.prototype()
168 return method
169
170221 def make_cppclass(scope, cl_name, decl):
222 import _cppyy
171223
172224 # get a list of base classes for class creation
173225 bases = [get_pycppclass(base) for base in decl.get_base_names()]
174226 if not bases:
175 bases = [CPPInstance,]
227 bases = [CPPClass,]
176228 else:
177229 # it's possible that the required class now has been built if one of
178230 # the base classes uses it in e.g. a function interface
187239 # prepare dictionary for python-side C++ class representation
188240 def dispatch(self, m_name, signature):
189241 cppol = decl.__dispatch__(m_name, signature)
190 return types.MethodType(make_method(m_name, cppol), self, type(self))
242 return MethodType(cppol, self, type(self))
191243 d_class = {"__cppdecl__" : decl,
192244 "__new__" : make_new(decl),
193245 "__module__" : make_module_name(scope),
198250 # insert (static) methods into the class dictionary
199251 for m_name in decl.get_method_names():
200252 cppol = decl.get_overload(m_name)
201 if cppol.is_static():
202 d_class[m_name] = make_static_function(m_name, cppol)
203 else:
204 d_class[m_name] = make_method(m_name, cppol)
253 d_class[m_name] = cppol
205254
206255 # add all data members to the dictionary of the class to be created, and
207256 # static ones also to the metaclass (needed for property setters)
208257 for d_name in decl.get_datamember_names():
209258 cppdm = decl.get_datamember(d_name)
210259 d_class[d_name] = cppdm
211 if cppdm.is_static():
260 if _cppyy._is_static_data(cppdm):
212261 d_meta[d_name] = cppdm
213262
214263 # create a metaclass to allow properties (for static data write access)
215264 metabases = [type(base) for base in bases]
216 metacpp = type(CPPScope)(cl_name+'_meta', _drop_cycles(metabases), d_meta)
265 cl_meta = type(CPPClassMeta)(cl_name+'_meta', _drop_cycles(metabases), d_meta)
217266
218267 # create the python-side C++ class
219 pycls = metacpp(cl_name, _drop_cycles(bases), d_class)
268 pycls = cl_meta(cl_name, _drop_cycles(bases), d_class)
220269
221270 # store the class on its outer scope
222271 setattr(scope, cl_name, pycls)
225274 # needs to run first, so that the generic pythonizations can use them
226275 import _cppyy
227276 _cppyy._register_class(pycls)
228 _pythonize(pycls)
277 _pythonize(pycls, pycls.__cppname__)
229278 return pycls
230279
231280 def make_cpptemplatetype(scope, template_name):
232281 return CPPTemplate(template_name, scope)
233282
234283
235 def get_scoped_pycppitem(scope, name):
284 def get_scoped_pycppitem(scope, name, type_only=False):
236285 import _cppyy
237286
238287 # resolve typedefs/aliases: these may cross namespaces, in which case
255304 else:
256305 pycppitem = make_cppclass(scope, name, cppitem)
257306
307 if type_only:
308 return pycppitem
309
258310 # templates
259311 if not cppitem:
260312 cppitem = _cppyy._is_template(final_scoped_name)
266318 if not cppitem:
267319 try:
268320 cppitem = scope.__cppdecl__.get_overload(name)
269 pycppitem = make_static_function(name, cppitem)
270 setattr(scope.__class__, name, pycppitem)
321 setattr(scope, name, cppitem)
271322 pycppitem = getattr(scope, name) # binds function as needed
272323 except AttributeError:
273324 pass
277328 try:
278329 cppdm = scope.__cppdecl__.get_datamember(name)
279330 setattr(scope, name, cppdm)
280 if cppdm.is_static():
331 if _cppyy._is_static_data(cppdm):
281332 setattr(scope.__class__, name, cppdm)
282333 pycppitem = getattr(scope, name) # gets actual property value
283334 except AttributeError:
284335 pass
285336
337 # enum type
338 if not cppitem:
339 if scope.__cppdecl__.has_enum(name):
340 pycppitem = int
341
286342 if pycppitem is not None: # pycppitem could be a bound C++ NULL, so check explicitly for Py_None
287343 return pycppitem
288344
289345 raise AttributeError("'%s' has no attribute '%s'" % (str(scope), name))
290346
291347
348 # helper for pythonization API
349 def extract_namespace(name):
350 # find the namespace the named class lives in, take care of templates
351 tpl_open = 0
352 for pos in range(len(name)-1, 1, -1):
353 c = name[pos]
354
355 # count '<' and '>' to be able to skip template contents
356 if c == '>':
357 tpl_open += 1
358 elif c == '<':
359 tpl_open -= 1
360
361 # collect name up to "::"
362 elif tpl_open == 0 and c == ':' and name[pos-1] == ':':
363 # found the extend of the scope ... done
364 return name[:pos-1], name[pos+1:]
365
366 # no namespace; assume outer scope
367 return '', name
368
292369 # pythonization by decoration (move to their own file?)
293 def python_style_getitem(self, idx):
370 def python_style_getitem(self, _idx):
294371 # python-style indexing: check for size and allow indexing from the back
295 try:
296 sz = len(self)
372 sz = len(self)
373 idx = _idx
374 if isinstance(idx, int):
297375 if idx < 0: idx = sz + idx
298 if idx < sz:
376 if 0 <= idx < sz:
299377 return self._getitem__unchecked(idx)
300 raise IndexError(
301 'index out of range: %d requested for %s of size %d' % (idx, str(self), sz))
302 except TypeError:
303 pass
304 return self._getitem__unchecked(idx)
378 else:
379 raise IndexError(
380 'index out of range: %s requested for %s of size %d' % (str(idx), str(self), sz))
381 # may fail for the same reasons as above, but will now give proper error message
382 return self._getitem__unchecked(_idx)
305383
306384 def python_style_sliceable_getitem(self, slice_or_idx):
307385 if type(slice_or_idx) == slice:
309387 nseq += [python_style_getitem(self, i) \
310388 for i in range(*slice_or_idx.indices(len(self)))]
311389 return nseq
312 else:
313 return python_style_getitem(self, slice_or_idx)
314
315
316 _pythonizations = {}
317 def _pythonize(pyclass):
318
319 try:
320 _pythonizations[pyclass.__name__](pyclass)
321 except KeyError:
322 pass
323
390 return python_style_getitem(self, slice_or_idx)
391
392 def _pythonize(pyclass, name):
324393 # general note: use 'in pyclass.__dict__' rather than 'hasattr' to prevent
325394 # adding pythonizations multiple times in derived classes
326395
353422
354423 # map push_back -> __iadd__ (generally true for STL)
355424 if 'push_back' in pyclass.__dict__ and not '__iadd__' in pyclass.__dict__:
356 def __iadd__(self, ll):
357 [self.push_back(x) for x in ll]
358 return self
359 pyclass.__iadd__ = __iadd__
425 if 'reserve' in pyclass.__dict__:
426 def iadd(self, ll):
427 self.reserve(len(ll))
428 for x in ll: self.push_back(x)
429 return self
430 else:
431 def iadd(self, ll):
432 for x in ll: self.push_back(x)
433 return self
434 pyclass.__iadd__ = iadd
360435
361436 # map begin()/end() protocol to iter protocol on STL(-like) classes, but
362437 # not on vector, which is pythonized in the capi (interp-level; there is
363438 # also the fallback on the indexed __getitem__, but that is slower)
364 if not 'vector' in pyclass.__name__[:11] and \
365 ('begin' in pyclass.__dict__ and 'end' in pyclass.__dict__):
366 if _cppyy._scope_byname(pyclass.__cppname__+'::iterator') or \
367 _cppyy._scope_byname(pyclass.__cppname__+'::const_iterator'):
368 def __iter__(self):
369 i = self.begin()
370 while i != self.end():
371 yield i.__deref__()
372 i.__preinc__()
373 i.__destruct__()
374 raise StopIteration
375 pyclass.__iter__ = __iter__
376 # else: rely on numbered iteration
377
378 # combine __getitem__ and __len__ to make a pythonized __getitem__
379 if '__getitem__' in pyclass.__dict__ and '__len__' in pyclass.__dict__:
380 pyclass._getitem__unchecked = pyclass.__getitem__
381 if '__setitem__' in pyclass.__dict__ and '__iadd__' in pyclass.__dict__:
382 pyclass.__getitem__ = python_style_sliceable_getitem
383 else:
384 pyclass.__getitem__ = python_style_getitem
439 add_checked_item = False
440 if name.find('std::vector', 0, 11) != 0:
441 if ('begin' in pyclass.__dict__ and 'end' in pyclass.__dict__):
442 if _cppyy._scope_byname(name+'::iterator') or \
443 _cppyy._scope_byname(name+'::const_iterator'):
444 def __iter__(self):
445 i = self.begin()
446 while i != self.end():
447 yield i.__deref__()
448 i.__preinc__()
449 i.__destruct__()
450 raise StopIteration
451 pyclass.__iter__ = __iter__
452 else:
453 # rely on numbered iteration
454 add_checked_item = True
455
456 # add python collection based initializer
457 if name.find('std::vector', 0, 11) == 0:
458 pyclass.__real_init__ = pyclass.__init__
459 def vector_init(self, *args):
460 if len(args) == 1 and isinstance(args[0], (tuple, list)):
461 ll = args[0]
462 self.__real_init__()
463 self.reserve(len(ll))
464 for item in ll:
465 self.push_back(item)
466 return
467 return self.__real_init__(*args)
468 pyclass.__init__ = vector_init
469
470 # size-up the return of data()
471 if hasattr(pyclass, 'data'): # not the case for e.g. vector<bool>
472 pyclass.__real_data = pyclass.data
473 def data_with_len(self):
474 arr = self.__real_data()
475 arr.reshape((len(self),))
476 return arr
477 pyclass.data = data_with_len
478
479 # TODO: must be a simpler way to check (or at least hook these to a namespace
480 # std specific pythonizor)
481 if add_checked_item or name.find('std::vector', 0, 11) == 0 or \
482 name.find('std::array', 0, 11) == 0 or name.find('std::deque', 0, 10) == 0:
483 # combine __getitem__ and __len__ to make a pythonized __getitem__
484 if '__getitem__' in pyclass.__dict__ and '__len__' in pyclass.__dict__:
485 pyclass._getitem__unchecked = pyclass.__getitem__
486 if '__setitem__' in pyclass.__dict__ and '__iadd__' in pyclass.__dict__:
487 pyclass.__getitem__ = python_style_sliceable_getitem
488 else:
489 pyclass.__getitem__ = python_style_getitem
385490
386491 # string comparisons
387 if pyclass.__name__ == _cppyy._std_string_name():
492 if name == _cppyy._std_string_name():
388493 def eq(self, other):
389494 if type(other) == pyclass:
390495 return self.c_str() == other.c_str()
394499 pyclass.__str__ = pyclass.c_str
395500
396501 # std::pair unpacking through iteration
397 if 'std::pair' == pyclass.__name__[:9] or 'pair' == pyclass.__name__[:4]:
502 if 'std::pair' == name[:9]:
398503 def getitem(self, idx):
399504 if idx == 0: return self.first
400505 if idx == 1: return self.second
404509 pyclass.__getitem__ = getitem
405510 pyclass.__len__ = return2
406511
407
408 def _init_pythonify():
512 # user provided, custom pythonizations
513 try:
514 ns_name, cl_name = extract_namespace(name)
515 pythonizors = _pythonizations[ns_name]
516 name = cl_name
517 except KeyError:
518 pythonizors = _pythonizations[''] # global scope
519
520 for p in pythonizors:
521 p(pyclass, name)
522
523 cppyyIsInitialized = False
524 def _post_import_startup():
525 # run only once (function is explicitly called in testing)
526 global cppyyIsInitialized
527 if cppyyIsInitialized:
528 return
529
409530 # _cppyy should not be loaded at the module level, as that will trigger a
410531 # call to space.getbuiltinmodule(), which will cause _cppyy to be loaded
411532 # at pypy-c startup, rather than on the "import _cppyy" statement
412533 import _cppyy
413534
414 # root of all proxy classes: CPPInstance in pythonify exists to combine
415 # the CPPScope metaclass with the interp-level CPPInstanceBase
416 global CPPInstance
417 class CPPInstance(_cppyy.CPPInstanceBase):
418 __metaclass__ = CPPScope
535 # root of all proxy classes: CPPClass in pythonify exists to combine the
536 # CPPClassMeta metaclass (for Python-side class behavior) with the
537 # interp-level CPPInstance (for bound object behavior)
538 global CPPClass
539 class CPPClass(with_metaclass(CPPClassMeta, _cppyy.CPPInstance)):
419540 pass
420541
421542 # class generator callback
446567 # install nullptr as a unique reference
447568 _cppyy.nullptr = _cppyy._get_nullptr()
448569
570 # done
571 cppyyIsInitialized = True
572
449573
450574 # user-defined pythonizations interface
451 _pythonizations = {}
452 def add_pythonization(class_name, callback):
453 """Takes a class name and a callback. The callback should take a single
454 argument, the class proxy, and is called the first time the named class
455 is bound."""
456 if not callable(callback):
457 raise TypeError("given '%s' object is not callable" % str(callback))
458 _pythonizations[class_name] = callback
575 _pythonizations = {'' : list()}
576 def add_pythonization(pythonizor, scope = ''):
577 """<pythonizor> should be a callable taking two arguments: a class proxy,
578 and its C++ name. It is called on each time a named class from <scope>
579 (the global one by default, but a relevant C++ namespace is recommended)
580 is bound.
581 """
582 if not callable(pythonizor):
583 raise TypeError("given '%s' object is not callable" % str(pythonizor))
584 try:
585 _pythonizations[scope].append(pythonizor)
586 except KeyError:
587 _pythonizations[scope] = list()
588 _pythonizations[scope].append(pythonizor)
589
590 def remove_pythonization(pythonizor, scope = ''):
591 """Remove previously registered <pythonizor> from <scope>.
592 """
593 try:
594 _pythonizations[scope].remove(pythonizor)
595 return True
596 except (KeyError, ValueError):
597 return False
5959 const std::string& returntype,
6060 EMethodType mtype = kNormal) :
6161 m_name(name), m_argtypes(argtypes), m_returntype(returntype), m_type(mtype) {}
62
6362 std::string m_name;
6463 std::vector<std::string> m_argtypes;
64 std::vector<std::string> m_argdefaults;
6565 std::string m_returntype;
6666 EMethodType m_type;
6767 };
7171 const std::string& type,
7272 ptrdiff_t offset, bool isstatic) :
7373 m_name(name), m_type(type), m_offset(offset), m_isstatic(isstatic) {}
74
7574 std::string m_name;
7675 std::string m_type;
7776 ptrdiff_t m_offset;
8079
8180 struct Cppyy_PseudoClassInfo {
8281 Cppyy_PseudoClassInfo() {}
83 Cppyy_PseudoClassInfo(const std::vector<Cppyy_PseudoMethodInfo>& methods,
84 long method_offset,
82 Cppyy_PseudoClassInfo(const std::vector<Cppyy_PseudoMethodInfo*>& methods,
8583 const std::vector<Cppyy_PseudoDatambrInfo>& data) :
86 m_methods(methods), m_method_offset(method_offset), m_datambrs(data) {}
87
88 std::vector<Cppyy_PseudoMethodInfo> m_methods;
89 long m_method_offset;
84 m_methods(methods), m_datambrs(data) {}
85 std::vector<Cppyy_PseudoMethodInfo*> m_methods;
9086 std::vector<Cppyy_PseudoDatambrInfo> m_datambrs;
9187 };
9288
9389 typedef std::map<cppyy_scope_t, Cppyy_PseudoClassInfo> Scopes_t;
9490 static Scopes_t s_scopes;
9591
96 static std::map<std::string, long> s_methods;
92 static std::map<std::string, Cppyy_PseudoMethodInfo*> s_methods;
93 struct CleanPseudoMethods {
94 ~CleanPseudoMethods() { for (auto& x : s_methods) delete x.second; }
95 } _clean;
9796
9897 int Pseudo_kNothing = 6;
9998 int Pseudo_kSomething = 111;
104103 offsetof(dummy::CppyyTestData, m_##dmname), false)); \
105104 /* <type> get_<type>() */ \
106105 argtypes.clear(); \
107 methods.push_back(Cppyy_PseudoMethodInfo( \
106 methods.push_back(new Cppyy_PseudoMethodInfo( \
108107 "get_"#dmname, argtypes, #dmtype)); \
109 s_methods["CppyyTestData::get_"#dmname] = s_method_id++; \
108 s_methods["CppyyTestData::get_"#dmname] = methods.back(); \
110109 /* <type>& get_<type>_r() */ \
111 methods.push_back(Cppyy_PseudoMethodInfo( \
110 methods.push_back(new Cppyy_PseudoMethodInfo( \
112111 "get_"#dmname"_r", argtypes, #dmtype"&")); \
113 s_methods["CppyyTestData::get_"#dmname"_r"] = s_method_id++; \
112 s_methods["CppyyTestData::get_"#dmname"_r"] = methods.back(); \
114113 /* const <type>& get_<type>_cr() */ \
115 methods.push_back(Cppyy_PseudoMethodInfo( \
114 methods.push_back(new Cppyy_PseudoMethodInfo( \
116115 "get_"#dmname"_cr", argtypes, "const "#dmtype"&")); \
117 s_methods["CppyyTestData::get_"#dmname"_cr"] = s_method_id++; \
116 s_methods["CppyyTestData::get_"#dmname"_cr"] = methods.back(); \
118117 /* void set_<type>(<type>) */ \
119118 argtypes.push_back(#dmtype); \
120 methods.push_back(Cppyy_PseudoMethodInfo( \
119 methods.push_back(new Cppyy_PseudoMethodInfo( \
121120 "set_"#dmname, argtypes, "void")); \
122 s_methods["CppyyTestData::set_"#dmname] = s_method_id++; \
121 s_methods["CppyyTestData::set_"#dmname] = methods.back(); \
123122 argtypes.clear(); \
124123 /* void set_<type>(const <type>&) */ \
125124 argtypes.push_back("const "#dmtype"&"); \
126 methods.push_back(Cppyy_PseudoMethodInfo( \
125 methods.push_back(new Cppyy_PseudoMethodInfo( \
127126 "set_"#dmname"_cr", argtypes, "void")); \
128 s_methods["CppyyTestData::set_"#dmname"_cr"] = s_method_id++
127 s_methods["CppyyTestData::set_"#dmname"_cr"] = methods.back()
129128
130129 #define PUBLIC_CPPYY_DATA2(dmname, dmtype) \
131130 PUBLIC_CPPYY_DATA(dmname, dmtype); \
134133 data.push_back(Cppyy_PseudoDatambrInfo("m_"#dmname"_array2", #dmtype"*", \
135134 offsetof(dummy::CppyyTestData, m_##dmname##_array2), false)); \
136135 argtypes.clear(); \
137 methods.push_back(Cppyy_PseudoMethodInfo( \
136 methods.push_back(new Cppyy_PseudoMethodInfo( \
138137 "get_"#dmname"_array", argtypes, #dmtype"*")); \
139 s_methods["CppyyTestData::get_"#dmname"_array"] = s_method_id++; \
140 methods.push_back(Cppyy_PseudoMethodInfo( \
138 s_methods["CppyyTestData::get_"#dmname"_array"] = methods.back(); \
139 methods.push_back(new Cppyy_PseudoMethodInfo( \
141140 "get_"#dmname"_array2", argtypes, #dmtype"*")); \
142 s_methods["CppyyTestData::get_"#dmname"_array2"] = s_method_id++
141 s_methods["CppyyTestData::get_"#dmname"_array2"] = methods.back()
143142
144143 #define PUBLIC_CPPYY_DATA3(dmname, dmtype, key) \
145144 PUBLIC_CPPYY_DATA2(dmname, dmtype); \
146145 argtypes.push_back(#dmtype"*"); \
147 methods.push_back(Cppyy_PseudoMethodInfo( \
146 methods.push_back(new Cppyy_PseudoMethodInfo( \
148147 "pass_array", argtypes, #dmtype"*")); \
149 s_methods["CppyyTestData::pass_array_"#dmname] = s_method_id++; \
148 s_methods["CppyyTestData::pass_array_"#dmname] = methods.back(); \
150149 argtypes.clear(); argtypes.push_back("void*"); \
151 methods.push_back(Cppyy_PseudoMethodInfo( \
150 methods.push_back(new Cppyy_PseudoMethodInfo( \
152151 "pass_void_array_"#key, argtypes, #dmtype"*")); \
153 s_methods["CppyyTestData::pass_void_array_"#key] = s_method_id++
152 s_methods["CppyyTestData::pass_void_array_"#key] = methods.back()
154153
155154 #define PUBLIC_CPPYY_STATIC_DATA(dmname, dmtype) \
156155 data.push_back(Cppyy_PseudoDatambrInfo("s_"#dmname, #dmtype, \
161160 Cppyy_InitPseudoReflectionInfo() {
162161 // class example01 --
163162 static long s_scope_id = 0;
164 static long s_method_id = 0;
165163
166164 { // namespace ''
167165 s_handles[""] = (cppyy_scope_t)++s_scope_id;
174172 { // class example01 --
175173 s_handles["example01"] = (cppyy_scope_t)++s_scope_id;
176174
177 std::vector<Cppyy_PseudoMethodInfo> methods;
175 std::vector<Cppyy_PseudoMethodInfo*> methods;
178176
179177 // static double staticAddToDouble(double a)
180178 std::vector<std::string> argtypes;
181179 argtypes.push_back("double");
182 methods.push_back(Cppyy_PseudoMethodInfo("staticAddToDouble", argtypes, "double", kStatic));
183 s_methods["static_example01::staticAddToDouble_double"] = s_method_id++;
180 methods.push_back(new Cppyy_PseudoMethodInfo("staticAddToDouble", argtypes, "double", kStatic));
181 s_methods["static_example01::staticAddToDouble_double"] = methods.back();
184182
185183 // static int staticAddOneToInt(int a)
186184 // static int staticAddOneToInt(int a, int b)
187185 argtypes.clear();
188186 argtypes.push_back("int");
189 methods.push_back(Cppyy_PseudoMethodInfo("staticAddOneToInt", argtypes, "int", kStatic));
190 s_methods["static_example01::staticAddOneToInt_int"] = s_method_id++;
187 methods.push_back(new Cppyy_PseudoMethodInfo("staticAddOneToInt", argtypes, "int", kStatic));
188 s_methods["static_example01::staticAddOneToInt_int"] = methods.back();
191189 argtypes.push_back("int");
192 methods.push_back(Cppyy_PseudoMethodInfo("staticAddOneToInt", argtypes, "int", kStatic));
193 s_methods["static_example01::staticAddOneToInt_int_int"] = s_method_id++;
190 methods.push_back(new Cppyy_PseudoMethodInfo("staticAddOneToInt", argtypes, "int", kStatic));
191 s_methods["static_example01::staticAddOneToInt_int_int"] = methods.back();
194192
195193 // static int staticAtoi(const char* str)
196194 argtypes.clear();
197195 argtypes.push_back("const char*");
198 methods.push_back(Cppyy_PseudoMethodInfo("staticAtoi", argtypes, "int", kStatic));
199 s_methods["static_example01::staticAtoi_cchar*"] = s_method_id++;
196 methods.push_back(new Cppyy_PseudoMethodInfo("staticAtoi", argtypes, "int", kStatic));
197 s_methods["static_example01::staticAtoi_cchar*"] = methods.back();
200198
201199 // static char* staticStrcpy(const char* strin)
202 methods.push_back(Cppyy_PseudoMethodInfo("staticStrcpy", argtypes, "char*", kStatic));
203 s_methods["static_example01::staticStrcpy_cchar*"] = s_method_id++;
200 methods.push_back(new Cppyy_PseudoMethodInfo("staticStrcpy", argtypes, "char*", kStatic));
201 s_methods["static_example01::staticStrcpy_cchar*"] = methods.back();
204202
205203 // static void staticSetPayload(payload* p, double d)
206204 // static payload* staticCyclePayload(payload* p, double d)
208206 argtypes.clear();
209207 argtypes.push_back("payload*");
210208 argtypes.push_back("double");
211 methods.push_back(Cppyy_PseudoMethodInfo("staticSetPayload", argtypes, "void", kStatic));
212 s_methods["static_example01::staticSetPayload_payload*_double"] = s_method_id++;
213 methods.push_back(Cppyy_PseudoMethodInfo("staticCyclePayload", argtypes, "payload*", kStatic));
214 s_methods["static_example01::staticCyclePayload_payload*_double"] = s_method_id++;
215 methods.push_back(Cppyy_PseudoMethodInfo("staticCopyCyclePayload", argtypes, "payload", kStatic));
216 s_methods["static_example01::staticCopyCyclePayload_payload*_double"] = s_method_id++;
209 methods.push_back(new Cppyy_PseudoMethodInfo("staticSetPayload", argtypes, "void", kStatic));
210 s_methods["static_example01::staticSetPayload_payload*_double"] = methods.back();
211 methods.push_back(new Cppyy_PseudoMethodInfo("staticCyclePayload", argtypes, "payload*", kStatic));
212 s_methods["static_example01::staticCyclePayload_payload*_double"] = methods.back();
213 methods.push_back(new Cppyy_PseudoMethodInfo("staticCopyCyclePayload", argtypes, "payload", kStatic));
214 s_methods["static_example01::staticCopyCyclePayload_payload*_double"] = methods.back();
217215
218216 // static int getCount()
219217 // static void setCount(int)
220218 argtypes.clear();
221 methods.push_back(Cppyy_PseudoMethodInfo("getCount", argtypes, "int", kStatic));
222 s_methods["static_example01::getCount"] = s_method_id++;
219 methods.push_back(new Cppyy_PseudoMethodInfo("getCount", argtypes, "int", kStatic));
220 s_methods["static_example01::getCount"] = methods.back();
223221 argtypes.push_back("int");
224 methods.push_back(Cppyy_PseudoMethodInfo("setCount", argtypes, "void", kStatic));
225 s_methods["static_example01::setCount_int"] = s_method_id++;
222 methods.push_back(new Cppyy_PseudoMethodInfo("setCount", argtypes, "void", kStatic));
223 s_methods["static_example01::setCount_int"] = methods.back();
226224
227225 // example01()
228226 // example01(int a)
229227 argtypes.clear();
230 methods.push_back(Cppyy_PseudoMethodInfo("example01", argtypes, "constructor", kConstructor));
231 s_methods["example01::example01"] = s_method_id++;
228 methods.push_back(new Cppyy_PseudoMethodInfo("example01", argtypes, "constructor", kConstructor));
229 s_methods["example01::example01"] = methods.back();
232230 argtypes.push_back("int");
233 methods.push_back(Cppyy_PseudoMethodInfo("example01", argtypes, "constructor", kConstructor));
234 s_methods["example01::example01_int"] = s_method_id++;
231 methods.push_back(new Cppyy_PseudoMethodInfo("example01", argtypes, "constructor", kConstructor));
232 s_methods["example01::example01_int"] = methods.back();
235233
236234 // int addDataToInt(int a)
237235 argtypes.clear();
238236 argtypes.push_back("int");
239 methods.push_back(Cppyy_PseudoMethodInfo("addDataToInt", argtypes, "int"));
240 s_methods["example01::addDataToInt_int"] = s_method_id++;
237 methods.push_back(new Cppyy_PseudoMethodInfo("addDataToInt", argtypes, "int"));
238 s_methods["example01::addDataToInt_int"] = methods.back();
241239
242240 // int addDataToIntConstRef(const int& a)
243241 argtypes.clear();
244242 argtypes.push_back("const int&");
245 methods.push_back(Cppyy_PseudoMethodInfo("addDataToIntConstRef", argtypes, "int"));
246 s_methods["example01::addDataToIntConstRef_cint&"] = s_method_id++;
243 methods.push_back(new Cppyy_PseudoMethodInfo("addDataToIntConstRef", argtypes, "int"));
244 s_methods["example01::addDataToIntConstRef_cint&"] = methods.back();
247245
248246 // int overloadedAddDataToInt(int a, int b)
249247 argtypes.clear();
250248 argtypes.push_back("int");
251249 argtypes.push_back("int");
252 methods.push_back(Cppyy_PseudoMethodInfo("overloadedAddDataToInt", argtypes, "int"));
253 s_methods["example01::overloadedAddDataToInt_int_int"] = s_method_id++;
250 methods.push_back(new Cppyy_PseudoMethodInfo("overloadedAddDataToInt", argtypes, "int"));
251 s_methods["example01::overloadedAddDataToInt_int_int"] = methods.back();
254252
255253 // int overloadedAddDataToInt(int a)
256254 // int overloadedAddDataToInt(int a, int b, int c)
257255 argtypes.clear();
258256 argtypes.push_back("int");
259 methods.push_back(Cppyy_PseudoMethodInfo("overloadedAddDataToInt", argtypes, "int"));
260 s_methods["example01::overloadedAddDataToInt_int"] = s_method_id++;
257 methods.push_back(new Cppyy_PseudoMethodInfo("overloadedAddDataToInt", argtypes, "int"));
258 s_methods["example01::overloadedAddDataToInt_int"] = methods.back();
261259 argtypes.push_back("int");
262260 argtypes.push_back("int");
263 methods.push_back(Cppyy_PseudoMethodInfo("overloadedAddDataToInt", argtypes, "int"));
264 s_methods["example01::overloadedAddDataToInt_int_int_int"] = s_method_id++;
261 methods.push_back(new Cppyy_PseudoMethodInfo("overloadedAddDataToInt", argtypes, "int"));
262 s_methods["example01::overloadedAddDataToInt_int_int_int"] = methods.back();
265263
266264 // double addDataToDouble(double a)
267265 argtypes.clear();
268266 argtypes.push_back("double");
269 methods.push_back(Cppyy_PseudoMethodInfo("addDataToDouble", argtypes, "double"));
270 s_methods["example01::addDataToDouble_double"] = s_method_id++;
267 methods.push_back(new Cppyy_PseudoMethodInfo("addDataToDouble", argtypes, "double"));
268 s_methods["example01::addDataToDouble_double"] = methods.back();
271269
272270 // int addDataToAtoi(const char* str)
273271 // char* addToStringValue(const char* str)
274272 argtypes.clear();
275273 argtypes.push_back("const char*");
276 methods.push_back(Cppyy_PseudoMethodInfo("addDataToAtoi", argtypes, "int"));
277 s_methods["example01::addDataToAtoi_cchar*"] = s_method_id++;
278 methods.push_back(Cppyy_PseudoMethodInfo("addToStringValue", argtypes, "char*"));
279 s_methods["example01::addToStringValue_cchar*"] = s_method_id++;
274 methods.push_back(new Cppyy_PseudoMethodInfo("addDataToAtoi", argtypes, "int"));
275 s_methods["example01::addDataToAtoi_cchar*"] = methods.back();
276 methods.push_back(new Cppyy_PseudoMethodInfo("addToStringValue", argtypes, "char*"));
277 s_methods["example01::addToStringValue_cchar*"] = methods.back();
280278
281279 // void setPayload(payload* p)
282280 // payload* cyclePayload(payload* p)
283281 // payload copyCyclePayload(payload* p)
284282 argtypes.clear();
285283 argtypes.push_back("payload*");
286 methods.push_back(Cppyy_PseudoMethodInfo("setPayload", argtypes, "void"));
287 s_methods["example01::setPayload_payload*"] = s_method_id++;
288 methods.push_back(Cppyy_PseudoMethodInfo("cyclePayload", argtypes, "payload*"));
289 s_methods["example01::cyclePayload_payload*"] = s_method_id++;
290 methods.push_back(Cppyy_PseudoMethodInfo("copyCyclePayload", argtypes, "payload"));
291 s_methods["example01::copyCyclePayload_payload*"] = s_method_id++;
292
293 Cppyy_PseudoClassInfo info(
294 methods, s_method_id - methods.size(), std::vector<Cppyy_PseudoDatambrInfo>());
284 methods.push_back(new Cppyy_PseudoMethodInfo("setPayload", argtypes, "void"));
285 s_methods["example01::setPayload_payload*"] = methods.back();
286 methods.push_back(new Cppyy_PseudoMethodInfo("cyclePayload", argtypes, "payload*"));
287 s_methods["example01::cyclePayload_payload*"] = methods.back();
288 methods.push_back(new Cppyy_PseudoMethodInfo("copyCyclePayload", argtypes, "payload"));
289 s_methods["example01::copyCyclePayload_payload*"] = methods.back();
290
291 Cppyy_PseudoClassInfo info(methods, std::vector<Cppyy_PseudoDatambrInfo>());
295292 s_scopes[(cppyy_scope_t)s_scope_id] = info;
296293 } // -- class example01
297294
300297 { // class payload --
301298 s_handles["payload"] = (cppyy_scope_t)++s_scope_id;
302299
303 std::vector<Cppyy_PseudoMethodInfo> methods;
300 std::vector<Cppyy_PseudoMethodInfo*> methods;
304301
305302 // payload(double d = 0.)
306303 std::vector<std::string> argtypes;
307304 argtypes.push_back("double");
308 methods.push_back(Cppyy_PseudoMethodInfo("payload", argtypes, "constructor", kConstructor));
309 s_methods["payload::payload_double"] = s_method_id++;
305 methods.push_back(new Cppyy_PseudoMethodInfo("payload", argtypes, "constructor", kConstructor));
306 s_methods["payload::payload_double"] = methods.back();
310307
311308 // double getData()
312309 argtypes.clear();
313 methods.push_back(Cppyy_PseudoMethodInfo("getData", argtypes, "double"));
314 s_methods["payload::getData"] = s_method_id++;
310 methods.push_back(new Cppyy_PseudoMethodInfo("getData", argtypes, "double"));
311 s_methods["payload::getData"] = methods.back();
315312
316313 // void setData(double d)
317314 argtypes.clear();
318315 argtypes.push_back("double");
319 methods.push_back(Cppyy_PseudoMethodInfo("setData", argtypes, "void"));
320 s_methods["payload::setData_double"] = s_method_id++;
321
322 Cppyy_PseudoClassInfo info(
323 methods, s_method_id - methods.size(), std::vector<Cppyy_PseudoDatambrInfo>());
316 methods.push_back(new Cppyy_PseudoMethodInfo("setData", argtypes, "void"));
317 s_methods["payload::setData_double"] = methods.back();
318
319 Cppyy_PseudoClassInfo info(methods, std::vector<Cppyy_PseudoDatambrInfo>());
324320 s_scopes[(cppyy_scope_t)s_scope_id] = info;
325321 } // -- class payload
326322
329325 { // class CppyyTestData --
330326 s_handles["CppyyTestData"] = (cppyy_scope_t)++s_scope_id;
331327
332 std::vector<Cppyy_PseudoMethodInfo> methods;
328 std::vector<Cppyy_PseudoMethodInfo*> methods;
333329
334330 // CppyyTestData()
335331 std::vector<std::string> argtypes;
336 methods.push_back(Cppyy_PseudoMethodInfo("CppyyTestData", argtypes, "constructor", kConstructor));
337 s_methods["CppyyTestData::CppyyTestData"] = s_method_id++;
338
339 methods.push_back(Cppyy_PseudoMethodInfo("destroy_arrays", argtypes, "void"));
340 s_methods["CppyyTestData::destroy_arrays"] = s_method_id++;
332 methods.push_back(new Cppyy_PseudoMethodInfo("CppyyTestData", argtypes, "constructor", kConstructor));
333 s_methods["CppyyTestData::CppyyTestData"] = methods.back();
334
335 methods.push_back(new Cppyy_PseudoMethodInfo("destroy_arrays", argtypes, "void"));
336 s_methods["CppyyTestData::destroy_arrays"] = methods.back();
341337
342338 std::vector<Cppyy_PseudoDatambrInfo> data;
343339 PUBLIC_CPPYY_DATA2(bool, bool);
344340 PUBLIC_CPPYY_DATA (char, char);
345341 PUBLIC_CPPYY_DATA (schar, signed char);
346 PUBLIC_CPPYY_DATA (uchar, unsigned char);
342 PUBLIC_CPPYY_DATA2(uchar, unsigned char);
347343 PUBLIC_CPPYY_DATA3(short, short, h);
348344 PUBLIC_CPPYY_DATA3(ushort, unsigned short, H);
349345 PUBLIC_CPPYY_DATA3(int, int, i);
346 PUBLIC_CPPYY_DATA (const_int, const int);
350347 PUBLIC_CPPYY_DATA3(uint, unsigned int, I);
351348 PUBLIC_CPPYY_DATA3(long, long, l);
352349 PUBLIC_CPPYY_DATA3(ulong, unsigned long, L);
379376 PUBLIC_CPPYY_STATIC_DATA(enum, CppyyTestData::EWhat);
380377 PUBLIC_CPPYY_STATIC_DATA(voidp, void*);
381378
379 // default tester for long double
380 argtypes.clear();
381 argtypes.push_back("long double");
382 methods.push_back(new Cppyy_PseudoMethodInfo("get_ldouble_def", argtypes, "long double"));
383 methods.back()->m_argdefaults.push_back("aap_t(1)");
384 s_methods["CppyyTestData::get_ldouble_def"] = methods.back();
385
382386 // pretend enum values
383387 data.push_back(Cppyy_PseudoDatambrInfo(
384388 "kNothing", "CppyyTestData::EWhat", (ptrdiff_t)&Pseudo_kNothing, true));
387391 data.push_back(Cppyy_PseudoDatambrInfo(
388392 "kLots", "CppyyTestData::EWhat", (ptrdiff_t)&Pseudo_kLots, true));
389393
390 Cppyy_PseudoClassInfo info(methods, s_method_id - methods.size(), data);
394 Cppyy_PseudoClassInfo info(methods, data);
391395 s_scopes[(cppyy_scope_t)s_scope_id] = info;
392396 } // -- class CppyyTest_data
393397
398 //====================================================================
399
400 { // namespace pyzables --
401 s_handles["pyzables"] = (cppyy_scope_t)++s_scope_id;
402 s_scopes[(cppyy_scope_t)s_scope_id] = Cppyy_PseudoClassInfo{};
403 s_handles["pyzables::SomeDummy1"] = (cppyy_scope_t)++s_scope_id;
404 s_scopes[(cppyy_scope_t)s_scope_id] = Cppyy_PseudoClassInfo{};
405 s_handles["pyzables::SomeDummy2"] = (cppyy_scope_t)++s_scope_id;
406 s_scopes[(cppyy_scope_t)s_scope_id] = Cppyy_PseudoClassInfo{};
407 } // -- namespace pyzables
394408 }
395409 } _init;
396410
409423 char* cppyy_resolve_name(const char* cppitem_name) {
410424 if (cppyy_is_enum(cppitem_name))
411425 return cppstring_to_cstring("internal_enum_type_t");
426 else if (strcmp(cppitem_name, "aap_t") == 0)
427 return cppstring_to_cstring("long double");
412428 return cppstring_to_cstring(cppitem_name);
413429 }
414430
430446
431447 /* method/function dispatching -------------------------------------------- */
432448 void cppyy_call_v(cppyy_method_t method, cppyy_object_t self, int nargs, void* args) {
433 long idx = (long)method;
449 Cppyy_PseudoMethodInfo* idx = (Cppyy_PseudoMethodInfo*)method;
434450 if (idx == s_methods["static_example01::staticSetPayload_payload*_double"]) {
435451 assert(!self && nargs == 2);
436452 dummy::example01::staticSetPayload((dummy::payload*)(*(long*)&((CPPYY_G__value*)args)[0]),
513529 } else if (idx == s_methods["CppyyTestData::set_double_cr"]) {
514530 assert(self && nargs == 1);
515531 ((dummy::CppyyTestData*)self)->set_double_cr(*(double*)&((CPPYY_G__value*)args)[0]);
532 } else if (idx == s_methods["CppyyTestData::set_ldouble"]) {
533 assert(self && nargs == 1);
534 ((dummy::CppyyTestData*)self)->set_ldouble(((CPPYY_G__value*)args)[0].obj.ld);
535 } else if (idx == s_methods["CppyyTestData::set_ldouble_cr"]) {
536 assert(self && nargs == 1);
537 ((dummy::CppyyTestData*)self)->set_ldouble_cr(*(long double*)&((CPPYY_G__value*)args)[0]);
516538 } else {
517539 assert(!"method unknown in cppyy_call_v");
518540 }
520542
521543 unsigned char cppyy_call_b(cppyy_method_t method, cppyy_object_t self, int nargs, void* args) {
522544 unsigned char result = 0;
523 const long idx = (long)method;
545 Cppyy_PseudoMethodInfo* idx = (Cppyy_PseudoMethodInfo*)method;
524546 if (idx == s_methods["CppyyTestData::get_bool"]) {
525547 assert(self && nargs == 0);
526548 result = (unsigned char)((dummy::CppyyTestData*)self)->get_bool();
532554
533555 char cppyy_call_c(cppyy_method_t method, cppyy_object_t self, int nargs, void* args) {
534556 char result = 0;
535 const long idx = (long)method;
557 Cppyy_PseudoMethodInfo* idx = (Cppyy_PseudoMethodInfo*)method;
536558 if (idx == s_methods["CppyyTestData::get_char"]) {
537559 assert(self && nargs == 0);
538560 result = ((dummy::CppyyTestData*)self)->get_char();
547569
548570 short cppyy_call_h(cppyy_method_t method, cppyy_object_t self, int nargs, void* args) {
549571 short result = 0;
550 const long idx = (long)method;
572 Cppyy_PseudoMethodInfo* idx = (Cppyy_PseudoMethodInfo*)method;
551573 if (idx == s_methods["CppyyTestData::get_short"]) {
552574 assert(self && nargs == 0);
553575 result = ((dummy::CppyyTestData*)self)->get_short();
562584
563585 int cppyy_call_i(cppyy_method_t method, cppyy_object_t self, int nargs, void* args) {
564586 int result = 0;
565 const long idx = (long)method;
587 Cppyy_PseudoMethodInfo* idx = (Cppyy_PseudoMethodInfo*)method;
566588 if (idx == s_methods["static_example01::staticAddOneToInt_int"]) {
567589 assert(!self && nargs == 1);
568590 result = dummy::example01::staticAddOneToInt(((CPPYY_G__value*)args)[0].obj.in);
594616
595617 long cppyy_call_l(cppyy_method_t method, cppyy_object_t self, int nargs, void* args) {
596618 long result = 0;
597 const long idx = (long)method;
619 Cppyy_PseudoMethodInfo* idx = (Cppyy_PseudoMethodInfo*)method;
598620 if (idx == s_methods["static_example01::staticStrcpy_cchar*"]) {
599621 assert(!self && nargs == 1);
600622 result = (long)dummy::example01::staticStrcpy(
627649 } else if (idx == s_methods["CppyyTestData::get_bool_array2"]) {
628650 assert(self && nargs == 0);
629651 result = (long)((dummy::CppyyTestData*)self)->get_bool_array2();
652 } else if (idx == s_methods["CppyyTestData::get_uchar_array"]) {
653 assert(self && nargs == 0);
654 result = (long)((dummy::CppyyTestData*)self)->get_uchar_array();
655 } else if (idx == s_methods["CppyyTestData::get_uchar_array2"]) {
656 assert(self && nargs == 0);
657 result = (long)((dummy::CppyyTestData*)self)->get_uchar_array2();
630658 } else if (idx == s_methods["CppyyTestData::get_short_array"]) {
631659 assert(self && nargs == 0);
632660 result = (long)((dummy::CppyyTestData*)self)->get_short_array();
735763
736764 long long cppyy_call_ll(cppyy_method_t method, cppyy_object_t self, int nargs, void* args) {
737765 long long result = 0;
738 const long idx = (long)method;
766 Cppyy_PseudoMethodInfo* idx = (Cppyy_PseudoMethodInfo*)method;
739767 if (idx == s_methods["CppyyTestData::get_llong"]) {
740768 assert(self && nargs == 0);
741769 result = ((dummy::CppyyTestData*)self)->get_llong();
750778
751779 float cppyy_call_f(cppyy_method_t method, cppyy_object_t self, int nargs, void* args) {
752780 float result = 0;
753 const long idx = (long)method;
781 Cppyy_PseudoMethodInfo* idx = (Cppyy_PseudoMethodInfo*)method;
754782 if (idx == s_methods["CppyyTestData::get_float"]) {
755783 assert(self && nargs == 0);
756784 result = ((dummy::CppyyTestData*)self)->get_float();
762790
763791 double cppyy_call_d(cppyy_method_t method, cppyy_object_t self, int nargs, void* args) {
764792 double result = 0.;
765 const long idx = (long)method;
793 Cppyy_PseudoMethodInfo* idx = (Cppyy_PseudoMethodInfo*)method;
766794 if (idx == s_methods["static_example01::staticAddToDouble_double"]) {
767795 assert(!self && nargs == 1);
768796 result = dummy::example01::staticAddToDouble(((CPPYY_G__value*)args)[0].obj.d);
777805 result = ((dummy::CppyyTestData*)self)->get_double();
778806 } else {
779807 assert(!"method unknown in cppyy_call_d");
808 }
809 return result;
810 }
811
812 double cppyy_call_nld(cppyy_method_t method, cppyy_object_t self, int nargs, void* args) {
813 double result = 0.;
814 Cppyy_PseudoMethodInfo* idx = (Cppyy_PseudoMethodInfo*)method;
815 if (idx == s_methods["CppyyTestData::get_ldouble_def"]) {
816 if (nargs == 1)
817 result = (double)((dummy::CppyyTestData*)self)->get_ldouble_def(
818 ((CPPYY_G__value*)args)[0].obj.ld);
819 else {
820 assert(self && nargs == 0);
821 result = (double)((dummy::CppyyTestData*)self)->get_ldouble_def();
822 }
823 } else if (idx == s_methods["CppyyTestData::get_ldouble"]) {
824 assert(self && nargs == 0);
825 result = (double)((dummy::CppyyTestData*)self)->get_ldouble();
826 } else {
827 assert(!"method unknown in cppyy_call_nld");
780828 }
781829 return result;
782830 }
792840
793841 void* cppyy_call_r(cppyy_method_t method, cppyy_object_t self, int nargs, void* args) {
794842 void* result = nullptr;
795 const long idx = (long)method;
843 Cppyy_PseudoMethodInfo* idx = (Cppyy_PseudoMethodInfo*)method;
796844 if (0) {}
797845 DISPATCH_CALL_R_GET(bool)
798846 DISPATCH_CALL_R_GET(short)
816864
817865 char* cppyy_call_s(cppyy_method_t method, cppyy_object_t self, int nargs, void* args, size_t* /* length */) {
818866 char* result = 0;
819 const long idx = (long)method;
867 Cppyy_PseudoMethodInfo* idx = (Cppyy_PseudoMethodInfo*)method;
820868 if (idx == s_methods["static_example01::staticStrcpy_cchar*"]) {
821869 assert(!self && nargs == 1);
822870 result = dummy::example01::staticStrcpy((const char*)(*(long*)&((CPPYY_G__value*)args)[0]));
828876
829877 cppyy_object_t cppyy_constructor(cppyy_method_t method, cppyy_type_t handle, int nargs, void* args) {
830878 void* result = 0;
831 const long idx = (long)method;
879 Cppyy_PseudoMethodInfo* idx = (Cppyy_PseudoMethodInfo*)method;
832880 if (idx == s_methods["example01::example01"]) {
833881 assert(nargs == 0);
834882 result = new dummy::example01;
848896 return (cppyy_object_t)result;
849897 }
850898
851 cppyy_funcaddr_t cppyy_function_address_from_index(cppyy_scope_t /* scope */, cppyy_index_t /* idx */) {
852 return (cppyy_funcaddr_t)0;
853 }
854
855 cppyy_funcaddr_t cppyy_function_address_from_method(cppyy_method_t /* method */) {
899 cppyy_funcaddr_t cppyy_function_address(cppyy_method_t /* method */) {
856900 return (cppyy_funcaddr_t)0;
857901 }
858902
880924
881925
882926 /* scope reflection information ------------------------------------------- */
883 int cppyy_is_namespace(cppyy_scope_t /* handle */) {
927 int cppyy_is_namespace(cppyy_scope_t handle) {
928 if (handle == s_handles["pyzables"])
929 return 1;
884930 return 0;
885931 }
886932
920966 return 0;
921967 }
922968
969 int cppyy_smartptr_info(const char* name, cppyy_type_t* raw, cppyy_method_t* deref) {
970 return 0;
971 }
972
923973
924974 /* method/function reflection information --------------------------------- */
975 cppyy_method_t cppyy_get_method(cppyy_scope_t handle, cppyy_index_t idx) {
976 if (s_scopes.find(handle) != s_scopes.end()) {
977 return (cppyy_method_t)s_scopes[handle].m_methods[idx];
978 }
979 assert(!"unknown class in cppyy_get_method");
980 return (cppyy_method_t)0;
981 }
982
925983 int cppyy_num_methods(cppyy_scope_t handle) {
926984 return s_scopes[handle].m_methods.size();
927985 }
928986
929 char* cppyy_method_name(cppyy_scope_t handle, cppyy_index_t method_index) {
930 return cppstring_to_cstring(s_scopes[handle].m_methods[(int)method_index].m_name);
931 }
932
933 char* cppyy_method_result_type(cppyy_scope_t handle, cppyy_index_t method_index) {
934 return cppstring_to_cstring(s_scopes[handle].m_methods[method_index].m_returntype);
987 char* cppyy_method_name(cppyy_method_t method) {
988 return cppstring_to_cstring(((Cppyy_PseudoMethodInfo*)method)->m_name);
989 }
990
991 char* cppyy_method_full_name(cppyy_method_t method) {
992 return cppstring_to_cstring(((Cppyy_PseudoMethodInfo*)method)->m_name);
993 }
994
995 char* cppyy_method_result_type(cppyy_method_t method) {
996 return cppstring_to_cstring(((Cppyy_PseudoMethodInfo*)method)->m_returntype);
935997 }
936998
937 int cppyy_method_num_args(cppyy_scope_t handle, cppyy_index_t method_index) {
938 return s_scopes[handle].m_methods[method_index].m_argtypes.size();
939 }
940
941 int cppyy_method_req_args(cppyy_scope_t handle, cppyy_index_t method_index) {
942 return cppyy_method_num_args(handle, method_index);
943 }
944
945 char* cppyy_method_arg_type(cppyy_scope_t handle, cppyy_index_t method_index, int arg_index) {
946 return cppstring_to_cstring(s_scopes[handle].m_methods[method_index].m_argtypes[arg_index]);
947 }
948
949 char* cppyy_method_arg_default(
950 cppyy_scope_t /* handle */, cppyy_index_t /* method_index */, int /* arg_index */) {
999 int cppyy_method_num_args(cppyy_method_t method) {
1000 return ((Cppyy_PseudoMethodInfo*)method)->m_argtypes.size();
1001 }
1002
1003 int cppyy_method_req_args(cppyy_method_t method) {
1004 return cppyy_method_num_args(method)-((Cppyy_PseudoMethodInfo*)method)->m_argdefaults.size();
1005 }
1006
1007 char* cppyy_method_arg_type(cppyy_method_t method, int idx) {
1008 return cppstring_to_cstring(((Cppyy_PseudoMethodInfo*)method)->m_argtypes[idx]);
1009 }
1010
1011 char* cppyy_method_arg_default(cppyy_method_t method, int idx) {
1012 if (idx < (int)((Cppyy_PseudoMethodInfo*)method)->m_argdefaults.size())
1013 return cppstring_to_cstring(((Cppyy_PseudoMethodInfo*)method)->m_argdefaults[idx]);
9511014 return cppstring_to_cstring("");
9521015 }
9531016
954 char* cppyy_method_signature(
955 cppyy_scope_t /* handle */, cppyy_index_t /* method_index */, int /* show_formalargs */) {
1017 char* cppyy_method_signature(cppyy_method_t, int /* show_formalargs */) {
9561018 return cppstring_to_cstring("");
9571019 }
9581020
959 char* cppyy_method_prototype(
960 cppyy_scope_t /* handle */, cppyy_index_t /* method_index */, int /* show_formalargs */) {
1021 char* cppyy_method_prototype(cppyy_scope_t, cppyy_method_t, int /* show_formalargs */) {
9611022 return cppstring_to_cstring("");
1023 }
1024
1025 int cppyy_exists_method_template(cppyy_scope_t scope, const char* name) {
1026 return 0;
9621027 }
9631028
9641029 int cppyy_method_is_template(cppyy_scope_t /* handle */, cppyy_index_t /* method_index */) {
9651030 return 0;
9661031 }
9671032
968 cppyy_method_t cppyy_get_method(cppyy_scope_t handle, cppyy_index_t method_index) {
969 if (s_scopes.find(handle) != s_scopes.end()) {
970 long id = s_scopes[handle].m_method_offset + (long)method_index;
971 return (cppyy_method_t)id;
972 }
973 assert(!"unknown class in cppyy_get_method");
974 return (cppyy_method_t)0;
975 }
976
9771033 cppyy_index_t cppyy_get_global_operator(cppyy_scope_t /* scope */,
9781034 cppyy_scope_t /* lc */, cppyy_scope_t /* rc */, const char* /* op */) {
9791035 return (cppyy_index_t)-1;
9811037
9821038
9831039 /* method properties ----------------------------------------------------- */
984 int cppyy_is_publicmethod(cppyy_type_t /* handle */, cppyy_index_t /* method_index */) {
1040 int cppyy_is_publicmethod(cppyy_method_t) {
9851041 return 1;
9861042 }
9871043
988 int cppyy_is_constructor(cppyy_type_t handle, cppyy_index_t method_index) {
989 if (s_scopes.find(handle) != s_scopes.end())
990 return s_scopes[handle].m_methods[method_index].m_type == kConstructor;
1044 int cppyy_is_constructor(cppyy_method_t method) {
1045 if (method)
1046 return ((Cppyy_PseudoMethodInfo*)method)->m_type == kConstructor;
9911047 assert(!"unknown class in cppyy_is_constructor");
9921048 return 0;
9931049 }
9941050
995 int cppyy_is_destructor(cppyy_type_t /* handle */, cppyy_index_t /* method_index */) {
1051 int cppyy_is_destructor(cppyy_method_t) {
9961052 return 0;
9971053 }
9981054
999 int cppyy_is_staticmethod(cppyy_type_t handle, cppyy_index_t method_index) {
1000 if (s_scopes.find(handle) != s_scopes.end())
1001 return s_scopes[handle].m_methods[method_index].m_type == kStatic;
1055 int cppyy_is_staticmethod(cppyy_method_t method) {
1056 if (method)
1057 return ((Cppyy_PseudoMethodInfo*)method)->m_type == kStatic;
10021058 assert(!"unknown class in cppyy_is_staticmethod");
10031059 return 0;
10041060 }
10311087 return s_scopes[handle].m_datambrs[idatambr].m_isstatic;
10321088 }
10331089
1034 int cppyy_is_const_data(cppyy_scope_t /* handle */, cppyy_index_t /* idatambr */) {
1090 int cppyy_is_const_data(cppyy_scope_t handle, cppyy_index_t idatambr) {
1091 if (s_scopes[handle].m_datambrs[idatambr].m_name == "m_const_int")
1092 return 1;
10351093 return 0;
10361094 }
10371095
10381096 int cppyy_is_enum_data(cppyy_scope_t /* handle */, cppyy_index_t /* idatambr */) {
10391097 return 0;
1098 }
1099
1100 int cppyy_get_dimension_size(
1101 cppyy_scope_t /* scope */, cppyy_index_t /* idata */, int /* dimension */) {
1102 return -1; // no dimensions
10401103 }
10411104
10421105
10681131 }
10691132
10701133 cppyy_object_t cppyy_charp2stdstring(const char* str, size_t sz) {
1071 void* arena = new char[sz];
1072 new (arena) std::string(str, sz);
1073 return (cppyy_object_t)arena;
1134 return (cppyy_object_t)new std::string(str, sz);
1135 }
1136
1137 const char* cppyy_stdstring2charp(cppyy_object_t ptr, size_t* lsz) {
1138 *lsz = ((std::string*)ptr)->size();
1139 return ((std::string*)ptr)->data();
10741140 }
10751141
10761142 cppyy_object_t cppyy_stdstring2stdstring(cppyy_object_t ptr) {
1077 void* arena = new char[sizeof(std::string)];
1078 new (arena) std::string(*(std::string*)ptr);
1079 return (cppyy_object_t)arena;
1080 }
1143 return (cppyy_object_t)new std::string(*(std::string*)ptr);
1144 }
1145
1146 double cppyy_longdouble2double(void* p) {
1147 return (double)*(long double*)p;
1148 }
1149
1150 void cppyy_double2longdouble(double d, void* p) {
1151 *(long double*)p = d;
1152 }
1153
1154 int cppyy_vectorbool_getitem(cppyy_object_t ptr, int idx) {
1155 return (int)(*(std::vector<bool>*)ptr)[idx];
1156 }
1157
1158 void cppyy_vectorbool_setitem(cppyy_object_t ptr, int idx, int value) {
1159 (*(std::vector<bool>*)ptr)[idx] = (bool)value;
1160 }
66 fragileDict.so \
77 operatorsDict.so \
88 overloadsDict.so \
9 pythonizablesDict.so \
910 stltypesDict.so \
1011 templatesDict.so
1112
1314
1415 HASGENREFLEX:=$(shell command -v genreflex 2> /dev/null)
1516
16 cppflags=-std=c++14 -O3 -m64 -fPIC -rdynamic
17 cppflags=-std=c++14 -O3 -fPIC -rdynamic
1718 ifdef HASGENREFLEX
1819 genreflex_flags:=$(shell genreflex --cppflags)
1920 cppflags+=$(genreflex_flags)
2324
2425 PLATFORM := $(shell uname -s)
2526 ifeq ($(PLATFORM),Darwin)
26 cppflags+=-dynamiclib -single_module -arch x86_64 -undefined dynamic_lookup
27 cppflags+=-dynamiclib -single_module -undefined dynamic_lookup
2728 endif
2829
2930
33
44
55 // for testing of default arguments
6 #define IMPLEMENT_DEFAULTER_CLASS(type, tname) \
6 #define IMPLEMENT_DEFAULTERS(type, tname) \
77 tname##_defaulter::tname##_defaulter(type a, type b, type c) { \
8 m_a = a; m_b = b; m_c = c; \
8 m_a = a; m_b = b; m_c = c; \
9 } \
10 type tname##_defaulter_func(int idx, type a, type b, type c) { \
11 if (idx == 0) return a; \
12 if (idx == 1) return b; \
13 if (idx == 2) return c; \
14 return (type)idx; \
915 }
10 IMPLEMENT_DEFAULTER_CLASS(short, short)
11 IMPLEMENT_DEFAULTER_CLASS(unsigned short, ushort)
12 IMPLEMENT_DEFAULTER_CLASS(int, int)
13 IMPLEMENT_DEFAULTER_CLASS(unsigned, uint)
14 IMPLEMENT_DEFAULTER_CLASS(long, long)
15 IMPLEMENT_DEFAULTER_CLASS(unsigned long, ulong)
16 IMPLEMENT_DEFAULTER_CLASS(long long, llong)
17 IMPLEMENT_DEFAULTER_CLASS(unsigned long long, ullong)
18 IMPLEMENT_DEFAULTER_CLASS(float, float)
19 IMPLEMENT_DEFAULTER_CLASS(double, double)
16 IMPLEMENT_DEFAULTERS(short, short)
17 IMPLEMENT_DEFAULTERS(unsigned short, ushort)
18 IMPLEMENT_DEFAULTERS(int, int)
19 IMPLEMENT_DEFAULTERS(unsigned, uint)
20 IMPLEMENT_DEFAULTERS(long, long)
21 IMPLEMENT_DEFAULTERS(unsigned long, ulong)
22 IMPLEMENT_DEFAULTERS(long long, llong)
23 IMPLEMENT_DEFAULTERS(unsigned long long, ullong)
24 IMPLEMENT_DEFAULTERS(float, float)
25 IMPLEMENT_DEFAULTERS(double, double)
26
27 std::string string_defaulter_func(int idx, const std::string& name1, std::string name2) {
28 if (idx == 0) return name1;
29 if (idx == 1) return name2;
30 return "mies";
31 }
2032
2133
2234 // for esoteric inheritance testing
7688 double my_global_array[500];
7789 static double sd = 1234.;
7890 double* my_global_ptr = &sd;
91 const char my_global_string2[] = "zus jet teun";
92 some_int_holder my_global_int_holders[5] = {
93 some_int_holder(13), some_int_holder(42), some_int_holder(88),
94 some_int_holder(-1), some_int_holder(17) };
7995
8096 // for life-line and identity testing
8197 int some_class_with_data::some_data::s_num_data = 0;
33
44
55 //===========================================================================
6 #define DECLARE_DEFAULTER_CLASS(type, tname) \
6 #define DECLARE_DEFAULTERS(type, tname) \
77 class tname##_defaulter { \
88 public: \
99 tname##_defaulter(type a = 11, type b = 22, type c = 33); \
1010 \
1111 public: \
1212 type m_a, m_b, m_c; \
13 };
14 DECLARE_DEFAULTER_CLASS(short, short) // for testing of default arguments
15 DECLARE_DEFAULTER_CLASS(unsigned short, ushort)
16 DECLARE_DEFAULTER_CLASS(int, int)
17 DECLARE_DEFAULTER_CLASS(unsigned, uint)
18 DECLARE_DEFAULTER_CLASS(long, long)
19 DECLARE_DEFAULTER_CLASS(unsigned long, ulong)
20 DECLARE_DEFAULTER_CLASS(long long, llong)
21 DECLARE_DEFAULTER_CLASS(unsigned long long, ullong)
22 DECLARE_DEFAULTER_CLASS(float, float)
23 DECLARE_DEFAULTER_CLASS(double, double)
13 }; \
14 type tname##_defaulter_func(int idx = 0, type a = 11, type b = 22, type c = 33);
15 DECLARE_DEFAULTERS(short, short) // for testing of default arguments
16 DECLARE_DEFAULTERS(unsigned short, ushort)
17 DECLARE_DEFAULTERS(int, int)
18 DECLARE_DEFAULTERS(unsigned, uint)
19 DECLARE_DEFAULTERS(long, long)
20 DECLARE_DEFAULTERS(unsigned long, ulong)
21 DECLARE_DEFAULTERS(long long, llong)
22 DECLARE_DEFAULTERS(unsigned long long, ullong)
23 DECLARE_DEFAULTERS(float, float)
24 DECLARE_DEFAULTERS(double, double)
25
26 std::string string_defaulter_func(int idx, const std::string& name1 = "aap", std::string name2 = "noot");
2427
2528
2629 //===========================================================================
265268 class some_comparable {
266269 };
267270
268 bool operator==(const some_comparable& c1, const some_comparable& c2 );
269 bool operator!=( const some_comparable& c1, const some_comparable& c2 );
271 bool operator==(const some_comparable& c1, const some_comparable& c2);
272 bool operator!=(const some_comparable& c1, const some_comparable& c2);
270273
271274
272275 //===========================================================================
273276 extern double my_global_double; // a couple of globals for access testing
274277 extern double my_global_array[500];
275278 extern double* my_global_ptr;
276 static const char my_global_string[] = "aap " " noot " " mies";
279 static const char my_global_string1[] = "aap " " noot " " mies";
280 extern const char my_global_string2[];
281
282 class some_int_holder {
283 public:
284 some_int_holder(int val) : m_val(val) {}
285
286 public:
287 int m_val;
288 char gap[7];
289 };
290 extern some_int_holder my_global_int_holders[5];
291
277292
278293 //===========================================================================
279294 class some_class_with_data { // for life-line and identity testing
299314 some_data m_data;
300315 };
301316
317 class refers_to_self { // for data member reuse testing
318 public:
319 refers_to_self* m_other = nullptr;
320 };
321
302322
303323 //===========================================================================
304324 class pointer_pass { // for testing passing of void*'s
407427 void throw_anything();
408428 void throw_exception();
409429 };
430
431
432 //===========================================================================
433 class UsingBase { // using declaration testing
434 public:
435 UsingBase(int n = 13) : m_int(n) {}
436 virtual char vcheck() { return 'A'; }
437 int m_int;
438 };
439
440 class UsingDerived : public UsingBase {
441 public:
442 using UsingBase::UsingBase;
443 virtual char vcheck() { return 'B'; }
444 int m_int2 = 42;
445 };
446
447
448 //===========================================================================
449 class TypedefToPrivateClass { // typedef resolution testing
450 private:
451 class PC {
452 public:
453 PC(int i) : m_val(i) {}
454 int m_val;
455 };
456
457 public:
458 typedef PC PP;
459 PP f() { return PC(42); }
460 };
00 <lcgdict>
11
22 <class pattern="*_defaulter" />
3 <function pattern="*_defaulter_func" />
34
45 <class name="base_class" />
56 <class name="derived_class" />
3132 <class name="some_convertible" />
3233 <class name="some_class_with_data" />
3334 <class name="some_class_with_data::some_data" />
35 <class name="refers_to_self" />
3436
3537 <class name="some_comparable" />
3638 <function name="operator==" />
3941 <variable name="my_global_double" />
4042 <variable name="my_global_array" />
4143 <variable name="my_global_ptr" />
44 <variable name="my_global_int_holders" />
4245
4346 <class name="ref_tester" />
4447 <class name="std::vector<ref_tester>" />
5760 <class name="overload_the_other_way" />
5861
5962 <class name="Thrower" />
63 <class pattern="Using*" />
64 <class name="TypedefToPrivateClass" />
6065
6166 </lcgdict>
00 import py, sys
1 from os.path import abspath, commonprefix, dirname
2
3 THIS_DIR = dirname(__file__)
14
25 @py.test.mark.tryfirst
36 def pytest_runtest_setup(item):
710 # run only tests that are covered by the dummy backend and tests
811 # that do not rely on reflex
912 import os
13 infomsg = 'backend is not installed'
1014 tst = os.path.basename(item.location[0])
1115 if not tst in ('test_helper.py', 'test_cppyy.py', 'test_pythonify.py',
12 'test_datatypes.py'):
13 py.test.skip("genreflex is not installed")
16 'test_cpp11features.py', 'test_datatypes.py',
17 'test_pythonization.py'):
18 py.test.skip(infomsg)
1419 import re
1520 if tst == 'test_pythonify.py' and \
1621 not re.search("AppTestPYTHONIFY.test0[1-5]", item.location[2]):
17 py.test.skip("genreflex is not installed")
22 py.test.skip(infomsg)
23 elif tst == 'test_cpp11features.py' and \
24 not re.search("AppTestCPP11FEATURES.test02", item.location[2]):
25 py.test.skip(infomsg)
1826 elif tst == 'test_datatypes.py' and \
1927 not re.search("AppTestDATATYPES.test0[1-7]", item.location[2]):
20 py.test.skip("genreflex is not installed")
28 py.test.skip(infomsg)
29 elif tst == 'test_pythonization.py' and \
30 not re.search("AppTestPYTHONIZATION.test0[0]", item.location[2]):
31 py.test.skip(infomsg)
2132
2233 def pytest_ignore_collect(path, config):
34 path = str(path)
2335 if py.path.local.sysfind('genreflex') is None and config.option.runappdirect:
24 return True # "can't run dummy tests in -A"
36 return commonprefix([path, THIS_DIR]) == THIS_DIR
2537 if disabled:
26 return True
38 return commonprefix([path, THIS_DIR]) == THIS_DIR
2739
2840 disabled = None
2941
55
66
77 //===========================================================================
8 CppyyTestData::CppyyTestData() : m_owns_arrays(false)
8 CppyyTestData::CppyyTestData() : m_const_int(17), m_owns_arrays(false)
99 {
1010 m_bool = false;
1111 m_char = 'a';
2828 m_voidp = (void*)0;
2929
3030 m_bool_array2 = new bool[N];
31 m_uchar_array2 = new unsigned char[N];
3132 m_short_array2 = new short[N];
3233 m_ushort_array2 = new unsigned short[N];
3334 m_int_array2 = new int[N];
4142 for (int i = 0; i < N; ++i) {
4243 m_bool_array[i] = bool(i%2);
4344 m_bool_array2[i] = bool((i+1)%2);
45 m_uchar_array[i] = 1u*i;
46 m_uchar_array2[i] = 2u*i;
4447 m_short_array[i] = -1*i;
4548 m_short_array2[i] = -2*i;
4649 m_ushort_array[i] = 3u*i;
7679 void CppyyTestData::destroy_arrays() {
7780 if (m_owns_arrays == true) {
7881 delete[] m_bool_array2;
82 delete[] m_uchar_array2;
7983 delete[] m_short_array2;
8084 delete[] m_ushort_array2;
8185 delete[] m_int_array2;
108112 float CppyyTestData::get_float() { return m_float; }
109113 double CppyyTestData::get_double() { return m_double; }
110114 long double CppyyTestData::get_ldouble() { return m_ldouble; }
115 long double CppyyTestData::get_ldouble_def(long double ld) { return ld; }
111116 CppyyTestData::EWhat CppyyTestData::get_enum() { return m_enum; }
112117 void* CppyyTestData::get_voidp() { return m_voidp; }
113118
114119 bool* CppyyTestData::get_bool_array() { return m_bool_array; }
115120 bool* CppyyTestData::get_bool_array2() { return m_bool_array2; }
121 unsigned char* CppyyTestData::get_uchar_array() { return m_uchar_array; }
122 unsigned char* CppyyTestData::get_uchar_array2() { return m_uchar_array2; }
116123 short* CppyyTestData::get_short_array() { return m_short_array; }
117124 short* CppyyTestData::get_short_array2() { return m_short_array2; }
118125 unsigned short* CppyyTestData::get_ushort_array() { return m_ushort_array; }
232239 void CppyyTestData::set_enum_cr(const EWhat& w) { m_enum = w; }
233240
234241 //- passers -----------------------------------------------------------------
242 unsigned char* CppyyTestData::pass_array(unsigned char* a) { return a; }
235243 short* CppyyTestData::pass_array(short* a) { return a; }
236244 unsigned short* CppyyTestData::pass_array(unsigned short* a) { return a; }
237245 int* CppyyTestData::pass_array(int* a) { return a; }
332340 CppyyTestPod* get_null_pod() {
333341 return (CppyyTestPod*)0;
334342 }
343
344
345 //= function pointer passing ================================================
346 int sum_of_int(int i1, int i2) {
347 return i1+i2;
348 }
349
350 double sum_of_double(double d1, double d2) {
351 return d1+d2;
352 }
353
354 double call_double_double(double (*d)(double, double), double d1, double d2) {
355 return d(d1, d2);
356 }
00 // copied from RtypesCore.h ...
1 #if defined(R__WIN32)
1 #if defined(R__WIN32) && !defined(__CINT__)
22 typedef __int64 Long64_t; //Portable signed long integer 8 bytes
33 typedef unsigned __int64 ULong64_t; //Portable unsigned long integer 8 bytes
44 #else
2525
2626 //===========================================================================
2727 namespace EnumSpace {
28 enum E {E1 = 1, E2};
29 };
28 enum E {E1 = 1, E2};
29 class EnumClass {
30 public:
31 enum {E1 = -1};
32 enum EE {E2 = -1};
33 };
34
35 typedef enum { AA = 1, BB, CC, DD } letter_code;
36 }
3037
3138
3239 //===========================================================================
3845 m_cc_called(true), m_x(s.m_x), m_y(s.m_y), m_z(s.m_z), m_t(s.m_t) {}
3946
4047 double operator[](int i) {
41 if (i == 0) return m_x;
42 if (i == 1) return m_y;
43 if (i == 2) return m_z;
44 if (i == 3) return m_t;
45 return -1;
48 if (i == 0) return m_x;
49 if (i == 1) return m_y;
50 if (i == 2) return m_z;
51 if (i == 3) return m_t;
52 return -1;
4653 }
4754
4855 bool operator==(const FourVector& o) {
49 return (m_x == o.m_x && m_y == o.m_y &&
50 m_z == o.m_z && m_t == o.m_t);
56 return (m_x == o.m_x && m_y == o.m_y &&
57 m_z == o.m_z && m_t == o.m_t);
5158 }
5259
5360 public:
8895 float get_float();
8996 double get_double();
9097 long double get_ldouble();
98 typedef long double aap_t;
99 long double get_ldouble_def(long double ld = aap_t(1));
91100 EWhat get_enum();
92101 void* get_voidp();
93102
94103 bool* get_bool_array();
95104 bool* get_bool_array2();
105 unsigned char* get_uchar_array();
106 unsigned char* get_uchar_array2();
96107 short* get_short_array();
97108 short* get_short_array2();
98109 unsigned short* get_ushort_array();
211222 void set_enum_cr(const EWhat&);
212223
213224 // passers
225 unsigned char* pass_array(unsigned char*);
214226 short* pass_array(short*);
215227 unsigned short* pass_array(unsigned short*);
216228 int* pass_array(int*);
220232 float* pass_array(float*);
221233 double* pass_array(double*);
222234
235 unsigned char* pass_void_array_B(void* a) { return pass_array((unsigned char*)a); }
223236 short* pass_void_array_h(void* a) { return pass_array((short*)a); }
224237 unsigned short* pass_void_array_H(void* a) { return pass_array((unsigned short*)a); }
225238 int* pass_void_array_i(void* a) { return pass_array((int*)a); }
242255 short m_short;
243256 unsigned short m_ushort;
244257 int m_int;
258 const int m_const_int; // special case: const testing
245259 unsigned int m_uint;
246260 long m_long;
247261 unsigned long m_ulong;
258272 // array types
259273 bool m_bool_array[N];
260274 bool* m_bool_array2;
275 unsigned char m_uchar_array[N];
276 unsigned char* m_uchar_array2;
261277 short m_short_array[N];
262278 short* m_short_array2;
263279 unsigned short m_ushort_array[N];
363379 void set_global_pod(CppyyTestPod* t);
364380 CppyyTestPod* get_global_pod();
365381 CppyyTestPod* get_null_pod();
382
383
384 //= function pointer passing ================================================
385 int sum_of_int(int i1, int i2);
386 double sum_of_double(double d1, double d2);
387 double call_double_double(double (*d)(double, double), double d1, double d2);
33 <class name="FourVector" />
44
55 <enum name="EFruit" />
6 <enum name="EnumSpace::E" />
7 <class name="EnumSpace::EnumClass" />
8 <enum name="EnumSpace::letter_code" />
69
710 <function pattern="get_*" />
811 <function pattern="set_*" />
1316 <variable name="g_int" />
1417 <variable name="g_pod" />
1518
19 <function name="sum_of_int" />
20 <function name="sum_of_double" />
21 <function name="call_double_double" />
22
1623 </lcgdict>
0 #include "pythonizables.h"
1
2
3 pyzables::MyBase::~MyBase() {}
4 pyzables::MyDerived::~MyDerived() {}
5
6 pyzables::MyBase* pyzables::GimeDerived() {
7 return new MyDerived();
8 }
9
10
11 //===========================================================================
12 int pyzables::Countable::sInstances = 0;
13 pyzables::SharedCountable_t pyzables::mine =
14 pyzables::SharedCountable_t(new pyzables::Countable);
15
16 void pyzables::renew_mine() { mine = std::shared_ptr<Countable>(new Countable); }
17
18 pyzables::SharedCountable_t pyzables::gime_mine() { return mine; }
19 pyzables::SharedCountable_t* pyzables::gime_mine_ptr() { return &mine; }
20 pyzables::SharedCountable_t& pyzables::gime_mine_ref() { return mine; }
21
22 unsigned int pyzables::pass_mine_sp(std::shared_ptr<Countable> ptr) { return ptr->m_check; }
23 unsigned int pyzables::pass_mine_sp_ref(std::shared_ptr<Countable>& ptr) { return ptr->m_check; }
24 unsigned int pyzables::pass_mine_sp_ptr(std::shared_ptr<Countable>* ptr) { return (*ptr)->m_check; }
25
26 unsigned int pyzables::pass_mine_rp(Countable c) { return c.m_check; }
27 unsigned int pyzables::pass_mine_rp_ref(const Countable& c) { return c.m_check; }
28 unsigned int pyzables::pass_mine_rp_ptr(const Countable* c) { return c->m_check; }
29
30 pyzables::Countable* pyzables::gime_naked_countable() { return new Countable{}; }
0 #include <memory>
1 #include <vector>
2
3
4 namespace pyzables {
5
6 //===========================================================================
7 class SomeDummy1 {};
8 class SomeDummy2 {};
9
10
11 //===========================================================================
12 class MyBase {
13 public:
14 virtual ~MyBase();
15 };
16 class MyDerived : public MyBase {
17 public:
18 virtual ~MyDerived();
19 };
20
21 MyBase* GimeDerived();
22
23
24 //===========================================================================
25 class Countable {
26 public:
27 Countable() { ++sInstances; }
28 Countable(const Countable&) { ++sInstances; }
29 Countable& operator=(const Countable&) { return *this; }
30 ~Countable() { --sInstances; }
31
32 public:
33 virtual const char* say_hi() { return "Hi!"; }
34
35 public:
36 unsigned int m_check = 0xcdcdcdcd;
37
38 public:
39 static int sInstances;
40 };
41
42 typedef std::shared_ptr<Countable> SharedCountable_t;
43 extern SharedCountable_t mine;
44
45 void renew_mine();
46
47 SharedCountable_t gime_mine();
48 SharedCountable_t* gime_mine_ptr();
49 SharedCountable_t& gime_mine_ref();
50
51 unsigned int pass_mine_sp(SharedCountable_t p);
52 unsigned int pass_mine_sp_ref(SharedCountable_t& p);
53 unsigned int pass_mine_sp_ptr(SharedCountable_t* p);
54
55 unsigned int pass_mine_rp(Countable);
56 unsigned int pass_mine_rp_ref(const Countable&);
57 unsigned int pass_mine_rp_ptr(const Countable*);
58
59 Countable* gime_naked_countable();
60
61 } // namespace pyzables
0 <lcgdict>
1
2 <class pattern="pyzables::*" />
3 <function pattern="pyzables::*" />
4 <variable pattern="pyzables::*" />
5
6 </lcgdict>
00 #include "stltypes.h"
11
2
3 //- explicit instantiations of used comparisons
4 #if defined __clang__
5 namespace std {
6 #define ns_prefix std::
7 #elif defined(__GNUC__) || defined(__GNUG__)
8 namespace __gnu_cxx {
9 #define ns_prefix
10 #endif
11 template bool ns_prefix operator==(const std::vector<int>::iterator&,
12 const std::vector<int>::iterator&);
13 template bool ns_prefix operator!=(const std::vector<int>::iterator&,
14 const std::vector<int>::iterator&);
15 }
216
317 //- class with lots of std::string handling
418 stringy_class::stringy_class(const char* s) : m_string(s) {}
822
923 void stringy_class::set_string1(const std::string& s) { m_string = s; }
1024 void stringy_class::set_string2(std::string s) { m_string = s; }
25
26
27 //- helpers for testing array
28 int ArrayTest::get_pp_px(Point** p, int idx) {
29 return p[idx]->px;
30 }
31
32 int ArrayTest::get_pp_py(Point** p, int idx) {
33 return p[idx]->py;
34 }
35
36 int ArrayTest::get_pa_px(Point* p[], int idx) {
37 return p[idx]->px;
38 }
39
40 int ArrayTest::get_pa_py(Point* p[], int idx) {
41 return p[idx]->py;
42 }
43
44
45 // helpers for string testing
46 std::string str_array_1[3] = {"a", "b", "c"};
47 std::string str_array_2[] = {"d", "e", "f", "g"};
48 std::string str_array_3[3][2] = {{"a", "b"}, {"c", "d"}, {"e", "f"}};
49 std::string str_array_4[4][2][2] = {
50 {{"a", "b"}, {"c", "d"}},
51 {{"e", "f"}, {"g", "h"}},
52 {{"i", "j"}, {"k", "l"}},
53 {{"m", "n"}, {"o", "p"}},
54 };
33 #include <utility>
44 #include <vector>
55
6
67 //- basic example class
78 class just_a_class {
89 public:
910 int m_i;
1011 };
12
13 // enum for vector of enums setitem tests
14 enum VecTestEnum {
15 EVal1 = 1, EVal2 = 3
16 };
17
18 namespace VecTestEnumNS {
19 enum VecTestEnum { EVal1 = 5, EVal2 = 42 };
20 }
21
1122
1223 //- class with lots of std::string handling
1324 class stringy_class {
3041 class stl_like_class {
3142 public:
3243 no_dict_available* begin() { return 0; }
33 no_dict_available* end() { return 0; }
44 no_dict_available* end() { return (no_dict_available*)1; }
3445 int size() { return 4; }
3546 int operator[](int i) { return i; }
3647 std::string operator[](double) { return "double"; }
3748 std::string operator[](const std::string&) { return "string"; }
3849 };
50
51 namespace {
52 stl_like_class<int> stlc_1;
53 }
54
55
56 //- helpers for testing array
57 namespace ArrayTest {
58
59 struct Point {
60 Point() : px(0), py(0) {}
61 Point(int x, int y) : px(x), py(y) {}
62 int px, py;
63 };
64
65 int get_pp_px(Point** p, int idx);
66 int get_pp_py(Point** p, int idx);
67 int get_pa_px(Point* p[], int idx);
68 int get_pa_py(Point* p[], int idx);
69
70 } // namespace ArrayTest
71
72
73 // helpers for string testing
74 extern std::string str_array_1[3];
75 extern std::string str_array_2[];
76 extern std::string str_array_3[3][2];
77 extern std::string str_array_4[4][2][2];
00 <lcgdict>
11
2 <namespace name="std" />
2 <class name="just_a_class" />
3 <enum name="VecTestEnum" />
4 <namespace name="VecTestEnumNS" />
5 <enum name="VecTestEnumNS::VecTestEnum" />
6 <class name="stringy_class" />
7 <class pattern="stl_like_class<*>" />
38
4 <class name="just_a_class" />
9 <namespace name="ArrayTest" />
10 <class pattern="ArrayTest::*" />
11 <function pattern="ArrayTest::*" />
512
6 <class name="std::string" />
7 <class name="stringy_class" />
13 <variable pattern="str_array_*" />
814
915 </lcgdict>
0 #include <string>
1 #include <sstream>
2 #include <vector>
3
4
05 //===========================================================================
16 class MyTemplatedMethodClass { // template methods
27 public:
2025 return sizeof(B);
2126 }
2227
23 //
28 //
2429 typedef MyTemplatedMethodClass MyTMCTypedef_t;
2530
2631 // explicit instantiation
3237 inline long MyTemplatedMethodClass::get_size<long>() {
3338 return 42;
3439 }
40
41
42 //===========================================================================
43 // global templated functions
44 template<typename T>
45 long global_get_size() {
46 return sizeof(T);
47 }
48
49 template <typename T>
50 int global_some_foo(T) {
51 return 42;
52 }
53
54 template <typename T>
55 int global_some_bar(T) {
56 return 13;
57 }
58
59 template <typename F>
60 struct SomeResult {
61 F m_retval;
62 };
63
64 template <class I, typename O = float>
65 SomeResult<O> global_get_some_result(const std::vector<I>& carrier) {
66 SomeResult<O> r{};
67 r.m_retval = O(carrier[0]);
68 return r;
69 }
70
71
72 //===========================================================================
73 // variadic functions
74 inline bool isSomeInt(int) { return true; }
75 inline bool isSomeInt(double) { return false; }
76 template <typename ...Args>
77 inline bool isSomeInt(Args...) { return false; }
78
79 namespace AttrTesting {
80
81 struct Obj1 { int var1; };
82 struct Obj2 { int var2; };
83
84 template <typename T>
85 constexpr auto has_var1(T t) -> decltype(t.var1, true) { return true; }
86
87 template <typename ...Args>
88 constexpr bool has_var1(Args...) { return false; }
89
90 template <typename T>
91 constexpr bool call_has_var1(T&& t) { return AttrTesting::has_var1(std::forward<T>(t)); }
92
93 template <int N, typename... T>
94 struct select_template_arg {};
95
96 template <typename T0, typename... T>
97 struct select_template_arg<0, T0, T...> {
98 typedef T0 type;
99 };
100
101 template <int N, typename T0, typename... T>
102 struct select_template_arg<N, T0, T...> {
103 typedef typename select_template_arg<N-1, T...>::type argument;
104 };
105
106 } // AttrTesting
107
108
109 namespace SomeNS {
110
111 template <typename T>
112 int some_foo(T) {
113 return 42;
114 }
115
116 template <int T>
117 int some_bar() {
118 return T;
119 }
120
121 inline std::string tuplify(std::ostringstream& out) {
122 out << "NULL)";
123 return out.str();
124 }
125
126 template<typename T, typename... Args>
127 std::string tuplify(std::ostringstream& out, T value, Args... args)
128 {
129 out << value << ", ";
130 return tuplify(out, args...);
131 }
132
133 } // namespace SomeNS
134
135
136 //===========================================================================
137 // using of static data
138 // TODO: this should live here instead of in test_templates.test08
139 /*
140 template <typename T> struct BaseClassWithStatic {
141 static T const ref_value;
142 };
143
144 template <typename T>
145 T const BaseClassWithStatic<T>::ref_value = 42;
146
147 template <typename T>
148 struct DerivedClassUsingStatic : public BaseClassWithStatic<T> {
149 using BaseClassWithStatic<T>::ref_value;
150
151 explicit DerivedClassUsingStatic(T x) : BaseClassWithStatic<T>() {
152 m_value = x > ref_value ? ref_value : x;
153 }
154
155 T m_value;
156 };
157 */
22 <class name="MyTemplatedMethodClass" />
33 <class name="MyTMCTypedef_t" />
44
5 <function name="global_get_size" />
6 <function name="global_some_foo" />
7 <function name="global_some_bar" />
8
9 <function name="isSomeInt" />
10
11 <namespace name="AttrTesting" />
12 <function pattern="AttrTesting::*" />
13
14 <function name="SomeNS::some_foo" />
15 <function name="SomeNS::some_bar" />
16 <function name="SomeNS::tuplify" />
17
518 </lcgdict>
2121 def setup_class(cls):
2222 cls.w_test_dct = cls.space.newtext(test_dct)
2323 cls.w_advanced = cls.space.appexec([], """():
24 import ctypes
24 import ctypes, _cppyy
25 _cppyy._post_import_startup()
2526 return ctypes.CDLL(%r, ctypes.RTLD_GLOBAL)""" % (test_dct, ))
2627
2728 def test01_default_arguments(self):
5455 assert d.m_b == t(4)
5556 assert d.m_c == t(5)
5657 d.__destruct__()
58
59 defaulter_func = getattr(cppyy.gbl, '%s_defaulter_func' %n)
60 answers = [11, 22, 33, 3]
61 for idx in range(4):
62 assert defaulter_func(idx) == answers[idx]
63
5764 test_defaulter('short', int)
5865 test_defaulter('ushort', int)
5966 test_defaulter('int', int)
6471 test_defaulter('ullong', long)
6572 test_defaulter('float', float)
6673 test_defaulter('double', float)
74
75 assert cppyy.gbl.string_defaulter_func(0) == "aap"
76 assert cppyy.gbl.string_defaulter_func(0, "zus") == "zus"
77 assert cppyy.gbl.string_defaulter_func(1) == "noot"
78 assert cppyy.gbl.string_defaulter_func(1, "zus") == "noot"
79 assert cppyy.gbl.string_defaulter_func(1, "zus", "jet") == "jet"
80 assert cppyy.gbl.string_defaulter_func(2) == "mies"
6781
6882 def test02_simple_inheritance(self):
6983 """Test binding of a basic inheritance structure"""
146160 assert gbl.a_ns.d_ns.e_class.f_class.s_f == 66
147161 assert gbl.a_ns.d_ns.e_class.f_class().m_f == -6
148162
163 raises(TypeError, gbl.a_ns)
164
149165 def test03a_namespace_lookup_on_update(self):
150166 """Test whether namespaces can be shared across dictionaries."""
151167
472488 d2.__destruct__()
473489 d1.__destruct__()
474490
491 RTS = cppyy.gbl.refers_to_self
492
493 r1 = RTS()
494 r2 = RTS()
495 r1.m_other = r2
496
497 r3 = r1.m_other
498 r4 = r1.m_other
499 assert r3 is r4
500
501 assert r3 == r2
502 assert r3 is r2
503
504 r3.extra = 42
505 assert r2.extra == 42
506 assert r4.extra == 42
507
475508 def test11_multi_methods(self):
476509 """Test calling of methods from multiple inheritance"""
477510
651684
652685 assert cppyy.gbl.my_global_double == 12.
653686 assert len(cppyy.gbl.my_global_array) == 500
654 assert cppyy.gbl.my_global_string == "aap noot mies"
687 assert cppyy.gbl.my_global_string1 == "aap noot mies"
688 assert cppyy.gbl.my_global_string2 == "zus jet teun"
655689 # TODO: currently fails b/c double** not understood as &double*
656690 #assert cppyy.gbl.my_global_ptr[0] == 1234.
657691
692 v = cppyy.gbl.my_global_int_holders
693 assert len(v) == 5
694 expected_vals = [13, 42, 88, -1, 17]
695 for i in range(len(v)):
696 assert v[i].m_val == expected_vals[i]
697
658698 def test22_exceptions(self):
659699 """Catching of C++ exceptions"""
660700
661701 import _cppyy as cppyy
662702 Thrower = cppyy.gbl.Thrower
663703
664 # TODO: clean up this interface:
665 Thrower.__cppdecl__.get_overload('throw_anything').__useffi__ = False
666 Thrower.__cppdecl__.get_overload('throw_exception').__useffi__ = False
704 Thrower.throw_anything.__useffi__ = False
705 Thrower.throw_exception.__useffi__ = False
667706
668707 t = Thrower()
669708
672711
673712 try:
674713 t.throw_exception()
675 except Exception, e:
714 except Exception as e:
676715 "C++ function failed" in str(e)
716
717 def test23_using(self):
718 """Accessibility of using declarations"""
719
720 import _cppyy as cppyy
721
722 assert cppyy.gbl.UsingBase().vcheck() == 'A'
723
724 B = cppyy.gbl.UsingDerived
725 assert not 'UsingBase' in B.__init__.__doc__
726
727 b1 = B()
728 assert b1.m_int == 13
729 assert b1.m_int2 == 42
730 assert b1.vcheck() == 'B'
731
732 b2 = B(10)
733 assert b2.m_int == 10
734 assert b2.m_int2 == 42
735 assert b2.vcheck() == 'B'
736
737 b3 = B(b2)
738 assert b3.m_int == 10
739 assert b3.m_int2 == 42
740 assert b3.vcheck() == 'B'
741
742 def test24_typedef_to_private_class(self):
743 """Typedefs to private classes should not resolve"""
744
745 import _cppyy as cppyy
746
747 assert cppyy.gbl.TypedefToPrivateClass().f().m_val == 42
1313 def setup_class(cls):
1414 cls.w_test_dct = cls.space.newtext(test_dct)
1515 cls.w_example01 = cls.space.appexec([], """():
16 import ctypes
16 import ctypes, _cppyy
17 _cppyy._post_import_startup()
1718 return ctypes.CDLL(%r, ctypes.RTLD_GLOBAL)""" % (test_dct, ))
1819
1920 def test01_shared_ptr(self):
1717 w_cppyyclass = interp_cppyy.scope_byname(space, "example01")
1818 w_cppyyclass2 = interp_cppyy.scope_byname(space, "example01")
1919 assert space.is_w(w_cppyyclass, w_cppyyclass2)
20 adddouble = w_cppyyclass.methods["staticAddToDouble"]
20 adddouble = w_cppyyclass.overloads["staticAddToDouble"]
2121 func, = adddouble.functions
2222 assert func.executor is None
2323 func._setup(None) # creates executor
3232 cls.w_lib, cls.w_instantiate, cls.w_example01, cls.w_payload = \
3333 cls.space.unpackiterable(cls.space.appexec([], """():
3434 import _cppyy, ctypes
35 _cppyy._post_import_startup()
3536 lib = ctypes.CDLL(%r, ctypes.RTLD_GLOBAL)
3637 def cpp_instantiate(tt, *args):
3738 inst = _cppyy._bind_object(0, tt, True)
38 tt.get_overload("__init__").call(inst, *args)
39 ol = tt.get_overload("__init__").__get__(inst)
40 ol(*args)
3941 return inst
4042 return lib, cpp_instantiate, _cppyy._scope_byname('example01'),\
4143 _cppyy._scope_byname('payload')""" % (test_dct, )))
4749 import sys, math
4850 t = self.example01
4951
50 res = t.get_overload("staticAddOneToInt").call(None, 1)
52 pylong = int
53 if sys.hexversion < 0x3000000:
54 pylong = long
55
56 res = t.get_overload("staticAddOneToInt")(1)
5157 assert res == 2
52 res = t.get_overload("staticAddOneToInt").call(None, 1, 2)
58 res = t.get_overload("staticAddOneToInt")(pylong(1))
59 assert res == 2
60 res = t.get_overload("staticAddOneToInt")(1, 2)
5361 assert res == 4
54 res = t.get_overload("staticAddOneToInt").call(None, -1)
62 res = t.get_overload("staticAddOneToInt")(-1)
5563 assert res == 0
5664 maxint32 = int(2 ** 31 - 1)
57 res = t.get_overload("staticAddOneToInt").call(None, maxint32-1)
65 res = t.get_overload("staticAddOneToInt")(maxint32-1)
5866 assert res == maxint32
59 res = t.get_overload("staticAddOneToInt").call(None, maxint32)
67 res = t.get_overload("staticAddOneToInt")(maxint32)
6068 assert res == -maxint32-1
6169
62 raises(TypeError, 't.get_overload("staticAddOneToInt").call(None, 1, [])')
63 raises(TypeError, 't.get_overload("staticAddOneToInt").call(None, 1.)')
64 raises(TypeError, 't.get_overload("staticAddOneToInt").call(None, maxint32+1)')
70 raises(TypeError, 't.get_overload("staticAddOneToInt")(1, [])')
71 raises(TypeError, 't.get_overload("staticAddOneToInt")(1.)')
72 raises(TypeError, 't.get_overload("staticAddOneToInt")(maxint32+1)')
6573
6674 def test02_static_double(self):
6775 """Test passing of a double and returning of a double on a static function."""
6876
6977 t = self.example01
7078
71 res = t.get_overload("staticAddToDouble").call(None, 0.09)
79 res = t.get_overload("staticAddToDouble")(0.09)
7280 assert res == 0.09 + 0.01
7381
7482 def test03_static_constcharp(self):
7785
7886 t = self.example01
7987
80 res = t.get_overload("staticAtoi").call(None, "1")
88 res = t.get_overload("staticAtoi")("1")
8189 assert res == 1
82 res = t.get_overload("staticStrcpy").call(None, "aap") # TODO: this leaks
90 res = t.get_overload("staticStrcpy")("aap") # TODO: this leaks
8391 assert res == "aap"
84 res = t.get_overload("staticStrcpy").call(None, u"aap") # TODO: this leaks
92 res = t.get_overload("staticStrcpy")(u"aap") # TODO: this leaks
8593 assert res == "aap"
8694
87 raises(TypeError, 't.get_overload("staticStrcpy").call(None, 1.)') # TODO: this leaks
95 raises(TypeError, 't.get_overload("staticStrcpy")(1.)') # TODO: this leaks
8896
8997 def test04_method_int(self):
9098 """Test passing of a int, returning of a int, and memory cleanup, on
93101
94102 t = self.example01
95103
96 assert t.get_overload("getCount").call(None) == 0
97
98 e1 = self.instantiate(t, 7)
99 assert t.get_overload("getCount").call(None) == 1
100 res = t.get_overload("addDataToInt").call(e1, 4)
104 assert t.get_overload("getCount")() == 0
105
106 e1 = self.instantiate(t, 7)
107 assert t.get_overload("getCount")() == 1
108 res = t.get_overload("addDataToInt")(e1, 4)
101109 assert res == 11
102 res = t.get_overload("addDataToInt").call(e1, -4)
110 res = t.get_overload("addDataToInt")(e1, -4)
103111 assert res == 3
104112 e1.__destruct__()
105 assert t.get_overload("getCount").call(None) == 0
106 raises(ReferenceError, 't.get_overload("addDataToInt").call(e1, 4)')
113 assert t.get_overload("getCount")() == 0
114 raises(ReferenceError, 't.get_overload("addDataToInt")(e1, 4)')
107115
108116 e1 = self.instantiate(t, 7)
109117 e2 = self.instantiate(t, 8)
110 assert t.get_overload("getCount").call(None) == 2
118 assert t.get_overload("getCount")() == 2
111119 e1.__destruct__()
112 assert t.get_overload("getCount").call(None) == 1
120 assert t.get_overload("getCount")() == 1
113121 e2.__destruct__()
114 assert t.get_overload("getCount").call(None) == 0
122 assert t.get_overload("getCount")() == 0
115123
116124 e2.__destruct__()
117 assert t.get_overload("getCount").call(None) == 0
118
119 raises(TypeError, t.get_overload("addDataToInt").call, 41, 4)
125 assert t.get_overload("getCount")() == 0
126
127 raises(TypeError, t.get_overload("addDataToInt"), 41, 4)
120128
121129 def test05_memory(self):
122130 """Test memory destruction and integrity."""
126134
127135 t = self.example01
128136
129 assert t.get_overload("getCount").call(None) == 0
130
131 e1 = self.instantiate(t, 7)
132 assert t.get_overload("getCount").call(None) == 1
133 res = t.get_overload("addDataToInt").call(e1, 4)
137 assert t.get_overload("getCount")() == 0
138
139 e1 = self.instantiate(t, 7)
140 assert t.get_overload("getCount")() == 1
141 res = t.get_overload("addDataToInt")(e1, 4)
134142 assert res == 11
135 res = t.get_overload("addDataToInt").call(e1, -4)
143 res = t.get_overload("addDataToInt")(e1, -4)
136144 assert res == 3
137145 e1 = None
138146 gc.collect()
139 assert t.get_overload("getCount").call(None) == 0
147 assert t.get_overload("getCount")() == 0
140148
141149 e1 = self.instantiate(t, 7)
142150 e2 = self.instantiate(t, 8)
143 assert t.get_overload("getCount").call(None) == 2
151 assert t.get_overload("getCount")() == 2
144152 e1 = None
145153 gc.collect()
146 assert t.get_overload("getCount").call(None) == 1
154 assert t.get_overload("getCount")() == 1
147155 e2.__destruct__()
148 assert t.get_overload("getCount").call(None) == 0
156 assert t.get_overload("getCount")() == 0
149157 e2 = None
150158 gc.collect()
151 assert t.get_overload("getCount").call(None) == 0
159 assert t.get_overload("getCount")() == 0
152160
153161 def test05a_memory2(self):
154162 """Test ownership control."""
157165
158166 t = self.example01
159167
160 assert t.get_overload("getCount").call(None) == 0
161
162 e1 = self.instantiate(t, 7)
163 assert t.get_overload("getCount").call(None) == 1
168 assert t.get_overload("getCount")() == 0
169
170 e1 = self.instantiate(t, 7)
171 assert t.get_overload("getCount")() == 1
164172 assert e1.__python_owns__ == True
165173 e1.__python_owns__ = False
166174 e1 = None
167175 gc.collect()
168 assert t.get_overload("getCount").call(None) == 1
176 assert t.get_overload("getCount")() == 1
169177
170178 # forced fix-up of object count for later tests
171 t.get_overload("setCount").call(None, 0)
179 t.get_overload("setCount")(0)
172180
173181
174182 def test06_method_double(self):
179187 t = self.example01
180188
181189 e = self.instantiate(t, 13)
182 res = t.get_overload("addDataToDouble").call(e, 16)
190 res = t.get_overload("addDataToDouble")(e, 16)
183191 assert round(res-29, 8) == 0.
184192 e.__destruct__()
185193
186194 e = self.instantiate(t, -13)
187 res = t.get_overload("addDataToDouble").call(e, 16)
195 res = t.get_overload("addDataToDouble")(e, 16)
188196 assert round(res-3, 8) == 0.
189197 e.__destruct__()
190 assert t.get_overload("getCount").call(None) == 0
198 assert t.get_overload("getCount")() == 0
191199
192200 def test07_method_constcharp(self):
193201 """Test passing of a C string and returning of a C string on a
197205 t = self.example01
198206
199207 e = self.instantiate(t, 42)
200 res = t.get_overload("addDataToAtoi").call(e, "13")
208 res = t.get_overload("addDataToAtoi")(e, "13")
201209 assert res == 55
202 res = t.get_overload("addToStringValue").call(e, "12") # TODO: this leaks
210 res = t.get_overload("addToStringValue")(e, "12") # TODO: this leaks
203211 assert res == "54"
204 res = t.get_overload("addToStringValue").call(e, "-12") # TODO: this leaks
212 res = t.get_overload("addToStringValue")(e, "-12") # TODO: this leaks
205213 assert res == "30"
206214 e.__destruct__()
207 assert t.get_overload("getCount").call(None) == 0
215 assert t.get_overload("getCount")() == 0
208216
209217 def test08_pass_object_by_pointer(self):
210218 """Test passing of an instance as an argument."""
214222 t2 = self.payload
215223
216224 pl = self.instantiate(t2, 3.14)
217 assert round(t2.get_overload("getData").call(pl)-3.14, 8) == 0
218 t1.get_overload("staticSetPayload").call(None, pl, 41.)
219 assert t2.get_overload("getData").call(pl) == 41.
225 assert round(t2.get_overload("getData")(pl)-3.14, 8) == 0
226 t1.get_overload("staticSetPayload")(pl, 41.)
227 assert t2.get_overload("getData")(pl) == 41.
220228
221229 e = self.instantiate(t1, 50)
222 t1.get_overload("setPayload").call(e, pl);
223 assert round(t2.get_overload("getData").call(pl)-50., 8) == 0
230 t1.get_overload("setPayload")(e, pl);
231 assert round(t2.get_overload("getData")(pl)-50., 8) == 0
224232
225233 e.__destruct__()
226234 pl.__destruct__()
227 assert t1.get_overload("getCount").call(None) == 0
235 assert t1.get_overload("getCount")() == 0
228236
229237 def test09_return_object_by_pointer(self):
230238 """Test returning of an instance as an argument."""
234242 t2 = self.payload
235243
236244 pl1 = self.instantiate(t2, 3.14)
237 assert round(t2.get_overload("getData").call(pl1)-3.14, 8) == 0
238 pl2 = t1.get_overload("staticCyclePayload").call(None, pl1, 38.)
239 assert t2.get_overload("getData").call(pl2) == 38.
245 assert round(t2.get_overload("getData")(pl1)-3.14, 8) == 0
246 pl2 = t1.get_overload("staticCyclePayload")(pl1, 38.)
247 assert t2.get_overload("getData")(pl2) == 38.
240248
241249 e = self.instantiate(t1, 50)
242 pl2 = t1.get_overload("cyclePayload").call(e, pl1);
243 assert round(t2.get_overload("getData").call(pl2)-50., 8) == 0
250 pl2 = t1.get_overload("cyclePayload")(e, pl1);
251 assert round(t2.get_overload("getData")(pl2)-50., 8) == 0
244252
245253 e.__destruct__()
246254 pl1.__destruct__()
247 assert t1.get_overload("getCount").call(None) == 0
255 assert t1.get_overload("getCount")() == 0
7171 # to allow the generated extension module be loaded first)
7272 cls.w_test_dct = cls.space.newtext(test_dct)
7373 cls.w_pre_imports = cls.space.appexec([], """():
74 import ctypes, _cppyy""") # prevents leak-checking complaints on ctypes' statics
74 import ctypes, _cppyy
75 _cppyy._post_import_startup()""") # early import of ctypes
76 # prevents leak-checking complaints on ctypes' statics
7577
7678 def setup_method(self, func):
7779 @unwrap_spec(name='text', init='text', body='text')
9092 %(body)s
9193
9294 PyMODINIT_FUNC
93 init%(name)s(void) {
95 #if PY_MAJOR_VERSION >= 3
96 PyInit_%(name)s(void)
97 #else
98 init%(name)s(void)
99 #endif
100 {
94101 %(init)s
95102 }
96103 """ % dict(name=name, init=init, body=body)
113120 name = 'bar'
114121
115122 init = """
116 if (Py_IsInitialized())
123 #if PY_MAJOR_VERSION >= 3
124 static struct PyModuleDef moduledef = {
125 PyModuleDef_HEAD_INIT,
126 "bar", "Module Doc", -1, methods, NULL, NULL, NULL, NULL,
127 };
128 #endif
129
130 if (Py_IsInitialized()) {
131 #if PY_MAJOR_VERSION >= 3
132 PyObject *module = PyModule_Create(&moduledef);
133 #else
117134 Py_InitModule("bar", methods);
135 #endif
136 }
118137 """
119138
120139 # note: only the symbols are needed for C, none for python
1313 def setup_class(cls):
1414 cls.w_test_dct = cls.space.newtext(test_dct)
1515 cls.w_datatypes = cls.space.appexec([], """():
16 import ctypes
16 import ctypes, _cppyy
17 _cppyy._post_import_startup()
1718 return ctypes.CDLL(%r, ctypes.RTLD_GLOBAL)""" % (test_dct, ))
1819 cls.w_N = cls.space.newint(5) # should be imported from the dictionary
1920
5455 assert round(c.m_double + 77., 11) == 0
5556 assert round(c.get_double_cr() + 77., 11) == 0
5657 assert round(c.get_double_r() + 77., 11) == 0
57 #assert round(c.m_ldouble + 88., 24) == 0
58 #assert round(c.get_ldouble_cr() + 88., 24) == 0
59 #assert round(c.get_ldouble_r() + 88., 24) == 0
60 assert round(c.m_double + 77., 8) == 0
58 assert round(c.m_ldouble + 88., 24) == 0
59 assert round(c.get_ldouble_cr() + 88., 24) == 0
60 assert round(c.get_ldouble_r() + 88., 24) == 0
61 assert round(c.get_ldouble_def() -1., 24) == 0
62 assert round(c.get_ldouble_def(2) -2., 24) == 0
63
64 """# complex<double> type
65 assert type(c.get_complex()) == complex
66 assert round(c.get_complex().real - 99., 11) == 0
67 assert round(c.get_complex().imag - 101., 11) == 0
68 assert repr(c.get_complex()) == '(99+101j)'
69 assert round(c.get_complex_cr().real - 99., 11) == 0
70 assert round(c.get_complex_cr().imag - 101., 11) == 0
71 assert round(c.get_complex_r().real - 99., 11) == 0
72 assert round(c.get_complex_r().imag - 101., 11) == 0
73 assert complex(cppyy.gbl.std.complex['double'](1, 2)) == complex(1, 2)
74
75 # complex<int> retains C++ type in all cases (but includes pythonization to
76 # resemble Python's complex more closely
77 assert type(c.get_icomplex()) == cppyy.gbl.std.complex[int]
78 assert round(c.get_icomplex().real - 121., 11) == 0
79 assert round(c.get_icomplex().imag - 141., 11) == 0
80 assert repr(c.get_icomplex()) == '(121+141j)'
81 assert round(c.get_icomplex_cr().real - 121., 11) == 0
82 assert round(c.get_icomplex_cr().imag - 141., 11) == 0
83 assert type(c.get_icomplex_r()) == cppyy.gbl.std.complex[int]
84 assert round(c.get_icomplex_r().real - 121., 11) == 0
85 assert round(c.get_icomplex_r().imag - 141., 11) == 0
86 assert complex(cppyy.gbl.std.complex['int'](1, 2)) == complex(1, 2)"""
6187
6288 # reading of enum types
6389 assert c.m_enum == CppyyTestData.kNothing
7197 assert c.get_bool_array2()[i] == bool((i+1)%2)
7298
7399 # reading of integer array types
74 names = [ 'short', 'ushort', 'int', 'uint', 'long', 'ulong']
75 alpha = [(-1, -2), (3, 4), (-5, -6), (7, 8), (-9, -10), (11, 12)]
100 names = ['uchar', 'short', 'ushort', 'int', 'uint', 'long', 'ulong']
101 alpha = [ (1, 2), (-1, -2), (3, 4), (-5, -6), (7, 8), (-9, -10), (11, 12)]
76102 for j in range(self.N):
77103 assert getattr(c, 'm_%s_array' % names[i])[i] == alpha[i][0]*i
78104 assert getattr(c, 'get_%s_array' % names[i])()[i] == alpha[i][0]*i
87113 assert round(c.m_double_array2[k] + 16.*k, 8) == 0
88114
89115 # out-of-bounds checks
116 raises(IndexError, c.m_uchar_array.__getitem__, self.N)
90117 raises(IndexError, c.m_short_array.__getitem__, self.N)
91118 raises(IndexError, c.m_ushort_array.__getitem__, self.N)
92119 raises(IndexError, c.m_int_array.__getitem__, self.N)
162189 assert eval('c.m_%s' % names[i]) == 3*i
163190
164191 # float types through functions
165 c.set_float( 0.123 ); assert round(c.get_float() - 0.123, 5) == 0
166 c.set_double( 0.456 ); assert round(c.get_double() - 0.456, 8) == 0
192 c.set_float(0.123); assert round(c.get_float() - 0.123, 5) == 0
193 c.set_double(0.456); assert round(c.get_double() - 0.456, 8) == 0
194 c.set_ldouble(0.789); assert round(c.get_ldouble() - 0.789, 8) == 0
167195
168196 # float types through data members
169 c.m_float = 0.123; assert round(c.get_float() - 0.123, 5) == 0
170 c.set_float(0.234); assert round(c.m_float - 0.234, 5) == 0
171 c.set_float_cr(0.456); assert round(c.m_float - 0.456, 5) == 0
172 c.m_double = 0.678; assert round(c.get_double() - 0.678, 8) == 0
173 c.set_double(0.890); assert round(c.m_double - 0.890, 8) == 0
174 c.set_double_cr(0.012); assert round(c.m_double - 0.012, 8) == 0
197 c.m_float = 0.123; assert round(c.get_float() - 0.123, 5) == 0
198 c.set_float(0.234); assert round(c.m_float - 0.234, 5) == 0
199 c.set_float_cr(0.456); assert round(c.m_float - 0.456, 5) == 0
200 c.m_double = 0.678; assert round(c.get_double() - 0.678, 8) == 0
201 c.set_double(0.890); assert round(c.m_double - 0.890, 8) == 0
202 c.set_double_cr(0.012); assert round(c.m_double - 0.012, 8) == 0
203 c.m_ldouble = 0.876; assert round(c.get_ldouble() - 0.876, 8) == 0
204 c.set_ldouble(0.098); assert round(c.m_ldouble - 0.098, 8) == 0
205 c.set_ldouble_cr(0.210); assert round(c.m_ldouble - 0.210, 8) == 0
175206
176207 # arrays; there will be pointer copies, so destroy the current ones
177208 c.destroy_arrays()
178209
179210 # integer arrays
180 names = ['short', 'ushort', 'int', 'uint', 'long', 'ulong']
211 names = ['uchar', 'short', 'ushort', 'int', 'uint', 'long', 'ulong']
181212 import array
182213 a = range(self.N)
183 atypes = ['h', 'H', 'i', 'I', 'l', 'L' ]
214 atypes = ['B', 'h', 'H', 'i', 'I', 'l', 'L']
184215 for j in range(len(names)):
185216 b = array.array(atypes[j], a)
186217 setattr(c, 'm_'+names[j]+'_array', b) # buffer copies
188219 assert eval('c.m_%s_array[i]' % names[j]) == b[i]
189220
190221 setattr(c, 'm_'+names[j]+'_array2', b) # pointer copies
191 b[i] = 28
222 assert 3 < self.N
223 b[3] = 28
192224 for i in range(self.N):
193225 assert eval('c.m_%s_array2[i]' % names[j]) == b[i]
194226
227 # can not write to constant data
228 assert c.m_const_int == 17
229 raises(TypeError, setattr, c, 'm_const_int', 71)
230
195231 c.__destruct__()
196232
197233 def test03_array_passing(self):
205241
206242 a = range(self.N)
207243 # test arrays in mixed order, to give overload resolution a workout
208 for t in ['d', 'i', 'f', 'H', 'I', 'h', 'L', 'l' ]:
244 for t in ['d', 'i', 'f', 'H', 'I', 'h', 'L', 'l']:
209245 b = array.array(t, a)
210246
211247 # typed passing
265301 assert CppyyTestData.s_ullong == 404
266302
267303 # floating point types
268 assert round(CppyyTestData.s_float + 606., 5) == 0
269 assert round(c.s_float + 606., 5) == 0
270 assert round(CppyyTestData.s_double + 707., 8) == 0
271 assert round(c.s_double + 707., 8) == 0
304 assert round(CppyyTestData.s_float + 606., 5) == 0
305 assert round(c.s_float + 606., 5) == 0
306 assert round(CppyyTestData.s_double + 707., 8) == 0
307 assert round(c.s_double + 707., 8) == 0
308 assert round(CppyyTestData.s_ldouble + 808., 8) == 0
309 assert round(c.s_ldouble + 808., 8) == 0
272310
273311 c.__destruct__()
274312
333371 assert CppyyTestData.s_double == -math.pi
334372 CppyyTestData.s_double = math.pi
335373 assert c.s_double == math.pi
374 c.s_ldouble = -math.pi
375 assert CppyyTestData.s_ldouble == -math.pi
376 CppyyTestData.s_ldouble = math.pi
377 assert c.s_ldouble == math.pi
336378
337379 c.__destruct__()
338380
465507 assert gbl.kBanana == 29
466508 assert gbl.kCitrus == 34
467509
510 assert gbl.EnumSpace.E
511 assert gbl.EnumSpace.EnumClass.E1 == -1 # anonymous
512 assert gbl.EnumSpace.EnumClass.E2 == -1 # named type
513
514 # typedef enum
515 assert gbl.EnumSpace.letter_code
516 assert gbl.EnumSpace.AA == 1
517 assert gbl.EnumSpace.BB == 2
518
468519 def test11_string_passing(self):
469520 """Test passing/returning of a const char*"""
470521
475526 assert c.get_valid_string('aap') == 'aap'
476527 #assert c.get_invalid_string() == ''
477528
478 def test12_copy_contructor(self):
529 def test12_copy_constructor(self):
479530 """Test copy constructor"""
480531
481532 import _cppyy as cppyy
673724
674725 c = CppyyTestData()
675726 for func in ['get_bool_array', 'get_bool_array2',
727 'get_uchar_array', 'get_uchar_array2',
676728 'get_ushort_array', 'get_ushort_array2',
677729 'get_int_array', 'get_int_array2',
678730 'get_uint_array', 'get_uint_array2',
679731 'get_long_array', 'get_long_array2',
680732 'get_ulong_array', 'get_ulong_array2']:
681733 arr = getattr(c, func)()
682 arr = arr.shape.fromaddress(arr.itemaddress(0), self.N)
683
684 """TODO: interface change ...
685734 arr.reshape((self.N,))
686735 assert len(arr) == self.N
687736
693742
694743 l = list(arr)
695744 for i in range(self.N):
696 assert arr[i] == l[i]"""
745 assert arr[i] == l[i]
697746
698747 def test20_voidp(self):
699748 """Test usage of void* data"""
742791
743792 c.s_voidp = c2
744793 address_equality_test(c.s_voidp, c2)
794
795 def test21_function_pointers(self):
796 """Function pointer passing"""
797
798 import os
799
800 # TODO: currently crashes if fast path disabled
801 try:
802 if os.environ['CPPYY_DISABLE_FASTPATH']:
803 return
804 except KeyError:
805 pass
806
807 import _cppyy as cppyy
808
809 f1 = cppyy.gbl.sum_of_int
810 f2 = cppyy.gbl.sum_of_double
811 f3 = cppyy.gbl.call_double_double
812
813 assert 5 == f1(2, 3)
814 assert 5. == f2(5., 0.)
815
816 raises(TypeError, f3, f1, 2, 3)
817
818 assert 5. == f3(f2, 5., 0.)
1313 def setup_class(cls):
1414 cls.w_test_dct = cls.space.newtext(test_dct)
1515 cls.w_fragile = cls.space.appexec([], """():
16 import ctypes
16 import ctypes, _cppyy
17 _cppyy._post_import_startup()
1718 return ctypes.CDLL(%r, ctypes.RTLD_GLOBAL)""" % (test_dct, ))
1819
1920 def test01_missing_classes(self):
4949
5050 assert helper.map_operator_name(None, "func", 0, "") == "func"
5151 assert helper.map_operator_name(None, "some_method", 0, "") == "some_method"
52
53
54 def test_namespace_extraction():
55 from pypy.module._cppyy import pythonify
56
57 assert pythonify.extract_namespace("vector")[0] == ""
58 assert pythonify.extract_namespace("std::vector")[0] == "std"
59 assert pythonify.extract_namespace("std::vector<double>")[0] == "std"
60 assert pythonify.extract_namespace("std::vector<std::vector>")[0] == "std"
61 assert pythonify.extract_namespace("vector<double>")[0] == ""
62 assert pythonify.extract_namespace("vector<std::vector>")[0] == ""
63 assert pythonify.extract_namespace("aap::noot::mies::zus")[0] == "aap::noot::mies"
1414 cls.w_N = cls.space.newint(5) # should be imported from the dictionary
1515 cls.w_test_dct = cls.space.newtext(test_dct)
1616 cls.w_operators = cls.space.appexec([], """():
17 import ctypes
17 import ctypes, _cppyy
18 _cppyy._post_import_startup()
1819 return ctypes.CDLL(%r, ctypes.RTLD_GLOBAL)""" % (test_dct, ))
1920
2021 def teardown_method(self, meth):
1616 def setup_class(cls):
1717 cls.w_test_dct = cls.space.newtext(test_dct)
1818 cls.w_overloads = cls.space.appexec([], """():
19 import ctypes
19 import ctypes, _cppyy
20 _cppyy._post_import_startup()
2021 return ctypes.CDLL(%r, ctypes.RTLD_GLOBAL)""" % (test_dct, ))
2122
2223 def test01_class_based_overloads(self):
5657 c = c_overload()
5758 raises(TypeError, c.__dispatch__, 'get_int', 12)
5859 raises(LookupError, c.__dispatch__, 'get_int', 'does_not_exist')
59 assert c.__dispatch__('get_int', 'a_overload*')(a_overload()) == 42
60 assert c.__dispatch__('get_int', 'b_overload*')(b_overload()) == 13
60 assert c.__dispatch__('get_int', 'a_overload*')(a_overload()) == 42
61 assert c_overload.get_int.__overload__('a_overload*')(c, a_overload()) == 42
62 assert c.__dispatch__('get_int', 'b_overload*')(b_overload()) == 13
63 assert c_overload.get_int.__overload__('b_overload*')(c, b_overload()) == 13
6164
6265 assert c_overload().__dispatch__('get_int', 'a_overload*')(a_overload()) == 42
6366 # TODO: #assert c_overload.__dispatch__('get_int', 'b_overload*')(c, b_overload()) == 13
6467
6568 d = d_overload()
66 assert d.__dispatch__('get_int', 'a_overload*')(a_overload()) == 42
67 assert d.__dispatch__('get_int', 'b_overload*')(b_overload()) == 13
69 assert d.__dispatch__('get_int', 'a_overload*')(a_overload()) == 42
70 assert d_overload.get_int.__overload__('a_overload*')(d, a_overload()) == 42
71 assert d.__dispatch__('get_int', 'b_overload*')(b_overload()) == 13
72 assert d_overload.get_int.__overload__('b_overload*')(d, b_overload()) == 13
6873
6974 nb = ns_a_overload.b_overload()
7075 raises(TypeError, nb.f, c_overload())
1515 def setup_class(cls):
1616 cls.w_test_dct = cls.space.newtext(test_dct)
1717 cls.w_example01 = cls.space.appexec([], """():
18 import ctypes
18 import ctypes, _cppyy
19 _cppyy._post_import_startup()
1920 return ctypes.CDLL(%r, ctypes.RTLD_GLOBAL)""" % (test_dct, ))
2021
2122 def test01_finding_classes(self):
314315
315316 _cppyy.gbl.example01.fresh = _cppyy.gbl.installableAddOneToInt
316317
317 e = _cppyy.gbl.example01(0)
318 e = _cppyy.gbl.example01(0)
318319 assert 2 == e.fresh(1)
319320 assert 3 == e.fresh(2)
320321
374375
375376 import _cppyy
376377
377 def example01a_pythonize(pyclass):
378 assert pyclass.__name__ == 'example01a'
379 def getitem(self, idx):
380 return self.addDataToInt(idx)
381 pyclass.__getitem__ = getitem
382
383 _cppyy.add_pythonization('example01a', example01a_pythonize)
378 def example01a_pythonize(pyclass, name):
379 if name == 'example01a':
380 def getitem(self, idx):
381 return self.addDataToInt(idx)
382 pyclass.__getitem__ = getitem
383
384 _cppyy.add_pythonization(example01a_pythonize)
384385
385386 e = _cppyy.gbl.example01a(1)
386387
0 import py, os, sys
1 from pytest import raises
2 from .support import setup_make
3
4
5 currpath = py.path.local(__file__).dirpath()
6 test_dct = str(currpath.join("pythonizablesDict.so"))
7
8 def setup_module(mod):
9 setup_make("pythonizablesDict.so")
10
11 class AppTestPYTHONIZATION:
12 spaceconfig = dict(usemodules=['_cppyy', '_rawffi', 'itertools'])
13
14 def setup_class(cls):
15 cls.w_test_dct = cls.space.newtext(test_dct)
16 cls.w_datatypes = cls.space.appexec([], """():
17 import ctypes, _cppyy
18 _cppyy._post_import_startup()
19 class py(object):
20 pass
21 py.add_pythonization = _cppyy.add_pythonization
22 py.remove_pythonization = _cppyy.remove_pythonization
23 py.pin_type = _cppyy._pin_type
24 _cppyy.py = py
25 return ctypes.CDLL(%r, ctypes.RTLD_GLOBAL)""" % (test_dct, ))
26
27 def test00_api(self):
28 """Test basic semantics of the pythonization API"""
29
30 import _cppyy as cppyy
31
32 raises(TypeError, cppyy.py.add_pythonization, 1)
33
34 def pythonizor1(klass, name):
35 pass
36
37 def pythonizor2(klass, name):
38 pass
39
40 pythonizor3 = pythonizor1
41
42 cppyy.py.add_pythonization(pythonizor1)
43 assert cppyy.py.remove_pythonization(pythonizor2) == False
44 assert cppyy.py.remove_pythonization(pythonizor3) == True
45
46 def pythonizor(klass, name):
47 if name == 'pyzables::SomeDummy1':
48 klass.test = 1
49
50 cppyy.py.add_pythonization(pythonizor)
51 assert cppyy.gbl.pyzables.SomeDummy1.test == 1
52
53 def pythonizor(klass, name):
54 if name == 'SomeDummy2':
55 klass.test = 2
56 cppyy.py.add_pythonization(pythonizor, 'pyzables')
57
58 def pythonizor(klass, name):
59 if name == 'pyzables::SomeDummy2':
60 klass.test = 3
61 cppyy.py.add_pythonization(pythonizor)
62
63 assert cppyy.gbl.pyzables.SomeDummy2.test == 2
64
65 def test01_type_pinning(self):
66 """Verify pinnability of returns"""
67
68 import _cppyy as cppyy
69
70 cppyy.gbl.pyzables.GimeDerived.__creates__ = True
71
72 result = cppyy.gbl.pyzables.GimeDerived()
73 assert type(result) == cppyy.gbl.pyzables.MyDerived
74
75 cppyy.py.pin_type(cppyy.gbl.pyzables.MyBase)
76 assert type(result) == cppyy.gbl.pyzables.MyDerived
77
78 def test02_transparency(self):
79 """Transparent use of smart pointers"""
80
81 import _cppyy as cppyy
82
83 Countable = cppyy.gbl.pyzables.Countable
84 mine = cppyy.gbl.pyzables.mine
85
86 assert type(mine) == Countable
87 assert mine.m_check == 0xcdcdcdcd
88 assert type(mine.__smartptr__()) == cppyy.gbl.std.shared_ptr(Countable)
89 assert mine.__smartptr__().get().m_check == 0xcdcdcdcd
90 assert mine.say_hi() == "Hi!"
91
92 def test03_converters(self):
93 """Smart pointer argument passing"""
94
95 import _cppyy as cppyy
96
97 pz = cppyy.gbl.pyzables
98 mine = pz.mine
99
100 assert 0xcdcdcdcd == pz.pass_mine_rp_ptr(mine)
101 assert 0xcdcdcdcd == pz.pass_mine_rp_ref(mine)
102 assert 0xcdcdcdcd == pz.pass_mine_rp(mine)
103
104 assert 0xcdcdcdcd == pz.pass_mine_sp_ptr(mine)
105 assert 0xcdcdcdcd == pz.pass_mine_sp_ref(mine)
106
107 assert 0xcdcdcdcd == pz.pass_mine_sp_ptr(mine.__smartptr__())
108 assert 0xcdcdcdcd == pz.pass_mine_sp_ref(mine.__smartptr__())
109
110 assert 0xcdcdcdcd == pz.pass_mine_sp(mine)
111 assert 0xcdcdcdcd == pz.pass_mine_sp(mine.__smartptr__())
112
113 # TODO:
114 # cppyy.gbl.mine = mine
115 pz.renew_mine()
116
117 def test04_executors(self):
118 """Smart pointer return types"""
119
120 import _cppyy as cppyy
121
122 pz = cppyy.gbl.pyzables
123 Countable = pz.Countable
124
125 mine = pz.gime_mine_ptr()
126 assert type(mine) == Countable
127 assert mine.m_check == 0xcdcdcdcd
128 assert type(mine.__smartptr__()) == cppyy.gbl.std.shared_ptr(Countable)
129 assert mine.__smartptr__().get().m_check == 0xcdcdcdcd
130 assert mine.say_hi() == "Hi!"
131
132 mine = pz.gime_mine_ref()
133 assert type(mine) == Countable
134 assert mine.m_check == 0xcdcdcdcd
135 assert type(mine.__smartptr__()) == cppyy.gbl.std.shared_ptr(Countable)
136 assert mine.__smartptr__().get().m_check == 0xcdcdcdcd
137 assert mine.say_hi() == "Hi!"
138
139 mine = pz.gime_mine()
140 assert type(mine) == Countable
141 assert mine.m_check == 0xcdcdcdcd
142 assert type(mine.__smartptr__()) == cppyy.gbl.std.shared_ptr(Countable)
143 assert mine.__smartptr__().get().m_check == 0xcdcdcdcd
144 assert mine.say_hi() == "Hi!"
145
146 def test05_creates_flag(self):
147 """Effect of creates flag on return type"""
148
149 import _cppyy as cppyy
150 import gc
151
152 pz = cppyy.gbl.pyzables
153 Countable = pz.Countable
154
155 gc.collect()
156 oldcount = Countable.sInstances # there's eg. one global variable
157
158 pz.gime_naked_countable.__creates__ = True
159 for i in range(10):
160 cnt = pz.gime_naked_countable()
161 gc.collect()
162 assert Countable.sInstances == oldcount + 1
163 del cnt
164 gc.collect()
165
166 assert Countable.sInstances == oldcount
167
168 def test06_api_regression_test(self):
169 """Used to fail b/c klass touched in cppyy"""
170
171 import _cppyy as cppyy
172
173 def root_pythonizor(klass, name):
174 if name == 'TString':
175 klass.__len__ = klass.Length
176
177 cppyy.py.add_pythonization(root_pythonizor)
178
179 assert len(cppyy.gbl.TString("aap")) == 3
1414 cls.w_N = cls.space.newint(13)
1515 cls.w_test_dct = cls.space.newtext(test_dct)
1616 cls.w_stlvector = cls.space.appexec([], """():
17 import ctypes
17 import ctypes, _cppyy
18 _cppyy._post_import_startup()
1819 return ctypes.CDLL(%r, ctypes.RTLD_GLOBAL)""" % (test_dct, ))
1920
2021 def test01_builtin_type_vector_types(self):
2122 """Test access to std::vector<int>/std::vector<double>"""
2223
23 import _cppyy
24
25 assert _cppyy.gbl.std is _cppyy.gbl.std
26 assert _cppyy.gbl.std.vector is _cppyy.gbl.std.vector
27
28 assert callable(_cppyy.gbl.std.vector)
24 import _cppyy as cppyy
25
26 assert cppyy.gbl.std is cppyy.gbl.std
27 assert cppyy.gbl.std.vector is cppyy.gbl.std.vector
28
29 assert callable(cppyy.gbl.std.vector)
2930
3031 type_info = (
3132 ("int", int),
3435 )
3536
3637 for c_type, p_type in type_info:
37 tv1 = getattr(_cppyy.gbl.std, 'vector<%s>' % c_type)
38 tv2 = _cppyy.gbl.std.vector(p_type)
38 tv1 = getattr(cppyy.gbl.std, 'vector<%s>' % c_type)
39 tv2 = cppyy.gbl.std.vector(p_type)
3940 assert tv1 is tv2
40 assert tv1.iterator is _cppyy.gbl.std.vector(p_type).iterator
41 assert tv1.iterator is cppyy.gbl.std.vector(p_type).iterator
4142
4243 #-----
43 v = tv1(); v += range(self.N) # default args from Reflex are useless :/
44 if p_type == int: # only type with == and != reflected in .xml
44 v = tv1(); v += range(self.N)
45 if p_type == int:
4546 assert v.begin().__eq__(v.begin())
4647 assert v.begin() == v.begin()
4748 assert v.end() == v.end()
5657
5758 assert v.size() == self.N
5859 assert len(v) == self.N
60 assert len(v.data()) == self.N
5961
6062 #-----
6163 v = tv1()
7173 def test02_user_type_vector_type(self):
7274 """Test access to an std::vector<just_a_class>"""
7375
74 import _cppyy
75
76 assert _cppyy.gbl.std is _cppyy.gbl.std
77 assert _cppyy.gbl.std.vector is _cppyy.gbl.std.vector
78
79 assert callable(_cppyy.gbl.std.vector)
80
81 tv1 = getattr(_cppyy.gbl.std, 'vector<just_a_class>')
82 tv2 = _cppyy.gbl.std.vector('just_a_class')
83 tv3 = _cppyy.gbl.std.vector(_cppyy.gbl.just_a_class)
76 import _cppyy as cppyy
77
78 assert cppyy.gbl.std is cppyy.gbl.std
79 assert cppyy.gbl.std.vector is cppyy.gbl.std.vector
80
81 assert callable(cppyy.gbl.std.vector)
82
83 tv1 = getattr(cppyy.gbl.std, 'vector<just_a_class>')
84 tv2 = cppyy.gbl.std.vector('just_a_class')
85 tv3 = cppyy.gbl.std.vector(cppyy.gbl.just_a_class)
8486
8587 assert tv1 is tv2
8688 assert tv2 is tv3
9395 assert hasattr(v, 'end' )
9496
9597 for i in range(self.N):
96 v.push_back(_cppyy.gbl.just_a_class())
98 v.push_back(cppyy.gbl.just_a_class())
9799 v[i].m_i = i
98100 assert v[i].m_i == i
99101
103105 def test03_empty_vector_type(self):
104106 """Test behavior of empty std::vector<int>"""
105107
106 import _cppyy
107
108 v = _cppyy.gbl.std.vector(int)()
108 import _cppyy as cppyy
109
110 v = cppyy.gbl.std.vector(int)()
109111 for arg in v:
110112 pass
111113 v.__destruct__()
113115 def test04_vector_iteration(self):
114116 """Test iteration over an std::vector<int>"""
115117
116 import _cppyy
117
118 v = _cppyy.gbl.std.vector(int)()
118 import _cppyy as cppyy
119
120 v = cppyy.gbl.std.vector(int)()
119121
120122 for i in range(self.N):
121123 v.push_back(i)
138140 def test05_push_back_iterables_with_iadd(self):
139141 """Test usage of += of iterable on push_back-able container"""
140142
141 import _cppyy
142
143 v = _cppyy.gbl.std.vector(int)()
143 import _cppyy as cppyy
144
145 v = cppyy.gbl.std.vector(int)()
144146
145147 v += [1, 2, 3]
146148 assert len(v) == 3
157159 raises(TypeError, v.__iadd__, (7, '8')) # string shouldn't pass
158160 assert len(v) == 7 # TODO: decide whether this should roll-back
159161
160 v2 = _cppyy.gbl.std.vector(int)()
162 v2 = cppyy.gbl.std.vector(int)()
161163 v2 += [8, 9]
162164 assert len(v2) == 2
163165 assert v2[0] == 8
172174 def test06_vector_indexing(self):
173175 """Test python-style indexing to an std::vector<int>"""
174176
175 import _cppyy
176
177 v = _cppyy.gbl.std.vector(int)()
177 import _cppyy as cppyy
178
179 v = cppyy.gbl.std.vector(int)()
178180
179181 for i in range(self.N):
180182 v.push_back(i)
194196 assert v2[-1] == v[-2]
195197 assert v2[self.N-4] == v[-2]
196198
199 def test07_vector_bool(self):
200 """Usability of std::vector<bool> which can be a specialization"""
201
202 import _cppyy as cppyy
203
204 vb = cppyy.gbl.std.vector(bool)(8)
205 assert [x for x in vb] == [False]*8
206
207 vb[0] = True
208 assert vb[0]
209 vb[-1] = True
210 assert vb[7]
211
212 assert [x for x in vb] == [True]+[False]*6+[True]
213
214 assert len(vb[4:8]) == 4
215 assert list(vb[4:8]) == [False]*3+[True]
216
217 def test08_vector_enum(self):
218 """Usability of std::vector<> of some enums"""
219
220 import _cppyy as cppyy
221
222 # TODO: would like to use cppyy.gbl.VecTestEnum but that's an int
223 assert cppyy.gbl.VecTestEnum
224 ve = cppyy.gbl.std.vector['VecTestEnum']()
225 ve.push_back(cppyy.gbl.EVal1);
226 assert ve[0] == 1
227 ve[0] = cppyy.gbl.EVal2
228 assert ve[0] == 3
229
230 assert cppyy.gbl.VecTestEnumNS.VecTestEnum
231 ve = cppyy.gbl.std.vector['VecTestEnumNS::VecTestEnum']()
232 ve.push_back(cppyy.gbl.VecTestEnumNS.EVal1);
233 assert ve[0] == 5
234 ve[0] = cppyy.gbl.VecTestEnumNS.EVal2
235 assert ve[0] == 42
236
197237
198238 class AppTestSTLSTRING:
199239 spaceconfig = dict(usemodules=['_cppyy', '_rawffi', 'itertools'])
201241 def setup_class(cls):
202242 cls.w_test_dct = cls.space.newtext(test_dct)
203243 cls.w_stlstring = cls.space.appexec([], """():
204 import ctypes
244 import ctypes, _cppyy
245 _cppyy._post_import_startup()
205246 return ctypes.CDLL(%r, ctypes.RTLD_GLOBAL)""" % (test_dct, ))
206247
207248 def test01_string_argument_passing(self):
208249 """Test mapping of python strings and std::string"""
209250
210 import _cppyy
211 std = _cppyy.gbl.std
212 stringy_class = _cppyy.gbl.stringy_class
251 import _cppyy as cppyy
252 std = cppyy.gbl.std
253 stringy_class = cppyy.gbl.stringy_class
213254
214255 c, s = stringy_class(""), std.string("test1")
215256
238279 def test02_string_data_access(self):
239280 """Test access to std::string object data members"""
240281
241 import _cppyy
242 std = _cppyy.gbl.std
243 stringy_class = _cppyy.gbl.stringy_class
282 import _cppyy as cppyy
283 std = cppyy.gbl.std
284 stringy_class = cppyy.gbl.stringy_class
244285
245286 c, s = stringy_class("dummy"), std.string("test string")
246287
259300
260301 return # don't bother; is fixed in cling-support
261302
262 import _cppyy
263 std = _cppyy.gbl.std
264 stringy_class = _cppyy.gbl.stringy_class
303 import _cppyy as cppyy
304 std = cppyy.gbl.std
305 stringy_class = cppyy.gbl.stringy_class
265306
266307 t0 = "aap\0noot"
267308 assert t0 == "aap\0noot"
271312 c.set_string1(s)
272313 assert t0 == c.get_string1()
273314 assert s == c.get_string1()
315
316 def test04_array_of_strings(self):
317 """Access to global arrays of strings"""
318
319 import _cppyy as cppyy
320
321 assert tuple(cppyy.gbl.str_array_1) == ('a', 'b', 'c')
322 str_array_2 = cppyy.gbl.str_array_2
323 # fix up the size
324 str_array_2.size = 4
325 assert tuple(str_array_2) == ('d', 'e', 'f', 'g')
326 assert tuple(str_array_2) == ('d', 'e', 'f', 'g')
327
328 # multi-dimensional
329 vals = ['a', 'b', 'c', 'd', 'e', 'f']
330 str_array_3 = cppyy.gbl.str_array_3
331 for i in range(3):
332 for j in range(2):
333 assert str_array_3[i][j] == vals[i*2+j]
334
335 vals = ['a', 'b', 'c', 'd', 'e', 'f', 'g', 'h',
336 'i', 'j', 'k', 'l', 'm', 'n', 'o', 'p']
337 str_array_4 = cppyy.gbl.str_array_4
338 for i in range(4):
339 for j in range(2):
340 for k in range(2):
341 assert str_array_4[i][j][k] == vals[i*4+j*2+k]
274342
275343
276344 class AppTestSTLLIST:
280348 cls.w_N = cls.space.newint(13)
281349 cls.w_test_dct = cls.space.newtext(test_dct)
282350 cls.w_stlstring = cls.space.appexec([], """():
283 import ctypes
351 import ctypes, _cppyy
352 _cppyy._post_import_startup()
284353 return ctypes.CDLL(%r, ctypes.RTLD_GLOBAL)""" % (test_dct, ))
285354
286355 def test01_builtin_list_type(self):
287356 """Test access to a list<int>"""
288357
289 import _cppyy
290 std = _cppyy.gbl.std
358 import _cppyy as cppyy
359 std = cppyy.gbl.std
291360
292361 type_info = (
293362 ("int", int),
297366
298367 for c_type, p_type in type_info:
299368 tl1 = getattr(std, 'list<%s>' % c_type)
300 tl2 = _cppyy.gbl.std.list(p_type)
369 tl2 = cppyy.gbl.std.list(p_type)
301370 assert tl1 is tl2
302 assert tl1.iterator is _cppyy.gbl.std.list(p_type).iterator
371 assert tl1.iterator is cppyy.gbl.std.list(p_type).iterator
303372
304373 #-----
305374 a = tl1()
321390 def test02_empty_list_type(self):
322391 """Test behavior of empty list<int>"""
323392
324 import _cppyy
325 std = _cppyy.gbl.std
393 import _cppyy as cppyy
394 std = cppyy.gbl.std
326395
327396 a = std.list(int)()
328397 for arg in a:
336405 cls.w_N = cls.space.newint(13)
337406 cls.w_test_dct = cls.space.newtext(test_dct)
338407 cls.w_stlstring = cls.space.appexec([], """():
339 import ctypes
408 import ctypes, _cppyy
409 _cppyy._post_import_startup()
340410 return ctypes.CDLL(%r, ctypes.RTLD_GLOBAL)""" % (test_dct, ))
341411
342412 def test01_builtin_map_type(self):
343413 """Test access to a map<int,int>"""
344414
345 import _cppyy
346 std = _cppyy.gbl.std
415 import _cppyy as cppyy
416 std = cppyy.gbl.std
347417
348418 a = std.map(int, int)()
349419 for i in range(self.N):
371441 def test02_keyed_maptype(self):
372442 """Test access to a map<std::string,int>"""
373443
374 import _cppyy
375 std = _cppyy.gbl.std
444 import _cppyy as cppyy
445 std = cppyy.gbl.std
376446
377447 a = std.map(std.string, int)()
378448 for i in range(self.N):
384454 def test03_empty_maptype(self):
385455 """Test behavior of empty map<int,int>"""
386456
387 import _cppyy
388 std = _cppyy.gbl.std
457 import _cppyy as cppyy
458 std = cppyy.gbl.std
389459
390460 m = std.map(int, int)()
391461 for key, value in m:
394464 def test04_unsignedvalue_typemap_types(self):
395465 """Test assignability of maps with unsigned value types"""
396466
397 import _cppyy, math, sys
398 std = _cppyy.gbl.std
467 import _cppyy as cppyy
468 import math, sys
469 std = cppyy.gbl.std
399470
400471 mui = std.map(str, 'unsigned int')()
401472 mui['one'] = 1
418489 def test05_STL_like_class_indexing_overloads(self):
419490 """Test overloading of operator[] in STL like class"""
420491
421 import _cppyy
422 stl_like_class = _cppyy.gbl.stl_like_class
492 import _cppyy as cppyy
493 stl_like_class = cppyy.gbl.stl_like_class
423494
424495 a = stl_like_class(int)()
425496 assert a["some string" ] == 'string'
428499 def test06_STL_like_class_iterators(self):
429500 """Test the iterator protocol mapping for an STL like class"""
430501
431 import _cppyy
432 stl_like_class = _cppyy.gbl.stl_like_class
502 import _cppyy as cppyy
503 stl_like_class = cppyy.gbl.stl_like_class
433504
434505 a = stl_like_class(int)()
435 for i in a:
436 pass
437
438 assert i == 3
506 assert len(a) == 4
507 for i, j in enumerate(a):
508 assert i == j
509
510 assert i == len(a)-1
439511
440512
441513 class AppTestSTLITERATOR:
444516 def setup_class(cls):
445517 cls.w_test_dct = cls.space.newtext(test_dct)
446518 cls.w_stlstring = cls.space.appexec([], """():
447 import ctypes
519 import ctypes, _cppyy
520 _cppyy._post_import_startup()
448521 return ctypes.CDLL(%r, ctypes.RTLD_GLOBAL)""" % (test_dct, ))
449522
450523 def test01_builtin_vector_iterators(self):
451524 """Test iterator comparison with operator== reflected"""
452525
453 import _cppyy
454 std = _cppyy.gbl.std
526 import _cppyy as cppyy
527 std = cppyy.gbl.std
455528
456529 v = std.vector(int)()
457530 v.resize(1)
481554 def setup_class(cls):
482555 cls.w_test_dct = cls.space.newtext(test_dct)
483556 cls.w_stlstring = cls.space.appexec([], """():
484 import ctypes
557 import ctypes, _cppyy
558 _cppyy._post_import_startup()
485559 return ctypes.CDLL(%r, ctypes.RTLD_GLOBAL)""" % (test_dct, ))
486560
487561 def test01_explicit_templates(self):
488562 """Explicit use of Template class"""
489563
490 import _cppyy
491
492 vector = _cppyy.Template('vector', _cppyy.gbl.std)
564 import _cppyy as cppyy
565
566 vector = cppyy.Template('vector', cppyy.gbl.std)
493567 assert vector[int] == vector(int)
494568
495569 v = vector[int]()
499573 assert len(v) == N
500574 for i in range(N):
501575 assert v[i] == i
576
577
578 class AppTestSTLARRAY:
579 spaceconfig = dict(usemodules=['_cppyy', '_rawffi', 'itertools'])
580
581 def setup_class(cls):
582 cls.w_test_dct = cls.space.newtext(test_dct)
583 cls.w_stlarray = cls.space.appexec([], """():
584 import ctypes, _cppyy
585 _cppyy._post_import_startup()
586 return ctypes.CDLL(%r, ctypes.RTLD_GLOBAL)""" % (test_dct, ))
587
588 def test01_array_of_basic_types(self):
589 """Usage of std::array of basic types"""
590
591 import _cppyy as cppyy
592 std = cppyy.gbl.std
593
594 a = std.array[int, 4]()
595 assert len(a) == 4
596 for i in range(len(a)):
597 a[i] = i
598 assert a[i] == i
599
600 def test02_array_of_pods(self):
601 """Usage of std::array of PODs"""
602
603 import _cppyy as cppyy
604 gbl, std = cppyy.gbl, cppyy.gbl.std
605
606 a = std.array[gbl.ArrayTest.Point, 4]()
607 assert len(a) == 4
608 for i in range(len(a)):
609 a[i].px = i
610 assert a[i].px == i
611 a[i].py = i**2
612 assert a[i].py == i**2
613
614 def test03_array_of_pointer_to_pods(self):
615 """Usage of std::array of pointer to PODs"""
616
617 import _cppyy as cppyy
618 gbl = cppyy.gbl
619 std = cppyy.gbl.std
620
621 ll = [gbl.ArrayTest.Point() for i in range(4)]
622 for i in range(len(ll)):
623 ll[i].px = 13*i
624 ll[i].py = 42*i
625
626 # more tests in cppyy/test/test_stltypes.py, but currently not supported
1212
1313 def setup_class(cls):
1414 cls.w_test_dct = cls.space.newtext(test_dct)
15 cls.w_datatypes = cls.space.appexec([], """():
16 import ctypes
15 cls.w_templates = cls.space.appexec([], """():
16 import ctypes, _cppyy
17 _cppyy._post_import_startup()
1718 return ctypes.CDLL(%r, ctypes.RTLD_GLOBAL)""" % (test_dct, ))
1819
1920 def test01_template_member_functions(self):
2223 import _cppyy
2324
2425 m = _cppyy.gbl.MyTemplatedMethodClass()
25
26 return
2726
2827 # pre-instantiated
2928 assert m.get_size['char']() == m.get_char_size()
3938
4039 # auto through typedef
4140 assert m.get_size['MyTMCTypedef_t']() == m.get_self_size()
41
42 def test02_non_type_template_args(self):
43 """Use of non-types as template arguments"""
44
45 import _cppyy
46
47 _cppyy.gbl.gInterpreter.Declare("template<int i> int nt_templ_args() { return i; };")
48
49 assert _cppyy.gbl.nt_templ_args[1]() == 1
50 assert _cppyy.gbl.nt_templ_args[256]() == 256
51
52 def test03_templated_function(self):
53 """Templated global and static functions lookup and calls"""
54
55 import _cppyy as cppyy
56
57 # TODO: the following only works if something else has already
58 # loaded the headers associated with this template
59 ggs = cppyy.gbl.global_get_size
60 assert ggs['char']() == 1
61
62 gsf = cppyy.gbl.global_some_foo
63
64 assert gsf[int](3) == 42
65 assert gsf(3) == 42
66 assert gsf(3.) == 42
67
68 gsb = cppyy.gbl.global_some_bar
69
70 assert gsb(3) == 13
71 assert gsb['double'](3.) == 13
72
73 # TODO: the following only works in a namespace
74 nsgsb = cppyy.gbl.SomeNS.some_bar
75
76 assert nsgsb[3]
77 assert nsgsb[3]() == 3
78
79 # TODO: add some static template method
80
81 # test forced creation of subsequent overloads
82 vector = cppyy.gbl.std.vector
83 # float in, float out
84 ggsr = cppyy.gbl.global_get_some_result['std::vector<float>']
85 assert type(ggsr(vector['float']([0.5])).m_retval) == float
86 assert ggsr(vector['float']([0.5])).m_retval == 0.5
87 # int in, float out
88 ggsr = cppyy.gbl.global_get_some_result['std::vector<int>']
89 assert type(ggsr(vector['int']([5])).m_retval) == float
90 assert ggsr(vector['int']([5])).m_retval == 5.
91 # float in, int out
92 # TODO: this now matches the earlier overload
93 #ggsr = cppyy.gbl.global_get_some_result['std::vector<float>, int']
94 #assert type(ggsr(vector['float']([0.3])).m_retval) == int
95 #assert ggsr(vector['float']([0.3])).m_retval == 0
96 # int in, int out
97 # TODO: same as above, matches earlier overload
98 #ggsr = cppyy.gbl.global_get_some_result['std::vector<int>, int']
99 #assert type(ggsr(vector['int']([5])).m_retval) == int
100 #assert ggsr(vector['int']([5])).m_retval == 5
101
102 def test04_variadic_function(self):
103 """Call a variadic function"""
104
105 import _cppyy
106
107 s = _cppyy.gbl.std.ostringstream('(', _cppyy.gbl.std.ios_base.ate)
108 # Fails; selects void* overload (?!)
109 #s << "("
110 _cppyy.gbl.SomeNS.tuplify(s, 1, 4., "aap")
111 assert s.str() == "(1, 4, aap, NULL)"
112
113 _cppyy.gbl.gInterpreter.Declare("""
114 template<typename... myTypes>
115 int test04_variadic_func() { return sizeof...(myTypes); }
116 """)
117
118 assert _cppyy.gbl.test04_variadic_func['int', 'double', 'void*']() == 3
119
120 def test05_variadic_overload(self):
121 """Call an overloaded variadic function"""
122
123 import _cppyy
124
125 assert _cppyy.gbl.isSomeInt(3.) == False
126 assert _cppyy.gbl.isSomeInt(1) == True
127 assert _cppyy.gbl.isSomeInt() == False
128 assert _cppyy.gbl.isSomeInt(1, 2, 3) == False
129
130 def test06_variadic_sfinae(self):
131 """Attribute testing through SFINAE"""
132
133 import _cppyy
134 Obj1 = _cppyy.gbl.AttrTesting.Obj1
135 Obj2 = _cppyy.gbl.AttrTesting.Obj2
136 has_var1 = _cppyy.gbl.AttrTesting.has_var1
137 call_has_var1 = _cppyy.gbl.AttrTesting.call_has_var1
138
139 move = _cppyy.gbl.std.move
140
141 assert has_var1(Obj1()) == hasattr(Obj1(), 'var1')
142 assert has_var1(Obj2()) == hasattr(Obj2(), 'var1')
143 assert has_var1(3) == hasattr(3, 'var1')
144 assert has_var1("aap") == hasattr("aap", 'var1')
145
146 assert call_has_var1(move(Obj1())) == True
147 assert call_has_var1(move(Obj2())) == False
148
149 def test07_type_deduction(self):
150 """Traits/type deduction"""
151
152 import _cppyy
153 Obj1 = _cppyy.gbl.AttrTesting.Obj1
154 Obj2 = _cppyy.gbl.AttrTesting.Obj2
155 select_template_arg = _cppyy.gbl.AttrTesting.select_template_arg
156
157 # assert select_template_arg[0, Obj1, Obj2].argument == Obj1
158 assert select_template_arg[1, Obj1, Obj2].argument == Obj2
159 raises(TypeError, select_template_arg.__getitem__, 2, Obj1, Obj2)
160
161 # TODO, this doesn't work for builtin types as the 'argument'
162 # typedef will not resolve to a class
163 #assert select_template_arg[1, int, float].argument == float
164
165 def test08_using_of_static_data(self):
166 """Derived class using static data of base"""
167
168 import _cppyy
169
170 # TODO: the following should live in templates.h, but currently fails
171 # in TClass::GetListOfMethods()
172 _cppyy.gbl.gInterpreter.Declare("""
173 template <typename T> struct BaseClassWithStatic {
174 static T const ref_value;
175 };
176
177 template <typename T>
178 T const BaseClassWithStatic<T>::ref_value = 42;
179
180 template <typename T>
181 struct DerivedClassUsingStatic : public BaseClassWithStatic<T> {
182 using BaseClassWithStatic<T>::ref_value;
183
184 explicit DerivedClassUsingStatic(T x) : BaseClassWithStatic<T>() {
185 m_value = x > ref_value ? ref_value : x;
186 }
187
188 T m_value;
189 };""")
190
191
192 # TODO: the ref_value property is inaccessible (offset == -1)
193 # assert _cppyy.gbl.BaseClassWithStatic["size_t"].ref_value == 42
194
195 b1 = _cppyy.gbl.DerivedClassUsingStatic["size_t"]( 0)
196 b2 = _cppyy.gbl.DerivedClassUsingStatic["size_t"](100)
197
198 # assert b1.ref_value == 42
199 assert b1.m_value == 0
200
201 # assert b2.ref_value == 42
202 assert b2.m_value == 42
203
204
205 class AppTestBOOSTANY:
206 spaceconfig = dict(usemodules=['_cppyy', '_rawffi', 'itertools'])
207
208 def setup_class(cls):
209 cls.w_test_dct = cls.space.newtext(test_dct)
210 cls.w_templates = cls.space.appexec([], """():
211 import ctypes, _cppyy
212 _cppyy._post_import_startup()""")
213
214 def test01_any_class(self):
215 """Usage of boost::any"""
216
217 import _cppyy
218
219 if not _cppyy.gbl.gInterpreter.Declare('#include "boost/any.hpp"'):
220 import warnings
221 warnings.warn('skipping boost/any testing')
222 return
223
224 assert _cppyy.gbl.boost
225 assert _cppyy.gbl.boost.any
226
227 std, boost = _cppyy.gbl.std, _cppyy.gbl.boost
228
229 assert std.list[boost.any]
230
231 val = boost.any()
232 # test both by-ref and by rvalue
233 v = std.vector[int]()
234 val.__assign__(v)
235 val.__assign__(std.move(std.vector[int](range(100))))
236
237 _cppyy.gbl.gInterpreter.ProcessLine(
238 "namespace _cppyy_internal { auto* stdvectid = &typeid(std::vector<int>); }")
239
240 assert val.type() == _cppyy.gbl._cppyy_internal.stdvectid
241
242 extract = boost.any_cast[std.vector[int]](val)
243 assert type(extract) is std.vector[int]
244 assert len(extract) == 100
245 extract += range(100)
246 assert len(extract) == 200
247
248 val.__assign__(std.move(extract)) # move forced
249
250 # TODO: we hit boost::any_cast<int>(boost::any* operand) instead
251 # of the reference version which raises
252 boost.any_cast.__useffi__ = False
253 try:
254 # raises(Exception, boost.any_cast[int], val)
255 assert not boost.any_cast[int](val)
256 except Exception:
257 # getting here is good, too ...
258 pass
259
260 extract = boost.any_cast[std.vector[int]](val)
261 assert len(extract) == 200
1515 # load cpyext early, or its global vars are counted as leaks in the test
1616 # (note that the module is not otherwise used in the test itself)
1717 import pypy.module.cpyext
18
19 # change capi's direct_ptradd and exchange_address to being jit-opaque
20 @jit.dont_look_inside
21 def _opaque_direct_ptradd(ptr, offset):
22 address = rffi.cast(rffi.CCHARP, ptr)
23 return rffi.cast(capi.C_OBJECT, lltype.direct_ptradd(address, offset))
24 capi.direct_ptradd = _opaque_direct_ptradd
25
26 @jit.dont_look_inside
27 def _opaque_exchange_address(ptr, cif_descr, index):
28 offset = rffi.cast(rffi.LONG, cif_descr.exchange_args[index])
29 return rffi.ptradd(ptr, offset)
30 capi.exchange_address = _opaque_exchange_address
3118
3219 # add missing alt_errno (??)
3320 def get_tlobj(self):
7360 typename = "str"
7461 def __init__(self, val):
7562 self.val = val
63 class FakeTuple(FakeBase):
64 typename = "tuple"
65 def __init__(self, val):
66 self.val = val
7667 class FakeType(FakeBase):
7768 typename = "type"
7869 def __init__(self, name):
7970 self.name = name
8071 self.__name__ = name
8172 def getname(self, space, name):
73 if sys.hexversion < 0x3000000:
74 return self.name
8275 return unicode(self.name)
8376 class FakeBuffer(FakeBase):
8477 typedname = "buffer"
116109 class FakeSpace(object):
117110 fake = True
118111
119 w_None = None
120 w_str = FakeType("str")
121 w_int = FakeType("int")
112 w_None = None
113 w_str = FakeType("str")
114 w_text = FakeType("str")
115 w_bytes = FakeType("str")
116 w_int = FakeType("int")
122117 w_float = FakeType("float")
123118
124119 def __init__(self):
145140 self.w_TypeError = FakeException(self, "TypeError")
146141 self.w_ValueError = FakeException(self, "ValueError")
147142
143 self.w_True = FakeBool(True)
144 self.w_False = FakeBool(False)
145
148146 def issequence_w(self, w_obj):
149147 return True
150148
183181 @specialize.argtype(1)
184182 def newtext(self, obj):
185183 return FakeString(obj)
184
185 @specialize.argtype(1)
186 def newtuple(self, obj):
187 return FakeTuple(obj)
188
189 def getitem(self, coll, i):
190 return coll.val[i.val]
186191
187192 def float_w(self, w_obj, allow_conversion=True):
188193 assert isinstance(w_obj, FakeFloat)
202207 def exception_match(self, typ, sub):
203208 return typ is sub
204209
210 def is_none(self, w_obj):
211 return w_obj is None
212
205213 def is_w(self, w_one, w_two):
206214 return w_one is w_two
207215
264272
265273 def call_function(self, w_func, *args_w):
266274 return None
275
276 def call_obj_args(self, w_callable, w_obj, args):
277 return w_callable.call_args([w_obj]+args)
267278
268279 def _freeze_(self):
269280 return True
280291 def f():
281292 cls = interp_cppyy.scope_byname(space, "example01")
282293 inst = interp_cppyy._bind_object(space, FakeInt(0), cls, True)
283 cls.get_overload("__init__").call(inst, [FakeInt(0)])
294 cls.get_overload("__init__").descr_get(inst, []).call_args([FakeInt(0)])
284295 cppmethod = cls.get_overload(method_name)
285296 assert isinstance(inst, interp_cppyy.W_CPPInstance)
286297 i = 10
287298 while i > 0:
288299 drv.jit_merge_point(inst=inst, cppmethod=cppmethod, i=i)
289 cppmethod.call(inst, [FakeInt(i)])
300 cppmethod.descr_get(inst, []).call_args([FakeInt(i)])
290301 i -= 1
291302 return 7
292303 f()
293304 space = FakeSpace()
294305 result = self.meta_interp(f, [], listops=True, backendopt=True, listcomp=True)
295 self.check_jitcell_token_count(1) # same for fast and slow path??
306 self.check_jitcell_token_count(1)
296307 # rely on replacement of capi calls to raise exception instead (see FakeSpace.__init__)
297308
298309 @py.test.mark.dont_track_allocations("cppmethod.cif_descr kept 'leaks'")
7272 break
7373 raise
7474 self.line_num += 1
75 if space.isinstance_w(w_line, space.w_bytes):
76 raise self.error(u"iterator should return strings, not bytes "
77 u"(did you open the file in text mode?")
7578 line = space.unicode_w(w_line)
7679 for c in line:
7780 if c == u'\0':
3232 def test_cannot_read_bytes(self):
3333 import _csv
3434 reader = _csv.reader([b'foo'])
35 raises((TypeError, _csv.Error), next, reader)
35 raises(_csv.Error, next, reader)
3636
3737 def test_read_oddinputs(self):
3838 self._read_test([], [])
00 import os
1 from rpython.rlib.objectmodel import we_are_translated
12 from pypy.interpreter.mixedmodule import MixedModule
23 from pypy.module.sys import initpath
34 from pypy.module._frozen_importlib import interp_import
7677
7778 def startup(self, space):
7879 """Copy our __import__ to builtins."""
80 if not we_are_translated():
81 self.startup_at_translation_time_only(space)
82 self.space.builtin.setdictvalue(space, '__import__', self.w_import)
83
84 def startup_at_translation_time_only(self, space):
85 # Issue #2834
86 # Call _bootstrap._install() at translation time only, not at
87 # runtime. By looking around what it does, this should not
88 # freeze any machine-specific paths. I *think* it only sets up
89 # stuff that depends on the platform.
7990 w_install = self.getdictvalue(space, '_install')
8091 space.call_function(w_install,
8192 space.getbuiltinmodule('sys'),
8293 space.getbuiltinmodule('_imp'))
83 self.space.builtin.setdictvalue(space, '__import__', self.w_import)
4646 w_bytesio.write(char)
4747 finally:
4848 w_bytesio.seek(tell)
49
50 def get_raw_address(self):
51 raise ValueError("BytesIOBuffer does not have a raw address")
5249
5350
5451 class W_BytesIO(W_BufferedIOBase):
195195 wrap_oserror2(space, e, w_name,
196196 exception_name='w_IOError',
197197 eintr_retry=True)
198 if not rposix._WIN32:
199 try:
200 _open_inhcache.set_non_inheritable(self.fd)
201 except OSError as e:
202 raise wrap_oserror2(space, e, w_name,
203 eintr_retry=False)
198 try:
199 _open_inhcache.set_non_inheritable(self.fd)
200 except OSError as e:
201 raise wrap_oserror2(space, e, w_name,
202 eintr_retry=False)
204203 else:
205204 w_fd = space.call_function(w_opener, w_name,
206205 space.newint(flags))
224223 raise wrap_oserror2(space, e, w_name,
225224 eintr_retry=False)
226225
226
227227 try:
228228 st = os.fstat(self.fd)
229229 except OSError as e:
168168 #
169169 exc = raises(TypeError, readinto, u"hello")
170170 msg = str(exc.value)
171 print(msg)
171 # print(msg)
172172 assert " read-write b" in msg and msg.endswith(", not str")
173173 #
174174 exc = raises(TypeError, readinto, memoryview(b"hello"))
175175 msg = str(exc.value)
176 print(msg)
176 # print(msg)
177177 assert " read-write b" in msg and msg.endswith(", not memoryview")
178178 #
179179 f.close()
110110 #
111111 exc = raises(TypeError, readinto, u"hello")
112112 msg = str(exc.value)
113 print(msg)
113 # print(msg)
114114 assert " read-write b" in msg and msg.endswith(", not str")
115115 #
116116 exc = raises(TypeError, readinto, memoryview(b"hello"))
117117 msg = str(exc.value)
118 print(msg)
118 # print(msg)
119119 assert " read-write b" in msg and msg.endswith(", not memoryview")
120120 #
121121 b.close()
163163 #
164164 exc = raises(TypeError, f.readinto, u"hello")
165165 msg = str(exc.value)
166 print(msg)
166 # print(msg)
167167 assert " read-write b" in msg and msg.endswith(", not str")
168168 #
169169 exc = raises(TypeError, f.readinto, memoryview(b"hello"))
170170 msg = str(exc.value)
171 print(msg)
171 # print(msg)
172172 assert " read-write b" in msg and msg.endswith(", not memoryview")
173173 #
174174 f.close()
278278 raises(FileExistsError, _io.FileIO, filename, 'x')
279279
280280 def test_non_inheritable(self):
281 import _io, posix
281 import _io
282 os = self.posix
282283 f = _io.FileIO(self.tmpfile, 'r')
283 assert posix.get_inheritable(f.fileno()) == False
284 assert os.get_inheritable(f.fileno()) == False
284285 f.close()
285286
286287 def test_FileIO_fd_does_not_change_inheritable(self):
287 import _io, posix
288 fd1, fd2 = posix.pipe()
289 posix.set_inheritable(fd1, True)
290 posix.set_inheritable(fd2, False)
288 import _io
289 os = self.posix
290 fd1, fd2 = os.pipe()
291 os.set_inheritable(fd1, True)
292 os.set_inheritable(fd2, False)
291293 f1 = _io.FileIO(fd1, 'r')
292294 f2 = _io.FileIO(fd2, 'w')
293 assert posix.get_inheritable(fd1) == True
294 assert posix.get_inheritable(fd2) == False
295 assert os.get_inheritable(fd1) == True
296 assert os.get_inheritable(fd2) == False
295297 f1.close()
296298 f2.close()
297299
298300 def test_close_upon_reinit(self):
299 import _io, posix
301 import _io
302 os = self.posix
300303 f = _io.FileIO(self.tmpfile, 'r')
301304 fd1 = f.fileno()
302305 f.__init__(self.tmpfile, 'w')
303306 fd2 = f.fileno()
304307 if fd1 != fd2:
305 raises(OSError, posix.close, fd1)
308 raises(OSError, os.close, fd1)
306309
307310 def test_opener_negative(self):
308311 import _io
5959 TIMESPEC = platform.Struct('struct timespec', [('tv_sec', rffi.TIME_T),
6060 ('tv_nsec', rffi.LONG)])
6161 SEM_FAILED = platform.ConstantInteger('SEM_FAILED')
62 SEM_VALUE_MAX = platform.ConstantInteger('SEM_VALUE_MAX')
62 SEM_VALUE_MAX = platform.DefinedConstantInteger('SEM_VALUE_MAX')
6363 SEM_TIMED_WAIT = platform.Has('sem_timedwait')
6464 SEM_T_SIZE = platform.SizeOf('sem_t')
6565
7272 # rffi.cast(SEM_T, config['SEM_FAILED'])
7373 SEM_FAILED = config['SEM_FAILED']
7474 SEM_VALUE_MAX = config['SEM_VALUE_MAX']
75 if SEM_VALUE_MAX is None: # on Hurd
76 SEM_VALUE_MAX = sys.maxint
7577 SEM_TIMED_WAIT = config['SEM_TIMED_WAIT']
7678 SEM_T_SIZE = config['SEM_T_SIZE']
7779 if sys.platform == 'darwin':
2222 with rffi.scoped_alloc_buffer(buffersize) as buf:
2323 read_bytes = socketrecv(handle, buf.raw, buffersize, 0)
2424 if read_bytes >= 0:
25 return space.newtext(buf.str(read_bytes))
25 return space.newbytes(buf.str(read_bytes))
2626 raise getWindowsError(space)
2727
2828 @unwrap_spec(handle=int, data='bufferstr')
0 from pypy.module._rawffi.alt.test.test_funcptr import BaseAppTestFFI
1
2 class AppTestFFIType(BaseAppTestFFI):
0 class AppTestFFIType(object):
1 spaceconfig = dict(usemodules=('_rawffi',))
32
43 def test_simple_types(self):
54 from _rawffi.alt import types
76 assert str(types.uint) == "<ffi type uint>"
87 assert types.sint.name == 'sint'
98 assert types.uint.name == 'uint'
10
9
1110 def test_sizeof(self):
1211 from _rawffi.alt import types
1312 assert types.sbyte.sizeof() == 1
3534 assert x is types.char_p
3635 x = types.Pointer(types.unichar)
3736 assert x is types.unichar_p
38
190190
191191
192192 W_ArrayInstance.typedef = TypeDef(
193 'ArrayInstance',
193 'ArrayInstance', None, None, "read-write",
194194 __repr__ = interp2app(W_ArrayInstance.descr_repr),
195195 __setitem__ = interp2app(W_ArrayInstance.descr_setitem),
196196 __getitem__ = interp2app(W_ArrayInstance.descr_getitem),
214214 self._free()
215215
216216 W_ArrayInstanceAutoFree.typedef = TypeDef(
217 'ArrayInstanceAutoFree',
217 'ArrayInstanceAutoFree', None, None, "read-write",
218218 __repr__ = interp2app(W_ArrayInstance.descr_repr),
219219 __setitem__ = interp2app(W_ArrayInstance.descr_setitem),
220220 __getitem__ = interp2app(W_ArrayInstance.descr_getitem),
134134 return W_CallbackPtr(space, w_callable, w_args, w_result, flags)
135135
136136 W_CallbackPtr.typedef = TypeDef(
137 'CallbackPtr',
137 'CallbackPtr', None, None, "read",
138138 __new__ = interp2app(descr_new_callbackptr),
139139 byptr = interp2app(W_CallbackPtr.byptr),
140140 buffer = GetSetProperty(W_CallbackPtr.getbuffer),
378378
379379
380380 W_StructureInstance.typedef = TypeDef(
381 'StructureInstance',
381 'StructureInstance', None, None, "read-write",
382382 __repr__ = interp2app(W_StructureInstance.descr_repr),
383383 __getattr__ = interp2app(W_StructureInstance.getattr),
384384 __setattr__ = interp2app(W_StructureInstance.setattr),
400400 self._free()
401401
402402 W_StructureInstanceAutoFree.typedef = TypeDef(
403 'StructureInstanceAutoFree',
403 'StructureInstanceAutoFree', None, None, "read-write",
404404 __repr__ = interp2app(W_StructureInstance.descr_repr),
405405 __getattr__ = interp2app(W_StructureInstance.getattr),
406406 __setattr__ = interp2app(W_StructureInstance.setattr),
147147 return False
148148 return space.isinstance_w(self.w_pattern, space.w_unicode)
149149
150 def getstring(self, w_string):
151 """Accepts a string-like object (str, bytes, bytearray, buffer...)
152 and returns a tuple (len, rpython_unicode, rpython_str, rpython_buf),
153 where only one of the rpython_xxx is non-None.
154 """
155 unicodestr = None
156 string = None
157 buf = None
158 space = self.space
159 if space.isinstance_w(w_string, space.w_unicode):
160 unicodestr = space.unicode_w(w_string)
161 length = len(unicodestr)
162 elif space.isinstance_w(w_string, space.w_bytes):
163 string = space.bytes_w(w_string)
164 length = len(string)
165 else:
166 buf = space.readbuf_w(w_string)
167 length = buf.getlength()
168 assert length >= 0
169 return (length, unicodestr, string, buf)
170
171 def make_ctx(self, w_string, pos=0, endpos=sys.maxint, flags=0):
150 def make_ctx(self, w_string, pos=0, endpos=sys.maxint):
172151 """Make a StrMatchContext, BufMatchContext or a UnicodeMatchContext for
173152 searching in the given w_string object."""
174153 space = self.space
175 length, unicodestr, string, buf = self.getstring(w_string)
176154 if pos < 0:
177155 pos = 0
178 elif pos > length:
179 pos = length
180156 if endpos < pos:
181157 endpos = pos
182 elif endpos > length:
183 endpos = length
184 flags = self.flags | flags
185 #
186 if unicodestr is not None:
158 if space.isinstance_w(w_string, space.w_unicode):
187159 if self.is_known_bytes():
188160 raise oefmt(space.w_TypeError,
189161 "can't use a bytes pattern on a string-like "
190162 "object")
191 return rsre_core.UnicodeMatchContext(unicodestr,
192 pos, endpos, flags)
193 else:
194 if self.is_known_unicode():
195 raise oefmt(space.w_TypeError,
196 "can't use a string pattern on a bytes-like "
197 "object")
198 if string is not None:
199 return rsre_core.StrMatchContext(string,
200 pos, endpos, flags)
201 else:
202 return rsre_core.BufMatchContext(buf,
203 pos, endpos, flags)
163 unicodestr = space.unicode_w(w_string)
164 length = len(unicodestr)
165 if pos > length:
166 pos = length
167 if endpos > length:
168 endpos = length
169 return rsre_core.UnicodeMatchContext(
170 unicodestr, pos, endpos, self.flags)
171 elif self.is_known_unicode():
172 raise oefmt(space.w_TypeError,
173 "can't use a string pattern on a bytes-like "
174 "object")
175 elif space.isinstance_w(w_string, space.w_bytes):
176 string = space.bytes_w(w_string)
177 length = len(string)
178 if pos > length:
179 pos = length
180 if endpos > length:
181 endpos = length
182 return rsre_core.StrMatchContext(string, pos, endpos, self.flags)
183 else:
184 buf = space.readbuf_w(w_string)
185 size = buf.getlength()
186 assert size >= 0
187 if pos > size:
188 pos = size
189 if endpos > size:
190 endpos = size
191 return rsre_core.BufMatchContext(buf, pos, endpos, self.flags)
204192
205193 def getmatch(self, ctx, found):
206194 if found:
313301 # w_string are both string or both unicode objects, and if w_ptemplate
314302 # is a literal
315303 use_builder = False
304 is_buffer = False
316305 filter_as_unicode = filter_as_string = None
317306 if space.is_true(space.callable(w_ptemplate)):
318307 w_filter = w_ptemplate
319308 filter_is_callable = True
320309 else:
321 length, filter_as_unicode, filter_as_string, buf = (
322 self.getstring(w_ptemplate))
323 if filter_as_unicode is not None:
310 if space.isinstance_w(w_ptemplate, space.w_unicode):
311 filter_as_unicode = space.unicode_w(w_ptemplate)
324312 literal = u'\\' not in filter_as_unicode
325313 use_builder = (
326314 space.isinstance_w(w_string, space.w_unicode) and literal)
327315 else:
328 if buf is not None:
329 filter_as_string = buf.as_str()
316 if space.isinstance_w(w_ptemplate, space.w_bytes):
317 filter_as_string = space.bytes_w(w_ptemplate)
318 else:
319 filter_as_string = space.readbuf_w(w_ptemplate).as_str()
320 is_buffer = True
330321 literal = '\\' not in filter_as_string
331322 use_builder = (
332323 space.isinstance_w(w_string, space.w_bytes) and literal)
337328 # not a literal; hand it over to the template compiler
338329 # FIX for a CPython 3.5 bug: if w_ptemplate is a buffer
339330 # (e.g. a bytearray), convert it to a byte string here.
340 if buf is not None:
331 if is_buffer:
341332 w_ptemplate = space.newbytes(filter_as_string)
342333 w_re = import_re(space)
343334 w_filter = space.call_method(w_re, '_subx',
630621 assert idx >= 0
631622 return fmarks[idx], fmarks[idx+1]
632623 else:
633 raise oefmt(space.w_IndexError, "group index out of range")
624 raise oefmt(space.w_IndexError, "no such group")
634625
635626 def _last_index(self):
636627 mark = self.ctx.match_marks
6060 except ImportError:
6161 skip('no test, -A on cpython?')
6262 # With showarning() missing, make sure that output is okay.
63 del warnings.showwarning
63 saved = warnings.showwarning
64 try:
65 del warnings.showwarning
6466
65 stderr = sys.stderr
66 try:
67 sys.stderr = io.StringIO()
68 inner('test message')
69 result = sys.stderr.getvalue()
67 stderr = sys.stderr
68 try:
69 sys.stderr = io.StringIO()
70 inner('test message')
71 result = sys.stderr.getvalue()
72 finally:
73 sys.stderr = stderr
74
75 assert result.count('\n') == 2
76 assert ' warnings.warn(message, ' in result
7077 finally:
71 sys.stderr = stderr
72
73 assert result.count('\n') == 2
74 assert ' warnings.warn(message, ' in result
78 warnings.showwarning = saved
7579
7680 def test_filename_none(self):
7781 import _warnings
178178 lltype.free(self._buffer, flavor='raw')
179179
180180 def setlen(self, size, zero=False, overallocate=True):
181 if self._buffer:
182 delta_memory_pressure = -self.allocated * self.itemsize
183 else:
184 delta_memory_pressure = 0
181185 if size > 0:
182186 if size > self.allocated or size < self.allocated / 2:
183187 if overallocate:
190194 some = 0
191195 self.allocated = size + some
192196 byte_size = self.allocated * self.itemsize
197 delta_memory_pressure += byte_size
193198 if zero:
194199 new_buffer = lltype.malloc(
195 rffi.CCHARP.TO, byte_size, flavor='raw',
196 add_memory_pressure=True, zero=True)
200 rffi.CCHARP.TO, byte_size, flavor='raw', zero=True)
197201 else:
198202 new_buffer = lltype.malloc(
199 rffi.CCHARP.TO, byte_size, flavor='raw',
200 add_memory_pressure=True)
203 rffi.CCHARP.TO, byte_size, flavor='raw')
201204 copy_bytes = min(size, self.len) * self.itemsize
202205 rffi.c_memcpy(rffi.cast(rffi.VOIDP, new_buffer),
203206 rffi.cast(rffi.VOIDP, self._buffer),
214217 lltype.free(self._buffer, flavor='raw')
215218 self._buffer = new_buffer
216219 self.len = size
220 # adds the difference between the old and the new raw-malloced
221 # size. If setlen() is called a lot on the same array object,
222 # it is important to take into account the fact that we also do
223 # lltype.free() above.
224 rgc.add_memory_pressure(delta_memory_pressure)
217225
218226 def _fromiterable(self, w_seq):
219227 # used by fromsequence().
258266 return None
259267 oldbuffer = self._buffer
260268 self._buffer = lltype.malloc(rffi.CCHARP.TO,
261 (self.len - (j - i)) * self.itemsize, flavor='raw',
262 add_memory_pressure=True)
269 (self.len - (j - i)) * self.itemsize, flavor='raw')
270 # Issue #2913: don't pass add_memory_pressure here, otherwise
271 # memory pressure grows but actual raw memory usage doesn't---we
272 # are freeing the old buffer at the end of this function.
263273 if i:
264274 rffi.c_memcpy(
265275 rffi.cast(rffi.VOIDP, self._buffer),
7575 import pypy.module.cpyext.pytraceback
7676 import pypy.module.cpyext.methodobject
7777 import pypy.module.cpyext.dictproxyobject
78 import pypy.module.cpyext.marshal
7879 import pypy.module.cpyext.genobject
7980 import pypy.module.cpyext.namespaceobject
8081
6060
6161 configure_eci = ExternalCompilationInfo(
6262 include_dirs=include_dirs,
63 includes=['Python.h', 'stdarg.h', 'structmember.h'],
63 includes=['Python.h', 'stdarg.h', 'structmember.h', 'marshal.h'],
6464 compile_extra=['-DPy_BUILD_CORE'])
6565
6666 class CConfig:
9292
9393 if sys.platform == 'win32':
9494 dash = '_'
95 WIN32 = True
9596 else:
9697 dash = ''
98 WIN32 = False
99
97100
98101 def fclose(fp):
99102 try:
118121 pypy_decl = 'pypy_decl.h'
119122 udir.join(pypy_decl).write("/* Will be filled later */\n")
120123 udir.join('pypy_structmember_decl.h').write("/* Will be filled later */\n")
124 udir.join('pypy_marshal_decl.h').write("/* Will be filled later */\n")
121125 udir.join('pypy_macros.h').write("/* Will be filled later */\n")
122126
123127 constant_names = """
507511 header = DEFAULT_HEADER
508512 if func.__name__ in FUNCTIONS_BY_HEADER[header]:
509513 raise ValueError("%s already registered" % func.__name__)
514 func._revdb_c_only_ = True # hack for revdb
510515 api_function = COnlyApiFunction(argtypes, restype, func)
511516 FUNCTIONS_BY_HEADER[header][func.__name__] = api_function
512517 return api_function
608613 'PyObject_CallMethod', 'PyObject_CallFunctionObjArgs', 'PyObject_CallMethodObjArgs',
609614 '_PyObject_CallFunction_SizeT', '_PyObject_CallMethod_SizeT',
610615
611 'PyObject_GetBuffer', 'PyBuffer_Release',
616 'PyObject_DelItemString', 'PyObject_GetBuffer', 'PyBuffer_Release',
612617 '_Py_setfilesystemdefaultencoding',
613
614 'PyCObject_FromVoidPtr', 'PyCObject_FromVoidPtrAndDesc', 'PyCObject_AsVoidPtr',
615 'PyCObject_GetDesc', 'PyCObject_Import', 'PyCObject_SetVoidPtr',
616 'PyCObject_Type', '_Py_get_cobject_type',
617618
618619 'PyCapsule_New', 'PyCapsule_IsValid', 'PyCapsule_GetPointer',
619620 'PyCapsule_GetName', 'PyCapsule_GetDestructor', 'PyCapsule_GetContext',
646647 'Py_FrozenFlag', 'Py_TabcheckFlag', 'Py_UnicodeFlag', 'Py_IgnoreEnvironmentFlag',
647648 'Py_DivisionWarningFlag', 'Py_DontWriteBytecodeFlag', 'Py_NoUserSiteDirectory',
648649 '_Py_QnewFlag', 'Py_Py3kWarningFlag', 'Py_HashRandomizationFlag', '_Py_PackageContext',
650 'PyOS_InputHook',
649651
650652 'PyMem_RawMalloc', 'PyMem_RawCalloc', 'PyMem_RawRealloc', 'PyMem_RawFree',
651653 'PyMem_Malloc', 'PyMem_Calloc', 'PyMem_Realloc', 'PyMem_Free',
656658 'PyType_FromSpec',
657659 'Py_IncRef', 'Py_DecRef', 'PyObject_Free', 'PyObject_GC_Del', 'PyType_GenericAlloc',
658660 '_PyObject_New', '_PyObject_NewVar',
659 '_PyObject_GC_New', '_PyObject_GC_NewVar',
661 '_PyObject_GC_Malloc', '_PyObject_GC_New', '_PyObject_GC_NewVar',
660662 'PyObject_Init', 'PyObject_InitVar',
661 'PyTuple_New',
663 'PyTuple_New', '_Py_Dealloc',
662664 ]
663665 TYPES = {}
664666 FORWARD_DECLS = []
670672 'PyObject*', 'space.w_None', header=pypy_decl)
671673 register_global('_Py_TrueStruct',
672674 'PyObject*', 'space.w_True', header=pypy_decl)
673 register_global('_Py_ZeroStruct',
675 register_global('_Py_FalseStruct',
674676 'PyObject*', 'space.w_False', header=pypy_decl)
675677 register_global('_Py_NotImplementedStruct',
676678 'PyObject*', 'space.w_NotImplemented', header=pypy_decl)
714716 "PyByteArray_Type": "space.w_bytearray",
715717 "PyMemoryView_Type": "space.w_memoryview",
716718 "PyBaseObject_Type": "space.w_object",
717 'PyNone_Type': 'space.type(space.w_None)',
718 'PyNotImplemented_Type': 'space.type(space.w_NotImplemented)',
719 '_PyNone_Type': 'space.type(space.w_None)',
720 '_PyNotImplemented_Type': 'space.type(space.w_NotImplemented)',
719721 'PyCell_Type': 'space.gettypeobject(Cell.typedef)',
720722 'PyModule_Type': 'space.gettypeobject(Module.typedef)',
721723 'PyProperty_Type': 'space.gettypeobject(W_Property.typedef)',
786788
787789 # a pointer to PyObject
788790 PyObjectP = rffi.CArrayPtr(PyObject)
791
792 # int *
793 INTP_real = rffi.CArrayPtr(rffi.INT_real)
789794
790795 def configure_types():
791796 for config in (CConfig, CConfig2):
11161121 # of the cpyext module. The C functions are called with no wrapper,
11171122 # but must not do anything like calling back PyType_Ready(). We
11181123 # use them just to get a pointer to the PyTypeObjects defined in C.
1119 get_cobject_type = rffi.llexternal('_%s_get_cobject_type' % prefix,
1120 [], PyTypeObjectPtr,
1121 compilation_info=eci, _nowrapper=True)
11221124 get_capsule_type = rffi.llexternal('_%s_get_capsule_type' % prefix,
11231125 [], PyTypeObjectPtr,
11241126 compilation_info=eci, _nowrapper=True)
11291131 def init_types(space):
11301132 from pypy.module.cpyext.typeobject import py_type_ready
11311133 from pypy.module.sys.interp_encoding import getfilesystemencoding
1132 py_type_ready(space, get_cobject_type())
11331134 py_type_ready(space, get_capsule_type())
11341135 s = space.text_w(getfilesystemencoding(space))
11351136 setdefenc(rffi.str2charp(s, track_allocation=False)) # "leaks"
11481149
11491150 def attach_c_functions(space, eci, prefix):
11501151 state = space.fromcache(State)
1151 state.C._Py_Dealloc = rffi.llexternal('_Py_Dealloc',
1152 [PyObject], lltype.Void,
1153 compilation_info=eci,
1154 _nowrapper=True)
1152 state.C._Py_Dealloc = rffi.llexternal(
1153 mangle_name(prefix, '_Py_Dealloc'),
1154 [PyObject], lltype.Void,
1155 compilation_info=eci,
1156 _nowrapper=True)
11551157 state.C.PyObject_Free = rffi.llexternal(
11561158 mangle_name(prefix, 'PyObject_Free'),
11571159 [rffi.VOIDP], lltype.Void,
11741176 '_PyPy_tuple_dealloc', [PyObject], lltype.Void,
11751177 compilation_info=eci, _nowrapper=True)
11761178 _, state.C.set_marker = rffi.CExternVariable(
1177 Py_ssize_t, '_pypy_rawrefcount_w_marker_deallocating',
1178 eci, _nowrapper=True, c_type='Py_ssize_t')
1179 rffi.VOIDP, '_pypy_rawrefcount_w_marker_deallocating',
1180 eci, _nowrapper=True, c_type='void *')
11791181 state.C._PyPy_subtype_dealloc = rffi.llexternal(
11801182 '_PyPy_subtype_dealloc', [PyObject], lltype.Void,
11811183 compilation_info=eci, _nowrapper=True)
11821184 state.C._PyPy_object_dealloc = rffi.llexternal(
11831185 '_PyPy_object_dealloc', [PyObject], lltype.Void,
1186 compilation_info=eci, _nowrapper=True)
1187 FUNCPTR = lltype.Ptr(lltype.FuncType([], rffi.INT))
1188 state.C.get_pyos_inputhook = rffi.llexternal(
1189 '_PyPy_get_PyOS_InputHook', [], FUNCPTR,
11841190 compilation_info=eci, _nowrapper=True)
11851191
11861192
12321238 global_objects.append('PyTypeObject _PyExc_%s;' % name)
12331239 global_code = '\n'.join(global_objects)
12341240
1235 prologue = ("#include <Python.h>\n"
1236 "#include <structmember.h>\n"
1241 prologue = ("#include <Python.h>\n" +
1242 "#include <structmember.h>\n" +
1243 "#include <marshal.h>\n" +
1244 ("#include <pypy_numpy.h>\n" if use_micronumpy else "") +
12371245 "#include <src/thread.c>\n")
1238 if use_micronumpy:
1239 prologue = ("#include <Python.h>\n"
1240 "#include <structmember.h>\n"
1241 "#include <pypy_numpy.h>\n"
1242 "#include <src/thread.c>\n")
12431246 code = (prologue +
12441247 struct_declaration_code +
12451248 global_code +
14921495 source_dir / "pythonrun.c",
14931496 source_dir / "sysmodule.c",
14941497 source_dir / "complexobject.c",
1495 source_dir / "cobject.c",
14961498 source_dir / "structseq.c",
14971499 source_dir / "capsule.c",
14981500 source_dir / "pysignals.c",
15461548
15471549 if sys.platform == 'win32':
15481550 get_pythonapi_source = '''
1549 #include <windows.h>
15501551 RPY_EXTERN
15511552 HANDLE pypy_get_pythonapi_handle() {
15521553 MEMORY_BASIC_INFORMATION mi;
15601561 }
15611562 '''
15621563 separate_module_sources.append(get_pythonapi_source)
1564 kwds['post_include_bits'] = ['#include <windows.h>',
1565 'RPY_EXTERN HANDLE pypy_get_pythonapi_handle();',
1566 ]
15631567
15641568 eci = ExternalCompilationInfo(
15651569 include_dirs=include_dirs,
16701674 try:
16711675 ll_libname = rffi.str2charp(path)
16721676 try:
1673 dll = rdynload.dlopen(ll_libname, space.sys.dlopenflags)
1677 if WIN32:
1678 # Allow other DLLs in the same directory with "path"
1679 dll = rdynload.dlopenex(ll_libname)
1680 else:
1681 dll = rdynload.dlopen(ll_libname, space.sys.dlopenflags)
16741682 finally:
16751683 lltype.free(ll_libname, flavor='raw')
16761684 except rdynload.DLOpenError as e:
17861794 return
17871795 return exec_def(space, w_mod, mod_as_pyobj)
17881796
1797 def invoke_pyos_inputhook(space):
1798 state = space.fromcache(State)
1799 c_inputhook = state.C.get_pyos_inputhook()
1800 if c_inputhook:
1801 generic_cpy_call(space, c_inputhook)
1802
17891803 @specialize.ll()
17901804 def generic_cpy_call(space, func, *args):
17911805 FT = lltype.typeOf(func).TO
1111 from pypy.module.__pypy__.interp_pypydatetime import (W_DateTime_Date,
1212 W_DateTime_Time, W_DateTime_Delta)
1313 from rpython.tool.sourcetools import func_renamer
14 from pypy.module.cpyext.state import State
1415
1516 cts.parse_header(parse_dir / 'cpyext_datetime.h')
1617
1718
1819 PyDateTime_CAPI = cts.gettype('PyDateTime_CAPI')
1920
20 datetimeAPI_global = []
2121
2222 @cpython_api([], lltype.Ptr(PyDateTime_CAPI))
2323 def _PyDateTime_Import(space):
24 if len(datetimeAPI_global) >0:
25 return datetimeAPI_global[0]
24 state = space.fromcache(State)
25 if len(state.datetimeAPI) > 0:
26 return state.datetimeAPI[0]
2627 datetimeAPI = lltype.malloc(PyDateTime_CAPI, flavor='raw',
2728 track_allocation=False)
2829
6566 _PyDelta_FromDelta.api_func.functype,
6667 _PyDelta_FromDelta.api_func.get_wrapper(space))
6768
68 datetimeAPI_global.append(datetimeAPI)
69 return datetimeAPI
69 state.datetimeAPI.append(datetimeAPI)
70 return state.datetimeAPI[0]
7071
7172 PyDateTime_Time = cts.gettype('PyDateTime_Time*')
7273 PyDateTime_DateTime = cts.gettype('PyDateTime_DateTime*')
119120 dealloc=type_dealloc,
120121 )
121122
122 # why do we need date_dealloc? Since W_DateTime_Date is the base class for
123 # app level datetime.date. If a c-extension class uses datetime.date for its
124 # base class and defines a tp_dealloc, we will get this:
125 # c_class->tp_dealloc == tp_dealloc_func
126 # c_class->tp_base == datetime.date,
127 # datetime.date->tp_dealloc = _PyPy_subtype_dealloc
128 # datetime.date->tp_base = W_DateTime_Date
129 # W_DateTime_Date->tp_dealloc = _PyPy_subtype_dealloc
130 # but _PyPy_subtype_dealloc will call tp_dealloc_func, which can call its
131 # base's tp_dealloc and we get recursion. So break the recursion by setting
132 # W_DateTime_Date->tp_dealloc
133123 make_typedescr(W_DateTime_Date.typedef,
134124 basestruct=PyDateTime_DateTime.TO,
135125 attach=type_attach,
136 dealloc=date_dealloc,
126 dealloc=type_dealloc,
137127 )
138128
139129 make_typedescr(W_DateTime_Delta.typedef,
143133
144134 def type_attach(space, py_obj, w_obj, w_userdata=None):
145135 '''Fills a newly allocated py_obj from the w_obj
136 If it is a datetime.time or datetime.datetime, it may have tzinfo
146137 '''
147 if space.type(w_obj).name == 'date':
148 # No tzinfo
149 return
150 py_datetime = rffi.cast(PyDateTime_Time, py_obj)
151 w_tzinfo = space.getattr(w_obj, space.newtext('_tzinfo'))
152 if space.is_none(w_tzinfo):
153 py_datetime.c_hastzinfo = cts.cast('unsigned char', 0)
154 py_datetime.c_tzinfo = lltype.nullptr(PyObject.TO)
155 else:
156 py_datetime.c_hastzinfo = cts.cast('unsigned char', 1)
157 py_datetime.c_tzinfo = make_ref(space, w_tzinfo)
138 state = space.fromcache(State)
139 if len(state.datetimeAPI) ==0:
140 # can happen in subclassing
141 _PyDateTime_Import(space)
142 if state.datetimeAPI[0].c_TimeType == py_obj.c_ob_type:
143 py_datetime = rffi.cast(PyDateTime_Time, py_obj)
144 w_tzinfo = space.getattr(w_obj, space.newtext('tzinfo'))
145 if space.is_none(w_tzinfo):
146 py_datetime.c_hastzinfo = cts.cast('unsigned char', 0)
147 py_datetime.c_tzinfo = lltype.nullptr(PyObject.TO)
148 else:
149 py_datetime.c_hastzinfo = cts.cast('unsigned char', 1)
150 py_datetime.c_tzinfo = make_ref(space, w_tzinfo)
151 elif state.datetimeAPI[0].c_DateTimeType == py_obj.c_ob_type:
152 # For now this is exactly the same structure as PyDateTime_Time
153 py_datetime = rffi.cast(PyDateTime_DateTime, py_obj)
154 w_tzinfo = space.getattr(w_obj, space.newtext('tzinfo'))
155 if space.is_none(w_tzinfo):
156 py_datetime.c_hastzinfo = cts.cast('unsigned char', 0)
157 py_datetime.c_tzinfo = lltype.nullptr(PyObject.TO)
158 else:
159 py_datetime.c_hastzinfo = cts.cast('unsigned char', 1)
160 py_datetime.c_tzinfo = make_ref(space, w_tzinfo)
158161
159162 @slot_function([PyObject], lltype.Void)
160163 def type_dealloc(space, py_obj):
161 py_datetime = rffi.cast(PyDateTime_Time, py_obj)
162 if (widen(py_datetime.c_hastzinfo) != 0):
163 decref(space, py_datetime.c_tzinfo)
164164 from pypy.module.cpyext.object import _dealloc
165 _dealloc(space, py_obj)
166
167 @slot_function([PyObject], lltype.Void)
168 def date_dealloc(space, py_obj):
169 from pypy.module.cpyext.object import _dealloc
165 state = space.fromcache(State)
166 # cannot raise here, so just crash
167 assert len(state.datetimeAPI) > 0
168 if state.datetimeAPI[0].c_TimeType == py_obj.c_ob_type:
169 py_datetime = rffi.cast(PyDateTime_Time, py_obj)
170 if (widen(py_datetime.c_hastzinfo) != 0):
171 decref(space, py_datetime.c_tzinfo)
172 elif state.datetimeAPI[0].c_DateTimeType == py_obj.c_ob_type:
173 py_datetime = rffi.cast(PyDateTime_DateTime, py_obj)
174 if (widen(py_datetime.c_hastzinfo) != 0):
175 decref(space, py_datetime.c_tzinfo)
170176 _dealloc(space, py_obj)
171177
172178 def timedeltatype_attach(space, py_obj, w_obj, w_userdata=None):
88 from pypy.module.cpyext.pyobject import PyObject
99 from pypy.module.cpyext.pyerrors import PyErr_SetFromErrno
1010 from pypy.module.cpyext.funcobject import PyCodeObject
11 from pypy.module.cpyext.frameobject import PyFrameObject
1112 from pypy.module.__builtin__ import compiling
1213
1314 PyCompilerFlags = cpython_struct(
5657 if caller is None:
5758 return None
5859 return caller.get_w_globals() # borrowed ref
60
61 @cpython_api([], PyFrameObject, error=CANNOT_FAIL, result_borrowed=True)
62 def PyEval_GetFrame(space):
63 caller = space.getexecutioncontext().gettopframe_nohidden()
64 return caller # borrowed ref, may be null
5965
6066 @cpython_api([PyCodeObject, PyObject, PyObject], PyObject)
6167 def PyEval_EvalCode(space, w_code, w_globals, w_locals):
122122 #include "memoryobject.h"
123123 #include "eval.h"
124124 #include "pymem.h"
125 #include "pycobject.h"
126125 #include "pycapsule.h"
127126 #include "bytesobject.h"
128127 #include "sliceobject.h"
22 #ifdef __cplusplus
33 extern "C" {
44 #endif
5
6 PyAPI_FUNC(int) PyObject_DelItemString(PyObject *o, char *key);
7
8 /*
9 Remove the mapping for object, key, from the object *o.
10 Returns -1 on failure. This is equivalent to
11 the Python statement: del o[key].
12 */
13
514
615 /* new buffer API */
716
2635 /* Releases a Py_buffer obtained from getbuffer ParseTuple's s*.
2736 */
2837
38 /* Mapping protocol:*/
39
40 /* implemented as a macro:
41
42 int PyMapping_DelItemString(PyObject *o, char *key);
43
44 Remove the mapping for object, key, from the object *o.
45 Returns -1 on failure. This is equivalent to
46 the Python statement: del o[key].
47 */
48 #define PyMapping_DelItemString(O,K) PyObject_DelItemString((O),(K))
49
50 /* implemented as a macro:
51
52 int PyMapping_DelItem(PyObject *o, PyObject *key);
53
54 Remove the mapping for object, key, from the object *o.
55 Returns -1 on failure. This is equivalent to
56 the Python statement: del o[key].
57 */
58 #define PyMapping_DelItem(O,K) PyObject_DelItem((O),(K))
2959
3060 #ifdef __cplusplus
3161 }
0
1 /* Bool object interface */
0 /* Boolean object interface */
21
32 #ifndef Py_BOOLOBJECT_H
43 #define Py_BOOLOBJECT_H
65 extern "C" {
76 #endif
87
9 #define Py_False ((PyObject *) &_Py_ZeroStruct)
8 #define PyBool_Check(x) (Py_TYPE(x) == &PyBool_Type)
9
10 /* Py_False and Py_True are the only two bools in existence.
11 Don't forget to apply Py_INCREF() when returning either!!! */
12
13 /* Use these macros */
14 #define Py_False ((PyObject *) &_Py_FalseStruct)
1015 #define Py_True ((PyObject *) &_Py_TrueStruct)
1116
1217 /* Macros for returning Py_True or Py_False, respectively */
1318 #define Py_RETURN_TRUE return Py_INCREF(Py_True), Py_True
1419 #define Py_RETURN_FALSE return Py_INCREF(Py_False), Py_False
1520
16 #define PyBool_Check(op) ((op)->ob_type == &PyBool_Type)
17
1821 #ifdef __cplusplus
1922 }
2023 #endif
0 #ifndef Py_MARSHAL_H
1 #define Py_MARSHAL_H
2 #ifdef __cplusplus
3 extern "C" {
4 #endif
5
6 #define Py_MARSHAL_VERSION 2
7 #include "pypy_marshal_decl.h"
8
9 #ifdef __cplusplus
10 }
11 #endif
12 #endif /* !Py_MARSHAL_H */
6060 #endif
6161 PyAPI_FUNC(void) Py_IncRef(PyObject *);
6262 PyAPI_FUNC(void) Py_DecRef(PyObject *);
63 extern Py_ssize_t _pypy_rawrefcount_w_marker_deallocating;
63 extern void *_pypy_rawrefcount_w_marker_deallocating;
6464 PyAPI_FUNC(void) _Py_Dealloc(PyObject *);
6565
6666
321321 } while (0)
322322
323323 #define PyObject_TypeCheck(ob, tp) \
324 ((ob)->ob_type == (tp) || PyType_IsSubtype((ob)->ob_type, (tp)))
324 (Py_TYPE(ob) == (tp) || PyType_IsSubtype(Py_TYPE(ob), (tp)))
325325
326326 #define Py_TRASHCAN_SAFE_BEGIN(pyObj) do {
327327 #define Py_TRASHCAN_SAFE_END(pyObj) ; } while(0);
371371
372372 PyAPI_FUNC(PyObject *) _PyObject_New(PyTypeObject *);
373373 PyAPI_FUNC(PyVarObject *) _PyObject_NewVar(PyTypeObject *, Py_ssize_t);
374 PyAPI_FUNC(PyObject *) _PyObject_GC_Malloc(size_t);
374375 PyAPI_FUNC(PyObject *) _PyObject_GC_New(PyTypeObject *);
375376 PyAPI_FUNC(PyVarObject *) _PyObject_GC_NewVar(PyTypeObject *, Py_ssize_t);
376377
2727 /* Version as a string */
2828 #define PY_VERSION "3.5.3"
2929
30 /* PyPy version as a string */
31 #define PYPY_VERSION "6.0.0"
32 #define PYPY_VERSION_NUM 0x06000000
33
30 /* PyPy version as a string: make sure to keep this in sync with:
31 * module/sys/version.py
32 * doc/conf.py
33 */
34 #define PYPY_VERSION "7.1.0-alpha0"
35 #define PYPY_VERSION_NUM 0x07010000
3436 /* Defined to mean a PyPy where cpyext holds more regular references
3537 to PyObjects, e.g. staying alive as long as the internal PyPy object
3638 stays alive. */
+0
-56
pypy/module/cpyext/include/pycobject.h less more
0 #ifndef Py_COBJECT_H
1 #define Py_COBJECT_H
2 #ifdef __cplusplus
3 extern "C" {
4 #endif
5
6 PyAPI_DATA(PyTypeObject) PyCObject_Type;
7
8 #define PyCObject_Check(op) ((op)->ob_type == &PyCObject_Type)
9
10 /* Create a PyCObject from a pointer to a C object and an optional
11 destructor function. If the second argument is non-null, then it
12 will be called with the first argument if and when the PyCObject is
13 destroyed.
14
15 */
16 PyAPI_FUNC(PyObject *) PyCObject_FromVoidPtr(
17 void *cobj, void (*destruct)(void*));
18
19
20 /* Create a PyCObject from a pointer to a C object, a description object,
21 and an optional destructor function. If the third argument is non-null,
22 then it will be called with the first and second arguments if and when
23 the PyCObject is destroyed.
24 */
25 PyAPI_FUNC(PyObject *) PyCObject_FromVoidPtrAndDesc(
26 void *cobj, void *desc, void (*destruct)(void*,void*));
27
28 /* Retrieve a pointer to a C object from a PyCObject. */
29 PyAPI_FUNC(void *) PyCObject_AsVoidPtr(PyObject *);
30
31 /* Retrieve a pointer to a description object from a PyCObject. */
32 PyAPI_FUNC(void *) PyCObject_GetDesc(PyObject *);
33
34 /* Import a pointer to a C object from a module using a PyCObject. */
35 PyAPI_FUNC(void *) PyCObject_Import(const char *module_name, const char *cobject_name);
36
37 /* Modify a C object. Fails (==0) if object has a destructor. */
38 PyAPI_FUNC(int) PyCObject_SetVoidPtr(PyObject *self, void *cobj);
39
40
41 #if (PY_VERSION_HEX >= 0x02060000 || defined(Py_BUILD_CORE))
42 typedef struct {
43 PyObject_HEAD
44 void *cobject;
45 void *desc;
46 void (*destructor)(void *);
47 } PyCObject;
48 #endif
49
50 PyAPI_FUNC(PyTypeObject *) _Py_get_cobject_type(void);
51
52 #ifdef __cplusplus
53 }
54 #endif
55 #endif /* !Py_COBJECT_H */
3030 #endif
3131
3232 #ifndef Py_BUILD_CORE /* not building the core - must be an ext */
33 # if defined(_MSC_VER) && !defined(_CFFI_)
34 /* So MSVC users need not specify the .lib file in
35 * their Makefile (other compilers are generally
36 * taken care of by distutils.) */
37 # ifdef _DEBUG
38 # error("debug first with cpython")
33 # if defined(_MSC_VER) && !defined(_CFFI_)
34 /* So MSVC users need not specify the .lib file in
35 * their Makefile (other compilers are generally
36 * taken care of by distutils.)
37 */
38 # ifdef _DEBUG
39 # error("debug first with cpython")
3940 # pragma comment(lib,"python35.lib")
40 # else
41 # else
4142 # pragma comment(lib,"python35.lib")
42 # endif /* _DEBUG */
43 # endif /* _DEBUG */
44 # define HAVE_COPYSIGN 1
45 # define copysign _copysign
46 # ifdef MS_WIN64
47 typedef __int64 ssize_t;
48 # else
49 typedef _W64 int ssize_t;
50 # endif
51 #define HAVE_SSIZE_T 1
52
53
4354 # endif
4455 #endif /* _MSC_VER */
4556
44 Symbols and macros to supply platform-independent interfaces to mathematical
55 functions and constants
66 **************************************************************************/
7
8 /* High precision definition of pi and e (Euler)
9 * The values are taken from libc6's math.h.
10 */
11 #ifndef Py_MATH_PIl
12 #define Py_MATH_PIl 3.1415926535897932384626433832795029L
13 #endif
14 #ifndef Py_MATH_PI
15 #define Py_MATH_PI 3.14159265358979323846
16 #endif
17
18 #ifndef Py_MATH_El
19 #define Py_MATH_El 2.7182818284590452353602874713526625L
20 #endif
21
22 #ifndef Py_MATH_E
23 #define Py_MATH_E 2.7182818284590452354
24 #endif
25
26 /* Tau (2pi) to 40 digits, taken from tauday.com/tau-digits. */
27 #ifndef Py_MATH_TAU
28 #define Py_MATH_TAU 6.2831853071795864769252867665590057683943L
29 #endif
30
31 /* Py_IS_NAN(X)
32 * Return 1 if float or double arg is a NaN, else 0.
33 * Caution:
34 * X is evaluated more than once.
35 * This may not work on all platforms. Each platform has *some*
36 * way to spell this, though -- override in pyconfig.h if you have
37 * a platform where it doesn't work.
38 */
39 #ifndef Py_IS_NAN
40 #if __STDC_VERSION__ >= 199901L || __cplusplus >= 201103L
41 #define Py_IS_NAN(X) isnan(X)
42 #else
43 #define Py_IS_NAN(X) ((X) != (X))
44 #endif
45 #endif
46
47 /* Py_IS_INFINITY(X)
48 * Return 1 if float or double arg is an infinity, else 0.
49 * Caution:
50 * X is evaluated more than once.
51 * This implementation may set the underflow flag if |X| is very small;
52 * it really can't be implemented correctly (& easily) before C99.
53 * Override in pyconfig.h if you have a better spelling on your platform.
54 */
55 #ifndef Py_IS_INFINITY
56 # if __STDC_VERSION__ >= 199901L || __cplusplus >= 201103L
57 # define Py_IS_INFINITY(X) isinf(X)
58 # else
59 # define Py_IS_INFINITY(X) ((X) && ((X)*0.5 == (X)))
60 # endif
61 #endif
62
63 /* Py_IS_FINITE(X)
64 * Return 1 if float or double arg is neither infinite nor NAN, else 0.
65 * Some compilers (e.g. VisualStudio) have intrisics for this, so a special
66 * macro for this particular test is useful
67 */
68 #ifndef Py_IS_FINITE
69 #if __STDC_VERSION__ >= 199901L || __cplusplus >= 201103L
70 #define Py_IS_FINITE(X) isfinite(X)
71 #else
72 #define Py_IS_FINITE(X) (!Py_IS_INFINITY(X) && !Py_IS_NAN(X))
73 #endif
74 #endif
775
876 /* HUGE_VAL is supposed to expand to a positive double infinity. Python
977 * uses Py_HUGE_VAL instead because some platforms are broken in this
127127 #else
128128 #endif
129129
130 /*
131 * Hide GCC attributes from compilers that don't support them.
132 */
133 #if (!defined(__GNUC__) || __GNUC__ < 2 || \
134 (__GNUC__ == 2 && __GNUC_MINOR__ < 7) ) && \
135 !defined(RISCOS)
136 #define Py_GCC_ATTRIBUTE(x)
137 #else
138 #define Py_GCC_ATTRIBUTE(x) __attribute__(x)
139 #endif
140
141 /*
142 * Specify alignment on compilers that support it.
143 */
144 #if defined(__GNUC__) && __GNUC__ >= 3
145 #define Py_ALIGNED(x) __attribute__((aligned(x)))
146 #else
147 #define Py_ALIGNED(x)
148 #endif
149
150 /*
151 * Older Microsoft compilers don't support the C99 long long literal suffixes,
152 * so these will be defined in PC/pyconfig.h for those compilers.
153 */
154 #ifndef Py_LL
155 #define Py_LL(x) x##LL
156 #endif
157
158 #ifndef Py_ULL
159 #define Py_ULL(x) Py_LL(x##U)
160 #endif
161
130162 #endif /* Py_PYPORT_H */
4040
4141 #define Py_CompileString(str, filename, start) Py_CompileStringFlags(str, filename, start, NULL)
4242
43 /* Stuff with no proper home (yet) */
44 PyAPI_DATA(int) (*PyOS_InputHook)(void);
45 typedef int (*_pypy_pyos_inputhook)(void);
46 PyAPI_FUNC(_pypy_pyos_inputhook) _PyPy_get_PyOS_InputHook(void);
47
4348 #ifdef __cplusplus
4449 }
4550 #endif
00 from rpython.rtyper.lltypesystem import lltype, rffi
11 from pypy.module.cpyext.api import (
22 cpython_api, PyObject, build_type_checkers_flags, Py_ssize_t,
3 CONST_STRING, ADDR, CANNOT_FAIL)
4 from pypy.objspace.std.longobject import W_LongObject
3 CONST_STRING, ADDR, CANNOT_FAIL, INTP_real)
54 from pypy.interpreter.error import OperationError, oefmt
65 from rpython.rlib.rbigint import rbigint, InvalidSignednessError
76
120119 num = space.bigint_w(w_long)
121120 return num.ulonglongmask()
122121
123 @cpython_api([PyObject, rffi.CArrayPtr(rffi.INT_real)], lltype.Signed,
122 @cpython_api([PyObject, INTP_real], lltype.Signed,
124123 error=-1)
125124 def PyLong_AsLongAndOverflow(space, w_long, overflow_ptr):
126125 """
141140 overflow_ptr[0] = rffi.cast(rffi.INT_real, -1)
142141 return -1
143142
144 @cpython_api([PyObject, rffi.CArrayPtr(rffi.INT_real)], rffi.LONGLONG,
143 @cpython_api([PyObject, INTP_real], rffi.LONGLONG,
145144 error=-1)
146145 def PyLong_AsLongLongAndOverflow(space, w_long, overflow_ptr):
147146 """
233232
234233 @cpython_api([PyObject], rffi.INT_real, error=CANNOT_FAIL)
235234 def _PyLong_Sign(space, w_long):
236 assert isinstance(w_long, W_LongObject)
237 return w_long.num.sign
235 bigint = space.bigint_w(w_long)
236 return bigint.sign
238237
239238 CONST_UCHARP = lltype.Ptr(lltype.Array(rffi.UCHAR, hints={'nolength': True,
240239 'render_as_const': True}))
0 from rpython.rtyper.lltypesystem import rffi, lltype
1 from pypy.module.cpyext.api import cpython_api, Py_ssize_t
2 from pypy.module.cpyext.pyobject import PyObject
3
4
5 _HEADER = 'pypy_marshal_decl.h'
6
7 @cpython_api([rffi.CCHARP, Py_ssize_t], PyObject, header=_HEADER)
8 def PyMarshal_ReadObjectFromString(space, p, size):
9 from pypy.module.marshal.interp_marshal import loads
10 s = rffi.charpsize2str(p, size)
11 return loads(space, space.newbytes(s))
12
13 @cpython_api([PyObject, rffi.INT_real], PyObject, header=_HEADER)
14 def PyMarshal_WriteObjectToString(space, w_x, version):
15 from pypy.module.marshal.interp_marshal import dumps
16 return dumps(space, w_x, space.newint(version))
171171 return space.newtext(txtsig)
172172 return space.w_None
173173
174 def fget_module(self, space):
175 if self.w_module is None:
176 return space.w_None
177 return self.w_module
178
179 def fset_module(self, space, w_module):
180 self.w_module = w_module
181
182 def fdel_module(self, space):
183 self.w_module = space.w_None
184
174185 class W_PyCMethodObject(W_PyCFunctionObject):
175186
176187 def __init__(self, space, ml, w_type):
332343 __call__ = interp2app(W_PyCFunctionObject.descr_call),
333344 __doc__ = GetSetProperty(W_PyCFunctionObject.get_doc),
334345 __text_signature__ = GetSetProperty(W_PyCFunctionObject.get_txtsig),
335 __module__ = interp_attrproperty_w('w_module', cls=W_PyCFunctionObject),
346 __module__ = GetSetProperty(W_PyCFunctionObject.fget_module,
347 W_PyCFunctionObject.fset_module,
348 W_PyCFunctionObject.fdel_module),
336349 __name__ = interp_attrproperty('name', cls=W_PyCFunctionObject,
337350 wrapfn="newtext_or_none"),
338351 )
1111 from pypy.objspace.std.typeobject import W_TypeObject
1212 from pypy.objspace.std.bytesobject import invoke_bytes_method
1313 from pypy.interpreter.error import OperationError, oefmt
14 from pypy.interpreter.executioncontext import ExecutionContext
1415 import pypy.module.__builtin__.operation as operation
1516
1617
419420 def _PyPyGC_AddMemoryPressure(space, report):
420421 from rpython.rlib import rgc
421422 rgc.add_memory_pressure(report)
423
424
425 ExecutionContext.cpyext_recursive_repr = None
426
427 @cpython_api([PyObject], rffi.INT_real, error=-1)
428 def Py_ReprEnter(space, w_obj):
429 ec = space.getexecutioncontext()
430 d = ec.cpyext_recursive_repr
431 if d is None:
432 d = ec.cpyext_recursive_repr = {}
433 if w_obj in d:
434 return 1
435 d[w_obj] = None
436 return 0
437
438 @cpython_api([PyObject], lltype.Void)
439 def Py_ReprLeave(space, w_obj):
440 ec = space.getexecutioncontext()
441 d = ec.cpyext_recursive_repr
442 if d is not None:
443 try:
444 del d[w_obj]
445 except KeyError:
446 pass
4040 w_mode = space.newtext(rffi.charp2str(mode))
4141 return space.call_method(space.builtin, 'open', w_filename, w_mode)
4242
43 @cpython_api([FILEP, CONST_STRING, CONST_STRING, rffi.VOIDP], PyObject)
44 def PyFile_FromFile(space, fp, name, mode, close):
45 """Create a new PyFileObject from the already-open standard C file
46 pointer, fp. The function close will be called when the file should be
47 closed. Return NULL on failure."""
48 raise NotImplementedError
49
50 @cpython_api([PyObject, rffi.INT_real], lltype.Void)
51 def PyFile_SetBufSize(space, w_file, n):
52 """Available on systems with setvbuf() only. This should only be called
53 immediately after file object creation."""
54 raise NotImplementedError
55
5643 @cpython_api([CONST_STRING, PyObject], rffi.INT_real, error=-1)
5744 def PyFile_WriteString(space, s, w_p):
5845 """Write string s to file object p. Return 0 on success or -1 on
7461 w_str = space.repr(w_obj)
7562 space.call_method(w_p, "write", w_str)
7663 return 0
77
78 @cpython_api([PyObject], PyObject)
79 def PyFile_Name(space, w_p):
80 """Return the name of the file specified by p as a string object."""
81 w_name = space.getattr(w_p, space.newtext("name"))
82 return w_name # borrowed ref, should be a W_StringObject from the file
260260 if w_obj is not None:
261261 if w_obj is not w_marker_deallocating:
262262 return w_obj
263 type_name = rffi.charp2str(cts.cast('char*', ref.c_ob_type.c_tp_name))
263264 fatalerror(
264265 "*** Invalid usage of a dying CPython object ***\n"
265266 "\n"
274275 "freed, making that reference point to garbage.\n"
275276 ">>> PyPy could contain some workaround to still work if\n"
276277 "you are lucky, but it is not done so far; better fix the bug in\n"
277 "the CPython extension.")
278 "the CPython extension.\n"
279 ">>> This object is of type '%s'" % (type_name,))
278280
279281 # This reference is not yet a real interpreter object.
280282 # Realize it.
409411 if we_are_translated():
410412 llptr = cast_instance_to_base_ptr(w_marker_deallocating)
411413 state = space.fromcache(State)
412 state.C.set_marker(rffi.cast(Py_ssize_t, llptr))
414 state.C.set_marker(llptr)
413415
414416 @cpython_api([rffi.VOIDP], lltype.Signed, error=CANNOT_FAIL)
415417 def _Py_HashPointer(space, ptr):
00 import errno
11 from pypy.interpreter.error import oefmt
2 from pypy.module.cpyext.api import cpython_api, CONST_STRING
2 from pypy.module.cpyext.api import cpython_api, CONST_STRING, INTP_real
33 from pypy.module.cpyext.pyobject import PyObject
44 from rpython.rlib import rdtoa
55 from rpython.rlib import rfloat
7979 if not user_endptr:
8080 lltype.free(endptr, flavor='raw')
8181
82 @cpython_api([rffi.DOUBLE, lltype.Char, rffi.INT_real, rffi.INT_real, rffi.INTP], rffi.CCHARP)
82 @cpython_api([rffi.DOUBLE, lltype.Char, rffi.INT_real, rffi.INT_real, INTP_real], rffi.CCHARP)
8383 def PyOS_double_to_string(space, val, format_code, precision, flags, ptype):
8484 """Convert a double val to a string using supplied
8585 format_code, precision, and flags.
113113 buffer, rtype = rfloat.double_to_string(val, format_code,
114114 intmask(precision),
115115 intmask(flags))
116 if ptype != lltype.nullptr(rffi.INTP.TO):
117 ptype[0] = rffi.cast(rffi.INT, DOUBLE_TO_STRING_TYPES_MAP[rtype])
116 if ptype != lltype.nullptr(INTP_real.TO):
117 ptype[0] = rffi.cast(rffi.INT_real, DOUBLE_TO_STRING_TYPES_MAP[rtype])
118118 bufp = rffi.str2charp(buffer)
119119 return bufp
2121
2222 /* Operations on any object */
2323
24 int
25 PyObject_DelItemString(PyObject *o, char *key)
26 {
27 PyObject *okey;
28 int ret;
29
30 if (o == NULL || key == NULL) {
31 null_error();
32 return -1;
33 }
34 okey = PyUnicode_FromString(key);
35 if (okey == NULL)
36 return -1;
37 ret = PyObject_DelItem(o, okey);
38 Py_DECREF(okey);
39 return ret;
40 }
2441 int
2542 PyObject_CheckReadBuffer(PyObject *obj)
2643 {
93110 (*pb->bf_releasebuffer)(obj, &view);
94111 Py_XDECREF(view.obj);
95112 return 0;
113 }
114
115 /* Buffer C-API for Python 3.0 */
116
117 int
118 PyObject_GetBuffer(PyObject *obj, Py_buffer *view, int flags)
119 {
120 if (!PyObject_CheckBuffer(obj)) {
121 PyErr_Format(PyExc_TypeError,
122 "'%100s' does not have the buffer interface",
123 Py_TYPE(obj)->tp_name);
124 return -1;
125 }
126 return (*(obj->ob_type->tp_as_buffer->bf_getbuffer))(obj, view, flags);
96127 }
97128
98129 void*
109140 }
110141 return (void*)pointer;
111142 }
143
112144
113145 void
114146 _Py_add_one_to_index_F(int nd, Py_ssize_t *index, const Py_ssize_t *shape)
252284
253285
254286
255 /* Buffer C-API for Python 3.0 */
256
257 int
258 PyObject_GetBuffer(PyObject *obj, Py_buffer *view, int flags)
259 {
260 if (!PyObject_CheckBuffer(obj)) {
261 PyErr_Format(PyExc_TypeError,
262 "'%100s' does not have the buffer interface",
263 Py_TYPE(obj)->tp_name);
264 return -1;
265 }
266 return (*(obj->ob_type->tp_as_buffer->bf_getbuffer))(obj, view, flags);
267 }
268287
269288 void
270289 PyBuffer_Release(Py_buffer *view)
426445 return retval;
427446 }
428447
448
429449 static PyObject *
430450 objargs_mktuple(va_list va)
431451 {
+0
-162
pypy/module/cpyext/src/cobject.c less more
0
1 /* Wrap void* pointers to be passed between C modules */
2
3 #include "Python.h"
4
5
6 /* Declarations for objects of type PyCObject */
7
8 typedef void (*destructor1)(void *);
9 typedef void (*destructor2)(void *, void*);
10
11 PyObject *
12 PyCObject_FromVoidPtr(void *cobj, void (*destr)(void *))
13 {
14 PyCObject *self;
15
16 self = PyObject_NEW(PyCObject, &PyCObject_Type);
17 if (self == NULL)
18 return NULL;
19 self->cobject=cobj;
20 self->destructor=destr;
21 self->desc=NULL;
22
23 return (PyObject *)self;
24 }
25
26 PyObject *
27 PyCObject_FromVoidPtrAndDesc(void *cobj, void *desc,
28 void (*destr)(void *, void *))
29 {
30 PyCObject *self;
31
32 if (!desc) {
33 PyErr_SetString(PyExc_TypeError,
34 "PyCObject_FromVoidPtrAndDesc called with null"
35 " description");
36 return NULL;
37 }
38 self = PyObject_NEW(PyCObject, &PyCObject_Type);
39 if (self == NULL)
40 return NULL;
41 self->cobject = cobj;
42 self->destructor = (destructor1)destr;
43 self->desc = desc;
44
45 return (PyObject *)self;
46 }
47
48 void *
49 PyCObject_AsVoidPtr(PyObject *self)
50 {
51 if (self) {
52 if (PyCapsule_CheckExact(self)) {
53 const char *name = PyCapsule_GetName(self);
54 return (void *)PyCapsule_GetPointer(self, name);
55 }
56 if (self->ob_type == &PyCObject_Type)
57 return ((PyCObject *)self)->cobject;
58 PyErr_SetString(PyExc_TypeError,
59 "PyCObject_AsVoidPtr with non-C-object");
60 }
61 if (!PyErr_Occurred())
62 PyErr_SetString(PyExc_TypeError,
63 "PyCObject_AsVoidPtr called with null pointer");
64 return NULL;
65 }
66
67 void *
68 PyCObject_GetDesc(PyObject *self)
69 {
70 if (self) {
71 if (self->ob_type == &PyCObject_Type)
72 return ((PyCObject *)self)->desc;
73 PyErr_SetString(PyExc_TypeError,
74 "PyCObject_GetDesc with non-C-object");
75 }
76 if (!PyErr_Occurred())
77 PyErr_SetString(PyExc_TypeError,
78 "PyCObject_GetDesc called with null pointer");
79 return NULL;
80 }
81
82 void *
83 PyCObject_Import(const char *module_name, const char *name)
84 {
85 PyObject *m, *c;
86 void *r = NULL;
87
88 if ((m = PyImport_ImportModule(module_name))) {
89 if ((c = PyObject_GetAttrString(m,name))) {
90 r = PyCObject_AsVoidPtr(c);
91 Py_DECREF(c);
92 }
93 Py_DECREF(m);
94 }
95 return r;
96 }
97
98 int
99 PyCObject_SetVoidPtr(PyObject *self, void *cobj)
100 {
101 PyCObject* cself = (PyCObject*)self;
102 if (cself == NULL || !PyCObject_Check(cself) ||
103 cself->destructor != NULL) {
104 PyErr_SetString(PyExc_TypeError,
105 "Invalid call to PyCObject_SetVoidPtr");
106 return 0;
107 }
108 cself->cobject = cobj;
109 return 1;
110 }
111
112 static void
113 PyCObject_dealloc(PyCObject *self)
114 {
115 if (self->destructor) {
116 if(self->desc)
117 ((destructor2)(self->destructor))(self->cobject, self->desc);
118 else
119 (self->destructor)(self->cobject);
120 }
121 PyObject_DEL(self);
122 }
123
124
125 PyDoc_STRVAR(PyCObject_Type__doc__,
126 "C objects to be exported from one extension module to another\n\
127 \n\
128 C objects are used for communication between extension modules. They\n\
129 provide a way for an extension module to export a C interface to other\n\
130 extension modules, so that extension modules can use the Python import\n\
131 mechanism to link to one another.");
132
133 PyTypeObject PyCObject_Type = {
134 PyVarObject_HEAD_INIT(NULL, 0)
135 "PyCObject", /*tp_name*/
136 sizeof(PyCObject), /*tp_basicsize*/
137 0, /*tp_itemsize*/
138 /* methods */
139 (destructor)PyCObject_dealloc, /*tp_dealloc*/
140 0, /*tp_print*/
141 0, /*tp_getattr*/
142 0, /*tp_setattr*/
143 0, /*tp_compare*/
144 0, /*tp_repr*/
145 0, /*tp_as_number*/
146 0, /*tp_as_sequence*/
147 0, /*tp_as_mapping*/
148 0, /*tp_hash*/
149 0, /*tp_call*/
150 0, /*tp_str*/
151 0, /*tp_getattro*/
152 0, /*tp_setattro*/
153 0, /*tp_as_buffer*/
154 0, /*tp_flags*/
155 PyCObject_Type__doc__ /*tp_doc*/
156 };
157
158 PyTypeObject *_Py_get_cobject_type(void)
159 {
160 return &PyCObject_Type;
161 }
3030 void _Py_setfilesystemdefaultencoding(const char *enc) {
3131 Py_FileSystemDefaultEncoding = enc;
3232 }
33 int (*PyOS_InputHook)(void) = 0; /* only ever filled in by C extensions */
34 PyAPI_FUNC(_pypy_pyos_inputhook) _PyPy_get_PyOS_InputHook(void) {
35 return PyOS_InputHook;
36 }
1313 * tests we cannot call set_marker(), so we need to set a special value
1414 * directly here)
1515 */
16 Py_ssize_t _pypy_rawrefcount_w_marker_deallocating = 0xDEADFFF;
16 void* _pypy_rawrefcount_w_marker_deallocating = (void*) 0xDEADFFF;
1717
1818 void
1919 _Py_Dealloc(PyObject *obj)
2020 {
2121 PyTypeObject *pto = obj->ob_type;
2222 /* this is the same as rawrefcount.mark_deallocating() */
23 obj->ob_pypy_link = _pypy_rawrefcount_w_marker_deallocating;
23 obj->ob_pypy_link = (Py_ssize_t)_pypy_rawrefcount_w_marker_deallocating;
2424 pto->tp_dealloc(obj);
2525 }
2626
5757 _PyObject_New(PyTypeObject *type)
5858 {
5959 return (PyObject*)_PyObject_NewVar(type, 0);
60 }
61
62 PyObject * _PyObject_GC_Malloc(size_t size)
63 {
64 return (PyObject *)PyObject_Malloc(size);
6065 }
6166
6267 PyObject * _PyObject_GC_New(PyTypeObject *type)
4141 # A mapping {filename: copy-of-the-w_dict}, similar to CPython's
4242 # variable 'extensions' in Python/import.c.
4343 self.extensions = {}
44 # XXX will leak if _PyDateTime_Import already called
45 self.datetimeAPI = []
4446
4547 def set_exception(self, operror):
4648 self.clear_exception()
0 import re
1 import os
2
3
4 for line in open('stubs.py'):
5 if not line.strip():
6 continue
7 if line.startswith(' '):
8 continue
9 if line.startswith('#'):
10 continue
11 if line.startswith('@cpython_api'):
12 continue
13 if line.endswith(' = rffi.VOIDP\n'):
14 continue
15
16 #print line.rstrip()
17 m = re.match(r"def ([\w\d_]+)[(]", line)
18 assert m, line
19 funcname = m.group(1)
20 os.system('grep -w %s [a-r]*.py s[a-s]*.py str*.py stubsa*.py sy*.py [t-z]*.py' % funcname)
0 from pypy.module.cpyext.api import (
1 cpython_api, PyObject, PyObjectP, CANNOT_FAIL
2 )
3 from pypy.module.cpyext.complexobject import Py_complex_ptr as Py_complex
4 from rpython.rtyper.lltypesystem import rffi, lltype
5
6 CWCHARPP = lltype.Ptr(lltype.Array(rffi.CWCHARP, hints={'nolength': True}))
7
8 # we don't really care
9 PyTypeObjectPtr = rffi.VOIDP
10 Py_ssize_t = rffi.SSIZE_T
11 PyModuleDef = rffi.VOIDP
12 PyMethodDef = rffi.VOIDP
13 PyGetSetDef = rffi.VOIDP
14 PyMemberDef = rffi.VOIDP
15 va_list = rffi.VOIDP
16 wrapperbase = rffi.VOIDP
17 FILE = rffi.VOIDP
18 PyFrameObject = rffi.VOIDP
19 _inittab = rffi.VOIDP
20 PyThreadState = rffi.VOIDP
21 PyInterpreterState = rffi.VOIDP
22 Py_UNICODE = lltype.UniChar
23 PyCompilerFlags = rffi.VOIDP
24 struct_node = rffi.VOIDP
25 Py_tracefunc = rffi.VOIDP
0 #----this file is not imported, only here for reference----
1
2 #from pypy.module.cpyext.api import (
3 # cpython_api, PyObject, PyObjectP, CANNOT_FAIL
4 # )
5 #from pypy.module.cpyext.complexobject import Py_complex_ptr as Py_complex
6 #from rpython.rtyper.lltypesystem import rffi, lltype
267
278
289 @cpython_api([rffi.CCHARP], Py_ssize_t, error=-1)
227208 this method returns zero and sets errno to EDOM."""
228209 raise NotImplementedError
229210
230 @cpython_api([rffi.DOUBLE, lltype.Char, rffi.INT_real, rffi.INT_real, rffi.INTP], rffi.CCHARP)
231 def PyOS_double_to_string(space, val, format_code, precision, flags, ptype):
232 """Convert a double val to a string using supplied
233 format_code, precision, and flags.
234
235 format_code must be one of 'e', 'E', 'f', 'F',
236 'g', 'G' or 'r'. For 'r', the supplied precision
237 must be 0 and is ignored. The 'r' format code specifies the
238 standard repr() format.
239
240 flags can be zero or more of the values Py_DTSF_SIGN,
241 Py_DTSF_ADD_DOT_0, or Py_DTSF_ALT, or-ed together:
242
243 Py_DTSF_SIGN means to always precede the returned string with a sign
244 character, even if val is non-negative.
245
246 Py_DTSF_ADD_DOT_0 means to ensure that the returned string will not look
247 like an integer.
248
249 Py_DTSF_ALT means to apply "alternate" formatting rules. See the
250 documentation for the PyOS_snprintf() '#' specifier for
251 details.
252
253 If ptype is non-NULL, then the value it points to will be set to one of
254 Py_DTST_FINITE, Py_DTST_INFINITE, or Py_DTST_NAN, signifying that
255 val is a finite number, an infinite number, or not a number, respectively.
256
257 The return value is a pointer to buffer with the converted string or
258 NULL if the conversion failed. The caller is responsible for freeing the
259 returned string by calling PyMem_Free().
260 """
261 raise NotImplementedError
262
263211 @cpython_api([rffi.CCHARP, rffi.CCHARP], rffi.CCHARP)
264212 def PyOS_stricmp(space, s1, s2):
265213 """Case insensitive comparison of strings. The function works almost
272220 """Case insensitive comparison of strings. The function works almost
273221 identically to strncmp() except that it ignores the case.
274222 """
275 raise NotImplementedError
276
277 @cpython_api([PyObject], rffi.INT_real, error=CANNOT_FAIL)
278 def PyTZInfo_Check(space, ob):
279 """Return true if ob is of type PyDateTime_TZInfoType or a subtype of
280 PyDateTime_TZInfoType. ob must not be NULL.
281 """
282 raise NotImplementedError
283
284 @cpython_api([PyObject], rffi.INT_real, error=CANNOT_FAIL)
285 def PyTZInfo_CheckExact(space, ob):
286 """Return true if ob is of type PyDateTime_TZInfoType. ob must not be
287 NULL.
288 """
289 raise NotImplementedError
290
291 @cpython_api([PyTypeObjectPtr, PyGetSetDef], PyObject)
292 def PyDescr_NewGetSet(space, type, getset):
293223 raise NotImplementedError
294224
295225 @cpython_api([PyTypeObjectPtr, PyMemberDef], PyObject)
482412 0 on success, -1 on failure."""
483413 raise NotImplementedError
484414
485 @cpython_api([PyObject], rffi.INT_real, error=-1)
486 def Py_ReprEnter(space, object):
487 """Called at the beginning of the tp_repr implementation to
488 detect cycles.
489
490 If the object has already been processed, the function returns a
491 positive integer. In that case the tp_repr implementation
492 should return a string object indicating a cycle. As examples,
493 dict objects return {...} and list objects
494 return [...].
495
496 The function will return a negative integer if the recursion limit
497 is reached. In that case the tp_repr implementation should
498 typically return NULL.
499
500 Otherwise, the function returns zero and the tp_repr
501 implementation can continue normally."""
502 raise NotImplementedError
503
504 @cpython_api([PyObject], lltype.Void)
505 def Py_ReprLeave(space, object):
506 """Ends a Py_ReprEnter(). Must be called once for each
507 invocation of Py_ReprEnter() that returns zero."""
508 raise NotImplementedError
509
510415 @cpython_api([rffi.INT_real, rffi.CCHARP, rffi.CCHARP, rffi.INT_real, rffi.CCHARP, rffi.CCHARP, rffi.CCHARP, rffi.INT_real], PyObject)
511416 def PyFile_FromFd(space, fd, name, mode, buffering, encoding, errors, newline, closefd):
512417 """Create a Python file object from the file descriptor of an already
12211126 version indicates the file format."""
12221127 raise NotImplementedError
12231128
1224 @cpython_api([PyObject, rffi.INT_real], PyObject)
1225 def PyMarshal_WriteObjectToString(space, value, version):
1226 """Return a string object containing the marshalled representation of value.
1227
1228 version indicates the file format."""
1229 raise NotImplementedError
1230
12311129 @cpython_api([FILE], lltype.Signed, error=-1)
12321130 def PyMarshal_ReadLongFromFile(space, file):
12331131 """Return a C long from the data stream in a FILE* opened
12611159 (EOFError or TypeError) and returns NULL."""
12621160 raise NotImplementedError
12631161
1264 @cpython_api([rffi.CCHARP, Py_ssize_t], PyObject)
1265 def PyMarshal_ReadObjectFromString(space, string, len):
1266 """Return a Python object from the data stream in a character buffer
1267 containing len bytes pointed to by string. On error, sets the
1268 appropriate exception (EOFError or TypeError) and returns
1269 NULL."""
1270 raise NotImplementedError
1271
12721162 @cpython_api([PyObject, rffi.INT_real, lltype.Char], PyObject)
12731163 def PyMemoryView_GetContiguous(space, obj, buffertype, order):
12741164 """Create a memoryview object to a contiguous chunk of memory (in either
13091199 """
13101200 raise NotImplementedError
13111201
1312 @cpython_api([PyObject], rffi.VOIDP)
1313 def PyModule_GetState(space, module):
1314 """Return the "state" of the module, that is, a pointer to the block of memory
1315 allocated at module creation time, or NULL. See
1316 PyModuleDef.m_size."""
1317 raise NotImplementedError
1318
1319 @cpython_api([PyObject], PyModuleDef)
1320 def PyModule_GetDef(space, module):
1321 """Return a pointer to the PyModuleDef struct from which the module was
1322 created, or NULL if the module wasn't created with
1323 PyModule_Create()."""
1324 raise NotImplementedError
1325
1326
1327 @cpython_api([PyModuleDef], PyObject)
1328 def PyModule_Create(space, module):
1329 """Create a new module object, given the definition in module. This behaves
1330 like PyModule_Create2() with module_api_version set to
1331 PYTHON_API_VERSION."""
1332 raise NotImplementedError
1333
1334
1335 @cpython_api([PyModuleDef, rffi.INT_real], PyObject)
1336 def PyModule_Create2(space, module, module_api_version):
1337 """Create a new module object, given the definition in module, assuming the
1338 API version module_api_version. If that version does not match the version
1339 of the running interpreter, a RuntimeWarning is emitted.
1340
1341 Most uses of this function should be using PyModule_Create()
1342 instead; only use this if you are sure you need it."""
1343 raise NotImplementedError
1344
13451202 @cpython_api([PyObject, rffi.INT_real], PyObject)
13461203 def PyNumber_ToBase(space, n, base):
13471204 """Returns the integer n converted to base base as a string. The base
13501207 '0x', respectively. If n is not a Python int, it is converted with
13511208 PyNumber_Index() first."""
13521209 raise NotImplementedError
1353
1354 @cpython_api([PyObject], PyObject)
1355 def PyObject_Bytes(space, o):
1356 """
1357 Compute a bytes representation of object o. NULL is returned on
1358 failure and a bytes object on success. This is equivalent to the Python
1359 expression bytes(o), when o is not an integer. Unlike bytes(o),
1360 a TypeError is raised when o is an integer instead of a zero-initialized
1361 bytes object."""
1362 raise NotImplementedError
1363
1364 @cpython_api([], PyFrameObject)
1365 def PyEval_GetFrame(space):
1366 """Return the current thread state's frame, which is NULL if no frame is
1367 currently executing."""
1368 raise NotImplementedError
1369 borrow_from()
13701210
13711211 @cpython_api([PyFrameObject], rffi.INT_real, error=-1)
13721212 def PyFrame_GetLineNumber(space, frame):
88 void* buf;
99 Py_ssize_t buf_len;
1010 if (PyObject_AsWriteBuffer(args, &buf, &buf_len) < 0) {
11 PyErr_SetString(PyExc_ValueError, "bad value");
11 //PyErr_SetString(PyExc_ValueError, "bad value");
1212 return NULL;
1313 }
1414 return PyLong_FromLong(buf_len);
1515 """)])
1616 assert module.write_buffer_len(bytearray(b'123')) == 3
1717 assert module.write_buffer_len(array.array('i', [1, 2, 3])) == 12
18 #
19 import _cffi_backend
20 BChar = _cffi_backend.new_primitive_type("char")
21 BCharPtr = _cffi_backend.new_pointer_type(BChar)
22 BCharArray = _cffi_backend.new_array_type(BCharPtr, None)
23 p = _cffi_backend.newp(BCharArray, b"abcde")
24 bb = _cffi_backend.buffer(p)
25 assert module.write_buffer_len(bb) == 6
1826
1927
2028 class AppTestMmap(AppTestCpythonExtensionBase):
135135
136136 class LeakCheckingTest(object):
137137 """Base class for all cpyext tests."""
138 spaceconfig = dict(usemodules=['cpyext', 'thread', 'struct', 'array',
138 spaceconfig = {"usemodules" : ['cpyext', 'thread', 'struct', 'array',
139139 'itertools', 'time', 'binascii', 'mmap',
140 ])
140 '_cffi_backend',
141 ],
142 "objspace.disable_entrypoints_in_cffi": True}
141143
142144 @classmethod
143145 def preload_builtins(cls, space):
306306 from datetime import tzinfo, datetime, timedelta, time
307307 # copied from datetime documentation
308308 class GMT1(tzinfo):
309 def utcoffset(self, dt):
310 return timedelta(hours=1) + self.dst(dt)
311 def dst(self, dt):
312 return timedelta(0)
313 def tzname(self,dt):
309 def __del__(self):
310 print('deleting GMT1')
311 def utcoffset(self, dt):
312 return timedelta(hours=1) + self.dst(dt)
313 def dst(self, dt):
314 return timedelta(0)
315 def tzname(self,dt):
314316 return "GMT +1"
315317 gmt1 = GMT1()
316318 dt1 = module.time_with_tzinfo(gmt1)
317319 assert dt1 == time(6, 6, 6, 6, gmt1)
318320 assert '+01' in str(dt1)
319 assert module.datetime_with_tzinfo(gmt1) == datetime(
320 2000, 6, 6, 6, 6, 6, 6, gmt1)
321 dt_tz = module.datetime_with_tzinfo(gmt1)
322 assert dt_tz == datetime(2000, 6, 6, 6, 6, 6, 6, gmt1)
321323
322324 def test_checks(self):
323325 module = self.import_extension('foo', [
509509 assert run_async(list1()) == ([], [0, 1, 2])
510510 assert run_async(list2()) == ([], [0, 1, 2])
511511 """
512
513 def test_getframe(self):
514 import sys
515 module = self.import_extension('foo', [
516 ("getframe1", "METH_NOARGS",
517 """
518 PyFrameObject *x = PyEval_GetFrame();
519 Py_INCREF(x);
520 return (PyObject *)x;
521 """),], prologue="#include <frameobject.h>\n")
522 res = module.getframe1()
523 assert res is sys._getframe(0)
109109 return PyLong_FromLong(res);"""),
110110 ])
111111 assert module.test() == 1111
112
113 def test_pymath_consts(self):
114 # test preprocessor constants in their string form to avoid
115 # floating-point conversion issues (and to avoid having to
116 # conditionalize on compiler support for long double)
117 for const_name, const_strval in [
118 ('Py_MATH_PIl', b"3.1415926535897932384626433832795029L"),
119 ('Py_MATH_PI', b"3.14159265358979323846"),
120 ('Py_MATH_El', b"2.7182818284590452353602874713526625L"),
121 ('Py_MATH_E', b"2.7182818284590452354"),
122 ('Py_MATH_TAU', b"6.2831853071795864769252867665590057683943L"),
123 ]:
124 module = self.import_extension('foo_%s' % const_name, [
125 ("test", "METH_NOARGS",
126 """
127 #define xstr(s) str(s)
128 #define str(s) #s
129 return PyBytes_FromString(xstr(%s));""" % const_name)
130 ])
131 assert module.test() == const_strval
132
133 def test_Py_IS_NAN(self):
134 module = self.import_extension('foo', [
135 ("test", "METH_O",
136 """
137 double d = PyFloat_AsDouble(args);
138 return PyBool_FromLong(Py_IS_NAN(d));
139 """),
140 ])
141 assert not module.test(0)
142 assert not module.test(1)
143 assert not module.test(-1)
144 assert not module.test(float('inf'))
145 assert module.test(float('nan'))
146
147 def test_Py_IS_INFINITY(self):
148 module = self.import_extension('foo', [
149 ("test", "METH_O",
150 """
151 double d = PyFloat_AsDouble(args);
152 return PyBool_FromLong(Py_IS_INFINITY(d));
153 """),
154 ])
155 assert not module.test(0)
156 assert not module.test(1)
157 assert not module.test(-1)
158 assert not module.test(float('nan'))
159 assert module.test(float('inf'))
160 assert module.test(float('-inf'))
161
162 def test_Py_IS_FINITE(self):
163 module = self.import_extension('foo', [
164 ("test", "METH_O",
165 """
166 double d = PyFloat_AsDouble(args);
167 return PyBool_FromLong(Py_IS_FINITE(d));
168 """),
169 ])
170 assert module.test(0)
171 assert module.test(1)
172 assert module.test(-1)
173 assert not module.test(float('nan'))
174 assert not module.test(float('inf'))
175 assert not module.test(float('-inf'))
176
177 def test_Py_HUGE_VAL(self):
178 module = self.import_extension('foo', [
179 ("test", "METH_NOARGS",
180 """
181 return PyFloat_FromDouble(Py_HUGE_VAL);
182 """),
183 ])
184 assert module.test() == float('inf')
185
186 def test_Py_NAN(self):
187 module = self.import_extension('foo', [
188 ("test", "METH_NOARGS",
189 """
190 return PyFloat_FromDouble(Py_NAN);
191 """),
192 ])
193 import struct
194 float_bits = struct.Struct('d').pack
195 assert float_bits(module.test()) == float_bits(float('nan'))
135135 assert api._PyLong_Sign(space.wraplong(0L)) == 0
136136 assert api._PyLong_Sign(space.wraplong(2L)) == 1
137137 assert api._PyLong_Sign(space.wraplong(-2L)) == -1
138 assert api._PyLong_Sign(space.wrap(0)) == 0
139 assert api._PyLong_Sign(space.wrap(42)) == 1
140 assert api._PyLong_Sign(space.wrap(-42)) == -1
138141
139142 assert api._PyLong_NumBits(space.wrap(0)) == 0
140143 assert api._PyLong_NumBits(space.wrap(1)) == 1
0 from pypy.module.cpyext.test.test_cpyext import AppTestCpythonExtensionBase
1
2
3 class AppTestMarshal(AppTestCpythonExtensionBase):
4 def test_PyMarshal_ReadObjectFromString(self):
5 module = self.import_extension('foo', [
6 ("mloads", "METH_O",
7 """
8 char *input = PyBytes_AsString(args);
9 Py_ssize_t length = PyBytes_Size(args);
10 return PyMarshal_ReadObjectFromString(input, length);
11 """)],
12 prologue='#include <marshal.h>')
13 import marshal
14 assert module.mloads(marshal.dumps(42.5)) == 42.5
15 x = [None, True, (4, 5), b"adkj", u"\u1234"]
16 assert module.mloads(marshal.dumps(x)) == x
17
18 def test_PyMarshal_WriteObjectToString(self):
19 module = self.import_extension('foo', [
20 ("mdumps", "METH_VARARGS",
21 """
22 PyObject *obj;
23 int version;
24 if (!PyArg_ParseTuple(args, "Oi", &obj, &version))
25 return NULL;
26 return PyMarshal_WriteObjectToString(obj, version);
27 """)],
28 prologue='#include <marshal.h>')
29 import marshal
30 for x in [42, b"foo", u"\u2345", (4, None, False)]:
31 for version in [0, 1, 2]:
32 assert module.mdumps(x, version) == marshal.dumps(x, version)
170170 assert mod.check(A) == 0
171171 assert mod.check(A.meth) == 0
172172 assert mod.check(A.stat) == 0
173
174 def test_module_attribute(self):
175 mod = self.import_extension('MyModule', [
176 ('getarg_NO', 'METH_NOARGS',
177 '''
178 Py_INCREF(Py_None);
179 return Py_None;
180 '''
181 ),
182 ])
183 assert mod.getarg_NO() is None
184 assert mod.getarg_NO.__module__ == 'MyModule'
185 mod.getarg_NO.__module__ = 'foobar'
186 assert mod.getarg_NO.__module__ == 'foobar'
173187
174188 def test_text_signature(self):
175189 mod = self.import_module('docstrings')
0 from pypy.module.cpyext.test.test_cpyext import AppTestCpythonExtensionBase
1
2
3 class AppTestMisc(AppTestCpythonExtensionBase):
4
5 def test_pyos_inputhook(self):
6 module = self.import_extension('foo', [
7 ("set_pyos_inputhook", "METH_NOARGS",
8 '''
9 PyOS_InputHook = &my_callback;
10 Py_RETURN_NONE;
11 '''),
12 ("fetch_value", "METH_NOARGS",
13 '''
14 return PyLong_FromLong(my_flag);
15 '''),
16 ], prologue='''
17 static long my_flag = 0;
18 static int my_callback(void) { return ++my_flag; }
19 ''')
20
21 try:
22 import __pypy__
23 except ImportError:
24 skip("only runs on top of pypy")
25 assert module.fetch_value() == 0
26 __pypy__.pyos_inputhook()
27 assert module.fetch_value() == 0
28 module.set_pyos_inputhook() # <= set
29 assert module.fetch_value() == 0
30 __pypy__.pyos_inputhook()
31 assert module.fetch_value() == 1
32 __pypy__.pyos_inputhook()
33 assert module.fetch_value() == 2
34 assert module.fetch_value() == 2
44 from rpython.rtyper.lltypesystem import rffi
55 from pypy.module.cpyext.pyobject import get_w_obj_and_decref
66 from pypy.module.cpyext.api import (
7 Py_LT, Py_LE, Py_NE, Py_EQ, Py_GE, Py_GT)
7 Py_LT, Py_LE, Py_NE, Py_EQ, Py_GE, Py_GT, INTP_real)
88 from pypy.module.cpyext.object import (
99 PyObject_IsTrue, PyObject_Not, PyObject_GetAttrString,
1010 PyObject_DelAttrString, PyObject_GetAttr, PyObject_DelAttr,
410410 module.foo(35000)
411411 assert self.cur_memory_pressure() == 65536 + 80000 + 70000
412412
413 def test_repr_enter_leave(self):
414 module = self.import_extension('foo', [
415 ("enter", "METH_O",
416 """
417 return PyLong_FromLong(Py_ReprEnter(args));
418 """),
419 ("leave", "METH_O",
420 """
421 Py_ReprLeave(args);
422 Py_INCREF(Py_None);
423 return Py_None;
424 """)])
425 obj1 = [42]
426 obj2 = [42] # another list
427
428 n = module.enter(obj1)
429 assert n == 0
430 module.leave(obj1)
431
432 n = module.enter(obj1)
433 assert n == 0
434 n = module.enter(obj1)
435 assert n == 1
436 n = module.enter(obj1)
437 assert n == 1
438 module.leave(obj1)
439
440 n = module.enter(obj1)
441 assert n == 0
442 n = module.enter(obj2)
443 assert n == 0
444 n = module.enter(obj1)
445 assert n == 1
446 n = module.enter(obj2)
447 assert n == 1
448 module.leave(obj1)
449 n = module.enter(obj2)
450 assert n == 1
451 module.leave(obj2)
452
453
413454 class AppTestPyBuffer_FillInfo(AppTestCpythonExtensionBase):
414455 """
415456 PyBuffer_FillInfo populates the fields of a Py_buffer from its arguments.
478478 ])
479479 raises(SystemError, module.oops)
480480
481 @pytest.mark.skipif("not config.option.runappdirect", reason='-A only')
481482 def test_error_thread_race(self):
482483 # Check race condition: thread 0 returns from cpyext with error set,
483484 # after thread 1 has set an error but before it returns.
4747
4848 space.call_method(w_file, "close")
4949
50 def test_file_name(self, space, api):
51 name = str(udir / "_test_file")
52 with rffi.scoped_str2charp(name) as filename:
53 with rffi.scoped_str2charp("wb") as mode:
54 w_file = api.PyFile_FromString(filename, mode)
55 assert space.str_w(api.PyFile_Name(w_file)) == name
56
57 @pytest.mark.xfail
58 def test_file_setbufsize(self, space, api):
59 api.PyFile_SetBufSize()
60
6150 def test_file_writestring(self, space, api, capfd):
6251 w_stdout = space.sys.get("stdout")
6352 with rffi.scoped_str2charp("test\n") as s:
33 from pypy.module.cpyext.test.test_api import BaseApiTest, raises_w
44 from rpython.rtyper.lltypesystem import rffi
55 from rpython.rtyper.lltypesystem import lltype
6 from pypy.module.cpyext.pystrtod import PyOS_string_to_double
6 from pypy.module.cpyext.pystrtod import PyOS_string_to_double, INTP_real
77
88
99 class TestPyOS_string_to_double(BaseApiTest):
8989 class TestPyOS_double_to_string(BaseApiTest):
9090
9191 def test_format_code(self, api):
92 ptype = lltype.malloc(rffi.INTP.TO, 1, flavor='raw')
92 ptype = lltype.malloc(INTP_real.TO, 1, flavor='raw')
9393 r = api.PyOS_double_to_string(150.0, 'e', 1, 0, ptype)
9494 assert '1.5e+02' == rffi.charp2str(r)
9595 type_value = rffi.cast(lltype.Signed, ptype[0])
9898 lltype.free(ptype, flavor='raw')
9999
100100 def test_precision(self, api):
101 ptype = lltype.malloc(rffi.INTP.TO, 1, flavor='raw')
101 ptype = lltype.malloc(INTP_real.TO, 1, flavor='raw')
102102 r = api.PyOS_double_to_string(3.14159269397, 'g', 5, 0, ptype)
103103 assert '3.1416' == rffi.charp2str(r)
104104 type_value = rffi.cast(lltype.Signed, ptype[0])
107107 lltype.free(ptype, flavor='raw')
108108
109109 def test_flags_sign(self, api):
110 ptype = lltype.malloc(rffi.INTP.TO, 1, flavor='raw')
110 ptype = lltype.malloc(INTP_real.TO, 1, flavor='raw')
111111 r = api.PyOS_double_to_string(-3.14, 'g', 3, 1, ptype)
112112 assert '-3.14' == rffi.charp2str(r)
113113 type_value = rffi.cast(lltype.Signed, ptype[0])
116116 lltype.free(ptype, flavor='raw')
117117
118118 def test_flags_add_dot_0(self, api):
119 ptype = lltype.malloc(rffi.INTP.TO, 1, flavor='raw')
119 ptype = lltype.malloc(INTP_real.TO, 1, flavor='raw')
120120 r = api.PyOS_double_to_string(3, 'g', 5, 2, ptype)
121121 assert '3.0' == rffi.charp2str(r)
122122 type_value = rffi.cast(lltype.Signed, ptype[0])
125125 lltype.free(ptype, flavor='raw')
126126
127127 def test_flags_alt(self, api):
128 ptype = lltype.malloc(rffi.INTP.TO, 1, flavor='raw')
128 ptype = lltype.malloc(INTP_real.TO, 1, flavor='raw')
129129 r = api.PyOS_double_to_string(314., 'g', 3, 4, ptype)
130130 assert '314.' == rffi.charp2str(r)
131131 type_value = rffi.cast(lltype.Signed, ptype[0])
134134 lltype.free(ptype, flavor='raw')
135135
136136 def test_ptype_nan(self, api):
137 ptype = lltype.malloc(rffi.INTP.TO, 1, flavor='raw')
137 ptype = lltype.malloc(INTP_real.TO, 1, flavor='raw')
138138 r = api.PyOS_double_to_string(float('nan'), 'g', 3, 4, ptype)
139139 assert 'nan' == rffi.charp2str(r)
140140 type_value = rffi.cast(lltype.Signed, ptype[0])
143143 lltype.free(ptype, flavor='raw')
144144
145145 def test_ptype_infinity(self, api):
146 ptype = lltype.malloc(rffi.INTP.TO, 1, flavor='raw')
146 ptype = lltype.malloc(INTP_real.TO, 1, flavor='raw')
147147 r = api.PyOS_double_to_string(1e200 * 1e200, 'g', 0, 0, ptype)
148148 assert 'inf' == rffi.charp2str(r)
149149 type_value = rffi.cast(lltype.Signed, ptype[0])
152152 lltype.free(ptype, flavor='raw')
153153
154154 def test_ptype_null(self, api):
155 ptype = lltype.nullptr(rffi.INTP.TO)
155 ptype = lltype.nullptr(INTP_real.TO)
156156 r = api.PyOS_double_to_string(3.14, 'g', 3, 0, ptype)
157157 assert '3.14' == rffi.charp2str(r)
158 assert ptype == lltype.nullptr(rffi.INTP.TO)
158 assert ptype == lltype.nullptr(INTP_real.TO)
159159 rffi.free_charp(r)
33 from pypy.module.cpyext.test.test_cpyext import AppTestCpythonExtensionBase
44 from pypy.module.cpyext.unicodeobject import (
55 Py_UNICODE, PyUnicodeObject, new_empty_unicode)
6 from pypy.module.cpyext.api import PyObjectP, PyObject, Py_CLEANUP_SUPPORTED
6 from pypy.module.cpyext.api import (PyObjectP, PyObject,
7 Py_CLEANUP_SUPPORTED, INTP_real)
78 from pypy.module.cpyext.pyobject import decref, from_ref
89 from rpython.rtyper.lltypesystem import rffi, lltype
910 import sys, py
675676 def test_decode_null_encoding(self, space):
676677 null_charp = lltype.nullptr(rffi.CCHARP.TO)
677678 u_text = u'abcdefg'
678 s_text = space.str_w(PyUnicode_AsEncodedString(space, space.wrap(u_text), null_charp, null_charp))
679 s_text = space.bytes_w(PyUnicode_AsEncodedString(space, space.wrap(u_text), null_charp, null_charp))
679680 b_text = rffi.str2charp(s_text)
680681 assert space.unicode_w(PyUnicode_Decode(
681682 space, b_text, len(s_text), null_charp, null_charp)) == u_text
682683 with raises_w(space, TypeError):
683684 PyUnicode_FromEncodedObject(
684685 space, space.wrap(u_text), null_charp, None)
686 assert space.unicode_w(PyUnicode_FromEncodedObject(
687 space, space.newbytes(s_text), null_charp, None)) == u_text
685688 rffi.free_charp(b_text)
686689
687690 def test_mbcs(self, space):
725728 value = 1
726729 else:
727730 value = 0
728 pendian = lltype.malloc(INT_realP.TO, 1, flavor='raw')
731 pendian = lltype.malloc(INTP_real.TO, 1, flavor='raw')
729732 pendian[0] = rffi.cast(rffi.INT_real, value)
730733 else:
731734 pendian = None
738741 rffi.free_charp(strict_charp)
739742 if pendian:
740743 if realendian is not None:
741 assert rffi.cast(rffi.INT, realendian) == pendian[0]
744 assert rffi.cast(rffi.INT_real, realendian) == pendian[0]
742745 lltype.free(pendian, flavor='raw')
743746
744747 test("\x61\x00\x62\x00\x63\x00\x64\x00", -1)
761764 value = 1
762765 else:
763766 value = 0
764 pendian = lltype.malloc(INT_realP.TO, 1, flavor='raw')
767 pendian = lltype.malloc(INTP_real.TO, 1, flavor='raw')
765768 pendian[0] = rffi.cast(rffi.INT_real, value)
766769 else:
767770 pendian = None
55 from pypy.module.unicodedata import unicodedb
66 from pypy.module.cpyext.api import (
77 CANNOT_FAIL, Py_ssize_t, build_type_checkers, cpython_api,
8 bootstrap_function, CONST_STRING,
8 bootstrap_function, CONST_STRING, INTP_real,
99 CONST_WSTRING, Py_CLEANUP_SUPPORTED, slot_function, cts, parse_dir)
1010 from pypy.module.cpyext.pyerrors import PyErr_BadArgument
1111 from pypy.module.cpyext.pyobject import (
485485 in the unicode() built-in function. The codec to be used is looked up
486486 using the Python codec registry. Return NULL if an exception was raised by
487487 the codec."""
488 if not encoding:
489 # This tracks CPython 2.7, in CPython 3.4 'utf-8' is hardcoded instead
490 encoding = PyUnicode_GetDefaultEncoding(space)
491 w_str = space.newbytes(rffi.charpsize2str(s, size))
492 w_encoding = space.newtext(rffi.charp2str(encoding))
488 return _pyunicode_decode(space, rffi.charpsize2str(s, size),
489 encoding, errors)
490
491 def _pyunicode_decode(space, s, encoding, errors):
492 if encoding:
493 w_encoding = space.newtext(rffi.charp2str(encoding))
494 else:
495 # python 3.4 changed to this from defaultencoding
496 w_encoding = space.newtext('utf-8')
497 w_str = space.newbytes(s)
493498 if errors:
494499 w_errors = space.newtext(rffi.charp2str(errors))
495500 else:
524529
525530 All other objects, including Unicode objects, cause a TypeError to be
526531 set."""
527 if not encoding:
528 raise oefmt(space.w_TypeError, "decoding Unicode is not supported")
529 w_encoding = space.newtext(rffi.charp2str(encoding))
530 if errors:
531 w_errors = space.newtext(rffi.charp2str(errors))
532 else:
533 w_errors = None
534
535 # - unicode is disallowed
536 # - raise TypeError for non-string types
537 if space.isinstance_w(w_obj, space.w_unicode):
538 w_meth = None
539 else:
540 try:
541 w_meth = space.getattr(w_obj, space.newtext('decode'))
542 except OperationError as e:
543 if not e.match(space, space.w_AttributeError):
544 raise
545 w_meth = None
546 if w_meth is None:
547 raise oefmt(space.w_TypeError, "decoding Unicode is not supported")
548 return space.call_function(w_meth, w_encoding, w_errors)
532 if space.isinstance_w(w_obj, space.w_bytes):
533 s = space.bytes_w(w_obj)
534 if not s:
535 return space.newtext('')
536 elif space.isinstance_w(w_obj, space.w_unicode):
537 raise oefmt(space.w_TypeError, "decoding str is not supported")
538 elif space.isinstance_w(w_obj, space.w_bytearray): # Python 2.x specific
539 raise oefmt(space.w_TypeError, "decoding bytearray is not supported")
540 else:
541 s = space.charbuf_w(w_obj)
542 return _pyunicode_decode(space, s, encoding, errors)
549543
550544
551545 @cpython_api([PyObject, PyObjectP], rffi.INT_real, error=0)
767761 if sys.platform == 'win32':
768762 make_conversion_functions('MBCS', 'mbcs')
769763
770 @cpython_api([CONST_STRING, Py_ssize_t, CONST_STRING, INT_realP], PyObject)
764 @cpython_api([CONST_STRING, Py_ssize_t, CONST_STRING, INTP_real], PyObject)
771765 def PyUnicode_DecodeUTF16(space, s, size, llerrors, pbyteorder):
772766 """Decode length bytes from a UTF-16 encoded buffer string and return the
773767 corresponding Unicode object. errors (if non-NULL) defines the error
821815
822816 return space.newunicode(result)
823817
824 @cpython_api([CONST_STRING, Py_ssize_t, CONST_STRING, INT_realP], PyObject)
818 @cpython_api([CONST_STRING, Py_ssize_t, CONST_STRING, INTP_real], PyObject)
825819 def PyUnicode_DecodeUTF32(space, s, size, llerrors, pbyteorder):
826820 """Decode length bytes from a UTF-32 encoded buffer string and
827821 return the corresponding Unicode object. errors (if non-NULL)
44
55 if sys.platform.startswith('darwin'):
66 eci = ExternalCompilationInfo()
7 elif sys.platform.startswith('linux'):
8 # crypt() is defined only in crypt.h on some Linux variants (eg. Fedora 28)
9 eci = ExternalCompilationInfo(libraries=['crypt'], includes=["crypt.h"])
710 else:
811 eci = ExternalCompilationInfo(libraries=['crypt'])
912 c_crypt = rffi.llexternal('crypt', [rffi.CCHARP, rffi.CCHARP], rffi.CCHARP,
234234 self.descr_settraceback(space, w_traceback)
235235 return self
236236
237 def _cleanup_(self):
238 raise Exception("Prebuilt instances of (subclasses of) BaseException "
239 "must be avoided in Python 3.x. They have mutable "
240 "attributes related to tracebacks, so whenever they "
241 "are raised in the actual program they will "
242 "accumulate more frames and never free them.")
243
237244 def _new(cls, basecls=None):
238245 if basecls is None:
239246 basecls = cls
9494 assert ee.strerror == "x"
9595 assert ee.filename == "y"
9696 assert EnvironmentError(3, "x").filename is None
97 e = EnvironmentError(1, "hello", "world")
98 assert str(e) == "[Errno 1] hello: 'world'"
9799
98100 def test_windows_error(self):
99101 try:
121123 assert str(SyntaxError("msg", ("file.py", 2, 3, 4))) == "msg (file.py, line 2)"
122124
123125 def test_system_exit(self):
126 assert issubclass(SystemExit, BaseException)
124127 assert SystemExit().code is None
125128 assert SystemExit("x").code == "x"
126129 assert SystemExit(1, 2).code == (1, 2)
2121 'get_stats': 'app_referents.get_stats',
2222 })
2323 self.interpleveldefs.update({
24 'collect_step': 'interp_gc.collect_step',
2425 'get_rpy_roots': 'referents.get_rpy_roots',
2526 'get_rpy_referents': 'referents.get_rpy_referents',
2627 'get_rpy_memory_usage': 'referents.get_rpy_memory_usage',
5656 'total_allocated_memory', 'jit_backend_allocated',
5757 'peak_memory', 'peak_allocated_memory', 'total_arena_memory',
5858 'total_rawmalloced_memory', 'nursery_size',
59 'peak_arena_memory', 'peak_rawmalloced_memory'):
59 'peak_arena_memory', 'peak_rawmalloced_memory',
60 ):
6061 setattr(self, item, self._format(getattr(self._s, item)))
6162 self.memory_used_sum = self._format(self._s.total_gc_memory + self._s.total_memory_pressure +
6263 self._s.jit_backend_used)
6364 self.memory_allocated_sum = self._format(self._s.total_allocated_memory + self._s.total_memory_pressure +
6465 self._s.jit_backend_allocated)
66 self.total_gc_time = self._s.total_gc_time
6567
6668 def _format(self, v):
6769 if v < 1000000:
9193 raw assembler allocated: %s%s
9294 -----------------------------
9395 Total: %s
96
97 Total time spent in GC: %s
9498 """ % (self.total_gc_memory, self.peak_memory,
9599 self.total_arena_memory,
96100 self.total_rawmalloced_memory,
105109 self.nursery_size,
106110 self.jit_backend_allocated,
107111 extra,
108 self.memory_allocated_sum)
112 self.memory_allocated_sum,
113 self.total_gc_time / 1000.0)
109114
110115
111116 def get_stats(memory_pressure=False):
00 from rpython.memory.gc.hook import GcHooks
1 from rpython.memory.gc import incminimark
1 from rpython.memory.gc import incminimark
2 from rpython.rlib import rgc
23 from rpython.rlib.nonconst import NonConstant
34 from rpython.rlib.rarithmetic import r_uint, r_longlong, longlongmax
45 from pypy.interpreter.gateway import interp2app, unwrap_spec, WrappedDefault
56 from pypy.interpreter.baseobjspace import W_Root
67 from pypy.interpreter.typedef import TypeDef, interp_attrproperty, GetSetProperty
78 from pypy.interpreter.executioncontext import AsyncAction
9
10 inf = float("inf")
811
912 class LowLevelGcHooks(GcHooks):
1013 """
114117 self.descr_set_on_gc_collect(space, space.w_None)
115118
116119
117 class GcMinorHookAction(AsyncAction):
120 class NoRecursiveAction(AsyncAction):
121 depth = 0
122
123 def perform(self, ec, frame):
124 if self.depth == 0:
125 try:
126 self.depth += 1
127 return self._do_perform(ec, frame)
128 finally:
129 self.depth -= 1
130
131
132 class GcMinorHookAction(NoRecursiveAction):
118133 total_memory_used = 0
119134 pinned_objects = 0
120135
121136 def __init__(self, space):
122 AsyncAction.__init__(self, space)
137 NoRecursiveAction.__init__(self, space)
123138 self.w_callable = space.w_None
124139 self.reset()
125140
126141 def reset(self):
127142 self.count = 0
128 self.duration = r_longlong(0)
129 self.duration_min = r_longlong(longlongmax)
130 self.duration_max = r_longlong(0)
143 self.duration = 0.0
144 self.duration_min = inf
145 self.duration_max = 0.0
131146
132147 def fix_annotation(self):
133148 # the annotation of the class and its attributes must be completed
135150 # annotated with the correct types
136151 if NonConstant(False):
137152 self.count = NonConstant(-42)
138 self.duration = NonConstant(r_longlong(-42))
139 self.duration_min = NonConstant(r_longlong(-42))
140 self.duration_max = NonConstant(r_longlong(-42))
153 self.duration = NonConstant(-53.2)
154 self.duration_min = NonConstant(-53.2)
155 self.duration_max = NonConstant(-53.2)
141156 self.total_memory_used = NonConstant(r_uint(42))
142157 self.pinned_objects = NonConstant(-42)
143158 self.fire()
144159
145 def perform(self, ec, frame):
160 def _do_perform(self, ec, frame):
146161 w_stats = W_GcMinorStats(
147162 self.count,
148163 self.duration,
154169 self.space.call_function(self.w_callable, w_stats)
155170
156171
157 class GcCollectStepHookAction(AsyncAction):
172 class GcCollectStepHookAction(NoRecursiveAction):
158173 oldstate = 0
159174 newstate = 0
160175
161176 def __init__(self, space):
162 AsyncAction.__init__(self, space)
177 NoRecursiveAction.__init__(self, space)
163178 self.w_callable = space.w_None
164179 self.reset()
165180
166181 def reset(self):
167182 self.count = 0
168 self.duration = r_longlong(0)
169 self.duration_min = r_longlong(longlongmax)
170 self.duration_max = r_longlong(0)
183 self.duration = 0.0
184 self.duration_min = inf
185 self.duration_max = 0.0
171186
172187 def fix_annotation(self):
173188 # the annotation of the class and its attributes must be completed
175190 # annotated with the correct types
176191 if NonConstant(False):
177192 self.count = NonConstant(-42)
178 self.duration = NonConstant(r_longlong(-42))
179 self.duration_min = NonConstant(r_longlong(-42))
180 self.duration_max = NonConstant(r_longlong(-42))
193 self.duration = NonConstant(-53.2)
194 self.duration_min = NonConstant(-53.2)
195 self.duration_max = NonConstant(-53.2)
181196 self.oldstate = NonConstant(-42)
182197 self.newstate = NonConstant(-42)
183198 self.fire()
184199
185 def perform(self, ec, frame):
200 def _do_perform(self, ec, frame):
186201 w_stats = W_GcCollectStepStats(
187202 self.count,
188203 self.duration,
189204 self.duration_min,
190205 self.duration_max,
191206 self.oldstate,
192 self.newstate)
207 self.newstate,
208 rgc.is_done__states(self.oldstate, self.newstate))
193209 self.reset()
194210 self.space.call_function(self.w_callable, w_stats)
195211
196212
197 class GcCollectHookAction(AsyncAction):
213 class GcCollectHookAction(NoRecursiveAction):
198214 num_major_collects = 0
199215 arenas_count_before = 0
200216 arenas_count_after = 0
203219 rawmalloc_bytes_after = 0
204220
205221 def __init__(self, space):
206 AsyncAction.__init__(self, space)
222 NoRecursiveAction.__init__(self, space)
207223 self.w_callable = space.w_None
208224 self.reset()
209225
224240 self.rawmalloc_bytes_after = NonConstant(r_uint(42))
225241 self.fire()
226242
227 def perform(self, ec, frame):
243 def _do_perform(self, ec, frame):
228244 w_stats = W_GcCollectStats(self.count,
229245 self.num_major_collects,
230246 self.arenas_count_before,
249265
250266
251267 class W_GcCollectStepStats(W_Root):
268 # NOTE: this is specific to incminimark: if we want to integrate the
269 # applevel gc module with another gc, we probably need a more general
270 # approach to this.
271 #
272 # incminimark has 4 GC states: scanning, marking, sweeping and
273 # finalizing. However, from the user point of view, we have an additional
274 # "virtual" state: USERDEL, which represent when we run applevel
275 # finalizers after having completed a GC major collection. This state is
276 # never explicitly visible when using hooks, but it is used for the return
277 # value of gc.collect_step (see interp_gc.py)
278 STATE_SCANNING = incminimark.STATE_SCANNING
279 STATE_MARKING = incminimark.STATE_MARKING
280 STATE_SWEEPING = incminimark.STATE_SWEEPING
281 STATE_FINALIZING = incminimark.STATE_FINALIZING
282 STATE_USERDEL = incminimark.STATE_FINALIZING + 1 # used by StepCollector
283 GC_STATES = tuple(incminimark.GC_STATES + ['USERDEL'])
252284
253285 def __init__(self, count, duration, duration_min, duration_max,
254 oldstate, newstate):
286 oldstate, newstate, major_is_done):
255287 self.count = count
256288 self.duration = duration
257289 self.duration_min = duration_min
258290 self.duration_max = duration_max
259291 self.oldstate = oldstate
260292 self.newstate = newstate
293 self.major_is_done = major_is_done
261294
262295
263296 class W_GcCollectStats(W_Root):
275308
276309
277310 # just a shortcut to make the typedefs shorter
278 def wrap_many_ints(cls, names):
311 def wrap_many(cls, names):
279312 d = {}
280313 for name in names:
281 d[name] = interp_attrproperty(name, cls=cls, wrapfn="newint")
314 if "duration" in name:
315 wrapfn = "newfloat"
316 else:
317 wrapfn = "newint"
318 d[name] = interp_attrproperty(name, cls=cls, wrapfn=wrapfn)
282319 return d
283320
284321
302339
303340 W_GcMinorStats.typedef = TypeDef(
304341 "GcMinorStats",
305 **wrap_many_ints(W_GcMinorStats, (
342 **wrap_many(W_GcMinorStats, (
306343 "count",
307344 "duration",
308345 "duration_min",
313350
314351 W_GcCollectStepStats.typedef = TypeDef(
315352 "GcCollectStepStats",
316 STATE_SCANNING = incminimark.STATE_SCANNING,
317 STATE_MARKING = incminimark.STATE_MARKING,
318 STATE_SWEEPING = incminimark.STATE_SWEEPING,
319 STATE_FINALIZING = incminimark.STATE_FINALIZING,
320 GC_STATES = tuple(incminimark.GC_STATES),
321 **wrap_many_ints(W_GcCollectStepStats, (
353 STATE_SCANNING = W_GcCollectStepStats.STATE_SCANNING,
354 STATE_MARKING = W_GcCollectStepStats.STATE_MARKING,
355 STATE_SWEEPING = W_GcCollectStepStats.STATE_SWEEPING,
356 STATE_FINALIZING = W_GcCollectStepStats.STATE_FINALIZING,
357 STATE_USERDEL = W_GcCollectStepStats.STATE_USERDEL,
358 GC_STATES = tuple(W_GcCollectStepStats.GC_STATES),
359 major_is_done = interp_attrproperty(
360 "major_is_done",
361 cls=W_GcCollectStepStats,
362 wrapfn="newbool"),
363 **wrap_many(W_GcCollectStepStats, (
322364 "count",
323365 "duration",
324366 "duration_min",
329371
330372 W_GcCollectStats.typedef = TypeDef(
331373 "GcCollectStats",
332 **wrap_many_ints(W_GcCollectStats, (
374 **wrap_many(W_GcCollectStats, (
333375 "count",
334376 "num_major_collects",
335377 "arenas_count_before",
00 from pypy.interpreter.gateway import unwrap_spec
11 from pypy.interpreter.error import oefmt
22 from rpython.rlib import rgc
3 from pypy.module.gc.hook import W_GcCollectStepStats
34
45
56 @unwrap_spec(generation=int)
1516 cache.clear()
1617
1718 rgc.collect()
19 _run_finalizers(space)
1820
21 def _run_finalizers(space):
1922 # if we are running in gc.disable() mode but gc.collect() is called,
2023 # we should still call the finalizers now. We do this as an attempt
2124 # to get closer to CPython's behavior: in Py3.5 some tests
3841 return space.newint(0)
3942
4043 def enable(space):
41 """Non-recursive version. Enable finalizers now.
44 """Non-recursive version. Enable major collections and finalizers.
4245 If they were already enabled, no-op.
4346 If they were disabled even several times, enable them anyway.
4447 """
48 rgc.enable()
4549 if not space.user_del_action.enabled_at_app_level:
4650 space.user_del_action.enabled_at_app_level = True
4751 enable_finalizers(space)
4852
4953 def disable(space):
50 """Non-recursive version. Disable finalizers now. Several calls
51 to this function are ignored.
54 """Non-recursive version. Disable major collections and finalizers.
55 Multiple calls to this function are ignored.
5256 """
57 rgc.disable()
5358 if space.user_del_action.enabled_at_app_level:
5459 space.user_del_action.enabled_at_app_level = False
5560 disable_finalizers(space)
7681 if uda.pending_with_disabled_del is None:
7782 uda.pending_with_disabled_del = []
7883
84
85 class StepCollector(object):
86 """
87 Invoke rgc.collect_step() until we are done, then run the app-level
88 finalizers as a separate step
89 """
90
91 def __init__(self, space):
92 self.space = space
93 self.finalizing = False
94
95 def do(self):
96 if self.finalizing:
97 self._run_finalizers()
98 self.finalizing = False
99 oldstate = W_GcCollectStepStats.STATE_USERDEL
100 newstate = W_GcCollectStepStats.STATE_SCANNING
101 major_is_done = True # now we are finally done
102 else:
103 states = self._collect_step()
104 oldstate = rgc.old_state(states)
105 newstate = rgc.new_state(states)
106 major_is_done = False # USERDEL still to do
107 if rgc.is_done(states):
108 newstate = W_GcCollectStepStats.STATE_USERDEL
109 self.finalizing = True
110 #
111 duration = -1
112 return W_GcCollectStepStats(
113 count = 1,
114 duration = duration,
115 duration_min = duration,
116 duration_max = duration,
117 oldstate = oldstate,
118 newstate = newstate,
119 major_is_done = major_is_done)
120
121 def _collect_step(self):
122 return rgc.collect_step()
123
124 def _run_finalizers(self):
125 _run_finalizers(self.space)
126
127 def collect_step(space):
128 """
129 If the GC is incremental, run a single gc-collect-step. Return True when
130 the major collection is completed.
131 If the GC is not incremental, do a full collection and return True.
132 """
133 sc = space.fromcache(StepCollector)
134 w_stats = sc.do()
135 return w_stats
136
79137 # ____________________________________________________________
80138
81139 @unwrap_spec(filename='fsencode')
188188 self.peak_arena_memory = rgc.get_stats(rgc.PEAK_ARENA_MEMORY)
189189 self.peak_rawmalloced_memory = rgc.get_stats(rgc.PEAK_RAWMALLOCED_MEMORY)
190190 self.nursery_size = rgc.get_stats(rgc.NURSERY_SIZE)
191 self.total_gc_time = rgc.get_stats(rgc.TOTAL_GC_TIME)
191192
192193 W_GcStats.typedef = TypeDef("GcStats",
193194 total_memory_pressure=interp_attrproperty("total_memory_pressure",
213214 peak_rawmalloced_memory=interp_attrproperty("peak_rawmalloced_memory",
214215 cls=W_GcStats, wrapfn="newint"),
215216 nursery_size=interp_attrproperty("nursery_size",
217 cls=W_GcStats, wrapfn="newint"),
218 total_gc_time=interp_attrproperty("total_gc_time",
216219 cls=W_GcStats, wrapfn="newint"),
217220 )
218221
00 import py
1
1 import pytest
2 from rpython.rlib import rgc
3 from pypy.interpreter.baseobjspace import ObjSpace
4 from pypy.interpreter.gateway import interp2app, unwrap_spec
5 from pypy.module.gc.interp_gc import StepCollector, W_GcCollectStepStats
26
37 class AppTestGC(object):
8
9 def setup_class(cls):
10 if cls.runappdirect:
11 pytest.skip("these tests cannot work with -A")
12 space = cls.space
13 def rgc_isenabled(space):
14 return space.newbool(rgc.isenabled())
15 cls.w_rgc_isenabled = space.wrap(interp2app(rgc_isenabled))
16
417 def test_collect(self):
518 import gc
619 gc.collect() # mostly a "does not crash" kind of test
6275 def test_enable(self):
6376 import gc
6477 assert gc.isenabled()
78 assert self.rgc_isenabled()
6579 gc.disable()
6680 assert not gc.isenabled()
81 assert not self.rgc_isenabled()
6782 gc.enable()
6883 assert gc.isenabled()
84 assert self.rgc_isenabled()
6985 gc.enable()
7086 assert gc.isenabled()
87 assert self.rgc_isenabled()
7188
7289 def test_gc_collect_overrides_gc_disable(self):
7390 import gc
8299 assert deleted == [1]
83100 gc.enable()
84101
102 def test_gc_collect_step(self):
103 import gc
104
105 class X(object):
106 deleted = 0
107 def __del__(self):
108 X.deleted += 1
109
110 gc.disable()
111 X(); X(); X();
112 n = 0
113 while True:
114 n += 1
115 if gc.collect_step().major_is_done:
116 break
117
118 assert n >= 2 # at least one step + 1 finalizing
119 assert X.deleted == 3
85120
86121 class AppTestGcDumpHeap(object):
87122 pytestmark = py.test.mark.xfail(run=False)
155190 gc.collect() # the classes C should all go away here
156191 for r in rlist:
157192 assert r() is None
193
194
195 def test_StepCollector():
196 W = W_GcCollectStepStats
197 SCANNING = W.STATE_SCANNING
198 MARKING = W.STATE_MARKING
199 SWEEPING = W.STATE_SWEEPING
200 FINALIZING = W.STATE_FINALIZING
201 USERDEL = W.STATE_USERDEL
202
203 class MyStepCollector(StepCollector):
204 my_steps = 0
205 my_done = False
206 my_finalized = 0
207
208 def __init__(self):
209 StepCollector.__init__(self, space=None)
210 self._state_transitions = iter([
211 (SCANNING, MARKING),
212 (MARKING, SWEEPING),
213 (SWEEPING, FINALIZING),
214 (FINALIZING, SCANNING)])
215
216 def _collect_step(self):
217 self.my_steps += 1
218 try:
219 oldstate, newstate = next(self._state_transitions)
220 except StopIteration:
221 assert False, 'should not happen, did you call _collect_step too much?'
222 return rgc._encode_states(oldstate, newstate)
223
224 def _run_finalizers(self):
225 self.my_finalized += 1
226
227 sc = MyStepCollector()
228 transitions = []
229 while True:
230 result = sc.do()
231 transitions.append((result.oldstate, result.newstate, sc.my_finalized))
232 if result.major_is_done:
233 break
234
235 assert transitions == [
236 (SCANNING, MARKING, False),
237 (MARKING, SWEEPING, False),
238 (SWEEPING, FINALIZING, False),
239 (FINALIZING, USERDEL, False),
240 (USERDEL, SCANNING, True)
241 ]
242 # there is one more transition than actual step, because
243 # FINALIZING->USERDEL is "virtual"
244 assert sc.my_steps == len(transitions) - 1
2525
2626 @unwrap_spec(ObjSpace)
2727 def fire_many(space):
28 gchooks.fire_gc_minor(5, 0, 0)
29 gchooks.fire_gc_minor(7, 0, 0)
30 gchooks.fire_gc_collect_step(5, 0, 0)
31 gchooks.fire_gc_collect_step(15, 0, 0)
32 gchooks.fire_gc_collect_step(22, 0, 0)
28 gchooks.fire_gc_minor(5.0, 0, 0)
29 gchooks.fire_gc_minor(7.0, 0, 0)
30 gchooks.fire_gc_collect_step(5.0, 0, 0)
31 gchooks.fire_gc_collect_step(15.0, 0, 0)
32 gchooks.fire_gc_collect_step(22.0, 0, 0)
3333 gchooks.fire_gc_collect(1, 2, 3, 4, 5, 6)
3434
3535 cls.w_fire_gc_minor = space.wrap(interp2app(fire_gc_minor))
6868
6969 def test_on_gc_collect_step(self):
7070 import gc
71 SCANNING = 0
72 MARKING = 1
73 SWEEPING = 2
74 FINALIZING = 3
7175 lst = []
7276 def on_gc_collect_step(stats):
7377 lst.append((stats.count,
7478 stats.duration,
7579 stats.oldstate,
76 stats.newstate))
80 stats.newstate,
81 stats.major_is_done))
7782 gc.hooks.on_gc_collect_step = on_gc_collect_step
78 self.fire_gc_collect_step(10, 20, 30)
79 self.fire_gc_collect_step(40, 50, 60)
80 assert lst == [
81 (1, 10, 20, 30),
82 (1, 40, 50, 60),
83 self.fire_gc_collect_step(10, SCANNING, MARKING)
84 self.fire_gc_collect_step(40, FINALIZING, SCANNING)
85 assert lst == [
86 (1, 10, SCANNING, MARKING, False),
87 (1, 40, FINALIZING, SCANNING, True),
8388 ]
8489 #
8590 gc.hooks.on_gc_collect_step = None
86 self.fire_gc_collect_step(70, 80, 90) # won't fire
87 assert lst == [
88 (1, 10, 20, 30),
89 (1, 40, 50, 60),
90 ]
91 oldlst = lst[:]
92 self.fire_gc_collect_step(70, SCANNING, MARKING) # won't fire
93 assert lst == oldlst
9194
9295 def test_on_gc_collect(self):
9396 import gc
122125 assert S.STATE_MARKING == 1
123126 assert S.STATE_SWEEPING == 2
124127 assert S.STATE_FINALIZING == 3
125 assert S.GC_STATES == ('SCANNING', 'MARKING', 'SWEEPING', 'FINALIZING')
128 assert S.GC_STATES == ('SCANNING', 'MARKING', 'SWEEPING',
129 'FINALIZING', 'USERDEL')
126130
127131 def test_cumulative(self):
128132 import gc
175179 assert gc.hooks.on_gc_minor is None
176180 assert gc.hooks.on_gc_collect_step is None
177181 assert gc.hooks.on_gc_collect is None
182
183 def test_no_recursive(self):
184 import gc
185 lst = []
186 def on_gc_minor(stats):
187 lst.append((stats.count,
188 stats.duration,
189 stats.total_memory_used,
190 stats.pinned_objects))
191 self.fire_gc_minor(1, 2, 3) # won't fire NOW
192 gc.hooks.on_gc_minor = on_gc_minor
193 self.fire_gc_minor(10, 20, 30)
194 self.fire_gc_minor(40, 50, 60)
195 # the duration for the 2nd call is 41, because it also counts the 1
196 # which was fired recursively
197 assert lst == [
198 (1, 10, 20, 30),
199 (2, 41, 50, 60),
200 ]
1919 cls.w_udir = cls.space.wrap(str(udir))
2020
2121 def w__py_file(self):
22 f = open('@TEST.py', 'w')
22 fname = self.udir + '/@TEST.py'
23 f = open(fname, 'w')
2324 f.write('MARKER = 42\n')
2425 f.close()
25 return '@TEST.py'
26 return fname
2627
2728 def w__pyc_file(self):
2829 import marshal, imp
2930 co = compile("marker=42", "x.py", "exec")
30 f = open('@TEST.pyc', 'wb')
31 fname = self.udir + '/@TEST.pyc'
32 f = open(fname, 'wb')
3133 f.write(imp.get_magic())
3234 f.write(b'\x00\x00\x00\x00')
3335 f.write(b'\x00\x00\x00\x00')
3436 marshal.dump(co, f)
3537 f.close()
36 return '@TEST.pyc'
38 return fname
3739
3840 def test_find_module(self):
3941 import os, imp
100100 foobar = "found = 123",
101101 barbaz = "other = 543")
102102 setuppkg("pkg.withoutall",
103 __init__ = "",
104 foobar = "found = 123")
103 __init__ = "globals()[''] = 456",
104 foobar = "found = 123\n")
105105 setuppkg("pkg.bogusall",
106106 __init__ = "__all__ = 42")
107107 setuppkg("pkg_r", inpkg = "import x.y")
701701 d = {}
702702 exec("from pkg.withoutall import *", d)
703703 assert d["foobar"].found == 123
704
705 def test_import_star_empty_string(self):
706 for case in ["not-imported-yet", "already-imported"]:
707 d = {}
708 exec("from pkg.withoutall import *", d)
709 assert "" in d
704710
705711 def test_import_star_with_bogus___all__(self):
706712 for case in ["not-imported-yet", "already-imported"]:
537537 def chain_from_iterable(space, w_cls, w_arg):
538538 """chain.from_iterable(iterable) --> chain object
539539
540 Alternate chain() contructor taking a single iterable argument
540 Alternate chain() constructor taking a single iterable argument
541541 that evaluates lazily."""
542542 r = space.allocate_instance(W_Chain, w_cls)
543543 r.__init__(space, space.iter(w_arg))
44 from rpython.rlib import rfloat
55 from rpython.rtyper.lltypesystem.module.test.math_cases import (MathTests,
66 get_tester)
7
8 consistent_host = True
9 if '__pypy__' not in sys.builtin_module_names:
10 if sys.version_info < (2, 6):
11 consistent_host = False
127
138 class TestDirect(MathTests):
149 pass
2924 def make_test_case((fnname, args, expected), dict):
3025 #
3126 def test_func(self):
32 if not consistent_host:
33 py.test.skip("inconsistent behavior before 2.6")
3427 try:
3528 fn = getattr(math, fnname)
3629 except AttributeError:
1717 filename = filename[:-1]
1818 space = cls.space
1919 cls.w_math_cases = space.wrap(filename)
20 cls.w_consistent_host = space.wrap(test_direct.consistent_host)
2120
2221 @classmethod
2322 def make_callable_wrapper(cls, func):
5251 yield fnname, args, expected
5352
5453 def test_all_cases(self):
55 if not self.consistent_host:
56 skip("please test this on top of PyPy or CPython >= 2.6")
5754 import math
5855 for fnname, args, expected in self.cases():
5956 fn = getattr(math, fnname)
653653 def descr__getattr__(self, space, w_key):
654654 return space.getattr(self.w_obj, w_key)
655655
656 W_GenericBox.typedef = TypeDef("numpy.generic",
656 W_GenericBox.typedef = TypeDef("numpy.generic", None, None, "read-write",
657657 __new__ = interp2app(W_GenericBox.descr__new__.im_func),
658658
659659 __getitem__ = interp2app(W_GenericBox.descr_getitem),
387387 not self.flags & NPY.ARRAY_F_CONTIGUOUS):
388388 raise oefmt(errtype, "ndarray is not Fortran contiguous")
389389 if ((flags & space.BUF_ANY_CONTIGUOUS) == space.BUF_ANY_CONTIGUOUS and
390 not (self.flags & NPY.ARRAY_F_CONTIGUOUS and
390 not (self.flags & NPY.ARRAY_F_CONTIGUOUS or
391391 self.flags & NPY.ARRAY_C_CONTIGUOUS)):
392392 raise oefmt(errtype, "ndarray is not contiguous")
393393 if ((flags & space.BUF_STRIDES) != space.BUF_STRIDES and
819819 if (axis1 < 0 or axis2 < 0 or axis1 >= self.ndims() or
820820 axis2 >= self.ndims()):
821821 raise oefmt(space.w_ValueError,
822 "axis1(=%d) and axis2(=%d) must be withing range "
822 "axis1(=%d) and axis2(=%d) must be within range "
823823 "(ndim=%d)", axis1, axis2, self.ndims())
824824 if axis1 == axis2:
825825 raise oefmt(space.w_ValueError,
133133 space.newtext(message))
134134
135135
136 def get_node_type(space, w_tuple):
136 def get_node_type(space, tup_w, w_tuple):
137137 try:
138 w_type = space.getitem(w_tuple, space.newint(0))
139 return space.int_w(w_type)
138 return space.int_w(tup_w[0])
140139 except OperationError:
141140 raise parser_error(space, w_tuple, "Illegal component tuple.")
142141
145144 self.lineno = 0
146145
147146 def build_node_tree(space, w_tuple):
148 type = get_node_type(space, w_tuple)
147 tup_w = space.unpackiterable(w_tuple)
148 if len(tup_w) == 0:
149 raise parser_error(space, w_tuple, "tuple too short")
150
151 type = get_node_type(space, tup_w, w_tuple)
149152 node_state = NodeState()
150153 if 0 <= type < 256:
151154 # The tuple is simple, but it doesn't start with a start symbol.
152155 # Raise an exception now and be done with it.
153156 raise parser_error(space, w_tuple,
154157 "Illegal syntax-tree; cannot start with terminal symbol.")
158 return build_node_children(space, type, tup_w, node_state)
159
160 def build_node_children(space, type, tup_w, node_state):
155161 node = pyparse.parser.Nonterminal(type)
156 build_node_children(space, w_tuple, node, node_state)
157 return node
158
159 def build_node_children(space, w_tuple, node, node_state):
160 for w_elem in space.unpackiterable(w_tuple)[1:]:
161 type = get_node_type(space, w_elem)
162 for i in range(1, len(tup_w)):
163 w_elem = tup_w[i]
164 subtup_w = space.unpackiterable(w_elem)
165 type = get_node_type(space, subtup_w, w_elem)
162166 if type < 256: # Terminal node
163 length = space.len_w(w_elem)
167 length = len(subtup_w)
164168 if length == 2:
165 _, w_obj = space.unpackiterable(w_elem, 2)
169 _, w_obj = subtup_w
166170 elif length == 3:
167 _, w_obj, w_lineno = space.unpackiterable(w_elem, 3)
171 _, w_obj, w_lineno = subtup_w
168172 else:
169173 raise parse_error(
170174 space, "terminal nodes must have 2 or 3 entries")
171175 strn = space.text_w(w_obj)
172176 child = pyparse.parser.Terminal(type, strn, node_state.lineno, 0)
173177 else:
174 child = pyparse.parser.Nonterminal(type)
178 child = build_node_children(space, type, subtup_w, node_state)
175179 node.append_child(child)
176 if type >= 256: # Nonterminal node
177 build_node_children(space, w_elem, child, node_state)
178 elif type == pyparse.pygram.tokens.NEWLINE:
180 if type == pyparse.pygram.tokens.NEWLINE:
179181 node_state.lineno += 1
180
181
182 def validate_node(space, tree):
182 return node
183
184
185 def validate_node(space, tree, parser):
183186 assert tree.type >= 256
184187 type = tree.type - 256
185 parser = pyparse.PythonParser(space)
186188 if type >= len(parser.grammar.dfas):
187189 raise parse_error(space, "Unrecognized node type %d." % type)
188190 dfa = parser.grammar.dfas[type]
195197 if label == ch.type:
196198 # The child is acceptable; validate it recursively
197199 if ch.type >= 256:
198 validate_node(space, ch)
200 validate_node(space, ch, parser)
199201 # Update the state, and move on to the next child.
200202 arcs, is_accepting = dfa.states[next_state]
201203 break
209211 def tuple2st(space, w_sequence):
210212 # Convert the tree to the internal form before checking it
211213 tree = build_node_tree(space, w_sequence)
212 validate_node(space, tree)
214 parser = pyparse.PythonParser(space)
215 validate_node(space, tree, parser)
213216 return W_STType(tree, 'eval')
24062406 if _WIN32:
24072407 have_functions.append("HAVE_MS_WINDOWS")
24082408
2409 def get_terminal_size(space, w_fd=None):
2409 def _get_terminal_size(space, w_fd=None):
24102410 if w_fd is None:
24112411 fd = rfile.RFile(rfile.c_stdout(), close2=(None, None)).fileno()
24122412 else:
24462446
24472447 w_columns = space.newint(r_uint(winsize.c_ws_col))
24482448 w_lines = space.newint(r_uint(winsize.c_ws_row))
2449
2449 return w_columns, w_lines
2450
2451 def get_terminal_size(space, w_fd=None):
2452 try:
2453 w_columns, w_lines = _get_terminal_size(space, w_fd)
2454 except OSError as e:
2455 raise wrap_oserror(space, e, eintr_retry=False)
24502456 w_tuple = space.newtuple([w_columns, w_lines])
24512457 w_terminal_size = space.getattr(space.getbuiltinmodule(os.name),
24522458 space.newtext('terminal_size'))
226226 def test_pickle(self):
227227 import pickle, os
228228 st = self.posix.stat(os.curdir)
229 print(type(st).__module__)
229 # print(type(st).__module__)
230230 s = pickle.dumps(st)
231 print(repr(s))
231 # print(repr(s))
232232 new = pickle.loads(s)
233233 assert new == st
234234 assert type(new) is type(st)
571571 with stream as fp:
572572 res = fp.read()
573573 assert res == '1\n'
574
575 if sys.platform == "win32":
576 # using startfile in app_startfile creates global state
577 test_popen.dont_track_allocations = True
578 test_popen_with.dont_track_allocations = True
579 test_popen_child_fds.dont_track_allocations = True
574580
575581 if hasattr(__import__(os.name), '_getfullpathname'):
576582 def test__getfullpathname(self):
14871493 raises(OSError, os.getxattr, self.path, 'user.test')
14881494 assert os.listxattr(self.path, follow_symlinks=False) == init_names
14891495
1496 def test_get_terminal_size(self):
1497 os = self.posix
1498 for args in [(), (1,), (0,), (42421,)]:
1499 try:
1500 w, h = os.get_terminal_size(*args)
1501 except (ValueError, OSError):
1502 continue
1503 assert isinstance(w, int)
1504 assert isinstance(h, int)
1505
14901506
14911507 class AppTestEnvironment(object):
14921508 def setup_class(cls):
3636 passwd_p = lltype.Ptr(config['passwd'])
3737
3838 def external(name, args, result, **kwargs):
39 return rffi.llexternal(name, args, result, compilation_info=eci, **kwargs)
39 return rffi.llexternal(name, args, result, compilation_info=eci,
40 releasegil=False, **kwargs)
4041
4142 c_getpwuid = external("getpwuid", [uid_t], passwd_p)
4243 c_getpwnam = external("getpwnam", [rffi.CCHARP], passwd_p)
1919 assert log.result % 1000 == 0
2020 loop, = log.loops_by_filename(self.filepath)
2121 ops = loop.ops_by_id('look')
22 assert log.opnames(ops) == []
22 assert log.opnames(ops) == ['guard_nonnull_class']
2323
2424 def test_identitydict(self):
2525 def fn(n):
406406 i138 = call_i(ConstClass(_ll_1_raw_malloc_varsize_zero__Signed), 6, descr=...)
407407 check_memory_error(i138)
408408 setfield_gc(p132, i138, descr=...)
409 setfield_gc(p132, 0, descr=...)
409410 setfield_gc(p132, ConstPtr(ptr139), descr=...)
410411 setfield_gc(p132, -1, descr=...)
411412 setfield_gc(p0, p133, descr=...)
243243 f80 = raw_load_f(i67, i79, descr=<ArrayF 8>)
244244 i81 = int_add(i71, 1)
245245 --TICK--
246 i92 = int_le(i33, _)
247 guard_true(i92, descr=...)
246248 jump(..., descr=...)
247249 """)
248250
282284 f86 = float_add(f74, f85)
283285 i87 = int_add(i76, 1)
284286 --TICK--
287 i98 = int_le(i36, _)
288 guard_true(i98, descr=...)
285289 jump(..., descr=...)
286290 """)
287291
389393 assert log.result == [0.] * N
390394 loop, = log.loops_by_filename(self.filepath)
391395 assert loop.match("""
396 i4 = int_lt(i91, 0)
397 guard_false(i4, descr=...)
392398 i92 = int_ge(i91, i37)
393399 guard_false(i92, descr=...)
394400 i93 = int_add(i91, 1)
2929 sa = 0
3030 while i < 30000:
3131 lst = range(i % 1000 + 2)
32 sa += max(*lst) # ID: max
32 sa += max(*lst) # ID: callmax
3333 i += 1
3434 return sa
3535 log = self.run(main, [])
3636 assert log.result == main()
3737 loop, = log.loops_by_filename(self.filepath)
38 assert loop.match("""
38 assert loop.match_by_id('callmax', """
3939 ...
40 p76 = call_assembler_r(..., descr=...)
40 p76 = call_may_force_r(_, _, _, _, descr=...)
4141 ...
4242 """)
43 loop2 = log.loops[0]
44 loop2.match('''
45 ...
46 label(..., descr=...)
47 ...
48 label(..., descr=...)
49 guard_not_invalidated?
50 i17 = int_ge(i11, i7)
51 guard_false(i17, descr=...)
52 p18 = getarrayitem_gc_r(p5, i11, descr=...)
53 i19 = int_add(i11, 1)
54 setfield_gc(p2, i19, descr=...)
55 guard_nonnull_class(p18, ConstClass(W_IntObject), descr=...)
56 i20 = getfield_gc_i(p18, descr=...)
57 i21 = int_gt(i20, i14)
58 guard_true(i21, descr=...)
59 jump(..., descr=...)
60 ''')
61 # XXX could be "guard_class(p18)" instead; we lost somewhere
62 # the information that it cannot be null.
43
44 #----- the following logic used to check the content of the assembly
45 #----- generated for the loop in max(), but now we no longer produce
46 #----- any custom assembly in this case. It used to say
47 #----- 'call_assembler_r' above, and now it says 'call_may_force_r'.
48 #loop2 = log.loops[0]
49 #loop2.match('''
50 #...
51 #label(..., descr=...)
52 #...
53 #label(..., descr=...)
54 #guard_not_invalidated?
55 #i17 = int_ge(i11, i7)
56 #guard_false(i17, descr=...)
57 #p18 = getarrayitem_gc_r(p5, i11, descr=...)
58 #i19 = int_add(i11, 1)
59 #setfield_gc(p2, i19, descr=...)
60 #guard_nonnull_class(p18, ConstClass(W_IntObject), descr=...)
61 #i20 = getfield_gc_i(p18, descr=...)
62 #i21 = int_gt(i20, i14)
63 #guard_true(i21, descr=...)
64 #jump(..., descr=...)
65 #''')
66 ## XXX could be "guard_class(p18)" instead; we lost somewhere
67 ## the information that it cannot be null.
6368
6469 def test_iter_max(self):
6570 def main():
112112 i12 = int_is_true(i4)
113113 guard_true(i12, descr=...)
114114 guard_not_invalidated(descr=...)
115 guard_nonnull_class(p10, ConstClass(W_IntObject), descr=...)
115116 i10p = getfield_gc_i(p10, descr=...)
116117 i10 = int_mul_ovf(2, i10p)
117118 guard_no_overflow(descr=...)
145146 RANGE_ITER_STEP_1 = """
146147 guard_not_invalidated?
147148 # W_IntRangeStepOneIterator.next()
149 i80 = int_lt(i11, 0)
150 guard_false(i80, descr=...)
148151 i16 = int_lt(i11, i12)
149152 guard_true(i16, descr=...)
150153 i20 = int_add(i11, 1)
151154 setfield_gc(p4, i20, descr=<.* .*W_IntRangeIterator.inst_current .*>)
152155 guard_not_invalidated?
153156 i21 = force_token()
157 i89 = int_lt(0, i9)
158 guard_true(i89, descr=...)
154159 i88 = int_sub(i9, 1)
155160
156161 # Compared with pypy2, we get these two operations extra.
22
33 import sys
44 import os
5 from rpython.rlib import _rsocket_rffi as _c
56
67
78 class Module(MixedModule):
3031 for symbol in symbol_map:
3132 interpleveldefs[symbol] = "space.wrap(interp_kqueue.%s)" % symbol
3233
34 if _c.PIPE_BUF is not None:
35 interpleveldefs['PIPE_BUF'] = 'space.wrap(%r)' % _c.PIPE_BUF
36
37
3338 def buildloaders(cls):
3439 from rpython.rlib import rpoll
3540 for name in rpoll.eventnames:
318318 # ^^^ CPython gives 100, PyPy gives 1. I think both are OK as
319319 # long as there is no crash.
320320
321 def test_PIPE_BUF(self):
322 # no PIPE_BUF on Windows; this test class is skipped on Windows.
323 import select
324 assert isinstance(select.PIPE_BUF, int)
325
321326
322327 class AppTestSelectWithSockets(_AppTestSelect):
323328 """Same tests with connected sockets.
5656 space.check_signal_action = interp_signal.CheckSignalAction(space)
5757 space.actionflag.register_periodic_action(space.check_signal_action,
5858 use_bytecode_counter=False)
59 space.actionflag.__class__ = interp_signal.SignalActionFlag
59 if space.reverse_debugging:
60 from pypy.interpreter.reverse_debugging import RDBSignalActionFlag
61 space.actionflag.__class__ = RDBSignalActionFlag
62 else:
63 space.actionflag.__class__ = interp_signal.SignalActionFlag
6064 # xxx yes I know the previous line is a hack
6165
6266 def startup(self, space):
378378 for w_signum in space.unpackiterable(self.w_signals):
379379 signum = space.int_w(w_signum)
380380 check_signum_in_range(space, signum)
381 err = c_sigaddset(self.mask, signum)
382 if err:
383 raise oefmt(space.w_ValueError,
384 "signal number %d out of range", signum)
381 # bpo-33329: ignore c_sigaddset() return value as it can fail
382 # for some reserved signals, but we want the `range(1, NSIG)`
383 # idiom to allow selecting all valid signals.
384 c_sigaddset(self.mask, signum)
385385 return self.mask
386386
387387 def __exit__(self, *args):
230230 if os.name == 'nt':
231231
232232 _source_code = r"""
233 #ifndef _WIN32_WINNT
233234 #define _WIN32_WINNT 0x0501
235 #endif
234236 #include <windows.h>
235237 #include <stdio.h>
236
237 RPY_EXPORTED
238 #include <stdlib.h>
239
238240 char *_pypy_init_home(void)
239241 {
240242 HMODULE hModule = 0;
270272 #include <stdio.h>
271273 #include <stdlib.h>
272274
273 RPY_EXPORTED
274275 char *_pypy_init_home(void)
275276 {
276277 Dl_info info;
288289 }
289290 """
290291
292 _source_code += """
293 inline
294 void _pypy_init_free(char *p)
295 {
296 free(p);
297 }
298 """
299
300 if we_are_translated():
301 post_include_bits = []
302 else:
303 # for tests
304 post_include_bits=['RPY_EXPORTED char *_pypy_init_home(void);',
305 'RPY_EXPORTED void _pypy_init_free(char*);',
306 ]
307
291308 _eci = ExternalCompilationInfo(separate_module_sources=[_source_code],
292 post_include_bits=['RPY_EXPORTED char *_pypy_init_home(void);'])
309 post_include_bits=post_include_bits)
293310 _eci = _eci.merge(rdynload.eci)
294311
295312 pypy_init_home = rffi.llexternal("_pypy_init_home", [], rffi.CCHARP,
296313 _nowrapper=True, compilation_info=_eci)
297 pypy_init_free = rffi.llexternal("free", [rffi.CCHARP], lltype.Void,
314 pypy_init_free = rffi.llexternal("_pypy_init_free", [rffi.CCHARP], lltype.Void,
298315 _nowrapper=True, compilation_info=_eci)
356356 sys.stderr = savestderr
357357 print(ascii(err.getvalue()))
358358 assert err.getvalue().endswith("ValueError: %s\n" % input)
359
360 def test_excepthook_flushes_stdout(self): r"""
361 import sys, io
362 savestdout = sys.stdout
363 out = io.StringIO()
364 sys.stdout = out
365
366 eh = sys.__excepthook__
367
368 try:
369 raise ValueError(42)
370 except ValueError as exc:
371 print("hello") # with end-of-line
372 eh(*sys.exc_info())
373 try:
374 raise ValueError(42)
375 except ValueError as exc:
376 print(123, 456, end="") # no end-of-line here
377 eh(*sys.exc_info())
378
379 sys.stdout = savestdout
380 assert out.getvalue() == 'hello\n123 456' # no final \n added in 3.x
381 """
359382
360383 # FIXME: testing the code for a lost or replaced excepthook in
361384 # Python/pythonrun.c::PyErr_PrintEx() is tricky.
99 #XXX # sync CPYTHON_VERSION with patchlevel.h, package.py
1010 CPYTHON_API_VERSION = 1013 #XXX # sync with include/modsupport.h
1111
12 PYPY_VERSION = (6, 0, 0, "final", 0) #XXX # sync patchlevel.h
12 # make sure to keep PYPY_VERSION in sync with:
13 # module/cpyext/include/patchlevel.h
14 # doc/conf.py
15 PYPY_VERSION = (7, 1, 0, "alpha", 0)
1316
1417
1518 import pypy
+0
-1
pypy/module/test_lib_pypy/cffi_tests/__init__.py less more
0 # Generated by pypy/tool/import_cffi.py
+0
-1
pypy/module/test_lib_pypy/cffi_tests/cffi0/__init__.py less more
0 # Generated by pypy/tool/import_cffi.py
+0
-1928
pypy/module/test_lib_pypy/cffi_tests/cffi0/backend_tests.py less more
0 # Generated by pypy/tool/import_cffi.py
1 import py
2 import platform
3 import sys, ctypes
4 from cffi import FFI, CDefError, FFIError, VerificationMissing
5 from pypy.module.test_lib_pypy.cffi_tests.support import *
6
7 SIZE_OF_INT = ctypes.sizeof(ctypes.c_int)
8 SIZE_OF_LONG = ctypes.sizeof(ctypes.c_long)
9 SIZE_OF_SHORT = ctypes.sizeof(ctypes.c_short)
10 SIZE_OF_PTR = ctypes.sizeof(ctypes.c_void_p)
11 SIZE_OF_WCHAR = ctypes.sizeof(ctypes.c_wchar)
12
13 def needs_dlopen_none():
14 if sys.platform == 'win32' and sys.version_info >= (3,):
15 py.test.skip("dlopen(None) cannot work on Windows for Python 3")
16
17
18 class BackendTests:
19
20 def test_integer_ranges(self):
21 ffi = FFI(backend=self.Backend())
22 for (c_type, size) in [('char', 1),
23 ('short', 2),
24 ('short int', 2),
25 ('', 4),
26 ('int', 4),
27 ('long', SIZE_OF_LONG),
28 ('long int', SIZE_OF_LONG),
29 ('long long', 8),
30 ('long long int', 8),
31 ]:
32 for unsigned in [None, False, True]:
33 c_decl = {None: '',
34 False: 'signed ',
35 True: 'unsigned '}[unsigned] + c_type
36 if c_decl == 'char' or c_decl == '':
37 continue
38 self._test_int_type(ffi, c_decl, size, unsigned)
39
40 def test_fixedsize_int(self):
41 ffi = FFI(backend=self.Backend())
42 for size in [1, 2, 4, 8]:
43 self._test_int_type(ffi, 'int%d_t' % (8*size), size, False)
44 self._test_int_type(ffi, 'uint%d_t' % (8*size), size, True)
45 self._test_int_type(ffi, 'intptr_t', SIZE_OF_PTR, False)
46 self._test_int_type(ffi, 'uintptr_t', SIZE_OF_PTR, True)
47 self._test_int_type(ffi, 'ptrdiff_t', SIZE_OF_PTR, False)
48 self._test_int_type(ffi, 'size_t', SIZE_OF_PTR, True)
49 self._test_int_type(ffi, 'ssize_t', SIZE_OF_PTR, False)
50
51 def _test_int_type(self, ffi, c_decl, size, unsigned):
52 if unsigned:
53 min = 0
54 max = (1 << (8*size)) - 1
55 else:
56 min = -(1 << (8*size-1))
57 max = (1 << (8*size-1)) - 1
58 min = int(min)
59 max = int(max)
60 p = ffi.cast(c_decl, min)
61 assert p == min
62 assert hash(p) == hash(min)
63 assert bool(p) is bool(min)
64 assert int(p) == min
65 p = ffi.cast(c_decl, max)
66 assert int(p) == max
67 p = ffi.cast(c_decl, long(max))
68 assert int(p) == max
69 q = ffi.cast(c_decl, min - 1)
70 assert ffi.typeof(q) is ffi.typeof(p) and int(q) == max
71 q = ffi.cast(c_decl, long(min - 1))
72 assert ffi.typeof(q) is ffi.typeof(p) and int(q) == max
73 assert q == p
74 assert int(q) == int(p)
75 assert hash(q) == hash(p)
76 c_decl_ptr = '%s *' % c_decl
77 py.test.raises(OverflowError, ffi.new, c_decl_ptr, min - 1)
78 py.test.raises(OverflowError, ffi.new, c_decl_ptr, max + 1)
79 py.test.raises(OverflowError, ffi.new, c_decl_ptr, long(min - 1))
80 py.test.raises(OverflowError, ffi.new, c_decl_ptr, long(max + 1))
81 assert ffi.new(c_decl_ptr, min)[0] == min
82 assert ffi.new(c_decl_ptr, max)[0] == max
83 assert ffi.new(c_decl_ptr, long(min))[0] == min
84 assert ffi.new(c_decl_ptr, long(max))[0] == max
85
86 def test_new_unsupported_type(self):
87 ffi = FFI(backend=self.Backend())
88 e = py.test.raises(TypeError, ffi.new, "int")
89 assert str(e.value) == "expected a pointer or array ctype, got 'int'"
90
91 def test_new_single_integer(self):
92 ffi = FFI(backend=self.Backend())
93 p = ffi.new("int *") # similar to ffi.new("int[1]")
94 assert p[0] == 0
95 p[0] = -123
96 assert p[0] == -123
97 p = ffi.new("int *", -42)
98 assert p[0] == -42
99 assert repr(p) == "<cdata 'int *' owning %d bytes>" % SIZE_OF_INT
100
101 def test_new_array_no_arg(self):
102 ffi = FFI(backend=self.Backend())
103 p = ffi.new("int[10]")
104 # the object was zero-initialized:
105 for i in range(10):
106 assert p[i] == 0
107
108 def test_array_indexing(self):
109 ffi = FFI(backend=self.Backend())
110 p = ffi.new("int[10]")
111 p[0] = 42
112 p[9] = 43
113 assert p[0] == 42
114 assert p[9] == 43
115 py.test.raises(IndexError, "p[10]")
116 py.test.raises(IndexError, "p[10] = 44")
117 py.test.raises(IndexError, "p[-1]")
118 py.test.raises(IndexError, "p[-1] = 44")
119
120 def test_new_array_args(self):
121 ffi = FFI(backend=self.Backend())
122 # this tries to be closer to C: where we say "int x[5] = {10, 20, ..}"
123 # then here we must enclose the items in a list
124 p = ffi.new("int[5]", [10, 20, 30, 40, 50])
125 assert p[0] == 10
126 assert p[1] == 20
127 assert p[2] == 30
128 assert p[3] == 40
129 assert p[4] == 50
130 p = ffi.new("int[4]", [25])
131 assert p[0] == 25
132 assert p[1] == 0 # follow C convention rather than LuaJIT's
133 assert p[2] == 0
134 assert p[3] == 0
135 p = ffi.new("int[4]", [ffi.cast("int", -5)])
136 assert p[0] == -5
137 assert repr(p) == "<cdata 'int[4]' owning %d bytes>" % (4*SIZE_OF_INT)
138
139 def test_new_array_varsize(self):
140 ffi = FFI(backend=self.Backend())
141 p = ffi.new("int[]", 10) # a single integer is the length
142 assert p[9] == 0
143 py.test.raises(IndexError, "p[10]")
144 #
145 py.test.raises(TypeError, ffi.new, "int[]")
146 #
147 p = ffi.new("int[]", [-6, -7]) # a list is all the items, like C
148 assert p[0] == -6
149 assert p[1] == -7
150 py.test.raises(IndexError, "p[2]")
151 assert repr(p) == "<cdata 'int[]' owning %d bytes>" % (2*SIZE_OF_INT)
152 #
153 p = ffi.new("int[]", 0)
154 py.test.raises(IndexError, "p[0]")
155 py.test.raises(ValueError, ffi.new, "int[]", -1)
156 assert repr(p) == "<cdata 'int[]' owning 0 bytes>"
157
158 def test_pointer_init(self):
159 ffi = FFI(backend=self.Backend())
160 n = ffi.new("int *", 24)
161 a = ffi.new("int *[10]", [ffi.NULL, ffi.NULL, n, n, ffi.NULL])
162 for i in range(10):
163 if i not in (2, 3):
164 assert a[i] == ffi.NULL
165 assert a[2] == a[3] == n
166
167 def test_cannot_cast(self):
168 ffi = FFI(backend=self.Backend())
169 a = ffi.new("short int[10]")
170 e = py.test.raises(TypeError, ffi.new, "long int **", a)
171 msg = str(e.value)
172 assert "'short[10]'" in msg and "'long *'" in msg
173
174 def test_new_pointer_to_array(self):
175 ffi = FFI(backend=self.Backend())
176 a = ffi.new("int[4]", [100, 102, 104, 106])
177 p = ffi.new("int **", a)
178 assert p[0] == ffi.cast("int *", a)
179 assert p[0][2] == 104
180 p = ffi.cast("int *", a)
181 assert p[0] == 100
182 assert p[1] == 102
183 assert p[2] == 104
184 assert p[3] == 106
185 # keepalive: a
186
187 def test_pointer_direct(self):
188 ffi = FFI(backend=self.Backend())
189 p = ffi.cast("int*", 0)
190 assert p is not None
191 assert bool(p) is False
192 assert p == ffi.cast("int*", 0)
193 assert p != None
194 assert repr(p) == "<cdata 'int *' NULL>"
195 a = ffi.new("int[]", [123, 456])
196 p = ffi.cast("int*", a)
197 assert bool(p) is True
198 assert p == ffi.cast("int*", a)
199 assert p != ffi.cast("int*", 0)
200 assert p[0] == 123
201 assert p[1] == 456
202
203 def test_repr(self):
204 typerepr = self.TypeRepr
205 ffi = FFI(backend=self.Backend())
206 ffi.cdef("struct foo { short a, b, c; };")
207 p = ffi.cast("short unsigned int", 0)
208 assert repr(p) == "<cdata 'unsigned short' 0>"
209 assert repr(ffi.typeof(p)) == typerepr % "unsigned short"
210 p = ffi.cast("unsigned short int", 0)
211 assert repr(p) == "<cdata 'unsigned short' 0>"
212 assert repr(ffi.typeof(p)) == typerepr % "unsigned short"
213 p = ffi.cast("int*", 0)
214 assert repr(p) == "<cdata 'int *' NULL>"
215 assert repr(ffi.typeof(p)) == typerepr % "int *"
216 #
217 p = ffi.new("int*")
218 assert repr(p) == "<cdata 'int *' owning %d bytes>" % SIZE_OF_INT
219 assert repr(ffi.typeof(p)) == typerepr % "int *"
220 p = ffi.new("int**")
221 assert repr(p) == "<cdata 'int * *' owning %d bytes>" % SIZE_OF_PTR
222 assert repr(ffi.typeof(p)) == typerepr % "int * *"
223 p = ffi.new("int [2]")
224 assert repr(p) == "<cdata 'int[2]' owning %d bytes>" % (2*SIZE_OF_INT)
225 assert repr(ffi.typeof(p)) == typerepr % "int[2]"
226 p = ffi.new("int*[2][3]")
227 assert repr(p) == "<cdata 'int *[2][3]' owning %d bytes>" % (
228 6*SIZE_OF_PTR)
229 assert repr(ffi.typeof(p)) == typerepr % "int *[2][3]"
230 p = ffi.new("struct foo *")
231 assert repr(p) == "<cdata 'struct foo *' owning %d bytes>" % (
232 3*SIZE_OF_SHORT)
233 assert repr(ffi.typeof(p)) == typerepr % "struct foo *"
234 #
235 q = ffi.cast("short", -123)
236 assert repr(q) == "<cdata 'short' -123>"
237 assert repr(ffi.typeof(q)) == typerepr % "short"
238 p = ffi.new("int*")
239 q = ffi.cast("short*", p)
240 assert repr(q).startswith("<cdata 'short *' 0x")
241 assert repr(ffi.typeof(q)) == typerepr % "short *"
242 p = ffi.new("int [2]")
243 q = ffi.cast("int*", p)
244 assert repr(q).startswith("<cdata 'int *' 0x")
245 assert repr(ffi.typeof(q)) == typerepr % "int *"
246 p = ffi.new("struct foo*")
247 q = ffi.cast("struct foo *", p)
248 assert repr(q).startswith("<cdata 'struct foo *' 0x")
249 assert repr(ffi.typeof(q)) == typerepr % "struct foo *"
250 prevrepr = repr(q)
251 q = q[0]
252 assert repr(q) == prevrepr.replace(' *', ' &')
253 assert repr(ffi.typeof(q)) == typerepr % "struct foo"
254
255 def test_new_array_of_array(self):
256 ffi = FFI(backend=self.Backend())
257 p = ffi.new("int[3][4]")
258 p[0][0] = 10
259 p[2][3] = 33
260 assert p[0][0] == 10
261 assert p[2][3] == 33
262 py.test.raises(IndexError, "p[1][-1]")
263
264 def test_constructor_array_of_array(self):
265 ffi = FFI(backend=self.Backend())
266 p = ffi.new("int[3][2]", [[10, 11], [12, 13], [14, 15]])
267 assert p[2][1] == 15
268
269 def test_new_array_of_pointer_1(self):
270 ffi = FFI(backend=self.Backend())
271 n = ffi.new("int*", 99)
272 p = ffi.new("int*[4]")
273 p[3] = n
274 a = p[3]
275 assert repr(a).startswith("<cdata 'int *' 0x")
276 assert a[0] == 99
277
278 def test_new_array_of_pointer_2(self):
279 ffi = FFI(backend=self.Backend())
280 n = ffi.new("int[1]", [99])
281 p = ffi.new("int*[4]")
282 p[3] = n
283 a = p[3]
284 assert repr(a).startswith("<cdata 'int *' 0x")
285 assert a[0] == 99
286
287 def test_char(self):
288 ffi = FFI(backend=self.Backend())
289 assert ffi.new("char*", b"\xff")[0] == b'\xff'
290 assert ffi.new("char*")[0] == b'\x00'
291 assert int(ffi.cast("char", 300)) == 300 - 256
292 assert not bool(ffi.cast("char", 0))
293 assert bool(ffi.cast("char", 1))
294 assert bool(ffi.cast("char", 255))
295 py.test.raises(TypeError, ffi.new, "char*", 32)
296 py.test.raises(TypeError, ffi.new, "char*", u+"x")
297 py.test.raises(TypeError, ffi.new, "char*", b"foo")
298 #
299 p = ffi.new("char[]", [b'a', b'b', b'\x9c'])
300 assert len(p) == 3
301 assert p[0] == b'a'
302 assert p[1] == b'b'
303 assert p[2] == b'\x9c'
304 p[0] = b'\xff'
305 assert p[0] == b'\xff'
306 p = ffi.new("char[]", b"abcd")
307 assert len(p) == 5
308 assert p[4] == b'\x00' # like in C, with: char[] p = "abcd";
309 #
310 p = ffi.new("char[4]", b"ab")
311 assert len(p) == 4
312 assert [p[i] for i in range(4)] == [b'a', b'b', b'\x00', b'\x00']
313 p = ffi.new("char[2]", b"ab")
314 assert len(p) == 2
315 assert [p[i] for i in range(2)] == [b'a', b'b']
316 py.test.raises(IndexError, ffi.new, "char[2]", b"abc")
317
318 def check_wchar_t(self, ffi):
319 try:
320 ffi.cast("wchar_t", 0)
321 except NotImplementedError:
322 py.test.skip("NotImplementedError: wchar_t")
323
324 def test_wchar_t(self):
325 ffi = FFI(backend=self.Backend())
326 self.check_wchar_t(ffi)
327 assert ffi.new("wchar_t*", u+'x')[0] == u+'x'
328 assert ffi.new("wchar_t*", u+'\u1234')[0] == u+'\u1234'
329 if SIZE_OF_WCHAR > 2:
330 assert ffi.new("wchar_t*", u+'\U00012345')[0] == u+'\U00012345'
331 else:
332 py.test.raises(TypeError, ffi.new, "wchar_t*", u+'\U00012345')
333 assert ffi.new("wchar_t*")[0] == u+'\x00'
334 assert int(ffi.cast("wchar_t", 300)) == 300
335 assert not bool(ffi.cast("wchar_t", 0))
336 assert bool(ffi.cast("wchar_t", 1))
337 assert bool(ffi.cast("wchar_t", 65535))
338 if SIZE_OF_WCHAR > 2:
339 assert bool(ffi.cast("wchar_t", 65536))
340 py.test.raises(TypeError, ffi.new, "wchar_t*", 32)
341 py.test.raises(TypeError, ffi.new, "wchar_t*", "foo")
342 #
343 p = ffi.new("wchar_t[]", [u+'a', u+'b', u+'\u1234'])
344 assert len(p) == 3
345 assert p[0] == u+'a'
346 assert p[1] == u+'b' and type(p[1]) is unicode
347 assert p[2] == u+'\u1234'
348 p[0] = u+'x'
349 assert p[0] == u+'x' and type(p[0]) is unicode
350 p[1] = u+'\u1357'
351 assert p[1] == u+'\u1357'
352 p = ffi.new("wchar_t[]", u+"abcd")
353 assert len(p) == 5
354 assert p[4] == u+'\x00'
355 p = ffi.new("wchar_t[]", u+"a\u1234b")
356 assert len(p) == 4
357 assert p[1] == u+'\u1234'
358 #
359 p = ffi.new("wchar_t[]", u+'\U00023456')
360 if SIZE_OF_WCHAR == 2:
361 assert len(p) == 3
362 assert p[0] == u+'\ud84d'
363 assert p[1] == u+'\udc56'
364 assert p[2] == u+'\x00'
365 else:
366 assert len(p) == 2
367 assert p[0] == u+'\U00023456'
368 assert p[1] == u+'\x00'
369 #
370 p = ffi.new("wchar_t[4]", u+"ab")
371 assert len(p) == 4
372 assert [p[i] for i in range(4)] == [u+'a', u+'b', u+'\x00', u+'\x00']
373 p = ffi.new("wchar_t[2]", u+"ab")
374 assert len(p) == 2
375 assert [p[i] for i in range(2)] == [u+'a', u+'b']
376 py.test.raises(IndexError, ffi.new, "wchar_t[2]", u+"abc")
377
378 def test_none_as_null_doesnt_work(self):
379 ffi = FFI(backend=self.Backend())
380 p = ffi.new("int*[1]")
381 assert p[0] is not None
382 assert p[0] != None
383 assert p[0] == ffi.NULL
384 assert repr(p[0]) == "<cdata 'int *' NULL>"
385 #
386 n = ffi.new("int*", 99)
387 p = ffi.new("int*[]", [n])
388 assert p[0][0] == 99
389 py.test.raises(TypeError, "p[0] = None")
390 p[0] = ffi.NULL
391 assert p[0] == ffi.NULL
392
393 def test_float(self):
394 ffi = FFI(backend=self.Backend())
395 p = ffi.new("float[]", [-2, -2.5])
396 assert p[0] == -2.0
397 assert p[1] == -2.5
398 p[1] += 17.75
399 assert p[1] == 15.25
400 #
401 p = ffi.new("float*", 15.75)
402 assert p[0] == 15.75
403 py.test.raises(TypeError, int, p)
404 py.test.raises(TypeError, float, p)
405 p[0] = 0.0
406 assert bool(p) is True
407 #
408 p = ffi.new("float*", 1.1)
409 f = p[0]
410 assert f != 1.1 # because of rounding effect
411 assert abs(f - 1.1) < 1E-7
412 #
413 INF = 1E200 * 1E200
414 assert 1E200 != INF
415 p[0] = 1E200
416 assert p[0] == INF # infinite, not enough precision
417
418 def test_struct_simple(self):
419 ffi = FFI(backend=self.Backend())
420 ffi.cdef("struct foo { int a; short b, c; };")
421 s = ffi.new("struct foo*")
422 assert s.a == s.b == s.c == 0
423 s.b = -23
424 assert s.b == -23
425 py.test.raises(OverflowError, "s.b = 32768")
426 #
427 s = ffi.new("struct foo*", [-2, -3])
428 assert s.a == -2
429 assert s.b == -3
430 assert s.c == 0
431 py.test.raises((AttributeError, TypeError), "del s.a")
432 assert repr(s) == "<cdata 'struct foo *' owning %d bytes>" % (
433 SIZE_OF_INT + 2 * SIZE_OF_SHORT)
434 #
435 py.test.raises(ValueError, ffi.new, "struct foo*", [1, 2, 3, 4])
436
437 def test_constructor_struct_from_dict(self):
438 ffi = FFI(backend=self.Backend())
439 ffi.cdef("struct foo { int a; short b, c; };")
440 s = ffi.new("struct foo*", {'b': 123, 'c': 456})
441 assert s.a == 0
442 assert s.b == 123
443 assert s.c == 456
444 py.test.raises(KeyError, ffi.new, "struct foo*", {'d': 456})
445
446 def test_struct_pointer(self):
447 ffi = FFI(backend=self.Backend())
448 ffi.cdef("struct foo { int a; short b, c; };")
449 s = ffi.new("struct foo*")
450 assert s[0].a == s[0].b == s[0].c == 0
451 s[0].b = -23
452 assert s[0].b == s.b == -23
453 py.test.raises(OverflowError, "s[0].b = -32769")
454 py.test.raises(IndexError, "s[1]")
455
456 def test_struct_opaque(self):
457 ffi = FFI(backend=self.Backend())
458 py.test.raises(TypeError, ffi.new, "struct baz*")
459 p = ffi.new("struct baz **") # this works
460 assert p[0] == ffi.NULL
461
462 def test_pointer_to_struct(self):
463 ffi = FFI(backend=self.Backend())
464 ffi.cdef("struct foo { int a; short b, c; };")
465 s = ffi.new("struct foo *")
466 s.a = -42
467 assert s[0].a == -42
468 p = ffi.new("struct foo **", s)
469 assert p[0].a == -42
470 assert p[0][0].a == -42
471 p[0].a = -43
472 assert s.a == -43
473 assert s[0].a == -43
474 p[0][0].a = -44
475 assert s.a == -44
476 assert s[0].a == -44
477 s.a = -45
478 assert p[0].a == -45
479 assert p[0][0].a == -45
480 s[0].a = -46
481 assert p[0].a == -46
482 assert p[0][0].a == -46
483
484 def test_constructor_struct_of_array(self):
485 ffi = FFI(backend=self.Backend())
486 ffi.cdef("struct foo { int a[2]; char b[3]; };")
487 s = ffi.new("struct foo *", [[10, 11], [b'a', b'b', b'c']])
488 assert s.a[1] == 11
489 assert s.b[2] == b'c'
490 s.b[1] = b'X'
491 assert s.b[0] == b'a'
492 assert s.b[1] == b'X'
493 assert s.b[2] == b'c'
494
495 def test_recursive_struct(self):
496 ffi = FFI(backend=self.Backend())
497 ffi.cdef("struct foo { int value; struct foo *next; };")
498 s = ffi.new("struct foo*")
499 t = ffi.new("struct foo*")
500 s.value = 123
501 s.next = t
502 t.value = 456
503 assert s.value == 123
504 assert s.next.value == 456
505
506 def test_union_simple(self):
507 ffi = FFI(backend=self.Backend())
508 ffi.cdef("union foo { int a; short b, c; };")
509 u = ffi.new("union foo*")
510 assert u.a == u.b == u.c == 0
511 u.b = -23
512 assert u.b == -23
513 assert u.a != 0
514 py.test.raises(OverflowError, "u.b = 32768")
515 #
516 u = ffi.new("union foo*", [-2])
517 assert u.a == -2
518 py.test.raises((AttributeError, TypeError), "del u.a")
519 assert repr(u) == "<cdata 'union foo *' owning %d bytes>" % SIZE_OF_INT
520
521 def test_union_opaque(self):
522 ffi = FFI(backend=self.Backend())
523 py.test.raises(TypeError, ffi.new, "union baz *")
524 u = ffi.new("union baz **") # this works
525 assert u[0] == ffi.NULL
526
527 def test_union_initializer(self):
528 ffi = FFI(backend=self.Backend())
529 ffi.cdef("union foo { char a; int b; };")
530 py.test.raises(TypeError, ffi.new, "union foo*", b'A')
531 py.test.raises(TypeError, ffi.new, "union foo*", 5)
532 py.test.raises(ValueError, ffi.new, "union foo*", [b'A', 5])
533 u = ffi.new("union foo*", [b'A'])
534 assert u.a == b'A'
535 py.test.raises(TypeError, ffi.new, "union foo*", [1005])
536 u = ffi.new("union foo*", {'b': 12345})
537 assert u.b == 12345
538 u = ffi.new("union foo*", [])
539 assert u.a == b'\x00'
540 assert u.b == 0
541
542 def test_sizeof_type(self):
543 ffi = FFI(backend=self.Backend())
544 ffi.cdef("""
545 struct foo { int a; short b, c, d; };
546 union foo { int a; short b, c, d; };
547 """)
548 for c_type, expected_size in [
549 ('char', 1),
550 ('unsigned int', 4),
551 ('char *', SIZE_OF_PTR),
552 ('int[5]', 20),
553 ('struct foo', 12),
554 ('union foo', 4),
555 ]:
556 size = ffi.sizeof(c_type)
557 assert size == expected_size, (size, expected_size, ctype)
558
559 def test_sizeof_cdata(self):
560 ffi = FFI(backend=self.Backend())
561 assert ffi.sizeof(ffi.new("short*")) == SIZE_OF_PTR
562 assert ffi.sizeof(ffi.cast("short", 123)) == SIZE_OF_SHORT
563 #
564 a = ffi.new("int[]", [10, 11, 12, 13, 14])
565 assert len(a) == 5
566 assert ffi.sizeof(a) == 5 * SIZE_OF_INT
567
568 def test_string_from_char_pointer(self):
569 ffi = FFI(backend=self.Backend())
570 x = ffi.new("char*", b"x")
571 assert str(x) == repr(x)
572 assert ffi.string(x) == b"x"
573 assert ffi.string(ffi.new("char*", b"\x00")) == b""
574 py.test.raises(TypeError, ffi.new, "char*", unicode("foo"))
575
576 def test_unicode_from_wchar_pointer(self):
577 ffi = FFI(backend=self.Backend())
578 self.check_wchar_t(ffi)
579 x = ffi.new("wchar_t*", u+"x")
580 assert unicode(x) == unicode(repr(x))
581 assert ffi.string(x) == u+"x"
582 assert ffi.string(ffi.new("wchar_t*", u+"\x00")) == u+""
583
584 def test_string_from_char_array(self):
585 ffi = FFI(backend=self.Backend())
586 p = ffi.new("char[]", b"hello.")
587 p[5] = b'!'
588 assert ffi.string(p) == b"hello!"
589 p[6] = b'?'
590 assert ffi.string(p) == b"hello!?"
591 p[3] = b'\x00'
592 assert ffi.string(p) == b"hel"
593 assert ffi.string(p, 2) == b"he"
594 py.test.raises(IndexError, "p[7] = b'X'")
595 #
596 a = ffi.new("char[]", b"hello\x00world")
597 assert len(a) == 12
598 p = ffi.cast("char *", a)
599 assert ffi.string(p) == b'hello'
600
601 def test_string_from_wchar_array(self):
602 ffi = FFI(backend=self.Backend())
603 self.check_wchar_t(ffi)
604 assert ffi.string(ffi.cast("wchar_t", "x")) == u+"x"
605 assert ffi.string(ffi.cast("wchar_t", u+"x")) == u+"x"
606 x = ffi.cast("wchar_t", "x")
607 assert str(x) == repr(x)
608 assert ffi.string(x) == u+"x"
609 #
610 p = ffi.new("wchar_t[]", u+"hello.")
611 p[5] = u+'!'
612 assert ffi.string(p) == u+"hello!"
613 p[6] = u+'\u04d2'
614 assert ffi.string(p) == u+"hello!\u04d2"
615 p[3] = u+'\x00'
616 assert ffi.string(p) == u+"hel"
617 assert ffi.string(p, 123) == u+"hel"
618 py.test.raises(IndexError, "p[7] = u+'X'")
619 #
620 a = ffi.new("wchar_t[]", u+"hello\x00world")
621 assert len(a) == 12
622 p = ffi.cast("wchar_t *", a)
623 assert ffi.string(p) == u+'hello'
624 assert ffi.string(p, 123) == u+'hello'
625 assert ffi.string(p, 5) == u+'hello'
626 assert ffi.string(p, 2) == u+'he'
627
628 def test_fetch_const_char_p_field(self):
629 # 'const' is ignored so far
630 ffi = FFI(backend=self.Backend())
631 ffi.cdef("struct foo { const char *name; };")
632 t = ffi.new("const char[]", b"testing")
633 s = ffi.new("struct foo*", [t])
634 assert type(s.name) not in (bytes, str, unicode)
635 assert ffi.string(s.name) == b"testing"
636 py.test.raises(TypeError, "s.name = None")
637 s.name = ffi.NULL
638 assert s.name == ffi.NULL
639
640 def test_fetch_const_wchar_p_field(self):
641 # 'const' is ignored so far
642 ffi = FFI(backend=self.Backend())
643 self.check_wchar_t(ffi)
644 ffi.cdef("struct foo { const wchar_t *name; };")
645 t = ffi.new("const wchar_t[]", u+"testing")
646 s = ffi.new("struct foo*", [t])
647 assert type(s.name) not in (bytes, str, unicode)
648 assert ffi.string(s.name) == u+"testing"
649 s.name = ffi.NULL
650 assert s.name == ffi.NULL
651
652 def test_voidp(self):
653 ffi = FFI(backend=self.Backend())
654 py.test.raises(TypeError, ffi.new, "void*")
655 p = ffi.new("void **")
656 assert p[0] == ffi.NULL
657 a = ffi.new("int[]", [10, 11, 12])
658 p = ffi.new("void **", a)
659 vp = p[0]
660 py.test.raises(TypeError, "vp[0]")
661 py.test.raises(TypeError, ffi.new, "short **", a)
662 #
663 ffi.cdef("struct foo { void *p; int *q; short *r; };")
664 s = ffi.new("struct foo *")
665 s.p = a # works
666 s.q = a # works
667 py.test.raises(TypeError, "s.r = a") # fails
668 b = ffi.cast("int *", a)
669 s.p = b # works
670 s.q = b # works
671 py.test.raises(TypeError, "s.r = b") # fails
672
673 def test_functionptr_simple(self):
674 ffi = FFI(backend=self.Backend())
675 py.test.raises(TypeError, ffi.callback, "int(*)(int)", 0)
676 def cb(n):
677 return n + 1
678 cb.__qualname__ = 'cb'
679 p = ffi.callback("int(*)(int)", cb)
680 res = p(41) # calling an 'int(*)(int)', i.e. a function pointer
681 assert res == 42 and type(res) is int
682 res = p(ffi.cast("int", -41))
683 assert res == -40 and type(res) is int
684 assert repr(p).startswith(
685 "<cdata 'int(*)(int)' calling <function cb at 0x")
686 assert ffi.typeof(p) is ffi.typeof("int(*)(int)")
687 q = ffi.new("int(**)(int)", p)
688 assert repr(q) == "<cdata 'int(* *)(int)' owning %d bytes>" % (
689 SIZE_OF_PTR)
690 py.test.raises(TypeError, "q(43)")
691 res = q[0](43)
692 assert res == 44
693 q = ffi.cast("int(*)(int)", p)
694 assert repr(q).startswith("<cdata 'int(*)(int)' 0x")
695 res = q(45)
696 assert res == 46
697
698 def test_functionptr_advanced(self):
699 ffi = FFI(backend=self.Backend())
700 t = ffi.typeof("int(*(*)(int))(int)")
701 assert repr(t) == self.TypeRepr % "int(*(*)(int))(int)"
702
703 def test_functionptr_voidptr_return(self):
704 ffi = FFI(backend=self.Backend())
705 def cb():
706 return ffi.NULL
707 p = ffi.callback("void*(*)()", cb)
708 res = p()
709 assert res is not None
710 assert res == ffi.NULL
711 int_ptr = ffi.new('int*')
712 void_ptr = ffi.cast('void*', int_ptr)
713 def cb():
714 return void_ptr
715 p = ffi.callback("void*(*)()", cb)
716 res = p()
717 assert res == void_ptr
718
719 def test_functionptr_intptr_return(self):
720 ffi = FFI(backend=self.Backend())
721 def cb():
722 return ffi.NULL
723 p = ffi.callback("int*(*)()", cb)
724 res = p()
725 assert res == ffi.NULL
726 int_ptr = ffi.new('int*')
727 def cb():
728 return int_ptr
729 p = ffi.callback("int*(*)()", cb)
730 res = p()
731 assert repr(res).startswith("<cdata 'int *' 0x")
732 assert res == int_ptr
733 int_array_ptr = ffi.new('int[1]')
734 def cb():
735 return int_array_ptr
736 p = ffi.callback("int*(*)()", cb)
737 res = p()
738 assert repr(res).startswith("<cdata 'int *' 0x")
739 assert res == int_array_ptr
740
741 def test_functionptr_void_return(self):
742 ffi = FFI(backend=self.Backend())
743 def foo():
744 pass
745 foo_cb = ffi.callback("void foo()", foo)
746 result = foo_cb()
747 assert result is None
748
749 def test_char_cast(self):
750 ffi = FFI(backend=self.Backend())
751 p = ffi.cast("int", b'\x01')
752 assert ffi.typeof(p) is ffi.typeof("int")
753 assert int(p) == 1
754 p = ffi.cast("int", ffi.cast("char", b"a"))
755 assert int(p) == ord("a")
756 p = ffi.cast("int", ffi.cast("char", b"\x80"))
757 assert int(p) == 0x80 # "char" is considered unsigned in this case
758 p = ffi.cast("int", b"\x81")
759 assert int(p) == 0x81
760
761 def test_wchar_cast(self):
762 ffi = FFI(backend=self.Backend())
763 self.check_wchar_t(ffi)
764 p = ffi.cast("int", ffi.cast("wchar_t", u+'\u1234'))
765 assert int(p) == 0x1234
766 p = ffi.cast("long long", ffi.cast("wchar_t", -1))
767 if SIZE_OF_WCHAR == 2: # 2 bytes, unsigned
768 assert int(p) == 0xffff
769 elif (sys.platform.startswith('linux') and
770 platform.machine().startswith('x86')): # known to be signed
771 assert int(p) == -1
772 else: # in general, it can be either signed or not
773 assert int(p) in [-1, 0xffffffff] # e.g. on arm, both cases occur
774 p = ffi.cast("int", u+'\u1234')
775 assert int(p) == 0x1234
776
777 def test_cast_array_to_charp(self):
778 ffi = FFI(backend=self.Backend())
779 a = ffi.new("short int[]", [0x1234, 0x5678])
780 p = ffi.cast("char*", a)
781 data = b''.join([p[i] for i in range(4)])
782 if sys.byteorder == 'little':
783 assert data == b'\x34\x12\x78\x56'
784 else:
785 assert data == b'\x12\x34\x56\x78'
786
787 def test_cast_between_pointers(self):
788 ffi = FFI(backend=self.Backend())
789 a = ffi.new("short int[]", [0x1234, 0x5678])
790 p = ffi.cast("short*", a)
791 p2 = ffi.cast("int*", p)
792 q = ffi.cast("char*", p2)
793 data = b''.join([q[i] for i in range(4)])
794 if sys.byteorder == 'little':
795 assert data == b'\x34\x12\x78\x56'
796 else:
797 assert data == b'\x12\x34\x56\x78'
798
799 def test_cast_pointer_and_int(self):
800 ffi = FFI(backend=self.Backend())
801 a = ffi.new("short int[]", [0x1234, 0x5678])
802 l1 = ffi.cast("intptr_t", a)
803 p = ffi.cast("short*", a)
804 l2 = ffi.cast("intptr_t", p)
805 assert int(l1) == int(l2) != 0
806 q = ffi.cast("short*", l1)
807 assert q == ffi.cast("short*", int(l1))
808 assert q[0] == 0x1234
809 assert int(ffi.cast("intptr_t", ffi.NULL)) == 0
810
811 def test_cast_functionptr_and_int(self):
812 ffi = FFI(backend=self.Backend())
813 def cb(n):
814 return n + 1
815 a = ffi.callback("int(*)(int)", cb)
816 p = ffi.cast("void *", a)
817 assert p
818 b = ffi.cast("int(*)(int)", p)
819 assert b(41) == 42
820 assert a == b
821 assert hash(a) == hash(b)
822
823 def test_callback_crash(self):
824 ffi = FFI(backend=self.Backend())
825 def cb(n):
826 raise Exception
827 a = ffi.callback("int(*)(int)", cb, error=42)
828 res = a(1) # and the error reported to stderr
829 assert res == 42
830
831 def test_structptr_argument(self):
832 ffi = FFI(backend=self.Backend())
833 ffi.cdef("struct foo_s { int a, b; };")
834 def cb(p):
835 return p[0].a * 1000 + p[0].b * 100 + p[1].a * 10 + p[1].b
836 a = ffi.callback("int(*)(struct foo_s[])", cb)
837 res = a([[5, 6], {'a': 7, 'b': 8}])
838 assert res == 5678
839 res = a([[5], {'b': 8}])
840 assert res == 5008
841
842 def test_array_argument_as_list(self):
843 ffi = FFI(backend=self.Backend())
844 ffi.cdef("struct foo_s { int a, b; };")
845 seen = []
846 def cb(argv):
847 seen.append(ffi.string(argv[0]))
848 seen.append(ffi.string(argv[1]))
849 a = ffi.callback("void(*)(char *[])", cb)
850 a([ffi.new("char[]", b"foobar"), ffi.new("char[]", b"baz")])
851 assert seen == [b"foobar", b"baz"]
852
853 def test_cast_float(self):
854 ffi = FFI(backend=self.Backend())
855 a = ffi.cast("float", 12)
856 assert float(a) == 12.0
857 a = ffi.cast("float", 12.5)
858 assert float(a) == 12.5
859 a = ffi.cast("float", b"A")
860 assert float(a) == ord("A")
861 a = ffi.cast("int", 12.9)
862 assert int(a) == 12
863 a = ffi.cast("char", 66.9 + 256)
864 assert ffi.string(a) == b"B"
865 #
866 a = ffi.cast("float", ffi.cast("int", 12))
867 assert float(a) == 12.0
868 a = ffi.cast("float", ffi.cast("double", 12.5))
869 assert float(a) == 12.5
870 a = ffi.cast("float", ffi.cast("char", b"A"))
871 assert float(a) == ord("A")
872 a = ffi.cast("int", ffi.cast("double", 12.9))
873 assert int(a) == 12
874 a = ffi.cast("char", ffi.cast("double", 66.9 + 256))
875 assert ffi.string(a) == b"B"
876
877 def test_enum(self):
878 ffi = FFI(backend=self.Backend())
879 ffi.cdef("enum foo { A0, B0, CC0, D0 };")
880 assert ffi.string(ffi.cast("enum foo", 0)) == "A0"
881 assert ffi.string(ffi.cast("enum foo", 2)) == "CC0"
882 assert ffi.string(ffi.cast("enum foo", 3)) == "D0"
883 assert ffi.string(ffi.cast("enum foo", 4)) == "4"
884 ffi.cdef("enum bar { A1, B1=-2, CC1, D1, E1 };")
885 assert ffi.string(ffi.cast("enum bar", 0)) == "A1"
886 assert ffi.string(ffi.cast("enum bar", -2)) == "B1"
887 assert ffi.string(ffi.cast("enum bar", -1)) == "CC1"
888 assert ffi.string(ffi.cast("enum bar", 1)) == "E1"
889 assert ffi.cast("enum bar", -2) == ffi.cast("enum bar", -2)
890 assert ffi.cast("enum foo", 0) == ffi.cast("enum bar", 0)
891 assert ffi.cast("enum bar", 0) == ffi.cast("int", 0)
892 assert repr(ffi.cast("enum bar", -1)) == "<cdata 'enum bar' -1: CC1>"
893 assert repr(ffi.cast("enum foo", -1)) == ( # enums are unsigned, if
894 "<cdata 'enum foo' 4294967295>") # they contain no neg value
895 ffi.cdef("enum baz { A2=0x1000, B2=0x2000 };")
896 assert ffi.string(ffi.cast("enum baz", 0x1000)) == "A2"
897 assert ffi.string(ffi.cast("enum baz", 0x2000)) == "B2"
898
899 def test_enum_in_struct(self):
900 ffi = FFI(backend=self.Backend())
901 ffi.cdef("enum foo { A, B, C, D }; struct bar { enum foo e; };")
902 s = ffi.new("struct bar *")
903 s.e = 0
904 assert s.e == 0
905 s.e = 3
906 assert s.e == 3
907 assert s[0].e == 3
908 s[0].e = 2
909 assert s.e == 2
910 assert s[0].e == 2
911 s.e = ffi.cast("enum foo", -1)
912 assert s.e == 4294967295
913 assert s[0].e == 4294967295
914 s.e = s.e
915 py.test.raises(TypeError, "s.e = 'B'")
916 py.test.raises(TypeError, "s.e = '2'")
917 py.test.raises(TypeError, "s.e = '#2'")
918 py.test.raises(TypeError, "s.e = '#7'")
919
920 def test_enum_non_contiguous(self):
921 ffi = FFI(backend=self.Backend())
922 ffi.cdef("enum foo { A, B=42, C };")
923 assert ffi.string(ffi.cast("enum foo", 0)) == "A"
924 assert ffi.string(ffi.cast("enum foo", 42)) == "B"
925 assert ffi.string(ffi.cast("enum foo", 43)) == "C"
926 invalid_value = ffi.cast("enum foo", 2)
927 assert int(invalid_value) == 2
928 assert ffi.string(invalid_value) == "2"
929
930 def test_enum_char_hex_oct(self):
931 ffi = FFI(backend=self.Backend())
932 ffi.cdef(r"enum foo{A='!', B='\'', C=0x10, D=010, E=- 0x10, F=-010};")
933 assert ffi.string(ffi.cast("enum foo", ord('!'))) == "A"
934 assert ffi.string(ffi.cast("enum foo", ord("'"))) == "B"
935 assert ffi.string(ffi.cast("enum foo", 16)) == "C"
936 assert ffi.string(ffi.cast("enum foo", 8)) == "D"
937 assert ffi.string(ffi.cast("enum foo", -16)) == "E"
938 assert ffi.string(ffi.cast("enum foo", -8)) == "F"
939
940 def test_enum_partial(self):
941 ffi = FFI(backend=self.Backend())
942 ffi.cdef(r"enum foo {A, ...}; enum bar { B, C };")
943 needs_dlopen_none()
944 lib = ffi.dlopen(None)
945 assert lib.B == 0
946 py.test.raises(VerificationMissing, getattr, lib, "A")
947 assert lib.C == 1
948
949 def test_array_of_struct(self):
950 ffi = FFI(backend=self.Backend())
951 ffi.cdef("struct foo { int a, b; };")
952 s = ffi.new("struct foo[1]")
953 py.test.raises(AttributeError, 's.b')
954 py.test.raises(AttributeError, 's.b = 412')
955 s[0].b = 412
956 assert s[0].b == 412
957 py.test.raises(IndexError, 's[1]')
958
959 def test_pointer_to_array(self):
960 ffi = FFI(backend=self.Backend())
961 p = ffi.new("int(**)[5]")
962 assert repr(p) == "<cdata 'int(* *)[5]' owning %d bytes>" % SIZE_OF_PTR
963
964 def test_iterate_array(self):
965 ffi = FFI(backend=self.Backend())
966 a = ffi.new("char[]", b"hello")
967 assert list(a) == [b"h", b"e", b"l", b"l", b"o", b"\0"]
968 assert list(iter(a)) == [b"h", b"e", b"l", b"l", b"o", b"\0"]
969 #
970 py.test.raises(TypeError, iter, ffi.cast("char *", a))
971 py.test.raises(TypeError, list, ffi.cast("char *", a))
972 py.test.raises(TypeError, iter, ffi.new("int *"))
973 py.test.raises(TypeError, list, ffi.new("int *"))
974
975 def test_offsetof(self):
976 ffi = FFI(backend=self.Backend())
977 ffi.cdef("struct foo { int a, b, c; };")
978 assert ffi.offsetof("struct foo", "a") == 0
979 assert ffi.offsetof("struct foo", "b") == 4
980 assert ffi.offsetof("struct foo", "c") == 8
981
982 def test_offsetof_nested(self):
983 ffi = FFI(backend=self.Backend())
984 ffi.cdef("struct foo { int a, b, c; };"
985 "struct bar { struct foo d, e; };")
986 assert ffi.offsetof("struct bar", "e") == 12
987 py.test.raises(KeyError, ffi.offsetof, "struct bar", "e.a")
988 assert ffi.offsetof("struct bar", "e", "a") == 12
989 assert ffi.offsetof("struct bar", "e", "b") == 16
990 assert ffi.offsetof("struct bar", "e", "c") == 20
991
992 def test_offsetof_array(self):
993 ffi = FFI(backend=self.Backend())
994 assert ffi.offsetof("int[]", 51) == 51 * ffi.sizeof("int")
995 assert ffi.offsetof("int *", 51) == 51 * ffi.sizeof("int")
996 ffi.cdef("struct bar { int a, b; int c[99]; };")
997 assert ffi.offsetof("struct bar", "c") == 2 * ffi.sizeof("int")
998 assert ffi.offsetof("struct bar", "c", 0) == 2 * ffi.sizeof("int")
999 assert ffi.offsetof("struct bar", "c", 51) == 53 * ffi.sizeof("int")
1000
1001 def test_alignof(self):
1002 ffi = FFI(backend=self.Backend())
1003 ffi.cdef("struct foo { char a; short b; char c; };")
1004 assert ffi.alignof("int") == 4
1005 assert ffi.alignof("double") in (4, 8)
1006 assert ffi.alignof("struct foo") == 2
1007
1008 def test_bitfield(self):
1009 ffi = FFI(backend=self.Backend())
1010 ffi.cdef("struct foo { int a:10, b:20, c:3; };")
1011 assert ffi.sizeof("struct foo") == 8
1012 s = ffi.new("struct foo *")
1013 s.a = 511
1014 py.test.raises(OverflowError, "s.a = 512")
1015 py.test.raises(OverflowError, "s[0].a = 512")
1016 assert s.a == 511
1017 s.a = -512
1018 py.test.raises(OverflowError, "s.a = -513")
1019 py.test.raises(OverflowError, "s[0].a = -513")
1020 assert s.a == -512
1021 s.c = 3
1022 assert s.c == 3
1023 py.test.raises(OverflowError, "s.c = 4")
1024 py.test.raises(OverflowError, "s[0].c = 4")
1025 s.c = -4
1026 assert s.c == -4
1027
1028 def test_bitfield_enum(self):
1029 ffi = FFI(backend=self.Backend())
1030 ffi.cdef("""
1031 typedef enum { AA, BB, CC } foo_e;
1032 typedef struct { foo_e f:2; } foo_s;
1033 """)
1034 s = ffi.new("foo_s *")
1035 s.f = 2
1036 assert s.f == 2
1037
1038 def test_anonymous_struct(self):
1039 ffi = FFI(backend=self.Backend())
1040 ffi.cdef("typedef struct { int a; } foo_t;")
1041 ffi.cdef("typedef struct { char b, c; } bar_t;")
1042 f = ffi.new("foo_t *", [12345])
1043 b = ffi.new("bar_t *", [b"B", b"C"])
1044 assert f.a == 12345
1045 assert b.b == b"B"
1046 assert b.c == b"C"
1047 assert repr(b).startswith("<cdata 'bar_t *'")
1048
1049 def test_struct_with_two_usages(self):
1050 for name in ['foo_s', '']: # anonymous or not
1051 ffi = FFI(backend=self.Backend())
1052 ffi.cdef("typedef struct %s { int a; } foo_t, *foo_p;" % name)
1053 f = ffi.new("foo_t *", [12345])
1054 ps = ffi.new("foo_p[]", [f])
1055
1056 def test_pointer_arithmetic(self):
1057 ffi = FFI(backend=self.Backend())
1058 s = ffi.new("short[]", list(range(100, 110)))
1059 p = ffi.cast("short *", s)
1060 assert p[2] == 102
1061 assert p+1 == p+1
1062 assert p+1 != p+0
1063 assert p == p+0 == p-0
1064 assert (p+1)[0] == 101
1065 assert (p+19)[-10] == 109
1066 assert (p+5) - (p+1) == 4
1067 assert p == s+0
1068 assert p+1 == s+1
1069
1070 def test_pointer_comparison(self):
1071 ffi = FFI(backend=self.Backend())
1072 s = ffi.new("short[]", list(range(100)))
1073 p = ffi.cast("short *", s)
1074 assert (p < s) is False
1075 assert (p <= s) is True
1076 assert (p == s) is True
1077 assert (p != s) is False
1078 assert (p > s) is False
1079 assert (p >= s) is True
1080 assert (s < p) is False
1081 assert (s <= p) is True
1082 assert (s == p) is True
1083 assert (s != p) is False
1084 assert (s > p) is False
1085 assert (s >= p) is True
1086 q = p + 1
1087 assert (q < s) is False
1088 assert (q <= s) is False
1089 assert (q == s) is False
1090 assert (q != s) is True
1091 assert (q > s) is True
1092 assert (q >= s) is True
1093 assert (s < q) is True
1094 assert (s <= q) is True
1095 assert (s == q) is False
1096 assert (s != q) is True
1097 assert (s > q) is False
1098 assert (s >= q) is False
1099 assert (q < p) is False
1100 assert (q <= p) is False
1101 assert (q == p) is False
1102 assert (q != p) is True
1103 assert (q > p) is True
1104 assert (q >= p) is True
1105 assert (p < q) is True
1106 assert (p <= q) is True
1107 assert (p == q) is False
1108 assert (p != q) is True
1109 assert (p > q) is False
1110 assert (p >= q) is False
1111 #
1112 assert (None == s) is False
1113 assert (None != s) is True
1114 assert (s == None) is False
1115 assert (s != None) is True
1116 assert (None == q) is False
1117 assert (None != q) is True
1118 assert (q == None) is False
1119 assert (q != None) is True
1120
1121 def test_integer_comparison(self):
1122 ffi = FFI(backend=self.Backend())
1123 x = ffi.cast("int", 123)
1124 y = ffi.cast("int", 456)
1125 assert x < y
1126 #
1127 z = ffi.cast("double", 78.9)
1128 assert x > z
1129 assert y > z
1130
1131 def test_ffi_buffer_ptr(self):
1132 ffi = FFI(backend=self.Backend())
1133 a = ffi.new("short *", 100)
1134 try:
1135 b = ffi.buffer(a)
1136 except NotImplementedError as e:
1137 py.test.skip(str(e))
1138 assert type(b) is ffi.buffer
1139 content = b[:]
1140 assert len(content) == len(b) == 2
1141 if sys.byteorder == 'little':
1142 assert content == b'\x64\x00'
1143 assert b[0] == b'\x64'
1144 b[0] = b'\x65'
1145 else:
1146 assert content == b'\x00\x64'
1147 assert b[1] == b'\x64'
1148 b[1] = b'\x65'
1149 assert a[0] == 101
1150
1151 def test_ffi_buffer_array(self):
1152 ffi = FFI(backend=self.Backend())
1153 a = ffi.new("int[]", list(range(100, 110)))
1154 try:
1155 b = ffi.buffer(a)
1156 except NotImplementedError as e:
1157 py.test.skip(str(e))
1158 content = b[:]
1159 if sys.byteorder == 'little':
1160 assert content.startswith(b'\x64\x00\x00\x00\x65\x00\x00\x00')
1161 b[4] = b'\x45'
1162 else:
1163 assert content.startswith(b'\x00\x00\x00\x64\x00\x00\x00\x65')
1164 b[7] = b'\x45'
1165 assert len(content) == 4 * 10
1166 assert a[1] == 0x45
1167
1168 def test_ffi_buffer_ptr_size(self):
1169 ffi = FFI(backend=self.Backend())
1170 a = ffi.new("short *", 0x4243)
1171 try:
1172 b = ffi.buffer(a, 1)
1173 except NotImplementedError as e:
1174 py.test.skip(str(e))
1175 content = b[:]
1176 assert len(content) == 1
1177 if sys.byteorder == 'little':
1178 assert content == b'\x43'
1179 b[0] = b'\x62'
1180 assert a[0] == 0x4262
1181 else:
1182 assert content == b'\x42'
1183 b[0] = b'\x63'
1184 assert a[0] == 0x6343
1185
1186 def test_ffi_buffer_array_size(self):
1187 ffi = FFI(backend=self.Backend())
1188 a1 = ffi.new("int[]", list(range(100, 110)))
1189 a2 = ffi.new("int[]", list(range(100, 115)))
1190 try:
1191 ffi.buffer(a1)
1192 except NotImplementedError as e:
1193 py.test.skip(str(e))
1194 assert ffi.buffer(a1)[:] == ffi.buffer(a2, 4*10)[:]
1195
1196 def test_ffi_buffer_with_file(self):
1197 ffi = FFI(backend=self.Backend())
1198 import tempfile, os, array
1199 fd, filename = tempfile.mkstemp()
1200 f = os.fdopen(fd, 'r+b')
1201 a = ffi.new("int[]", list(range(1005)))
1202 try:
1203 ffi.buffer(a, 512)
1204 except NotImplementedError as e:
1205 py.test.skip(str(e))
1206 f.write(ffi.buffer(a, 1000 * ffi.sizeof("int")))
1207 f.seek(0)
1208 assert f.read() == array.array('i', range(1000)).tostring()
1209 f.seek(0)
1210 b = ffi.new("int[]", 1005)
1211 f.readinto(ffi.buffer(b, 1000 * ffi.sizeof("int")))
1212 assert list(a)[:1000] + [0] * (len(a)-1000) == list(b)
1213 f.close()
1214 os.unlink(filename)
1215
1216 def test_ffi_buffer_with_io(self):
1217 ffi = FFI(backend=self.Backend())
1218 import io, array
1219 f = io.BytesIO()
1220 a = ffi.new("int[]", list(range(1005)))
1221 try:
1222 ffi.buffer(a, 512)
1223 except NotImplementedError as e:
1224 py.test.skip(str(e))
1225 f.write(ffi.buffer(a, 1000 * ffi.sizeof("int")))
1226 f.seek(0)
1227 assert f.read() == array.array('i', range(1000)).tostring()
1228 f.seek(0)
1229 b = ffi.new("int[]", 1005)
1230 f.readinto(ffi.buffer(b, 1000 * ffi.sizeof("int")))
1231 assert list(a)[:1000] + [0] * (len(a)-1000) == list(b)
1232 f.close()
1233
1234 def test_ffi_buffer_comparisons(self):
1235 ffi = FFI(backend=self.Backend())
1236 ba = bytearray(range(100, 110))
1237 if sys.version_info >= (2, 7):
1238 assert ba == memoryview(ba) # justification for the following
1239 a = ffi.new("uint8_t[]", list(ba))
1240 c = ffi.new("uint8_t[]", [99] + list(ba))
1241 try:
1242 b_full = ffi.buffer(a)
1243 b_short = ffi.buffer(a, 3)
1244 b_mid = ffi.buffer(a, 6)
1245 b_other = ffi.buffer(c, 6)
1246 except NotImplementedError as e:
1247 py.test.skip(str(e))
1248 else:
1249 content = b_full[:]
1250 assert content == b_full == ba
1251 assert b_other < b_short < b_mid < b_full
1252 assert ba > b_mid > ba[0:2]
1253 assert b_short != ba[1:4]
1254
1255 def test_array_in_struct(self):
1256 ffi = FFI(backend=self.Backend())
1257 ffi.cdef("struct foo_s { int len; short data[5]; };")
1258 p = ffi.new("struct foo_s *")
1259 p.data[3] = 5
1260 assert p.data[3] == 5
1261 assert repr(p.data).startswith("<cdata 'short[5]' 0x")
1262
1263 def test_struct_containing_array_varsize_workaround(self):
1264 ffi = FFI(backend=self.Backend())
1265 ffi.cdef("struct foo_s { int len; short data[0]; };")
1266 p = ffi.new("char[]", ffi.sizeof("struct foo_s") + 7 * SIZE_OF_SHORT)
1267 q = ffi.cast("struct foo_s *", p)
1268 assert q.len == 0
1269 # 'q.data' gets not a 'short[0]', but just a 'short *' instead
1270 assert repr(q.data).startswith("<cdata 'short *' 0x")
1271 assert q.data[6] == 0
1272 q.data[6] = 15
1273 assert q.data[6] == 15
1274
1275 def test_new_struct_containing_array_varsize(self):
1276 py.test.skip("later?")
1277 ffi = FFI(backend=self.Backend())
1278 ffi.cdef("struct foo_s { int len; short data[]; };")
1279 p = ffi.new("struct foo_s *", 10) # a single integer is the length
1280 assert p.len == 0
1281 assert p.data[9] == 0
1282 py.test.raises(IndexError, "p.data[10]")
1283
1284 def test_ffi_typeof_getcname(self):
1285 ffi = FFI(backend=self.Backend())
1286 assert ffi.getctype("int") == "int"
1287 assert ffi.getctype("int", 'x') == "int x"
1288 assert ffi.getctype("int*") == "int *"
1289 assert ffi.getctype("int*", '') == "int *"
1290 assert ffi.getctype("int*", 'x') == "int * x"
1291 assert ffi.getctype("int", '*') == "int *"
1292 assert ffi.getctype("int", ' * x ') == "int * x"
1293 assert ffi.getctype(ffi.typeof("int*"), '*') == "int * *"
1294 assert ffi.getctype("int", '[5]') == "int[5]"
1295 assert ffi.getctype("int[5]", '[6]') == "int[6][5]"
1296 assert ffi.getctype("int[5]", '(*)') == "int(*)[5]"
1297 # special-case for convenience: automatically put '()' around '*'
1298 assert ffi.getctype("int[5]", '*') == "int(*)[5]"
1299 assert ffi.getctype("int[5]", '*foo') == "int(*foo)[5]"
1300 assert ffi.getctype("int[5]", ' ** foo ') == "int(** foo)[5]"
1301
1302 def test_array_of_func_ptr(self):
1303 ffi = FFI(backend=self.Backend())
1304 f = ffi.cast("int(*)(int)", 42)
1305 assert f != ffi.NULL
1306 py.test.raises(CDefError, ffi.cast, "int(int)", 42)
1307 py.test.raises(CDefError, ffi.new, "int([5])(int)")
1308 a = ffi.new("int(*[5])(int)", [f])
1309 assert ffi.getctype(ffi.typeof(a)) == "int(*[5])(int)"
1310 assert len(a) == 5
1311 assert a[0] == f
1312 assert a[1] == ffi.NULL
1313 py.test.raises(TypeError, ffi.cast, "int(*)(int)[5]", 0)
1314 #
1315 def cb(n):
1316 return n + 1
1317 f = ffi.callback("int(*)(int)", cb)
1318 a = ffi.new("int(*[5])(int)", [f, f])
1319 assert a[1](42) == 43
1320
1321 def test_callback_as_function_argument(self):
1322 # In C, function arguments can be declared with a function type,
1323 # which is automatically replaced with the ptr-to-function type.
1324 ffi = FFI(backend=self.Backend())
1325 def cb(a, b):
1326 return chr(ord(a) + ord(b)).encode()
1327 f = ffi.callback("char cb(char, char)", cb)
1328 assert f(b'A', b'\x01') == b'B'
1329 def g(callback):
1330 return callback(b'A', b'\x01')
1331 g = ffi.callback("char g(char cb(char, char))", g)
1332 assert g(f) == b'B'
1333
1334 def test_vararg_callback(self):
1335 py.test.skip("callback with '...'")
1336 ffi = FFI(backend=self.Backend())
1337 def cb(i, va_list):
1338 j = ffi.va_arg(va_list, "int")
1339 k = ffi.va_arg(va_list, "long long")
1340 return i * 2 + j * 3 + k * 5
1341 f = ffi.callback("long long cb(long i, ...)", cb)
1342 res = f(10, ffi.cast("int", 100), ffi.cast("long long", 1000))
1343 assert res == 20 + 300 + 5000
1344
1345 def test_callback_decorator(self):
1346 ffi = FFI(backend=self.Backend())
1347 #
1348 @ffi.callback("long(long, long)", error=42)
1349 def cb(a, b):
1350 return a - b
1351 #
1352 assert cb(-100, -10) == -90
1353 sz = ffi.sizeof("long")
1354 assert cb((1 << (sz*8-1)) - 1, -10) == 42
1355
1356 def test_unique_types(self):
1357 ffi1 = FFI(backend=self.Backend())
1358 ffi2 = FFI(backend=self.Backend())
1359 assert ffi1.typeof("char") is ffi2.typeof("char ")
1360 assert ffi1.typeof("long") is ffi2.typeof("signed long int")
1361 assert ffi1.typeof("double *") is ffi2.typeof("double*")
1362 assert ffi1.typeof("int ***") is ffi2.typeof(" int * * *")
1363 assert ffi1.typeof("int[]") is ffi2.typeof("signed int[]")
1364 assert ffi1.typeof("signed int*[17]") is ffi2.typeof("int *[17]")
1365 assert ffi1.typeof("void") is ffi2.typeof("void")
1366 assert ffi1.typeof("int(*)(int,int)") is ffi2.typeof("int(*)(int,int)")
1367 #
1368 # these depend on user-defined data, so should not be shared
1369 assert ffi1.typeof("struct foo") is not ffi2.typeof("struct foo")
1370 assert ffi1.typeof("union foo *") is not ffi2.typeof("union foo*")
1371 # the following test is an opaque enum, which we no longer support
1372 #assert ffi1.typeof("enum foo") is not ffi2.typeof("enum foo")
1373 # sanity check: twice 'ffi1'
1374 assert ffi1.typeof("struct foo*") is ffi1.typeof("struct foo *")
1375
1376 def test_anonymous_enum(self):
1377 ffi = FFI(backend=self.Backend())
1378 ffi.cdef("typedef enum { Value0 = 0 } e, *pe;\n"
1379 "typedef enum { Value1 = 1 } e1;")
1380 assert ffi.getctype("e*") == 'e *'
1381 assert ffi.getctype("pe") == 'e *'
1382 assert ffi.getctype("e1*") == 'e1 *'
1383
1384 def test_opaque_enum(self):
1385 import warnings
1386 ffi = FFI(backend=self.Backend())
1387 ffi.cdef("enum foo;")
1388 with warnings.catch_warnings(record=True) as log:
1389 n = ffi.cast("enum foo", -1)
1390 assert int(n) == 0xffffffff
1391 assert str(log[0].message) == (
1392 "'enum foo' has no values explicitly defined; "
1393 "guessing that it is equivalent to 'unsigned int'")
1394
1395 def test_new_ctype(self):
1396 ffi = FFI(backend=self.Backend())
1397 p = ffi.new("int *")
1398 py.test.raises(TypeError, ffi.new, p)
1399 p = ffi.new(ffi.typeof("int *"), 42)
1400 assert p[0] == 42
1401
1402 def test_enum_with_non_injective_mapping(self):
1403 ffi = FFI(backend=self.Backend())
1404 ffi.cdef("enum e { AA=0, BB=0, CC=0, DD=0 };")
1405 e = ffi.cast("enum e", 0)
1406 assert ffi.string(e) == "AA" # pick the first one arbitrarily
1407
1408 def test_enum_refer_previous_enum_value(self):
1409 ffi = FFI(backend=self.Backend())
1410 ffi.cdef("enum e { AA, BB=2, CC=4, DD=BB, EE, FF=CC, GG=FF };")
1411 assert ffi.string(ffi.cast("enum e", 2)) == "BB"
1412 assert ffi.string(ffi.cast("enum e", 3)) == "EE"
1413 assert ffi.sizeof("char[DD]") == 2
1414 assert ffi.sizeof("char[EE]") == 3
1415 assert ffi.sizeof("char[FF]") == 4
1416 assert ffi.sizeof("char[GG]") == 4
1417
1418 def test_nested_anonymous_struct(self):
1419 ffi = FFI(backend=self.Backend())
1420 ffi.cdef("""
1421 struct foo_s {
1422 struct { int a, b; };
1423 union { int c, d; };
1424 };
1425 """)
1426 assert ffi.sizeof("struct foo_s") == 3 * SIZE_OF_INT
1427 p = ffi.new("struct foo_s *", [1, 2, 3])
1428 assert p.a == 1
1429 assert p.b == 2
1430 assert p.c == 3
1431 assert p.d == 3
1432 p.d = 17
1433 assert p.c == 17
1434 p.b = 19
1435 assert p.a == 1
1436 assert p.b == 19
1437 assert p.c == 17
1438 assert p.d == 17
1439 p = ffi.new("struct foo_s *", {'b': 12, 'd': 14})
1440 assert p.a == 0
1441 assert p.b == 12
1442 assert p.c == 14
1443 assert p.d == 14
1444 py.test.raises(ValueError, ffi.new, "struct foo_s *", [0, 0, 0, 0])
1445
1446 def test_nested_field_offset_align(self):
1447 ffi = FFI(backend=self.Backend())
1448 ffi.cdef("""
1449 struct foo_s {
1450 struct { int a; char b; };
1451 union { char c; };
1452 };
1453 """)
1454 assert ffi.offsetof("struct foo_s", "c") == 2 * SIZE_OF_INT
1455 assert ffi.sizeof("struct foo_s") == 3 * SIZE_OF_INT
1456
1457 def test_nested_anonymous_union(self):
1458 ffi = FFI(backend=self.Backend())
1459 ffi.cdef("""
1460 union foo_u {
1461 struct { int a, b; };
1462 union { int c, d; };
1463 };
1464 """)
1465 assert ffi.sizeof("union foo_u") == 2 * SIZE_OF_INT
1466 p = ffi.new("union foo_u *", [5])
1467 assert p.a == 5
1468 assert p.b == 0
1469 assert p.c == 5
1470 assert p.d == 5
1471 p.d = 17
1472 assert p.c == 17
1473 assert p.a == 17
1474 p.b = 19
1475 assert p.a == 17
1476 assert p.b == 19
1477 assert p.c == 17
1478 assert p.d == 17
1479 p = ffi.new("union foo_u *", {'d': 14})
1480 assert p.a == 14
1481 assert p.b == 0
1482 assert p.c == 14
1483 assert p.d == 14
1484 p = ffi.new("union foo_u *", {'a': -63, 'b': 12})
1485 assert p.a == -63
1486 assert p.b == 12
1487 assert p.c == -63
1488 assert p.d == -63
1489 p = ffi.new("union foo_u *", [123, 456])
1490 assert p.a == 123
1491 assert p.b == 456
1492 assert p.c == 123
1493 assert p.d == 123
1494 py.test.raises(ValueError, ffi.new, "union foo_u *", [0, 0, 0])
1495
1496 def test_nested_anonymous_struct_2(self):
1497 ffi = FFI(backend=self.Backend())
1498 ffi.cdef("""
1499 struct foo_s {
1500 int a;
1501 union { int b; union { int c, d; }; };
1502 int e;
1503 };
1504 """)
1505 assert ffi.sizeof("struct foo_s") == 3 * SIZE_OF_INT
1506 p = ffi.new("struct foo_s *", [11, 22, 33])
1507 assert p.a == 11
1508 assert p.b == p.c == p.d == 22
1509 assert p.e == 33
1510 py.test.raises(ValueError, ffi.new, "struct foo_s *", [11, 22, 33, 44])
1511 FOO = ffi.typeof("struct foo_s")
1512 fields = [(name, fld.offset, fld.flags) for (name, fld) in FOO.fields]
1513 assert fields == [
1514 ('a', 0 * SIZE_OF_INT, 0),
1515 ('b', 1 * SIZE_OF_INT, 0),
1516 ('c', 1 * SIZE_OF_INT, 1),
1517 ('d', 1 * SIZE_OF_INT, 1),
1518 ('e', 2 * SIZE_OF_INT, 0),
1519 ]
1520
1521 def test_cast_to_array_type(self):
1522 ffi = FFI(backend=self.Backend())
1523 p = ffi.new("int[4]", [-5])
1524 q = ffi.cast("int[3]", p)
1525 assert q[0] == -5
1526 assert repr(q).startswith("<cdata 'int[3]' 0x")
1527
1528 def test_gc(self):
1529 ffi = FFI(backend=self.Backend())
1530 p = ffi.new("int *", 123)
1531 seen = []
1532 def destructor(p1):
1533 assert p1 is p
1534 assert p1[0] == 123
1535 seen.append(1)
1536 q = ffi.gc(p, destructor)
1537 assert ffi.typeof(q) is ffi.typeof(p)
1538 import gc; gc.collect()
1539 assert seen == []
1540 del q
1541 import gc; gc.collect(); gc.collect(); gc.collect()
1542 assert seen == [1]
1543
1544 def test_gc_2(self):
1545 ffi = FFI(backend=self.Backend())
1546 p = ffi.new("int *", 123)
1547 seen = []
1548 q1 = ffi.gc(p, lambda p: seen.append(1))
1549 q2 = ffi.gc(q1, lambda p: seen.append(2))
1550 import gc; gc.collect()
1551 assert seen == []
1552 del q1, q2
1553 import gc; gc.collect(); gc.collect(); gc.collect(); gc.collect()
1554 assert seen == [2, 1]
1555
1556 def test_gc_3(self):
1557 ffi = FFI(backend=self.Backend())
1558 p = ffi.new("int *", 123)
1559 r = ffi.new("int *", 123)
1560 seen = []
1561 seen_r = []
1562 q1 = ffi.gc(p, lambda p: seen.append(1))
1563 s1 = ffi.gc(r, lambda r: seen_r.append(4))
1564 q2 = ffi.gc(q1, lambda p: seen.append(2))
1565 s2 = ffi.gc(s1, lambda r: seen_r.append(5))
1566 q3 = ffi.gc(q2, lambda p: seen.append(3))
1567 import gc; gc.collect()
1568 assert seen == []
1569 assert seen_r == []
1570 del q1, q2, q3, s2, s1
1571 import gc; gc.collect(); gc.collect(); gc.collect(); gc.collect()
1572 assert seen == [3, 2, 1]
1573 assert seen_r == [5, 4]
1574
1575 def test_gc_4(self):
1576 ffi = FFI(backend=self.Backend())
1577 p = ffi.new("int *", 123)
1578 seen = []
1579 q1 = ffi.gc(p, lambda p: seen.append(1))
1580 q2 = ffi.gc(q1, lambda p: seen.append(2))
1581 q3 = ffi.gc(q2, lambda p: seen.append(3))
1582 import gc; gc.collect()
1583 assert seen == []
1584 del q1, q3 # q2 remains, and has a hard ref to q1
1585 import gc; gc.collect(); gc.collect(); gc.collect()
1586 assert seen == [3]
1587
1588 def test_gc_disable(self):
1589 ffi = FFI(backend=self.Backend())
1590 p = ffi.new("int *", 123)
1591 py.test.raises(TypeError, ffi.gc, p, None)
1592 seen = []
1593 q1 = ffi.gc(p, lambda p: seen.append(1))
1594 q2 = ffi.gc(q1, lambda p: seen.append(2))
1595 import gc; gc.collect()
1596 assert seen == []
1597 assert ffi.gc(q1, None) is None
1598 del q1, q2
1599 import gc; gc.collect(); gc.collect(); gc.collect()
1600 assert seen == [2]
1601
1602 def test_gc_finite_list(self):
1603 ffi = FFI(backend=self.Backend())
1604 p = ffi.new("int *", 123)
1605 keepalive = []
1606 for i in range(10):
1607 keepalive.append(ffi.gc(p, lambda p: None))
1608 del keepalive[:]
1609 import gc; gc.collect(); gc.collect()
1610 for i in range(10):
1611 keepalive.append(ffi.gc(p, lambda p: None))
1612
1613 def test_CData_CType(self):
1614 ffi = FFI(backend=self.Backend())
1615 assert isinstance(ffi.cast("int", 0), ffi.CData)
1616 assert isinstance(ffi.new("int *"), ffi.CData)
1617 assert not isinstance(ffi.typeof("int"), ffi.CData)
1618 assert not isinstance(ffi.cast("int", 0), ffi.CType)
1619 assert not isinstance(ffi.new("int *"), ffi.CType)
1620
1621 def test_CData_CType_2(self):
1622 ffi = FFI(backend=self.Backend())
1623 assert isinstance(ffi.typeof("int"), ffi.CType)
1624
1625 def test_bool(self):
1626 ffi = FFI(backend=self.Backend())
1627 assert int(ffi.cast("_Bool", 0.1)) == 1
1628 assert int(ffi.cast("_Bool", -0.0)) == 0
1629 assert int(ffi.cast("_Bool", b'\x02')) == 1
1630 assert int(ffi.cast("_Bool", b'\x00')) == 0
1631 assert int(ffi.cast("_Bool", b'\x80')) == 1
1632 assert ffi.new("_Bool *", False)[0] == 0
1633 assert ffi.new("_Bool *", 1)[0] == 1
1634 py.test.raises(OverflowError, ffi.new, "_Bool *", 2)
1635 py.test.raises(TypeError, ffi.string, ffi.cast("_Bool", 2))
1636
1637 def test_use_own_bool(self):
1638 ffi = FFI(backend=self.Backend())
1639 ffi.cdef("""typedef int bool;""")
1640
1641 def test_ordering_bug1(self):
1642 ffi = FFI(backend=self.Backend())
1643 ffi.cdef("""
1644 struct foo_s {
1645 struct bar_s *p;
1646 };
1647 struct bar_s {
1648 struct foo_s foo;
1649 };
1650 """)
1651 q = ffi.new("struct foo_s *")
1652 bar = ffi.new("struct bar_s *")
1653 q.p = bar
1654 assert q.p.foo.p == ffi.NULL
1655
1656 def test_ordering_bug2(self):
1657 ffi = FFI(backend=self.Backend())
1658 ffi.cdef("""
1659 struct bar_s;
1660
1661 struct foo_s {
1662 void (*foo)(struct bar_s[]);
1663 };
1664
1665 struct bar_s {
1666 struct foo_s foo;
1667 };
1668 """)
1669 q = ffi.new("struct foo_s *")
1670
1671 def test_addressof(self):
1672 ffi = FFI(backend=self.Backend())
1673 ffi.cdef("struct foo_s { int x, y; };")
1674 p = ffi.new("struct foo_s *")
1675 a = ffi.addressof(p[0])
1676 assert repr(a).startswith("<cdata 'struct foo_s *' 0x")
1677 assert a == p
1678 py.test.raises(TypeError, ffi.addressof, p)
1679 py.test.raises((AttributeError, TypeError), ffi.addressof, 5)
1680 py.test.raises(TypeError, ffi.addressof, ffi.cast("int", 5))
1681
1682 def test_addressof_field(self):
1683 ffi = FFI(backend=self.Backend())
1684 ffi.cdef("struct foo_s { int x, y; };")
1685 p = ffi.new("struct foo_s *")
1686 a = ffi.addressof(p[0], 'y')
1687 assert repr(a).startswith("<cdata 'int *' 0x")
1688 assert int(ffi.cast("uintptr_t", a)) == (
1689 int(ffi.cast("uintptr_t", p)) + ffi.sizeof("int"))
1690 assert a == ffi.addressof(p, 'y')
1691 assert a != ffi.addressof(p, 'x')
1692
1693 def test_addressof_field_nested(self):
1694 ffi = FFI(backend=self.Backend())
1695 ffi.cdef("struct foo_s { int x, y; };"
1696 "struct bar_s { struct foo_s a, b; };")
1697 p = ffi.new("struct bar_s *")
1698 py.test.raises(KeyError, ffi.addressof, p[0], 'b.y')
1699 a = ffi.addressof(p[0], 'b', 'y')
1700 assert int(ffi.cast("uintptr_t", a)) == (
1701 int(ffi.cast("uintptr_t", p)) +
1702 ffi.sizeof("struct foo_s") + ffi.sizeof("int"))
1703
1704 def test_addressof_anonymous_struct(self):
1705 ffi = FFI()
1706 ffi.cdef("typedef struct { int x; } foo_t;")
1707 p = ffi.new("foo_t *")
1708 a = ffi.addressof(p[0])
1709 assert a == p
1710
1711 def test_addressof_array(self):
1712 ffi = FFI()
1713 p = ffi.new("int[52]")
1714 p0 = ffi.addressof(p)
1715 assert p0 == p
1716 assert ffi.typeof(p0) is ffi.typeof("int(*)[52]")
1717 py.test.raises(TypeError, ffi.addressof, p0)
1718 #
1719 p1 = ffi.addressof(p, 25)
1720 assert ffi.typeof(p1) is ffi.typeof("int *")
1721 assert (p1 - p) == 25
1722 assert ffi.addressof(p, 0) == p
1723
1724 def test_addressof_pointer(self):
1725 ffi = FFI()
1726 array = ffi.new("int[50]")
1727 p = ffi.cast("int *", array)
1728 py.test.raises(TypeError, ffi.addressof, p)
1729 assert ffi.addressof(p, 0) == p
1730 assert ffi.addressof(p, 25) == p + 25
1731 assert ffi.typeof(ffi.addressof(p, 25)) == ffi.typeof(p)
1732 #
1733 ffi.cdef("struct foo { int a, b; };")
1734 array = ffi.new("struct foo[50]")
1735 p = ffi.cast("int *", array)
1736 py.test.raises(TypeError, ffi.addressof, p)
1737 assert ffi.addressof(p, 0) == p
1738 assert ffi.addressof(p, 25) == p + 25
1739 assert ffi.typeof(ffi.addressof(p, 25)) == ffi.typeof(p)
1740
1741 def test_addressof_array_in_struct(self):
1742 ffi = FFI()
1743 ffi.cdef("struct foo { int a, b; int c[50]; };")
1744 p = ffi.new("struct foo *")
1745 p1 = ffi.addressof(p, "c", 25)
1746 assert ffi.typeof(p1) is ffi.typeof("int *")
1747 assert p1 == ffi.cast("int *", p) + 27
1748 assert ffi.addressof(p, "c") == ffi.cast("int *", p) + 2
1749 assert ffi.addressof(p, "c", 0) == ffi.cast("int *", p) + 2
1750 p2 = ffi.addressof(p, 1)
1751 assert ffi.typeof(p2) is ffi.typeof("struct foo *")
1752 assert p2 == p + 1
1753
1754 def test_multiple_independent_structs(self):
1755 ffi1 = FFI(); ffi1.cdef("struct foo { int x; };")
1756 ffi2 = FFI(); ffi2.cdef("struct foo { int y, z; };")
1757 foo1 = ffi1.new("struct foo *", [10])
1758 foo2 = ffi2.new("struct foo *", [20, 30])
1759 assert foo1.x == 10
1760 assert foo2.y == 20
1761 assert foo2.z == 30
1762
1763 def test_missing_include(self):
1764 backend = self.Backend()
1765 ffi1 = FFI(backend=backend)
1766 ffi2 = FFI(backend=backend)
1767 ffi1.cdef("typedef signed char schar_t;")
1768 py.test.raises(CDefError, ffi2.cast, "schar_t", 142)
1769
1770 def test_include_typedef(self):
1771 backend = self.Backend()
1772 ffi1 = FFI(backend=backend)
1773 ffi2 = FFI(backend=backend)
1774 ffi1.cdef("typedef signed char schar_t;")
1775 ffi2.include(ffi1)
1776 p = ffi2.cast("schar_t", 142)
1777 assert int(p) == 142 - 256
1778
1779 def test_include_struct(self):
1780 backend = self.Backend()
1781 ffi1 = FFI(backend=backend)
1782 ffi2 = FFI(backend=backend)
1783 ffi1.cdef("struct foo { int x; };")
1784 ffi2.include(ffi1)
1785 p = ffi2.new("struct foo *", [142])
1786 assert p.x == 142
1787
1788 def test_include_union(self):
1789 backend = self.Backend()
1790 ffi1 = FFI(backend=backend)
1791 ffi2 = FFI(backend=backend)
1792 ffi1.cdef("union foo { int x; };")
1793 ffi2.include(ffi1)
1794 p = ffi2.new("union foo *", [142])
1795 assert p.x == 142
1796
1797 def test_include_enum(self):
1798 backend = self.Backend()
1799 ffi1 = FFI(backend=backend)
1800 ffi2 = FFI(backend=backend)
1801 ffi1.cdef("enum foo { FA, FB, FC };")
1802 ffi2.include(ffi1)
1803 p = ffi2.cast("enum foo", 1)
1804 assert ffi2.string(p) == "FB"
1805 assert ffi2.sizeof("char[FC]") == 2
1806
1807 def test_include_typedef_2(self):
1808 backend = self.Backend()
1809 ffi1 = FFI(backend=backend)
1810 ffi2 = FFI(backend=backend)
1811 ffi1.cdef("typedef struct { int x; } *foo_p;")
1812 ffi2.include(ffi1)
1813 p = ffi2.new("foo_p", [142])
1814 assert p.x == 142
1815
1816 def test_ignore_multiple_declarations_of_constant(self):
1817 ffi = FFI(backend=self.Backend())
1818 ffi.cdef("#define FOO 42")
1819 ffi.cdef("#define FOO 42")
1820 py.test.raises(FFIError, ffi.cdef, "#define FOO 43")
1821
1822 def test_struct_packed(self):
1823 ffi = FFI(backend=self.Backend())
1824 ffi.cdef("struct nonpacked { char a; int b; };")
1825 ffi.cdef("struct is_packed { char a; int b; };", packed=True)
1826 assert ffi.sizeof("struct nonpacked") == 8
1827 assert ffi.sizeof("struct is_packed") == 5
1828 assert ffi.alignof("struct nonpacked") == 4
1829 assert ffi.alignof("struct is_packed") == 1
1830 s = ffi.new("struct is_packed[2]")
1831 s[0].b = 42623381
1832 s[0].a = b'X'
1833 s[1].b = -4892220
1834 s[1].a = b'Y'
1835 assert s[0].b == 42623381
1836 assert s[0].a == b'X'
1837 assert s[1].b == -4892220
1838 assert s[1].a == b'Y'
1839
1840 def test_define_integer_constant(self):
1841 ffi = FFI(backend=self.Backend())
1842 ffi.cdef("""
1843 #define DOT_0 0
1844 #define DOT 100
1845 #define DOT_OCT 0100l
1846 #define DOT_HEX 0x100u
1847 #define DOT_HEX2 0X10
1848 #define DOT_UL 1000UL
1849 enum foo {AA, BB=DOT, CC};
1850 """)
1851 needs_dlopen_none()
1852 lib = ffi.dlopen(None)
1853 assert ffi.string(ffi.cast("enum foo", 100)) == "BB"
1854 assert lib.DOT_0 == 0
1855 assert lib.DOT == 100
1856 assert lib.DOT_OCT == 0o100
1857 assert lib.DOT_HEX == 0x100
1858 assert lib.DOT_HEX2 == 0x10
1859 assert lib.DOT_UL == 1000
1860
1861 def test_opaque_struct_becomes_nonopaque(self):
1862 # Issue #193: if we use a struct between the first cdef() where it is
1863 # declared and another cdef() where its fields are defined, then the
1864 # definition was ignored.
1865 ffi = FFI(backend=self.Backend())
1866 ffi.cdef("struct foo_s;")
1867 py.test.raises(TypeError, ffi.new, "struct foo_s *")
1868 ffi.cdef("struct foo_s { int x; };")
1869 ffi.new("struct foo_s *")
1870
1871 def test_ffi_self_include(self):
1872 ffi = FFI(backend=self.Backend())
1873 py.test.raises(ValueError, ffi.include, ffi)
1874
1875 def test_anonymous_enum_include(self):
1876 ffi1 = FFI()
1877 ffi1.cdef("enum { EE1 };")
1878 ffi = FFI()
1879 ffi.include(ffi1)
1880 ffi.cdef("enum { EE2, EE3 };")
1881 needs_dlopen_none()
1882 lib = ffi.dlopen(None)
1883 assert lib.EE1 == 0
1884 assert lib.EE2 == 0
1885 assert lib.EE3 == 1
1886
1887 def test_init_once(self):
1888 def do_init():
1889 seen.append(1)
1890 return 42
1891 ffi = FFI()
1892 seen = []
1893 for i in range(3):
1894 res = ffi.init_once(do_init, "tag1")
1895 assert res == 42
1896 assert seen == [1]
1897 for i in range(3):
1898 res = ffi.init_once(do_init, "tag2")
1899 assert res == 42
1900 assert seen == [1, 1]
1901
1902 def test_init_once_multithread(self):
1903 import sys, time
1904 if sys.version_info < (3,):
1905 import thread
1906 else:
1907 import _thread as thread
1908 #
1909 def do_init():
1910 seen.append('init!')
1911 time.sleep(1)
1912 seen.append('init done')
1913 return 7
1914 ffi = FFI()
1915 seen = []
1916 for i in range(6):
1917 def f():
1918 res = ffi.init_once(do_init, "tag")
1919 seen.append(res)
1920 thread.start_new_thread(f, ())
1921 time.sleep(1.5)
1922 assert seen == ['init!', 'init done'] + 6 * [7]
1923
1924 def test_sizeof_struct_directly(self):
1925 # only works with the Python FFI instances
1926 ffi = FFI(backend=self.Backend())
1927 assert ffi.sizeof("struct{int a;}") == ffi.sizeof("int")
+0
-43
pypy/module/test_lib_pypy/cffi_tests/cffi0/callback_in_thread.py less more
0 # Generated by pypy/tool/import_cffi.py
1 import sys, time
2 sys.path.insert(0, sys.argv[1])
3 from cffi import FFI
4
5 def _run_callback_in_thread():
6 ffi = FFI()
7 ffi.cdef("""
8 typedef int (*mycallback_func_t)(int, int);
9 int threaded_ballback_test(mycallback_func_t mycb);
10 """)
11 lib = ffi.verify("""
12 #include <pthread.h>
13 typedef int (*mycallback_func_t)(int, int);
14 void *my_wait_function(void *ptr) {
15 mycallback_func_t cbfunc = (mycallback_func_t)ptr;
16 cbfunc(10, 10);
17 cbfunc(12, 15);
18 return NULL;
19 }
20 int threaded_ballback_test(mycallback_func_t mycb) {
21 pthread_t thread;
22 pthread_create(&thread, NULL, my_wait_function, (void*)mycb);
23 return 0;
24 }
25 """, extra_compile_args=['-pthread'])
26 seen = []
27 @ffi.callback('int(*)(int,int)')
28 def mycallback(x, y):
29 time.sleep(0.022)
30 seen.append((x, y))
31 return 0
32 lib.threaded_ballback_test(mycallback)
33 count = 300
34 while len(seen) != 2:
35 time.sleep(0.01)
36 count -= 1
37 assert count > 0, "timeout"
38 assert seen == [(10, 10), (12, 15)]
39
40 print('STARTING')
41 _run_callback_in_thread()
42 print('DONE')
+0
-8
pypy/module/test_lib_pypy/cffi_tests/cffi0/snippets/distutils_module/setup.py less more
0 # Generated by pypy/tool/import_cffi.py
1
2 from distutils.core import setup
3 import snip_basic_verify
4
5 setup(
6 py_modules=['snip_basic_verify'],
7 ext_modules=[snip_basic_verify.ffi.verifier.get_extension()])
+0
-18
pypy/module/test_lib_pypy/cffi_tests/cffi0/snippets/distutils_module/snip_basic_verify.py less more
0 # Generated by pypy/tool/import_cffi.py
1
2 from cffi import FFI
3 import sys
4
5 ffi = FFI()
6 ffi.cdef(""" // some declarations from the man page
7 struct passwd {
8 char *pw_name;
9 ...;
10 };
11 struct passwd *getpwuid(int uid);
12 """)
13 C = ffi.verify(""" // passed to the real C compiler
14 #include <sys/types.h>
15 #include <pwd.h>
16 """, libraries=[], # or a list of libraries to link with
17 force_generic_engine=hasattr(sys, '_force_generic_engine_'))
+0
-8
pypy/module/test_lib_pypy/cffi_tests/cffi0/snippets/distutils_package_1/setup.py less more
0 # Generated by pypy/tool/import_cffi.py
1
2 from distutils.core import setup
3 import snip_basic_verify1
4
5 setup(
6 packages=['snip_basic_verify1'],
7 ext_modules=[snip_basic_verify1.ffi.verifier.get_extension()])
+0
-18
pypy/module/test_lib_pypy/cffi_tests/cffi0/snippets/distutils_package_1/snip_basic_verify1/__init__.py less more
0 # Generated by pypy/tool/import_cffi.py
1
2 from cffi import FFI
3 import sys
4
5 ffi = FFI()
6 ffi.cdef(""" // some declarations from the man page
7 struct passwd {
8 char *pw_name;
9 ...;
10 };
11 struct passwd *getpwuid(int uid);
12 """)
13 C = ffi.verify(""" // passed to the real C compiler
14 #include <sys/types.h>
15 #include <pwd.h>
16 """, libraries=[], # or a list of libraries to link with
17 force_generic_engine=hasattr(sys, '_force_generic_engine_'))
+0
-9
pypy/module/test_lib_pypy/cffi_tests/cffi0/snippets/distutils_package_2/setup.py less more
0 # Generated by pypy/tool/import_cffi.py
1
2 from distutils.core import setup
3 import snip_basic_verify2
4
5 setup(
6 packages=['snip_basic_verify2'],
7 ext_package='snip_basic_verify2',
8 ext_modules=[snip_basic_verify2.ffi.verifier.get_extension()])
+0
-19
pypy/module/test_lib_pypy/cffi_tests/cffi0/snippets/distutils_package_2/snip_basic_verify2/__init__.py less more
0 # Generated by pypy/tool/import_cffi.py
1
2 from cffi import FFI
3 import sys
4
5 ffi = FFI()
6 ffi.cdef(""" // some declarations from the man page
7 struct passwd {
8 char *pw_name;
9 ...;
10 };
11 struct passwd *getpwuid(int uid);
12 """)
13 C = ffi.verify(""" // passed to the real C compiler
14 #include <sys/types.h>
15 #include <pwd.h>
16 """, libraries=[], # or a list of libraries to link with
17 ext_package='snip_basic_verify2',
18 force_generic_engine=hasattr(sys, '_force_generic_engine_'))
+0
-6
pypy/module/test_lib_pypy/cffi_tests/cffi0/snippets/infrastructure/setup.py less more
0 # Generated by pypy/tool/import_cffi.py
1
2 from distutils.core import setup
3
4 setup(packages=['snip_infrastructure'],
5 requires=['cffi'])
+0
-4
pypy/module/test_lib_pypy/cffi_tests/cffi0/snippets/infrastructure/snip_infrastructure/__init__.py less more
0 # Generated by pypy/tool/import_cffi.py
1
2 def func():
3 return 42
+0
-9
pypy/module/test_lib_pypy/cffi_tests/cffi0/snippets/setuptools_module/setup.py less more
0 # Generated by pypy/tool/import_cffi.py
1
2 from setuptools import setup
3 import snip_setuptools_verify
4
5 setup(
6 zip_safe=False,
7 py_modules=['snip_setuptools_verify'],
8 ext_modules=[snip_setuptools_verify.ffi.verifier.get_extension()])
+0
-18
pypy/module/test_lib_pypy/cffi_tests/cffi0/snippets/setuptools_module/snip_setuptools_verify.py less more
0 # Generated by pypy/tool/import_cffi.py
1
2 from cffi import FFI
3 import sys
4
5 ffi = FFI()
6 ffi.cdef(""" // some declarations from the man page
7 struct passwd {
8 char *pw_name;
9 ...;
10 };
11 struct passwd *getpwuid(int uid);
12 """)
13 C = ffi.verify(""" // passed to the real C compiler
14 #include <sys/types.h>
15 #include <pwd.h>
16 """, libraries=[], # or a list of libraries to link with
17 force_generic_engine=hasattr(sys, '_force_generic_engine_'))
+0
-9
pypy/module/test_lib_pypy/cffi_tests/cffi0/snippets/setuptools_package_1/setup.py less more
0 # Generated by pypy/tool/import_cffi.py
1
2 from setuptools import setup
3 import snip_setuptools_verify1
4
5 setup(
6 zip_safe=False,
7 packages=['snip_setuptools_verify1'],
8 ext_modules=[snip_setuptools_verify1.ffi.verifier.get_extension()])
+0
-18
pypy/module/test_lib_pypy/cffi_tests/cffi0/snippets/setuptools_package_1/snip_setuptools_verify1/__init__.py less more
0 # Generated by pypy/tool/import_cffi.py
1
2 from cffi import FFI
3 import sys
4
5 ffi = FFI()
6 ffi.cdef(""" // some declarations from the man page
7 struct passwd {
8 char *pw_name;
9 ...;
10 };
11 struct passwd *getpwuid(int uid);
12 """)
13 C = ffi.verify(""" // passed to the real C compiler
14 #include <sys/types.h>
15 #include <pwd.h>
16 """, libraries=[], # or a list of libraries to link with
17 force_generic_engine=hasattr(sys, '_force_generic_engine_'))
+0
-10
pypy/module/test_lib_pypy/cffi_tests/cffi0/snippets/setuptools_package_2/setup.py less more
0 # Generated by pypy/tool/import_cffi.py
1
2 from setuptools import setup
3 import snip_setuptools_verify2
4
5 setup(
6 zip_safe=False,
7 packages=['snip_setuptools_verify2'],
8 ext_package='snip_setuptools_verify2',
9 ext_modules=[snip_setuptools_verify2.ffi.verifier.get_extension()])
+0
-19
pypy/module/test_lib_pypy/cffi_tests/cffi0/snippets/setuptools_package_2/snip_setuptools_verify2/__init__.py less more
0 # Generated by pypy/tool/import_cffi.py
1
2 from cffi import FFI
3 import sys
4
5 ffi = FFI()
6 ffi.cdef(""" // some declarations from the man page
7 struct passwd {
8 char *pw_name;
9 ...;
10 };
11 struct passwd *getpwuid(int uid);
12 """)
13 C = ffi.verify(""" // passed to the real C compiler
14 #include <sys/types.h>
15 #include <pwd.h>
16 """, libraries=[], # or a list of libraries to link with
17 ext_package='snip_setuptools_verify2',
18 force_generic_engine=hasattr(sys, '_force_generic_engine_'))
+0
-42
pypy/module/test_lib_pypy/cffi_tests/cffi0/test_cdata.py less more
0 # Generated by pypy/tool/import_cffi.py
1 import py
2 from cffi import FFI
3
4 class FakeBackend(object):
5
6 def nonstandard_integer_types(self):
7 return {}
8
9 def sizeof(self, name):
10 return 1
11
12 def load_library(self, path):
13 return "fake library"
14
15 def new_primitive_type(self, name):
16 return FakeType("primitive " + name)
17
18 def new_void_type(self):
19 return FakeType("void")
20 def new_pointer_type(self, x):
21 return FakeType('ptr-to-%r' % (x,))
22 def new_array_type(self, x, y):
23 return FakeType('array-from-%r-len-%r' % (x, y))
24 def cast(self, x, y):
25 return 'casted!'
26 def _get_types(self):
27 return "CData", "CType"
28
29 buffer = "buffer type"
30
31
32 class FakeType(object):
33 def __init__(self, cdecl):
34 self.cdecl = cdecl
35
36
37 def test_typeof():
38 ffi = FFI(backend=FakeBackend())
39 clong = ffi.typeof("signed long int")
40 assert isinstance(clong, FakeType)
41 assert clong.cdecl == 'primitive long'
+0
-44
pypy/module/test_lib_pypy/cffi_tests/cffi0/test_ctypes.py less more
0 # Generated by pypy/tool/import_cffi.py
1 import py, sys
2 from pypy.module.test_lib_pypy.cffi_tests.cffi0 import backend_tests
3 from cffi.backend_ctypes import CTypesBackend
4
5
6 class TestCTypes(backend_tests.BackendTests):
7 # for individual tests see
8 # ====> backend_tests.py
9
10 Backend = CTypesBackend
11 TypeRepr = "<class 'ffi.CData<%s>'>"
12
13 def test_array_of_func_ptr(self):
14 py.test.skip("ctypes backend: not supported: "
15 "initializers for function pointers")
16
17 def test_structptr_argument(self):
18 py.test.skip("ctypes backend: not supported: passing a list "
19 "for a pointer argument")
20
21 def test_array_argument_as_list(self):
22 py.test.skip("ctypes backend: not supported: passing a list "
23 "for a pointer argument")
24
25 def test_cast_to_array_type(self):
26 py.test.skip("ctypes backend: not supported: casting to array")
27
28 def test_nested_anonymous_struct(self):
29 py.test.skip("ctypes backend: not supported: nested anonymous struct")
30
31 def test_nested_field_offset_align(self):
32 py.test.skip("ctypes backend: not supported: nested anonymous struct")
33
34 def test_nested_anonymous_union(self):
35 py.test.skip("ctypes backend: not supported: nested anonymous union")
36
37 def test_nested_anonymous_struct_2(self):
38 py.test.skip("ctypes backend: not supported: nested anonymous union")
39
40 def test_CData_CType_2(self):
41 if sys.version_info >= (3,):
42 py.test.skip("ctypes backend: not supported in Python 3: CType")
43 backend_tests.BackendTests.test_CData_CType_2(self)
+0
-554
pypy/module/test_lib_pypy/cffi_tests/cffi0/test_ffi_backend.py less more
0 # Generated by pypy/tool/import_cffi.py
1 import py, sys, platform
2 import pytest
3 from pypy.module.test_lib_pypy.cffi_tests.cffi0 import backend_tests, test_function, test_ownlib
4 from pypy.module.test_lib_pypy.cffi_tests.support import u
5 from cffi import FFI
6 import _cffi_backend
7
8
9 class TestFFI(backend_tests.BackendTests,
10 test_function.TestFunction,
11 test_ownlib.TestOwnLib):
12 TypeRepr = "<ctype '%s'>"
13
14 @staticmethod
15 def Backend():
16 return _cffi_backend
17
18 def test_not_supported_bitfield_in_result(self):
19 ffi = FFI(backend=self.Backend())
20 ffi.cdef("struct foo_s { int a,b,c,d,e; int x:1; };")
21 e = py.test.raises(NotImplementedError, ffi.callback,
22 "struct foo_s foo(void)", lambda: 42)
23 assert str(e.value) == ("struct foo_s(*)(): "
24 "callback with unsupported argument or return type or with '...'")
25
26 def test_inspecttype(self):
27 ffi = FFI(backend=self.Backend())
28 assert ffi.typeof("long").kind == "primitive"
29 assert ffi.typeof("long(*)(long, long**, ...)").cname == (
30 "long(*)(long, long * *, ...)")
31 assert ffi.typeof("long(*)(long, long**, ...)").ellipsis is True
32
33 def test_new_handle(self):
34 ffi = FFI(backend=self.Backend())
35 o = [2, 3, 4]
36 p = ffi.new_handle(o)
37 assert ffi.typeof(p) == ffi.typeof("void *")
38 assert ffi.from_handle(p) is o
39 assert ffi.from_handle(ffi.cast("char *", p)) is o
40 py.test.raises(RuntimeError, ffi.from_handle, ffi.NULL)
41
42 def test_callback_onerror(self):
43 ffi = FFI(backend=self.Backend())
44 seen = []
45 def oops(*args):
46 seen.append(args)
47 def otherfunc():
48 raise LookupError
49 def cb(n):
50 otherfunc()
51 a = ffi.callback("int(*)(int)", cb, error=42, onerror=oops)
52 res = a(234)
53 assert res == 42
54 assert len(seen) == 1
55 exc, val, tb = seen[0]
56 assert exc is LookupError
57 assert isinstance(val, LookupError)
58 assert tb.tb_frame.f_code.co_name == 'cb'
59 assert tb.tb_frame.f_locals['n'] == 234
60
61 def test_ffi_new_allocator_2(self):
62 ffi = FFI(backend=self.Backend())
63 seen = []
64 def myalloc(size):
65 seen.append(size)
66 return ffi.new("char[]", b"X" * size)
67 def myfree(raw):
68 seen.append(raw)
69 alloc1 = ffi.new_allocator(myalloc, myfree)
70 alloc2 = ffi.new_allocator(alloc=myalloc, free=myfree,
71 should_clear_after_alloc=False)
72 p1 = alloc1("int[10]")
73 p2 = alloc2("int[]", 10)
74 assert seen == [40, 40]
75 assert ffi.typeof(p1) == ffi.typeof("int[10]")
76 assert ffi.sizeof(p1) == 40
77 assert ffi.typeof(p2) == ffi.typeof("int[]")
78 assert ffi.sizeof(p2) == 40
79 assert p1[5] == 0
80 assert p2[6] == ord('X') * 0x01010101
81 raw1 = ffi.cast("char *", p1)
82 raw2 = ffi.cast("char *", p2)
83 del p1, p2
84 retries = 0
85 while len(seen) != 4:
86 retries += 1
87 assert retries <= 5
88 import gc; gc.collect()
89 assert seen == [40, 40, raw1, raw2]
90 assert repr(seen[2]) == "<cdata 'char[]' owning 41 bytes>"
91 assert repr(seen[3]) == "<cdata 'char[]' owning 41 bytes>"
92
93 def test_ffi_new_allocator_3(self):
94 ffi = FFI(backend=self.Backend())
95 seen = []
96 def myalloc(size):
97 seen.append(size)
98 return ffi.new("char[]", b"X" * size)
99 alloc1 = ffi.new_allocator(myalloc) # no 'free'
100 p1 = alloc1("int[10]")
101 assert seen == [40]
102 assert ffi.typeof(p1) == ffi.typeof("int[10]")
103 assert ffi.sizeof(p1) == 40
104 assert p1[5] == 0
105
106 def test_ffi_new_allocator_4(self):
107 ffi = FFI(backend=self.Backend())
108 py.test.raises(TypeError, ffi.new_allocator, free=lambda x: None)
109 #
110 def myalloc2(size):
111 raise LookupError
112 alloc2 = ffi.new_allocator(myalloc2)
113 py.test.raises(LookupError, alloc2, "int[5]")
114 #
115 def myalloc3(size):
116 return 42
117 alloc3 = ffi.new_allocator(myalloc3)
118 e = py.test.raises(TypeError, alloc3, "int[5]")
119 assert str(e.value) == "alloc() must return a cdata object (got int)"
120 #
121 def myalloc4(size):
122 return ffi.cast("int", 42)
123 alloc4 = ffi.new_allocator(myalloc4)
124 e = py.test.raises(TypeError, alloc4, "int[5]")
125 assert str(e.value) == "alloc() must return a cdata pointer, not 'int'"
126 #
127 def myalloc5(size):
128 return ffi.NULL
129 alloc5 = ffi.new_allocator(myalloc5)
130 py.test.raises(MemoryError, alloc5, "int[5]")
131
132
133 class TestBitfield:
134 def check(self, source, expected_ofs_y, expected_align, expected_size):
135 # NOTE: 'expected_*' is the numbers expected from GCC.
136 # The numbers expected from MSVC are not explicitly written
137 # in this file, and will just be taken from the compiler.
138 ffi = FFI()
139 ffi.cdef("struct s1 { %s };" % source)
140 ctype = ffi.typeof("struct s1")
141 # verify the information with gcc
142 ffi1 = FFI()
143 ffi1.cdef("""
144 static const int Gofs_y, Galign, Gsize;
145 struct s1 *try_with_value(int fieldnum, long long value);
146 """)
147 fnames = [name for name, cfield in ctype.fields
148 if name and cfield.bitsize > 0]
149 setters = ['case %d: s.%s = value; break;' % iname
150 for iname in enumerate(fnames)]
151 lib = ffi1.verify("""
152 struct s1 { %s };
153 struct sa { char a; struct s1 b; };
154 #define Gofs_y offsetof(struct s1, y)
155 #define Galign offsetof(struct sa, b)
156 #define Gsize sizeof(struct s1)
157 struct s1 *try_with_value(int fieldnum, long long value)
158 {
159 static struct s1 s;
160 memset(&s, 0, sizeof(s));
161 switch (fieldnum) { %s }
162 return &s;
163 }
164 """ % (source, ' '.join(setters)))
165 if sys.platform == 'win32':
166 expected_ofs_y = lib.Gofs_y
167 expected_align = lib.Galign
168 expected_size = lib.Gsize
169 else:
170 assert (lib.Gofs_y, lib.Galign, lib.Gsize) == (
171 expected_ofs_y, expected_align, expected_size)
172 # the real test follows
173 assert ffi.offsetof("struct s1", "y") == expected_ofs_y
174 assert ffi.alignof("struct s1") == expected_align
175 assert ffi.sizeof("struct s1") == expected_size
176 # compare the actual storage of the two
177 for name, cfield in ctype.fields:
178 if cfield.bitsize < 0 or not name:
179 continue
180 if int(ffi.cast(cfield.type, -1)) == -1: # signed
181 min_value = -(1 << (cfield.bitsize-1))
182 max_value = (1 << (cfield.bitsize-1)) - 1
183 else:
184 min_value = 0
185 max_value = (1 << cfield.bitsize) - 1
186 for t in [1, 2, 4, 8, 16, 128, 2813, 89728, 981729,
187 -1,-2,-4,-8,-16,-128,-2813,-89728,-981729]:
188 if min_value <= t <= max_value:
189 self._fieldcheck(ffi, lib, fnames, name, t)
190
191 def _fieldcheck(self, ffi, lib, fnames, name, value):
192 s = ffi.new("struct s1 *")
193 setattr(s, name, value)
194 assert getattr(s, name) == value
195 raw1 = ffi.buffer(s)[:]
196 buff1 = ffi.buffer(s)
197 t = lib.try_with_value(fnames.index(name), value)
198 raw2 = ffi.buffer(t, len(raw1))[:]
199 assert raw1 == raw2
200 buff2 = ffi.buffer(t, len(buff1))
201 assert buff1 == buff2
202
203 def test_bitfield_basic(self):
204 self.check("int a; int b:9; int c:20; int y;", 8, 4, 12)
205 self.check("int a; short b:9; short c:7; int y;", 8, 4, 12)
206 self.check("int a; short b:9; short c:9; int y;", 8, 4, 12)
207
208 def test_bitfield_reuse_if_enough_space(self):
209 self.check("int a:2; char y;", 1, 4, 4)
210 self.check("int a:1; char b ; int c:1; char y;", 3, 4, 4)
211 self.check("int a:1; char b:8; int c:1; char y;", 3, 4, 4)
212 self.check("char a; int b:9; char y;", 3, 4, 4)
213 self.check("char a; short b:9; char y;", 4, 2, 6)
214 self.check("int a:2; char b:6; char y;", 1, 4, 4)
215 self.check("int a:2; char b:7; char y;", 2, 4, 4)
216 self.check("int a:2; short b:15; char c:2; char y;", 5, 4, 8)
217 self.check("int a:2; char b:1; char c:1; char y;", 1, 4, 4)
218
219 @pytest.mark.skipif("platform.machine().startswith(('arm', 'aarch64'))")
220 def test_bitfield_anonymous_no_align(self):
221 L = FFI().alignof("long long")
222 self.check("char y; int :1;", 0, 1, 2)
223 self.check("char x; int z:1; char y;", 2, 4, 4)
224 self.check("char x; int :1; char y;", 2, 1, 3)
225 self.check("char x; long long z:48; char y;", 7, L, 8)
226 self.check("char x; long long :48; char y;", 7, 1, 8)
227 self.check("char x; long long z:56; char y;", 8, L, 8 + L)
228 self.check("char x; long long :56; char y;", 8, 1, 9)
229 self.check("char x; long long z:57; char y;", L + 8, L, L + 8 + L)
230 self.check("char x; long long :57; char y;", L + 8, 1, L + 9)
231
232 @pytest.mark.skipif(
233 "not platform.machine().startswith(('arm', 'aarch64'))")
234 def test_bitfield_anonymous_align_arm(self):
235 L = FFI().alignof("long long")
236 self.check("char y; int :1;", 0, 4, 4)
237 self.check("char x; int z:1; char y;", 2, 4, 4)
238 self.check("char x; int :1; char y;", 2, 4, 4)
239 self.check("char x; long long z:48; char y;", 7, L, 8)
240 self.check("char x; long long :48; char y;", 7, 8, 8)
241 self.check("char x; long long z:56; char y;", 8, L, 8 + L)
242 self.check("char x; long long :56; char y;", 8, L, 8 + L)
243 self.check("char x; long long z:57; char y;", L + 8, L, L + 8 + L)
244 self.check("char x; long long :57; char y;", L + 8, L, L + 8 + L)
245
246 @pytest.mark.skipif("platform.machine().startswith(('arm', 'aarch64'))")
247 def test_bitfield_zero(self):
248 L = FFI().alignof("long long")
249 self.check("char y; int :0;", 0, 1, 4)
250 self.check("char x; int :0; char y;", 4, 1, 5)
251 self.check("char x; int :0; int :0; char y;", 4, 1, 5)
252 self.check("char x; long long :0; char y;", L, 1, L + 1)
253 self.check("short x, y; int :0; int :0;", 2, 2, 4)
254 self.check("char x; int :0; short b:1; char y;", 5, 2, 6)
255 self.check("int a:1; int :0; int b:1; char y;", 5, 4, 8)
256
257 @pytest.mark.skipif(
258 "not platform.machine().startswith(('arm', 'aarch64'))")
259 def test_bitfield_zero_arm(self):
260 L = FFI().alignof("long long")
261 self.check("char y; int :0;", 0, 4, 4)
262 self.check("char x; int :0; char y;", 4, 4, 8)
263 self.check("char x; int :0; int :0; char y;", 4, 4, 8)
264 self.check("char x; long long :0; char y;", L, 8, L + 8)
265 self.check("short x, y; int :0; int :0;", 2, 4, 4)
266 self.check("char x; int :0; short b:1; char y;", 5, 4, 8)
267 self.check("int a:1; int :0; int b:1; char y;", 5, 4, 8)
268
269 def test_error_cases(self):
270 ffi = FFI()
271 py.test.raises(TypeError,
272 'ffi.cdef("struct s1 { float x:1; };"); ffi.new("struct s1 *")')
273 py.test.raises(TypeError,
274 'ffi.cdef("struct s2 { char x:0; };"); ffi.new("struct s2 *")')
275 py.test.raises(TypeError,
276 'ffi.cdef("struct s3 { char x:9; };"); ffi.new("struct s3 *")')
277
278 def test_struct_with_typedef(self):
279 ffi = FFI()
280 ffi.cdef("typedef struct { float x; } foo_t;")
281 p = ffi.new("foo_t *", [5.2])
282 assert repr(p).startswith("<cdata 'foo_t *' ")
283
284 def test_struct_array_no_length(self):
285 ffi = FFI()
286 ffi.cdef("struct foo_s { int x; int a[]; };")
287 p = ffi.new("struct foo_s *", [100, [200, 300, 400]])
288 assert p.x == 100
289 assert ffi.typeof(p.a) is ffi.typeof("int[]")
290 assert len(p.a) == 3 # length recorded
291 assert p.a[0] == 200
292 assert p.a[1] == 300
293 assert p.a[2] == 400
294 assert list(p.a) == [200, 300, 400]
295 q = ffi.cast("struct foo_s *", p)
296 assert q.x == 100
297 assert ffi.typeof(q.a) is ffi.typeof("int *") # no length recorded
298 py.test.raises(TypeError, len, q.a)
299 assert q.a[0] == 200
300 assert q.a[1] == 300
301 assert q.a[2] == 400
302 py.test.raises(TypeError, list, q.a)
303
304 @pytest.mark.skipif("sys.platform != 'win32'")
305 def test_getwinerror(self):
306 ffi = FFI()
307 code, message = ffi.getwinerror(1155)
308 assert code == 1155
309 assert message == ("No application is associated with the "
310 "specified file for this operation")
311 ffi.cdef("void SetLastError(int);")
312 lib = ffi.dlopen("Kernel32.dll")
313 lib.SetLastError(2)
314 code, message = ffi.getwinerror()
315 assert code == 2
316 assert message == "The system cannot find the file specified"
317 code, message = ffi.getwinerror(-1)
318 assert code == 2
319 assert message == "The system cannot find the file specified"
320
321 def test_from_buffer(self):
322 import array
323 ffi = FFI()
324 a = array.array('H', [10000, 20000, 30000])
325 c = ffi.from_buffer(a)
326 assert ffi.typeof(c) is ffi.typeof("char[]")
327 ffi.cast("unsigned short *", c)[1] += 500
328 assert list(a) == [10000, 20500, 30000]
329
330 def test_memmove(self):
331 ffi = FFI()
332 p = ffi.new("short[]", [-1234, -2345, -3456, -4567, -5678])
333 ffi.memmove(p, p + 1, 4)
334 assert list(p) == [-2345, -3456, -3456, -4567, -5678]
335 p[2] = 999
336 ffi.memmove(p + 2, p, 6)
337 assert list(p) == [-2345, -3456, -2345, -3456, 999]
338 ffi.memmove(p + 4, ffi.new("char[]", b"\x71\x72"), 2)
339 if sys.byteorder == 'little':
340 assert list(p) == [-2345, -3456, -2345, -3456, 0x7271]
341 else:
342 assert list(p) == [-2345, -3456, -2345, -3456, 0x7172]
343
344 def test_memmove_buffer(self):
345 import array
346 ffi = FFI()
347 a = array.array('H', [10000, 20000, 30000])
348 p = ffi.new("short[]", 5)
349 ffi.memmove(p, a, 6)
350 assert list(p) == [10000, 20000, 30000, 0, 0]
351 ffi.memmove(p + 1, a, 6)
352 assert list(p) == [10000, 10000, 20000, 30000, 0]
353 b = array.array('h', [-1000, -2000, -3000])
354 ffi.memmove(b, a, 4)
355 assert b.tolist() == [10000, 20000, -3000]
356 assert a.tolist() == [10000, 20000, 30000]
357 p[0] = 999
358 p[1] = 998
359 p[2] = 997
360 p[3] = 996
361 p[4] = 995
362 ffi.memmove(b, p, 2)
363 assert b.tolist() == [999, 20000, -3000]
364 ffi.memmove(b, p + 2, 4)
365 assert b.tolist() == [997, 996, -3000]
366 p[2] = -p[2]
367 p[3] = -p[3]
368 ffi.memmove(b, p + 2, 6)
369 assert b.tolist() == [-997, -996, 995]
370
371 def test_memmove_readonly_readwrite(self):
372 ffi = FFI()
373 p = ffi.new("signed char[]", 5)
374 ffi.memmove(p, b"abcde", 3)
375 assert list(p) == [ord("a"), ord("b"), ord("c"), 0, 0]
376 ffi.memmove(p, bytearray(b"ABCDE"), 2)
377 assert list(p) == [ord("A"), ord("B"), ord("c"), 0, 0]
378 py.test.raises((TypeError, BufferError), ffi.memmove, b"abcde", p, 3)
379 ba = bytearray(b"xxxxx")
380 ffi.memmove(dest=ba, src=p, n=3)
381 assert ba == bytearray(b"ABcxx")
382
383 def test_all_primitives(self):
384 ffi = FFI()
385 for name in [
386 "char",
387 "short",
388 "int",
389 "long",
390 "long long",
391 "signed char",
392 "unsigned char",
393 "unsigned short",
394 "unsigned int",
395 "unsigned long",
396 "unsigned long long",
397 "float",
398 "double",
399 "long double",
400 "wchar_t",
401 "char16_t",
402 "char32_t",
403 "_Bool",
404 "int8_t",
405 "uint8_t",
406 "int16_t",
407 "uint16_t",
408 "int32_t",
409 "uint32_t",
410 "int64_t",
411 "uint64_t",
412 "int_least8_t",
413 "uint_least8_t",
414 "int_least16_t",
415 "uint_least16_t",
416 "int_least32_t",
417 "uint_least32_t",
418 "int_least64_t",
419 "uint_least64_t",
420 "int_fast8_t",
421 "uint_fast8_t",
422 "int_fast16_t",
423 "uint_fast16_t",
424 "int_fast32_t",
425 "uint_fast32_t",
426 "int_fast64_t",
427 "uint_fast64_t",
428 "intptr_t",
429 "uintptr_t",
430 "intmax_t",
431 "uintmax_t",
432 "ptrdiff_t",
433 "size_t",
434 "ssize_t",
435 ]:
436 x = ffi.sizeof(name)
437 assert 1 <= x <= 16
438
439 def test_ffi_def_extern(self):
440 ffi = FFI()
441 py.test.raises(ValueError, ffi.def_extern)
442
443 def test_introspect_typedef(self):
444 ffi = FFI()
445 ffi.cdef("typedef int foo_t;")
446 assert ffi.list_types() == (['foo_t'], [], [])
447 assert ffi.typeof('foo_t').kind == 'primitive'
448 assert ffi.typeof('foo_t').cname == 'int'
449 #
450 ffi.cdef("typedef signed char a_t, c_t, g_t, b_t;")
451 assert ffi.list_types() == (['a_t', 'b_t', 'c_t', 'foo_t', 'g_t'],
452 [], [])
453
454 def test_introspect_struct(self):
455 ffi = FFI()
456 ffi.cdef("struct foo_s { int a; };")
457 assert ffi.list_types() == ([], ['foo_s'], [])
458 assert ffi.typeof('struct foo_s').kind == 'struct'
459 assert ffi.typeof('struct foo_s').cname == 'struct foo_s'
460
461 def test_introspect_union(self):
462 ffi = FFI()
463 ffi.cdef("union foo_s { int a; };")
464 assert ffi.list_types() == ([], [], ['foo_s'])
465 assert ffi.typeof('union foo_s').kind == 'union'
466 assert ffi.typeof('union foo_s').cname == 'union foo_s'
467
468 def test_introspect_struct_and_typedef(self):
469 ffi = FFI()
470 ffi.cdef("typedef struct { int a; } foo_t;")
471 assert ffi.list_types() == (['foo_t'], [], [])
472 assert ffi.typeof('foo_t').kind == 'struct'
473 assert ffi.typeof('foo_t').cname == 'foo_t'
474
475 def test_introspect_included_type(self):
476 ffi1 = FFI()
477 ffi2 = FFI()
478 ffi1.cdef("typedef signed char schar_t; struct sint_t { int x; };")
479 ffi2.include(ffi1)
480 assert ffi1.list_types() == ffi2.list_types() == (
481 ['schar_t'], ['sint_t'], [])
482
483 def test_introspect_order(self):
484 ffi = FFI()
485 ffi.cdef("union CFFIaaa { int a; }; typedef struct CFFIccc { int a; } CFFIb;")
486 ffi.cdef("union CFFIg { int a; }; typedef struct CFFIcc { int a; } CFFIbbb;")
487 ffi.cdef("union CFFIaa { int a; }; typedef struct CFFIa { int a; } CFFIbb;")
488 assert ffi.list_types() == (['CFFIb', 'CFFIbb', 'CFFIbbb'],
489 ['CFFIa', 'CFFIcc', 'CFFIccc'],
490 ['CFFIaa', 'CFFIaaa', 'CFFIg'])
491
492 def test_unpack(self):
493 ffi = FFI()
494 p = ffi.new("char[]", b"abc\x00def")
495 assert ffi.unpack(p+1, 7) == b"bc\x00def\x00"
496 p = ffi.new("int[]", [-123456789])
497 assert ffi.unpack(p, 1) == [-123456789]
498
499 def test_negative_array_size(self):
500 ffi = FFI()
501 py.test.raises(ValueError, ffi.cast, "int[-5]", 0)
502
503 def test_cannot_instantiate_manually(self):
504 ffi = FFI()
505 ct = type(ffi.typeof("void *"))
506 py.test.raises(TypeError, ct)
507 py.test.raises(TypeError, ct, ffi.NULL)
508 for cd in [type(ffi.cast("void *", 0)),
509 type(ffi.new("char[]", 3)),
510 type(ffi.gc(ffi.NULL, lambda x: None))]:
511 py.test.raises(TypeError, cd)
512 py.test.raises(TypeError, cd, ffi.NULL)
513 py.test.raises(TypeError, cd, ffi.typeof("void *"))
514
515 def test_explicitly_defined_char16_t(self):
516 ffi = FFI()
517 ffi.cdef("typedef uint16_t char16_t;")
518 x = ffi.cast("char16_t", 1234)
519 assert ffi.typeof(x) is ffi.typeof("uint16_t")
520
521 def test_char16_t(self):
522 ffi = FFI()
523 x = ffi.new("char16_t[]", 5)
524 assert len(x) == 5 and ffi.sizeof(x) == 10
525 x[2] = u+'\u1324'
526 assert x[2] == u+'\u1324'
527 y = ffi.new("char16_t[]", u+'\u1234\u5678')
528 assert len(y) == 3
529 assert list(y) == [u+'\u1234', u+'\u5678', u+'\x00']
530 assert ffi.string(y) == u+'\u1234\u5678'
531 z = ffi.new("char16_t[]", u+'\U00012345')
532 assert len(z) == 3
533 assert list(z) == [u+'\ud808', u+'\udf45', u+'\x00']
534 assert ffi.string(z) == u+'\U00012345'
535
536 def test_char32_t(self):
537 ffi = FFI()
538 x = ffi.new("char32_t[]", 5)
539 assert len(x) == 5 and ffi.sizeof(x) == 20
540 x[3] = u+'\U00013245'
541 assert x[3] == u+'\U00013245'
542 y = ffi.new("char32_t[]", u+'\u1234\u5678')
543 assert len(y) == 3
544 assert list(y) == [u+'\u1234', u+'\u5678', u+'\x00']
545 py_uni = u+'\U00012345'
546 z = ffi.new("char32_t[]", py_uni)
547 assert len(z) == 2
548 assert list(z) == [py_uni, u+'\x00'] # maybe a 2-unichars string
549 assert ffi.string(z) == py_uni
550 if len(py_uni) == 1: # 4-bytes unicodes in Python
551 s = ffi.new("char32_t[]", u+'\ud808\udf00')
552 assert len(s) == 3
553 assert list(s) == [u+'\ud808', u+'\udf00', u+'\x00']
+0
-520
pypy/module/test_lib_pypy/cffi_tests/cffi0/test_function.py less more
0 # Generated by pypy/tool/import_cffi.py
1 import py
2 from cffi import FFI, CDefError
3 import math, os, sys
4 import ctypes.util
5 from cffi.backend_ctypes import CTypesBackend
6 from pypy.module.test_lib_pypy.cffi_tests.udir import udir
7 from pypy.module.test_lib_pypy.cffi_tests.support import FdWriteCapture
8 from .backend_tests import needs_dlopen_none
9
10 try:
11 from StringIO import StringIO
12 except ImportError:
13 from io import StringIO
14
15
16 lib_m = 'm'
17 if sys.platform == 'win32':
18 #there is a small chance this fails on Mingw via environ $CC
19 import distutils.ccompiler
20 if distutils.ccompiler.get_default_compiler() == 'msvc':
21 lib_m = 'msvcrt'
22
23 class TestFunction(object):
24 Backend = CTypesBackend
25
26 def test_sin(self):
27 ffi = FFI(backend=self.Backend())
28 ffi.cdef("""
29 double sin(double x);
30 """)
31 m = ffi.dlopen(lib_m)
32 x = m.sin(1.23)
33 assert x == math.sin(1.23)
34
35 def test_sinf(self):
36 if sys.platform == 'win32':
37 py.test.skip("no sinf found in the Windows stdlib")
38 ffi = FFI(backend=self.Backend())
39 ffi.cdef("""
40 float sinf(float x);
41 """)
42 m = ffi.dlopen(lib_m)
43 x = m.sinf(1.23)
44 assert type(x) is float
45 assert x != math.sin(1.23) # rounding effects
46 assert abs(x - math.sin(1.23)) < 1E-6
47
48 def test_sin_no_return_value(self):
49 # check that 'void'-returning functions work too
50 ffi = FFI(backend=self.Backend())
51 ffi.cdef("""
52 void sin(double x);
53 """)
54 m = ffi.dlopen(lib_m)
55 x = m.sin(1.23)
56 assert x is None
57
58 def test_dlopen_filename(self):
59 path = ctypes.util.find_library(lib_m)
60 if not path:
61 py.test.skip("%s not found" % lib_m)
62 ffi = FFI(backend=self.Backend())
63 ffi.cdef("""
64 double cos(double x);
65 """)
66 m = ffi.dlopen(path)
67 x = m.cos(1.23)
68 assert x == math.cos(1.23)
69
70 m = ffi.dlopen(os.path.basename(path))
71 x = m.cos(1.23)
72 assert x == math.cos(1.23)
73
74 def test_dlopen_flags(self):
75 ffi = FFI(backend=self.Backend())
76 ffi.cdef("""
77 double cos(double x);
78 """)
79 m = ffi.dlopen(lib_m, ffi.RTLD_LAZY | ffi.RTLD_LOCAL)
80 x = m.cos(1.23)
81 assert x == math.cos(1.23)
82
83 def test_dlopen_constant(self):
84 ffi = FFI(backend=self.Backend())
85 ffi.cdef("""
86 #define FOOBAR 42
87 static const float baz = 42.5; /* not visible */
88 double sin(double x);
89 """)
90 m = ffi.dlopen(lib_m)
91 assert m.FOOBAR == 42
92 py.test.raises(NotImplementedError, "m.baz")
93
94 def test_tlsalloc(self):
95 if sys.platform != 'win32':
96 py.test.skip("win32 only")
97 if self.Backend is CTypesBackend:
98 py.test.skip("ctypes complains on wrong calling conv")
99 ffi = FFI(backend=self.Backend())
100 ffi.cdef("long TlsAlloc(void); int TlsFree(long);")
101 lib = ffi.dlopen('KERNEL32.DLL')
102 x = lib.TlsAlloc()
103 assert x != 0
104 y = lib.TlsFree(x)
105 assert y != 0
106
107 def test_fputs(self):
108 if not sys.platform.startswith('linux'):
109 py.test.skip("probably no symbol 'stderr' in the lib")
110 ffi = FFI(backend=self.Backend())
111 ffi.cdef("""
112 int fputs(const char *, void *);
113 void *stderr;
114 """)
115 needs_dlopen_none()
116 ffi.C = ffi.dlopen(None)
117 ffi.C.fputs # fetch before capturing, for easier debugging
118 with FdWriteCapture() as fd:
119 ffi.C.fputs(b"hello\n", ffi.C.stderr)
120 ffi.C.fputs(b" world\n", ffi.C.stderr)
121 res = fd.getvalue()
122 assert res == b'hello\n world\n'
123
124 def test_fputs_without_const(self):
125 if not sys.platform.startswith('linux'):
126 py.test.skip("probably no symbol 'stderr' in the lib")
127 ffi = FFI(backend=self.Backend())
128 ffi.cdef("""
129 int fputs(char *, void *);
130 void *stderr;
131 """)
132 needs_dlopen_none()
133 ffi.C = ffi.dlopen(None)
134 ffi.C.fputs # fetch before capturing, for easier debugging
135 with FdWriteCapture() as fd:
136 ffi.C.fputs(b"hello\n", ffi.C.stderr)
137 ffi.C.fputs(b" world\n", ffi.C.stderr)
138 res = fd.getvalue()
139 assert res == b'hello\n world\n'
140
141 def test_vararg(self):
142 if not sys.platform.startswith('linux'):
143 py.test.skip("probably no symbol 'stderr' in the lib")
144 ffi = FFI(backend=self.Backend())
145 ffi.cdef("""
146 int fprintf(void *, const char *format, ...);
147 void *stderr;
148 """)
149 needs_dlopen_none()
150 ffi.C = ffi.dlopen(None)
151 with FdWriteCapture() as fd:
152 ffi.C.fprintf(ffi.C.stderr, b"hello with no arguments\n")
153 ffi.C.fprintf(ffi.C.stderr,
154 b"hello, %s!\n", ffi.new("char[]", b"world"))
155 ffi.C.fprintf(ffi.C.stderr,
156 ffi.new("char[]", b"hello, %s!\n"),
157 ffi.new("char[]", b"world2"))
158 ffi.C.fprintf(ffi.C.stderr,
159 b"hello int %d long %ld long long %lld\n",
160 ffi.cast("int", 42),
161 ffi.cast("long", 84),
162 ffi.cast("long long", 168))
163 ffi.C.fprintf(ffi.C.stderr, b"hello %p\n", ffi.NULL)
164 res = fd.getvalue()
165 assert res == (b"hello with no arguments\n"
166 b"hello, world!\n"
167 b"hello, world2!\n"
168 b"hello int 42 long 84 long long 168\n"
169 b"hello (nil)\n")
170
171 def test_must_specify_type_of_vararg(self):
172 ffi = FFI(backend=self.Backend())
173 ffi.cdef("""
174 int printf(const char *format, ...);
175 """)
176 needs_dlopen_none()
177 ffi.C = ffi.dlopen(None)
178 e = py.test.raises(TypeError, ffi.C.printf, b"hello %d\n", 42)
179 assert str(e.value) == ("argument 2 passed in the variadic part "
180 "needs to be a cdata object (got int)")
181
182 def test_function_has_a_c_type(self):
183 ffi = FFI(backend=self.Backend())
184 ffi.cdef("""
185 int puts(const char *);
186 """)
187 needs_dlopen_none()
188 ffi.C = ffi.dlopen(None)
189 fptr = ffi.C.puts
190 assert ffi.typeof(fptr) == ffi.typeof("int(*)(const char*)")
191 if self.Backend is CTypesBackend:
192 assert repr(fptr).startswith("<cdata 'int puts(char *)' 0x")
193
194 def test_function_pointer(self):
195 ffi = FFI(backend=self.Backend())
196 def cb(charp):
197 assert repr(charp).startswith("<cdata 'char *' 0x")
198 return 42
199 fptr = ffi.callback("int(*)(const char *txt)", cb)
200 assert fptr != ffi.callback("int(*)(const char *)", cb)
201 assert repr(fptr) == "<cdata 'int(*)(char *)' calling %r>" % (cb,)
202 res = fptr(b"Hello")
203 assert res == 42
204 #
205 if not sys.platform.startswith('linux'):
206 py.test.skip("probably no symbol 'stderr' in the lib")
207 ffi.cdef("""
208 int fputs(const char *, void *);
209 void *stderr;
210 """)
211 needs_dlopen_none()
212 ffi.C = ffi.dlopen(None)
213 fptr = ffi.cast("int(*)(const char *txt, void *)", ffi.C.fputs)
214 assert fptr == ffi.C.fputs
215 assert repr(fptr).startswith("<cdata 'int(*)(char *, void *)' 0x")
216 with FdWriteCapture() as fd:
217 fptr(b"world\n", ffi.C.stderr)
218 res = fd.getvalue()
219 assert res == b'world\n'
220
221 def test_callback_returning_void(self):
222 ffi = FFI(backend=self.Backend())
223 for returnvalue in [None, 42]:
224 def cb():
225 return returnvalue
226 fptr = ffi.callback("void(*)(void)", cb)
227 old_stderr = sys.stderr
228 try:
229 sys.stderr = StringIO()
230 returned = fptr()
231 printed = sys.stderr.getvalue()
232 finally:
233 sys.stderr = old_stderr
234 assert returned is None
235 if returnvalue is None:
236 assert printed == ''
237 else:
238 assert "None" in printed
239
240 def test_passing_array(self):
241 ffi = FFI(backend=self.Backend())
242 ffi.cdef("""
243 int strlen(char[]);
244 """)
245 needs_dlopen_none()
246 ffi.C = ffi.dlopen(None)
247 p = ffi.new("char[]", b"hello")
248 res = ffi.C.strlen(p)
249 assert res == 5
250
251 def test_write_variable(self):
252 if not sys.platform.startswith('linux'):
253 py.test.skip("probably no symbol 'stdout' in the lib")
254 ffi = FFI(backend=self.Backend())
255 ffi.cdef("""
256 void *stdout;
257 """)
258 needs_dlopen_none()
259 C = ffi.dlopen(None)
260 pout = C.stdout
261 C.stdout = ffi.NULL
262 assert C.stdout == ffi.NULL
263 C.stdout = pout
264 assert C.stdout == pout
265
266 def test_strchr(self):
267 ffi = FFI(backend=self.Backend())
268 ffi.cdef("""
269 char *strchr(const char *s, int c);
270 """)
271 needs_dlopen_none()
272 ffi.C = ffi.dlopen(None)
273 p = ffi.new("char[]", b"hello world!")
274 q = ffi.C.strchr(p, ord('w'))
275 assert ffi.string(q) == b"world!"
276
277 def test_function_with_struct_argument(self):
278 if sys.platform == 'win32':
279 py.test.skip("no 'inet_ntoa'")
280 if (self.Backend is CTypesBackend and
281 '__pypy__' in sys.builtin_module_names):
282 py.test.skip("ctypes limitation on pypy")
283 ffi = FFI(backend=self.Backend())
284 ffi.cdef("""
285 struct in_addr { unsigned int s_addr; };
286 char *inet_ntoa(struct in_addr in);
287 """)
288 needs_dlopen_none()
289 ffi.C = ffi.dlopen(None)
290 ina = ffi.new("struct in_addr *", [0x04040404])
291 a = ffi.C.inet_ntoa(ina[0])
292 assert ffi.string(a) == b'4.4.4.4'
293
294 def test_function_typedef(self):
295 ffi = FFI(backend=self.Backend())
296 ffi.cdef("""
297 typedef double func_t(double);
298 func_t sin;
299 """)
300 m = ffi.dlopen(lib_m)
301 x = m.sin(1.23)
302 assert x == math.sin(1.23)
303
304 def test_fputs_custom_FILE(self):
305 if self.Backend is CTypesBackend:
306 py.test.skip("FILE not supported with the ctypes backend")
307 filename = str(udir.join('fputs_custom_FILE'))
308 ffi = FFI(backend=self.Backend())
309 ffi.cdef("int fputs(const char *, FILE *);")
310 needs_dlopen_none()
311 C = ffi.dlopen(None)
312 with open(filename, 'wb') as f:
313 f.write(b'[')
314 C.fputs(b"hello from custom file", f)
315 f.write(b'][')
316 C.fputs(b"some more output", f)
317 f.write(b']')
318 with open(filename, 'rb') as f:
319 res = f.read()
320 assert res == b'[hello from custom file][some more output]'
321
322 def test_constants_on_lib(self):
323 ffi = FFI(backend=self.Backend())
324 ffi.cdef("""enum foo_e { AA, BB, CC=5, DD };
325 typedef enum { EE=-5, FF } some_enum_t;""")
326 needs_dlopen_none()
327 lib = ffi.dlopen(None)
328 assert lib.AA == 0
329 assert lib.BB == 1
330 assert lib.CC == 5
331 assert lib.DD == 6
332 assert lib.EE == -5
333 assert lib.FF == -4
334
335 def test_void_star_accepts_string(self):
336 ffi = FFI(backend=self.Backend())
337 ffi.cdef("""int strlen(const void *);""")
338 needs_dlopen_none()
339 lib = ffi.dlopen(None)
340 res = lib.strlen(b"hello")
341 assert res == 5
342
343 def test_signed_char_star_accepts_string(self):
344 if self.Backend is CTypesBackend:
345 py.test.skip("not supported by the ctypes backend")
346 ffi = FFI(backend=self.Backend())
347 ffi.cdef("""int strlen(signed char *);""")
348 needs_dlopen_none()
349 lib = ffi.dlopen(None)
350 res = lib.strlen(b"hello")
351 assert res == 5
352
353 def test_unsigned_char_star_accepts_string(self):
354 if self.Backend is CTypesBackend:
355 py.test.skip("not supported by the ctypes backend")
356 ffi = FFI(backend=self.Backend())
357 ffi.cdef("""int strlen(unsigned char *);""")
358 needs_dlopen_none()
359 lib = ffi.dlopen(None)
360 res = lib.strlen(b"hello")
361 assert res == 5
362
363 def test_missing_function(self):
364 ffi = FFI(backend=self.Backend())
365 ffi.cdef("""
366 int nonexistent();
367 """)
368 m = ffi.dlopen(lib_m)
369 assert not hasattr(m, 'nonexistent')
370
371 def test_wraps_from_stdlib(self):
372 import functools
373 ffi = FFI(backend=self.Backend())
374 ffi.cdef("""
375 double sin(double x);
376 """)
377 def my_decorator(f):
378 @functools.wraps(f)
379 def wrapper(*args):
380 return f(*args) + 100
381 return wrapper
382 m = ffi.dlopen(lib_m)
383 sin100 = my_decorator(m.sin)
384 x = sin100(1.23)
385 assert x == math.sin(1.23) + 100
386
387 def test_free_callback_cycle(self):
388 if self.Backend is CTypesBackend:
389 py.test.skip("seems to fail with the ctypes backend on windows")
390 import weakref
391 def make_callback(data):
392 container = [data]
393 callback = ffi.callback('int()', lambda: len(container))
394 container.append(callback)
395 # Ref cycle: callback -> lambda (closure) -> container -> callback
396 return callback
397
398 class Data(object):
399 pass
400 ffi = FFI(backend=self.Backend())
401 data = Data()
402 callback = make_callback(data)
403 wr = weakref.ref(data)
404 del callback, data
405 for i in range(3):
406 if wr() is not None:
407 import gc; gc.collect()
408 assert wr() is None # 'data' does not leak
409
410 def test_windows_stdcall(self):
411 if sys.platform != 'win32':
412 py.test.skip("Windows-only test")
413 if self.Backend is CTypesBackend:
414 py.test.skip("not with the ctypes backend")
415 ffi = FFI(backend=self.Backend())
416 ffi.cdef("""
417 BOOL QueryPerformanceFrequency(LONGLONG *lpFrequency);
418 """)
419 m = ffi.dlopen("Kernel32.dll")
420 p_freq = ffi.new("LONGLONG *")
421 res = m.QueryPerformanceFrequency(p_freq)
422 assert res != 0
423 assert p_freq[0] != 0
424
425 def test_explicit_cdecl_stdcall(self):
426 if sys.platform != 'win32':
427 py.test.skip("Windows-only test")
428 if self.Backend is CTypesBackend:
429 py.test.skip("not with the ctypes backend")
430 win64 = (sys.maxsize > 2**32)
431 #
432 ffi = FFI(backend=self.Backend())
433 ffi.cdef("""
434 BOOL QueryPerformanceFrequency(LONGLONG *lpFrequency);
435 """)
436 m = ffi.dlopen("Kernel32.dll")
437 tp = ffi.typeof(m.QueryPerformanceFrequency)
438 assert str(tp) == "<ctype 'int(*)(long long *)'>"
439 #
440 ffi = FFI(backend=self.Backend())
441 ffi.cdef("""
442 BOOL __cdecl QueryPerformanceFrequency(LONGLONG *lpFrequency);
443 """)
444 m = ffi.dlopen("Kernel32.dll")
445 tpc = ffi.typeof(m.QueryPerformanceFrequency)
446 assert tpc is tp
447 #
448 ffi = FFI(backend=self.Backend())
449 ffi.cdef("""
450 BOOL WINAPI QueryPerformanceFrequency(LONGLONG *lpFrequency);
451 """)
452 m = ffi.dlopen("Kernel32.dll")
453 tps = ffi.typeof(m.QueryPerformanceFrequency)
454 if win64:
455 assert tps is tpc
456 else:
457 assert tps is not tpc
458 assert str(tps) == "<ctype 'int(__stdcall *)(long long *)'>"
459 #
460 ffi = FFI(backend=self.Backend())
461 ffi.cdef("typedef int (__cdecl *fnc_t)(int);")
462 ffi.cdef("typedef int (__stdcall *fns_t)(int);")
463 tpc = ffi.typeof("fnc_t")
464 tps = ffi.typeof("fns_t")
465 assert str(tpc) == "<ctype 'int(*)(int)'>"
466 if win64:
467 assert tps is tpc
468 else:
469 assert str(tps) == "<ctype 'int(__stdcall *)(int)'>"
470 #
471 fnc = ffi.cast("fnc_t", 0)
472 fns = ffi.cast("fns_t", 0)
473 ffi.new("fnc_t[]", [fnc])
474 if not win64:
475 py.test.raises(TypeError, ffi.new, "fnc_t[]", [fns])
476 py.test.raises(TypeError, ffi.new, "fns_t[]", [fnc])
477 ffi.new("fns_t[]", [fns])
478
479 def test_stdcall_only_on_windows(self):
480 ffi = FFI(backend=self.Backend())
481 ffi.cdef("double __stdcall sin(double x);") # stdcall ignored
482 m = ffi.dlopen(lib_m)
483 if (sys.platform == 'win32' and sys.maxsize < 2**32 and
484 self.Backend is not CTypesBackend):
485 assert "double(__stdcall *)(double)" in str(ffi.typeof(m.sin))
486 else:
487 assert "double(*)(double)" in str(ffi.typeof(m.sin))
488 x = m.sin(1.23)
489 assert x == math.sin(1.23)
490
491 def test_dir_on_dlopen_lib(self):
492 ffi = FFI(backend=self.Backend())
493 ffi.cdef("""
494 typedef enum { MYE1, MYE2 } myenum_t;
495 double myfunc(double);
496 double myvar;
497 const double myconst;
498 #define MYFOO 42
499 """)
500 m = ffi.dlopen(lib_m)
501 assert dir(m) == ['MYE1', 'MYE2', 'MYFOO', 'myconst', 'myfunc', 'myvar']
502
503 def test_dlclose(self):
504 if self.Backend is CTypesBackend:
505 py.test.skip("not with the ctypes backend")
506 ffi = FFI(backend=self.Backend())
507 ffi.cdef("int foobar(void); int foobaz;")
508 lib = ffi.dlopen(lib_m)
509 ffi.dlclose(lib)
510 e = py.test.raises(ValueError, getattr, lib, 'foobar')
511 assert str(e.value).startswith("library '")
512 assert str(e.value).endswith("' has already been closed")
513 e = py.test.raises(ValueError, getattr, lib, 'foobaz')
514 assert str(e.value).startswith("library '")
515 assert str(e.value).endswith("' has already been closed")
516 e = py.test.raises(ValueError, setattr, lib, 'foobaz', 42)
517 assert str(e.value).startswith("library '")
518 assert str(e.value).endswith("' has already been closed")
519 ffi.dlclose(lib) # does not raise
+0
-112
pypy/module/test_lib_pypy/cffi_tests/cffi0/test_model.py less more
0 # Generated by pypy/tool/import_cffi.py
1 from cffi.model import *
2
3
4 def test_void_type():
5 assert void_type.get_c_name() == "void"
6 assert void_type.get_c_name("foo") == "void foo"
7 assert void_type.get_c_name("*foo") == "void *foo"
8
9 def test_primitive_type():
10 int_type = PrimitiveType("int")
11 assert int_type.get_c_name() == "int"
12 assert int_type.get_c_name("foo") == "int foo"
13 assert int_type.get_c_name("*foo") == "int *foo"
14 assert int_type.get_c_name("[5]") == "int[5]"
15
16 def test_raw_function_type():
17 int_type = PrimitiveType("int")
18 fn_type = RawFunctionType([], int_type, False)
19 assert fn_type.get_c_name() == "int()(void)"
20 assert fn_type.get_c_name("*") == "int( *)(void)"
21 assert fn_type.get_c_name("*foo") == "int( *foo)(void)"
22 fn_type = RawFunctionType([int_type], int_type, False)
23 assert fn_type.get_c_name() == "int()(int)"
24 fn_type = RawFunctionType([int_type] * 2, int_type, False)
25 assert fn_type.get_c_name() == "int()(int, int)"
26 #
27 fn_type = RawFunctionType([int_type], int_type, True)
28 assert fn_type.get_c_name() == "int()(int, ...)"
29 assert fn_type.get_c_name("*foo") == "int( *foo)(int, ...)"
30 #
31 res_type = FunctionPtrType([int_type], int_type, True)
32 fn_type = RawFunctionType([int_type], res_type, True)
33 assert fn_type.get_c_name("x") == "int(*( x)(int, ...))(int, ...)"
34
35 def test_function_ptr_type():
36 int_type = PrimitiveType("int")
37 fn_type = FunctionPtrType([], int_type, False)
38 assert fn_type.get_c_name() == "int(*)(void)"
39 assert fn_type.get_c_name("*") == "int(* *)(void)"
40 assert fn_type.get_c_name("*foo") == "int(* *foo)(void)"
41 fn_type = FunctionPtrType([int_type], int_type, False)
42 assert fn_type.get_c_name() == "int(*)(int)"
43 fn_type = FunctionPtrType([int_type] * 2, int_type, False)
44 assert fn_type.get_c_name() == "int(*)(int, int)"
45 #
46 fn_type = FunctionPtrType([int_type], int_type, True)
47 assert fn_type.get_c_name() == "int(*)(int, ...)"
48
49 def test_pointer_type():
50 ptr_type = PointerType(PrimitiveType("int"))
51 assert ptr_type.get_c_name("x") == "int * x"
52
53 def test_const_pointer_type():
54 ptr_type = ConstPointerType(PrimitiveType("int"))
55 assert ptr_type.get_c_name("x") == "int const * x"
56 ptr_type = ConstPointerType(ArrayType(PrimitiveType("int"), 5))
57 assert ptr_type.get_c_name("") == "int(const *)[5]"
58 assert ptr_type.get_c_name("*x") == "int(const * *x)[5]"
59
60 def test_qual_pointer_type():
61 ptr_type = PointerType(PrimitiveType("long long"), Q_RESTRICT)
62 assert ptr_type.get_c_name("") == "long long __restrict *"
63 assert const_voidp_type.get_c_name("") == "void const *"
64
65 def test_unknown_pointer_type():
66 ptr_type = unknown_ptr_type("foo_p")
67 assert ptr_type.get_c_name("") == "foo_p"
68 assert ptr_type.get_c_name("x") == "foo_p x"
69
70 def test_unknown_type():
71 u_type = unknown_type("foo_t")
72 assert u_type.get_c_name("") == "foo_t"
73 assert u_type.get_c_name("x") == "foo_t x"
74
75 def test_array_type():
76 a_type = ArrayType(PrimitiveType("int"), None)
77 assert a_type.get_c_name("") == "int[]"
78 assert a_type.get_c_name("x") == "int x[]"
79 assert a_type.get_c_name("*x") == "int(*x)[]"
80 assert a_type.get_c_name(" *x") == "int(*x)[]"
81 assert a_type.get_c_name("[5]") == "int[5][]"
82 a_type = ArrayType(unknown_type("foo_t"), 5)
83 assert a_type.get_c_name("") == "foo_t[5]"
84 assert a_type.get_c_name("x") == "foo_t x[5]"
85 assert a_type.get_c_name("*x") == "foo_t(*x)[5]"
86 a_type = ArrayType(unknown_ptr_type("foo_p"), None)
87 assert a_type.get_c_name("") == "foo_p[]"
88 assert a_type.get_c_name("x") == "foo_p x[]"
89 assert a_type.get_c_name("*x") == "foo_p(*x)[]"
90 a_type = ArrayType(ConstPointerType(PrimitiveType("int")), None)
91 assert a_type.get_c_name("") == "int const *[]"
92 assert a_type.get_c_name("x") == "int const * x[]"
93 assert a_type.get_c_name("*x") == "int const *(*x)[]"
94 fn_type = FunctionPtrType([], PrimitiveType("int"), False)
95 a_type = ArrayType(fn_type, 5)
96 assert a_type.get_c_name("") == "int(*[5])(void)"
97 assert a_type.get_c_name("x") == "int(* x[5])(void)"
98 assert a_type.get_c_name("*x") == "int(*(*x)[5])(void)"
99
100 def test_struct_type():
101 struct_type = StructType("foo_s", None, None, None)
102 assert struct_type.get_c_name() == "struct foo_s"
103 assert struct_type.get_c_name("*x") == "struct foo_s *x"
104
105 def test_union_type():
106 union_type = UnionType("foo_s", None, None, None)
107 assert union_type.get_c_name() == "union foo_s"
108
109 def test_enum_type():
110 enum_type = EnumType("foo_e", [], [])
111 assert enum_type.get_c_name() == "enum foo_e"
+0
-333
pypy/module/test_lib_pypy/cffi_tests/cffi0/test_ownlib.py less more
0 # Generated by pypy/tool/import_cffi.py
1 import py, sys
2 import subprocess, weakref
3 from cffi import FFI
4 from cffi.backend_ctypes import CTypesBackend
5 from pypy.module.test_lib_pypy.cffi_tests.support import u
6
7
8 SOURCE = """\
9 #include <errno.h>
10
11 #ifdef _WIN32
12 #define EXPORT __declspec(dllexport)
13 #else
14 #define EXPORT
15 #endif
16
17 EXPORT int test_getting_errno(void) {
18 errno = 123;
19 return -1;
20 }
21
22 EXPORT int test_setting_errno(void) {
23 return errno;
24 };
25
26 typedef struct {
27 long x;
28 long y;
29 } POINT;
30
31 typedef struct {
32 long left;
33 long top;
34 long right;
35 long bottom;
36 } RECT;
37
38
39 EXPORT int PointInRect(RECT *prc, POINT pt)
40 {
41 if (pt.x < prc->left)
42 return 0;
43 if (pt.x > prc->right)
44 return 0;
45 if (pt.y < prc->top)
46 return 0;
47 if (pt.y > prc->bottom)
48 return 0;
49 return 1;
50 };
51
52 EXPORT long left = 10;
53 EXPORT long top = 20;
54 EXPORT long right = 30;
55 EXPORT long bottom = 40;
56
57 EXPORT RECT ReturnRect(int i, RECT ar, RECT* br, POINT cp, RECT dr,
58 RECT *er, POINT fp, RECT gr)
59 {
60 /*Check input */
61 if (ar.left + br->left + dr.left + er->left + gr.left != left * 5)
62 {
63 ar.left = 100;
64 return ar;
65 }
66 if (ar.right + br->right + dr.right + er->right + gr.right != right * 5)
67 {
68 ar.right = 100;
69 return ar;
70 }
71 if (cp.x != fp.x)
72 {
73 ar.left = -100;
74 }
75 if (cp.y != fp.y)
76 {
77 ar.left = -200;
78 }
79 switch(i)
80 {
81 case 0:
82 return ar;
83 break;
84 case 1:
85 return dr;
86 break;
87 case 2:
88 return gr;
89 break;
90
91 }
92 return ar;
93 }
94
95 EXPORT int my_array[7] = {0, 1, 2, 3, 4, 5, 6};
96
97 EXPORT unsigned short foo_2bytes(unsigned short a)
98 {
99 return (unsigned short)(a + 42);
100 }
101 EXPORT unsigned int foo_4bytes(unsigned int a)
102 {
103 return (unsigned int)(a + 42);
104 }
105 """
106
107 class TestOwnLib(object):
108 Backend = CTypesBackend
109
110 def setup_class(cls):
111 cls.module = None
112 from pypy.module.test_lib_pypy.cffi_tests.udir import udir
113 udir.join('testownlib.c').write(SOURCE)
114 if sys.platform == 'win32':
115 import os
116 # did we already build it?
117 if cls.Backend is CTypesBackend:
118 dll_path = str(udir) + '\\testownlib1.dll' # only ascii for the ctypes backend
119 else:
120 dll_path = str(udir) + '\\' + (u+'testownlib\u03be.dll') # non-ascii char
121 if os.path.exists(dll_path):
122 cls.module = dll_path
123 return
124 # try (not too hard) to find the version used to compile this python
125 # no mingw
126 from distutils.msvc9compiler import get_build_version
127 version = get_build_version()
128 toolskey = "VS%0.f0COMNTOOLS" % version
129 toolsdir = os.environ.get(toolskey, None)
130 if toolsdir is None:
131 return
132 productdir = os.path.join(toolsdir, os.pardir, os.pardir, "VC")
133 productdir = os.path.abspath(productdir)
134 vcvarsall = os.path.join(productdir, "vcvarsall.bat")
135 # 64?
136 arch = 'x86'
137 if sys.maxsize > 2**32:
138 arch = 'amd64'
139 if os.path.isfile(vcvarsall):
140 cmd = '"%s" %s' % (vcvarsall, arch) + ' & cl.exe testownlib.c ' \
141 ' /LD /Fetestownlib.dll'
142 subprocess.check_call(cmd, cwd = str(udir), shell=True)
143 os.rename(str(udir) + '\\testownlib.dll', dll_path)
144 cls.module = dll_path
145 else:
146 subprocess.check_call(
147 'cc testownlib.c -shared -fPIC -o testownlib.so',
148 cwd=str(udir), shell=True)
149 cls.module = str(udir.join('testownlib.so'))
150
151 def test_getting_errno(self):
152 if self.module is None:
153 py.test.skip("fix the auto-generation of the tiny test lib")
154 if sys.platform == 'win32':
155 py.test.skip("fails, errno at multiple addresses")
156 ffi = FFI(backend=self.Backend())
157 ffi.cdef("""
158 int test_getting_errno(void);
159 """)
160 ownlib = ffi.dlopen(self.module)
161 res = ownlib.test_getting_errno()
162 assert res == -1
163 assert ffi.errno == 123
164
165 def test_setting_errno(self):
166 if self.module is None:
167 py.test.skip("fix the auto-generation of the tiny test lib")
168 if sys.platform == 'win32':
169 py.test.skip("fails, errno at multiple addresses")
170 if self.Backend is CTypesBackend and '__pypy__' in sys.modules:
171 py.test.skip("XXX errno issue with ctypes on pypy?")
172 ffi = FFI(backend=self.Backend())
173 ffi.cdef("""
174 int test_setting_errno(void);
175 """)
176 ownlib = ffi.dlopen(self.module)
177 ffi.errno = 42
178 res = ownlib.test_setting_errno()
179 assert res == 42
180 assert ffi.errno == 42
181
182 def test_my_array_7(self):
183 if self.module is None:
184 py.test.skip("fix the auto-generation of the tiny test lib")
185 ffi = FFI(backend=self.Backend())
186 ffi.cdef("""
187 int my_array[7];
188 """)
189 ownlib = ffi.dlopen(self.module)
190 for i in range(7):
191 assert ownlib.my_array[i] == i
192 assert len(ownlib.my_array) == 7
193 if self.Backend is CTypesBackend:
194 py.test.skip("not supported by the ctypes backend")
195 ownlib.my_array = list(range(10, 17))
196 for i in range(7):
197 assert ownlib.my_array[i] == 10 + i
198 ownlib.my_array = list(range(7))
199 for i in range(7):
200 assert ownlib.my_array[i] == i
201
202 def test_my_array_no_length(self):
203 if self.module is None:
204 py.test.skip("fix the auto-generation of the tiny test lib")
205 if self.Backend is CTypesBackend:
206 py.test.skip("not supported by the ctypes backend")
207 ffi = FFI(backend=self.Backend())
208 ffi.cdef("""
209 int my_array[];
210 """)
211 ownlib = ffi.dlopen(self.module)
212 for i in range(7):
213 assert ownlib.my_array[i] == i
214 py.test.raises(TypeError, len, ownlib.my_array)
215 ownlib.my_array = list(range(10, 17))
216 for i in range(7):
217 assert ownlib.my_array[i] == 10 + i
218 ownlib.my_array = list(range(7))
219 for i in range(7):
220 assert ownlib.my_array[i] == i
221
222 def test_keepalive_lib(self):
223 if self.module is None:
224 py.test.skip("fix the auto-generation of the tiny test lib")
225 ffi = FFI(backend=self.Backend())
226 ffi.cdef("""
227 int test_getting_errno(void);
228 """)
229 ownlib = ffi.dlopen(self.module)
230 ffi_r = weakref.ref(ffi)
231 ownlib_r = weakref.ref(ownlib)
232 func = ownlib.test_getting_errno
233 del ffi
234 import gc; gc.collect() # ownlib stays alive
235 assert ownlib_r() is not None
236 assert ffi_r() is not None # kept alive by ownlib
237 res = func()
238 assert res == -1
239
240 def test_keepalive_ffi(self):
241 if self.module is None:
242 py.test.skip("fix the auto-generation of the tiny test lib")
243 ffi = FFI(backend=self.Backend())
244 ffi.cdef("""
245 int test_getting_errno(void);
246 """)
247 ownlib = ffi.dlopen(self.module)
248 ffi_r = weakref.ref(ffi)
249 ownlib_r = weakref.ref(ownlib)
250 func = ownlib.test_getting_errno
251 del ownlib
252 import gc; gc.collect() # ffi stays alive
253 assert ffi_r() is not None
254 assert ownlib_r() is not None # kept alive by ffi
255 res = func()
256 assert res == -1
257 if sys.platform != 'win32': # else, errno at multiple addresses
258 assert ffi.errno == 123
259
260 def test_struct_by_value(self):
261 if self.module is None:
262 py.test.skip("fix the auto-generation of the tiny test lib")
263 ffi = FFI(backend=self.Backend())
264 ffi.cdef("""
265 typedef struct {
266 long x;
267 long y;
268 } POINT;
269
270 typedef struct {
271 long left;
272 long top;
273 long right;
274 long bottom;
275 } RECT;
276
277 long left, top, right, bottom;
278
279 RECT ReturnRect(int i, RECT ar, RECT* br, POINT cp, RECT dr,
280 RECT *er, POINT fp, RECT gr);
281 """)
282 ownlib = ffi.dlopen(self.module)
283
284 rect = ffi.new('RECT[1]')
285 pt = ffi.new('POINT[1]')
286 pt[0].x = 15
287 pt[0].y = 25
288 rect[0].left = ownlib.left
289 rect[0].right = ownlib.right
290 rect[0].top = ownlib.top
291 rect[0].bottom = ownlib.bottom
292
293 for i in range(4):
294 ret = ownlib.ReturnRect(i, rect[0], rect, pt[0], rect[0],
295 rect, pt[0], rect[0])
296 assert ret.left == ownlib.left
297 assert ret.right == ownlib.right
298 assert ret.top == ownlib.top
299 assert ret.bottom == ownlib.bottom
300
301 def test_addressof_lib(self):
302 if self.module is None:
303 py.test.skip("fix the auto-generation of the tiny test lib")
304 if self.Backend is CTypesBackend:
305 py.test.skip("not implemented with the ctypes backend")
306 ffi = FFI(backend=self.Backend())
307 ffi.cdef("long left; int test_getting_errno(void);")
308 lib = ffi.dlopen(self.module)
309 lib.left = 123456
310 p = ffi.addressof(lib, "left")
311 assert ffi.typeof(p) == ffi.typeof("long *")
312 assert p[0] == 123456
313 p[0] += 1
314 assert lib.left == 123457
315 pfn = ffi.addressof(lib, "test_getting_errno")
316 assert ffi.typeof(pfn) == ffi.typeof("int(*)(void)")
317 assert pfn == lib.test_getting_errno
318
319 def test_char16_char32_t(self):
320 if self.module is None:
321 py.test.skip("fix the auto-generation of the tiny test lib")
322 if self.Backend is CTypesBackend:
323 py.test.skip("not implemented with the ctypes backend")
324 ffi = FFI(backend=self.Backend())
325 ffi.cdef("""
326 char16_t foo_2bytes(char16_t);
327 char32_t foo_4bytes(char32_t);
328 """)
329 lib = ffi.dlopen(self.module)
330 assert lib.foo_2bytes(u+'\u1234') == u+'\u125e'
331 assert lib.foo_4bytes(u+'\u1234') == u+'\u125e'
332 assert lib.foo_4bytes(u+'\U00012345') == u+'\U0001236f'
+0
-469
pypy/module/test_lib_pypy/cffi_tests/cffi0/test_parsing.py less more
0 # Generated by pypy/tool/import_cffi.py
1 import py, sys, re
2 from cffi import FFI, FFIError, CDefError, VerificationError
3 from .backend_tests import needs_dlopen_none
4
5
6 class FakeBackend(object):
7
8 def nonstandard_integer_types(self):
9 return {}
10
11 def sizeof(self, name):
12 return 1
13
14 def load_library(self, name, flags):
15 if sys.platform == 'win32':
16 assert name is None or "msvcr" in name
17 else:
18 assert name is None or "libc" in name or "libm" in name
19 return FakeLibrary()
20
21 def new_function_type(self, args, result, has_varargs):
22 args = [arg.cdecl for arg in args]
23 result = result.cdecl
24 return FakeType(
25 '<func (%s), %s, %s>' % (', '.join(args), result, has_varargs))
26
27 def new_primitive_type(self, name):
28 assert name == name.lower()
29 return FakeType('<%s>' % name)
30
31 def new_pointer_type(self, itemtype):
32 return FakeType('<pointer to %s>' % (itemtype,))
33
34 def new_struct_type(self, name):
35 return FakeStruct(name)
36
37 def complete_struct_or_union(self, s, fields, tp=None,
38 totalsize=-1, totalalignment=-1, sflags=0):
39 assert isinstance(s, FakeStruct)
40 s.fields = fields
41
42 def new_array_type(self, ptrtype, length):
43 return FakeType('<array %s x %s>' % (ptrtype, length))
44
45 def new_void_type(self):
46 return FakeType("<void>")
47 def cast(self, x, y):
48 return 'casted!'
49 def _get_types(self):
50 return "CData", "CType"
51
52 buffer = "buffer type"
53
54 class FakeType(object):
55 def __init__(self, cdecl):
56 self.cdecl = cdecl
57 def __str__(self):
58 return self.cdecl
59
60 class FakeStruct(object):
61 def __init__(self, name):
62 self.name = name
63 def __str__(self):
64 return ', '.join([str(y) + str(x) for x, y, z in self.fields])
65
66 class FakeLibrary(object):
67
68 def load_function(self, BType, name):
69 return FakeFunction(BType, name)
70
71 class FakeFunction(object):
72
73 def __init__(self, BType, name):
74 self.BType = str(BType)
75 self.name = name
76
77 lib_m = "m"
78 if sys.platform == 'win32':
79 #there is a small chance this fails on Mingw via environ $CC
80 import distutils.ccompiler
81 if distutils.ccompiler.get_default_compiler() == 'msvc':
82 lib_m = 'msvcrt'
83
84 def test_simple():
85 ffi = FFI(backend=FakeBackend())
86 ffi.cdef("double sin(double x);")
87 m = ffi.dlopen(lib_m)
88 func = m.sin # should be a callable on real backends
89 assert func.name == 'sin'
90 assert func.BType == '<func (<double>), <double>, False>'
91
92 def test_pipe():
93 ffi = FFI(backend=FakeBackend())
94 ffi.cdef("int pipe(int pipefd[2]);")
95 needs_dlopen_none()
96 C = ffi.dlopen(None)
97 func = C.pipe
98 assert func.name == 'pipe'
99 assert func.BType == '<func (<pointer to <int>>), <int>, False>'
100
101 def test_vararg():
102 ffi = FFI(backend=FakeBackend())
103 ffi.cdef("short foo(int, ...);")
104 needs_dlopen_none()
105 C = ffi.dlopen(None)
106 func = C.foo
107 assert func.name == 'foo'
108 assert func.BType == '<func (<int>), <short>, True>'
109
110 def test_no_args():
111 ffi = FFI(backend=FakeBackend())
112 ffi.cdef("""
113 int foo(void);
114 """)
115 needs_dlopen_none()
116 C = ffi.dlopen(None)
117 assert C.foo.BType == '<func (), <int>, False>'
118
119 def test_typedef():
120 ffi = FFI(backend=FakeBackend())
121 ffi.cdef("""
122 typedef unsigned int UInt;
123 typedef UInt UIntReally;
124 UInt foo(void);
125 """)
126 needs_dlopen_none()
127 C = ffi.dlopen(None)
128 assert str(ffi.typeof("UIntReally")) == '<unsigned int>'
129 assert C.foo.BType == '<func (), <unsigned int>, False>'
130
131 def test_typedef_more_complex():
132 ffi = FFI(backend=FakeBackend())
133 ffi.cdef("""
134 typedef struct { int a, b; } foo_t, *foo_p;
135 int foo(foo_p[]);
136 """)
137 needs_dlopen_none()
138 C = ffi.dlopen(None)
139 assert str(ffi.typeof("foo_t")) == '<int>a, <int>b'
140 assert str(ffi.typeof("foo_p")) == '<pointer to <int>a, <int>b>'
141 assert C.foo.BType == ('<func (<pointer to <pointer to '
142 '<int>a, <int>b>>), <int>, False>')
143
144 def test_typedef_array_convert_array_to_pointer():
145 ffi = FFI(backend=FakeBackend())
146 ffi.cdef("""
147 typedef int (*fn_t)(int[5]);
148 """)
149 with ffi._lock:
150 type = ffi._parser.parse_type("fn_t")
151 BType = ffi._get_cached_btype(type)
152 assert str(BType) == '<func (<pointer to <int>>), <int>, False>'
153
154 def test_remove_comments():
155 ffi = FFI(backend=FakeBackend())
156 ffi.cdef("""
157 double /*comment here*/ sin // blah blah
158 /* multi-
159 line-
160 //comment */ (
161 // foo
162 double // bar /* <- ignored, because it's in a comment itself
163 x, double/*several*//*comment*/y) /*on the same line*/
164 ;
165 """)
166 m = ffi.dlopen(lib_m)
167 func = m.sin
168 assert func.name == 'sin'
169 assert func.BType == '<func (<double>, <double>), <double>, False>'
170
171 def test_remove_line_continuation_comments():
172 ffi = FFI(backend=FakeBackend())
173 ffi.cdef("""
174 double // blah \\
175 more comments
176 x(void);
177 double // blah\\\\
178 y(void);
179 double // blah\\ \
180 etc
181 z(void);
182 """)
183 m = ffi.dlopen(lib_m)
184 m.x
185 m.y
186 m.z
187
188 def test_line_continuation_in_defines():
189 ffi = FFI(backend=FakeBackend())
190 ffi.cdef("""
191 #define ABC\\
192 42
193 #define BCD \\
194 43
195 """)
196 m = ffi.dlopen(lib_m)
197 assert m.ABC == 42
198 assert m.BCD == 43
199
200 def test_define_not_supported_for_now():
201 ffi = FFI(backend=FakeBackend())
202 e = py.test.raises(CDefError, ffi.cdef, '#define FOO "blah"')
203 assert str(e.value) == (
204 'only supports one of the following syntax:\n'
205 ' #define FOO ... (literally dot-dot-dot)\n'
206 ' #define FOO NUMBER (with NUMBER an integer'
207 ' constant, decimal/hex/octal)\n'
208 'got:\n'
209 ' #define FOO "blah"')
210
211 def test_unnamed_struct():
212 ffi = FFI(backend=FakeBackend())
213 ffi.cdef("typedef struct { int x; } foo_t;\n"
214 "typedef struct { int y; } *bar_p;\n")
215 assert 'typedef foo_t' in ffi._parser._declarations
216 assert 'typedef bar_p' in ffi._parser._declarations
217 assert 'anonymous foo_t' in ffi._parser._declarations
218 type_foo = ffi._parser.parse_type("foo_t")
219 type_bar = ffi._parser.parse_type("bar_p").totype
220 assert repr(type_foo) == "<foo_t>"
221 assert repr(type_bar) == "<struct $1>"
222 py.test.raises(VerificationError, type_bar.get_c_name)
223 assert type_foo.get_c_name() == "foo_t"
224
225 def test_override():
226 ffi = FFI(backend=FakeBackend())
227 needs_dlopen_none()
228 C = ffi.dlopen(None)
229 ffi.cdef("int foo(void);")
230 py.test.raises(FFIError, ffi.cdef, "long foo(void);")
231 assert C.foo.BType == '<func (), <int>, False>'
232 ffi.cdef("long foo(void);", override=True)
233 assert C.foo.BType == '<func (), <long>, False>'
234
235 def test_cannot_have_only_variadic_part():
236 # this checks that we get a sensible error if we try "int foo(...);"
237 ffi = FFI()
238 e = py.test.raises(CDefError, ffi.cdef, "int foo(...);")
239 assert str(e.value) == (
240 "<cdef source string>:1: foo: a function with only '(...)' "
241 "as argument is not correct C")
242
243 def test_parse_error():
244 ffi = FFI()
245 e = py.test.raises(CDefError, ffi.cdef, " x y z ")
246 assert str(e.value).startswith(
247 'cannot parse "x y z"\n<cdef source string>:1:')
248 e = py.test.raises(CDefError, ffi.cdef, "\n\n\n x y z ")
249 assert str(e.value).startswith(
250 'cannot parse "x y z"\n<cdef source string>:4:')
251
252 def test_error_custom_lineno():
253 ffi = FFI()
254 e = py.test.raises(CDefError, ffi.cdef, """
255 # 42 "foobar"
256
257 a b c d
258 """)
259 assert str(e.value).startswith('parse error\nfoobar:43:')
260
261 def test_cannot_declare_enum_later():
262 ffi = FFI()
263 e = py.test.raises(NotImplementedError, ffi.cdef,
264 "typedef enum foo_e foo_t; enum foo_e { AA, BB };")
265 assert str(e.value) == (
266 "enum foo_e: the '{}' declaration should appear on the "
267 "first time the enum is mentioned, not later")
268
269 def test_unknown_name():
270 ffi = FFI()
271 e = py.test.raises(CDefError, ffi.cast, "foobarbazunknown", 0)
272 assert str(e.value) == "unknown identifier 'foobarbazunknown'"
273 e = py.test.raises(CDefError, ffi.cast, "foobarbazunknown*", 0)
274 assert str(e.value).startswith('cannot parse "foobarbazunknown*"')
275 e = py.test.raises(CDefError, ffi.cast, "int(*)(foobarbazunknown)", 0)
276 assert str(e.value).startswith('cannot parse "int(*)(foobarbazunknown)"')
277
278 def test_redefine_common_type():
279 prefix = "" if sys.version_info < (3,) else "b"
280 ffi = FFI()
281 ffi.cdef("typedef char FILE;")
282 assert repr(ffi.cast("FILE", 123)) == "<cdata 'char' %s'{'>" % prefix
283 ffi.cdef("typedef char int32_t;")
284 assert repr(ffi.cast("int32_t", 123)) == "<cdata 'char' %s'{'>" % prefix
285 ffi = FFI()
286 ffi.cdef("typedef int bool, *FILE;")
287 assert repr(ffi.cast("bool", 123)) == "<cdata 'int' 123>"
288 assert re.match(r"<cdata 'int [*]' 0[xX]?0*7[bB]>",
289 repr(ffi.cast("FILE", 123)))
290 ffi = FFI()
291 ffi.cdef("typedef bool (*fn_t)(bool, bool);") # "bool," but within "( )"
292
293 def test_bool():
294 ffi = FFI()
295 ffi.cdef("void f(bool);")
296 #
297 ffi = FFI()
298 ffi.cdef("typedef _Bool bool; void f(bool);")
299
300 def test_unknown_argument_type():
301 ffi = FFI()
302 e = py.test.raises(CDefError, ffi.cdef, "void f(foobarbazzz);")
303 assert str(e.value) == ("<cdef source string>:1: f arg 1:"
304 " unknown type 'foobarbazzz' (if you meant"
305 " to use the old C syntax of giving untyped"
306 " arguments, it is not supported)")
307
308 def test_void_renamed_as_only_arg():
309 ffi = FFI()
310 ffi.cdef("typedef void void_t1;"
311 "typedef void_t1 void_t;"
312 "typedef int (*func_t)(void_t);")
313 assert ffi.typeof("func_t").args == ()
314
315 def test_WPARAM_on_windows():
316 if sys.platform != 'win32':
317 py.test.skip("Only for Windows")
318 ffi = FFI()
319 ffi.cdef("void f(WPARAM);")
320 #
321 # WPARAM -> UINT_PTR -> unsigned 32/64-bit integer
322 ffi = FFI()
323 value = int(ffi.cast("WPARAM", -42))
324 assert value == sys.maxsize * 2 - 40
325
326 def test__is_constant_globalvar():
327 for input, expected_output in [
328 ("int a;", False),
329 ("const int a;", True),
330 ("int *a;", False),
331 ("const int *a;", False),
332 ("int const *a;", False),
333 ("int *const a;", True),
334 ("int a[5];", False),
335 ("const int a[5];", False),
336 ("int *a[5];", False),
337 ("const int *a[5];", False),
338 ("int const *a[5];", False),
339 ("int *const a[5];", False),
340 ("int a[5][6];", False),
341 ("const int a[5][6];", False),
342 ]:
343 ffi = FFI()
344 ffi.cdef(input)
345 declarations = ffi._parser._declarations
346 assert ('constant a' in declarations) == expected_output
347 assert ('variable a' in declarations) == (not expected_output)
348
349 def test_restrict():
350 from cffi import model
351 for input, expected_output in [
352 ("int a;", False),
353 ("restrict int a;", True),
354 ("int *a;", False),
355 ]:
356 ffi = FFI()
357 ffi.cdef(input)
358 tp, quals = ffi._parser._declarations['variable a']
359 assert bool(quals & model.Q_RESTRICT) == expected_output
360
361 def test_different_const_funcptr_types():
362 lst = []
363 for input in [
364 "int(*)(int *a)",
365 "int(*)(int const *a)",
366 "int(*)(int * const a)",
367 "int(*)(int const a[])"]:
368 ffi = FFI(backend=FakeBackend())
369 lst.append(ffi._parser.parse_type(input))
370 assert lst[0] != lst[1]
371 assert lst[0] == lst[2]
372 assert lst[1] == lst[3]
373
374 def test_const_pointer_to_pointer():
375 from cffi import model
376 ffi = FFI(backend=FakeBackend())
377 #
378 tp, qual = ffi._parser.parse_type_and_quals("char * * (* const)")
379 assert (str(tp), qual) == ("<char * * *>", model.Q_CONST)
380 tp, qual = ffi._parser.parse_type_and_quals("char * (* const (*))")
381 assert (str(tp), qual) == ("<char * * const *>", 0)
382 tp, qual = ffi._parser.parse_type_and_quals("char (* const (* (*)))")
383 assert (str(tp), qual) == ("<char * const * *>", 0)
384 tp, qual = ffi._parser.parse_type_and_quals("char const * * *")
385 assert (str(tp), qual) == ("<char const * * *>", 0)
386 tp, qual = ffi._parser.parse_type_and_quals("const char * * *")
387 assert (str(tp), qual) == ("<char const * * *>", 0)
388 #
389 tp, qual = ffi._parser.parse_type_and_quals("char * * * const const")
390 assert (str(tp), qual) == ("<char * * *>", model.Q_CONST)
391 tp, qual = ffi._parser.parse_type_and_quals("char * * volatile *")
392 assert (str(tp), qual) == ("<char * * volatile *>", 0)
393 tp, qual = ffi._parser.parse_type_and_quals("char * volatile restrict * *")
394 assert (str(tp), qual) == ("<char * __restrict volatile * *>", 0)
395 tp, qual = ffi._parser.parse_type_and_quals("char const volatile * * *")
396 assert (str(tp), qual) == ("<char volatile const * * *>", 0)
397 tp, qual = ffi._parser.parse_type_and_quals("const char * * *")
398 assert (str(tp), qual) == ("<char const * * *>", 0)
399 #
400 tp, qual = ffi._parser.parse_type_and_quals(
401 "int(char*const*, short****const*)")
402 assert (str(tp), qual) == (
403 "<int()(char * const *, short * * * * const *)>", 0)
404 tp, qual = ffi._parser.parse_type_and_quals(
405 "char*const*(short*const****)")
406 assert (str(tp), qual) == (
407 "<char * const *()(short * const * * * *)>", 0)
408
409 def test_enum():
410 ffi = FFI()
411 ffi.cdef("""
412 enum Enum { POS = +1, TWO = 2, NIL = 0, NEG = -1, OP = (POS+TWO)-1};
413 """)
414 needs_dlopen_none()
415 C = ffi.dlopen(None)
416 assert C.POS == 1
417 assert C.TWO == 2
418 assert C.NIL == 0
419 assert C.NEG == -1
420 assert C.OP == 2
421
422 def test_stdcall():
423 ffi = FFI()
424 tp = ffi.typeof("int(*)(int __stdcall x(int),"
425 " long (__cdecl*y)(void),"
426 " short(WINAPI *z)(short))")
427 if sys.platform == 'win32' and sys.maxsize < 2**32:
428 stdcall = '__stdcall '
429 else:
430 stdcall = ''
431 assert str(tp) == (
432 "<ctype 'int(*)(int(%s*)(int), "
433 "long(*)(), "
434 "short(%s*)(short))'>" % (stdcall, stdcall))
435
436 def test_extern_python():
437 ffi = FFI()
438 ffi.cdef("""
439 int bok(int, int);
440 extern "Python" int foobar(int, int);
441 int baz(int, int);
442 """)
443 assert sorted(ffi._parser._declarations) == [
444 'extern_python foobar', 'function baz', 'function bok']
445 assert (ffi._parser._declarations['function bok'] ==
446 ffi._parser._declarations['extern_python foobar'] ==
447 ffi._parser._declarations['function baz'])
448
449 def test_extern_python_group():
450 ffi = FFI()
451 ffi.cdef("""
452 int bok(int);
453 extern "Python" {int foobar(int, int);int bzrrr(int);}
454 int baz(int, int);
455 """)
456 assert sorted(ffi._parser._declarations) == [
457 'extern_python bzrrr', 'extern_python foobar',
458 'function baz', 'function bok']
459 assert (ffi._parser._declarations['function baz'] ==
460 ffi._parser._declarations['extern_python foobar'] !=
461 ffi._parser._declarations['function bok'] ==
462 ffi._parser._declarations['extern_python bzrrr'])
463
464 def test_error_invalid_syntax_for_cdef():
465 ffi = FFI()
466 e = py.test.raises(CDefError, ffi.cdef, 'void foo(void) {}')
467 assert str(e.value) == ('<cdef source string>:1: unexpected <FuncDef>: '
468 'this construct is valid C but not valid in cdef()')
+0
-26
pypy/module/test_lib_pypy/cffi_tests/cffi0/test_platform.py less more
0 # Generated by pypy/tool/import_cffi.py
1 import os
2 from cffi.ffiplatform import maybe_relative_path, flatten
3
4
5 def test_not_absolute():
6 assert maybe_relative_path('foo/bar') == 'foo/bar'
7 assert maybe_relative_path('test_platform.py') == 'test_platform.py'
8
9 def test_different_absolute():
10 p = os.path.join('..', 'baz.py')
11 assert maybe_relative_path(p) == p
12
13 def test_absolute_mapping():
14 p = os.path.abspath('baz.py')
15 assert maybe_relative_path(p) == 'baz.py'
16 foobaz = os.path.join('foo', 'baz.py')
17 assert maybe_relative_path(os.path.abspath(foobaz)) == foobaz
18
19 def test_flatten():
20 assert flatten("foo") == "3sfoo"
21 assert flatten(-10000000000000000000000000000) == \
22 "-10000000000000000000000000000i"
23 assert flatten([4, 5]) == "2l4i5i"
24 assert flatten({4: 5}) == "1d4i5i"
25 assert flatten({"foo": ("bar", "baaz")}) == "1d3sfoo2l3sbar4sbaaz"
+0
-80
pypy/module/test_lib_pypy/cffi_tests/cffi0/test_unicode_literals.py less more
0 # Generated by pypy/tool/import_cffi.py
1 #
2 # ----------------------------------------------
3 # WARNING, ALL LITERALS IN THIS FILE ARE UNICODE
4 # ----------------------------------------------
5 #
6 from __future__ import unicode_literals
7 #
8 #
9 #
10 import sys, math
11 from cffi import FFI
12
13 lib_m = "m"
14 if sys.platform == 'win32':
15 #there is a small chance this fails on Mingw via environ $CC
16 import distutils.ccompiler
17 if distutils.ccompiler.get_default_compiler() == 'msvc':
18 lib_m = 'msvcrt'
19
20
21 def test_cast():
22 ffi = FFI()
23 assert int(ffi.cast("int", 3.14)) == 3 # unicode literal
24
25 def test_new():
26 ffi = FFI()
27 assert ffi.new("int[]", [3, 4, 5])[2] == 5 # unicode literal
28
29 def test_typeof():
30 ffi = FFI()
31 tp = ffi.typeof("int[51]") # unicode literal
32 assert tp.length == 51
33
34 def test_sizeof():
35 ffi = FFI()
36 assert ffi.sizeof("int[51]") == 51 * 4 # unicode literal
37
38 def test_alignof():
39 ffi = FFI()
40 assert ffi.alignof("int[51]") == 4 # unicode literal
41
42 def test_getctype():
43 ffi = FFI()
44 assert ffi.getctype("int**") == "int * *" # unicode literal
45 assert type(ffi.getctype("int**")) is str
46
47 def test_cdef():
48 ffi = FFI()
49 ffi.cdef("typedef int foo_t[50];") # unicode literal
50
51 def test_offsetof():
52 ffi = FFI()
53 ffi.cdef("typedef struct { int x, y; } foo_t;")
54 assert ffi.offsetof("foo_t", "y") == 4 # unicode literal
55
56 def test_enum():
57 ffi = FFI()
58 ffi.cdef("enum foo_e { AA, BB, CC };") # unicode literal
59 x = ffi.cast("enum foo_e", 1)
60 assert int(ffi.cast("int", x)) == 1
61
62 def test_dlopen():
63 ffi = FFI()
64 ffi.cdef("double sin(double x);")
65 m = ffi.dlopen(lib_m) # unicode literal
66 x = m.sin(1.23)
67 assert x == math.sin(1.23)
68
69 def test_verify():
70 ffi = FFI()
71 ffi.cdef("double test_verify_1(double x);") # unicode literal
72 lib = ffi.verify("double test_verify_1(double x) { return x * 42.0; }")
73 assert lib.test_verify_1(-1.5) == -63.0
74
75 def test_callback():
76 ffi = FFI()
77 cb = ffi.callback("int(int)", # unicode literal
78 lambda x: x + 42)
79 assert cb(5) == 47
+0
-2525
pypy/module/test_lib_pypy/cffi_tests/cffi0/test_verify.py less more
0 # Generated by pypy/tool/import_cffi.py
1 import py, re
2 import sys, os, math, weakref
3 from cffi import FFI, VerificationError, VerificationMissing, model, FFIError
4 from pypy.module.test_lib_pypy.cffi_tests.support import *
5
6
7 lib_m = ['m']
8 if sys.platform == 'win32':
9 #there is a small chance this fails on Mingw via environ $CC
10 import distutils.ccompiler
11 if distutils.ccompiler.get_default_compiler() == 'msvc':
12 lib_m = ['msvcrt']
13 pass # no obvious -Werror equivalent on MSVC
14 else:
15 if (sys.platform == 'darwin' and
16 [int(x) for x in os.uname()[2].split('.')] >= [11, 0, 0]):
17 # assume a standard clang or gcc
18 extra_compile_args = ['-Werror', '-Wall', '-Wextra', '-Wconversion']
19 # special things for clang
20 extra_compile_args.append('-Qunused-arguments')
21 else:
22 # assume a standard gcc
23 extra_compile_args = ['-Werror', '-Wall', '-Wextra', '-Wconversion']
24
25 class FFI(FFI):
26 def verify(self, *args, **kwds):
27 return super(FFI, self).verify(
28 *args, extra_compile_args=extra_compile_args, **kwds)
29
30 def setup_module():
31 import cffi.verifier
32 cffi.verifier.cleanup_tmpdir()
33 #
34 # check that no $ sign is produced in the C file; it used to be the
35 # case that anonymous enums would produce '$enum_$1', which was
36 # used as part of a function name. GCC accepts such names, but it's
37 # apparently non-standard.
38 _r_comment = re.compile(r"/\*.*?\*/|//.*?$", re.DOTALL | re.MULTILINE)
39 _r_string = re.compile(r'\".*?\"')
40 def _write_source_and_check(self, file=None):
41 base_write_source(self, file)
42 if file is None:
43 f = open(self.sourcefilename)
44 data = f.read()
45 f.close()
46 data = _r_comment.sub(' ', data)
47 data = _r_string.sub('"skipped"', data)
48 assert '$' not in data
49 base_write_source = cffi.verifier.Verifier._write_source
50 cffi.verifier.Verifier._write_source = _write_source_and_check
51
52
53 def test_module_type():
54 import cffi.verifier
55 ffi = FFI()
56 lib = ffi.verify()
57 if hasattr(lib, '_cffi_python_module'):
58 print('verify got a PYTHON module')
59 if hasattr(lib, '_cffi_generic_module'):
60 print('verify got a GENERIC module')
61 expected_generic = (cffi.verifier._FORCE_GENERIC_ENGINE or
62 '__pypy__' in sys.builtin_module_names)
63 assert hasattr(lib, '_cffi_python_module') == (not expected_generic)
64 assert hasattr(lib, '_cffi_generic_module') == expected_generic
65
66 def test_missing_function(ffi=None):
67 # uses the FFI hacked above with '-Werror'
68 if ffi is None:
69 ffi = FFI()
70 ffi.cdef("void some_completely_unknown_function();")
71 try:
72 lib = ffi.verify()
73 except (VerificationError, OSError):
74 pass # expected case: we get a VerificationError
75 else:
76 # but depending on compiler and loader details, maybe
77 # 'lib' could actually be imported but will fail if we
78 # actually try to call the unknown function... Hard
79 # to test anything more.
80 pass
81
82 def test_missing_function_import_error():
83 # uses the original FFI that just gives a warning during compilation
84 import cffi
85 test_missing_function(ffi=cffi.FFI())
86
87 def test_simple_case():
88 ffi = FFI()
89 ffi.cdef("double sin(double x);")
90 lib = ffi.verify('#include <math.h>', libraries=lib_m)
91 assert lib.sin(1.23) == math.sin(1.23)
92
93 def _Wconversion(cdef, source, **kargs):
94 if sys.platform in ('win32', 'darwin'):
95 py.test.skip("needs GCC")
96 ffi = FFI()
97 ffi.cdef(cdef)
98 py.test.raises(VerificationError, ffi.verify, source, **kargs)
99 extra_compile_args_orig = extra_compile_args[:]
100 extra_compile_args.remove('-Wconversion')
101 try:
102 lib = ffi.verify(source, **kargs)
103 finally:
104 extra_compile_args[:] = extra_compile_args_orig
105 return lib
106
107 def test_Wconversion_unsigned():
108 _Wconversion("unsigned foo(void);",
109 "int foo(void) { return -1;}")
110
111 def test_Wconversion_integer():
112 _Wconversion("short foo(void);",
113 "long long foo(void) { return 1<<sizeof(short);}")
114
115 def test_Wconversion_floating():
116 lib = _Wconversion("float sin(double);",
117 "#include <math.h>", libraries=lib_m)
118 res = lib.sin(1.23)
119 assert res != math.sin(1.23) # not exact, because of double->float
120 assert abs(res - math.sin(1.23)) < 1E-5
121
122 def test_Wconversion_float2int():
123 _Wconversion("int sinf(float);",
124 "#include <math.h>", libraries=lib_m)
125
126 def test_Wconversion_double2int():
127 _Wconversion("int sin(double);",
128 "#include <math.h>", libraries=lib_m)
129
130 def test_rounding_1():
131 ffi = FFI()
132 ffi.cdef("double sinf(float x);")
133 lib = ffi.verify('#include <math.h>', libraries=lib_m)
134 res = lib.sinf(1.23)
135 assert res != math.sin(1.23) # not exact, because of double->float
136 assert abs(res - math.sin(1.23)) < 1E-5
137
138 def test_rounding_2():
139 ffi = FFI()
140 ffi.cdef("double sin(float x);")
141 lib = ffi.verify('#include <math.h>', libraries=lib_m)
142 res = lib.sin(1.23)
143 assert res != math.sin(1.23) # not exact, because of double->float
144 assert abs(res - math.sin(1.23)) < 1E-5
145
146 def test_strlen_exact():
147 ffi = FFI()
148 ffi.cdef("size_t strlen(const char *s);")
149 lib = ffi.verify("#include <string.h>")
150 assert lib.strlen(b"hi there!") == 9
151
152 def test_strlen_approximate():
153 lib = _Wconversion("int strlen(char *s);",
154 "#include <string.h>")
155 assert lib.strlen(b"hi there!") == 9
156
157 def test_return_approximate():
158 for typename in ['short', 'int', 'long', 'long long']:
159 ffi = FFI()
160 ffi.cdef("%s foo(signed char x);" % typename)
161 lib = ffi.verify("signed char foo(signed char x) { return x;}")
162 assert lib.foo(-128) == -128
163 assert lib.foo(+127) == +127
164
165 def test_strlen_array_of_char():
166 ffi = FFI()
167 ffi.cdef("size_t strlen(char[]);")
168 lib = ffi.verify("#include <string.h>")
169 assert lib.strlen(b"hello") == 5
170
171 def test_longdouble():
172 ffi = FFI()
173 ffi.cdef("long double sinl(long double x);")
174 lib = ffi.verify('#include <math.h>', libraries=lib_m)
175 for input in [1.23,
176 ffi.cast("double", 1.23),
177 ffi.cast("long double", 1.23)]:
178 x = lib.sinl(input)
179 assert repr(x).startswith("<cdata 'long double'")
180 assert (float(x) - math.sin(1.23)) < 1E-10
181
182 def test_longdouble_precision():
183 # Test that we don't loose any precision of 'long double' when
184 # passing through Python and CFFI.
185 ffi = FFI()
186 ffi.cdef("long double step1(long double x);")
187 SAME_SIZE = ffi.sizeof("long double") == ffi.sizeof("double")
188 lib = ffi.verify("""
189 long double step1(long double x)
190 {
191 return 4*x-x*x;
192 }
193 """)
194 def do(cast_to_double):
195 x = 0.9789
196 for i in range(10000):
197 x = lib.step1(x)
198 if cast_to_double:
199 x = float(x)
200 return float(x)
201
202 more_precise = do(False)
203 less_precise = do(True)
204 if SAME_SIZE:
205 assert more_precise == less_precise
206 else:
207 assert abs(more_precise - less_precise) > 0.1
208 # Check the particular results on Intel
209 import platform
210 if (platform.machine().startswith('i386') or
211 platform.machine().startswith('i486') or
212 platform.machine().startswith('i586') or
213 platform.machine().startswith('i686') or
214 platform.machine().startswith('x86')):
215 assert abs(more_precise - 0.656769) < 0.001
216 assert abs(less_precise - 3.99091) < 0.001
217 else:
218 py.test.skip("don't know the very exact precision of 'long double'")
219
220
221 all_primitive_types = model.PrimitiveType.ALL_PRIMITIVE_TYPES
222 if sys.platform == 'win32':
223 all_primitive_types = all_primitive_types.copy()
224 del all_primitive_types['ssize_t']
225 all_integer_types = sorted(tp for tp in all_primitive_types
226 if all_primitive_types[tp] == 'i')
227 all_float_types = sorted(tp for tp in all_primitive_types
228 if all_primitive_types[tp] == 'f')
229
230 def all_signed_integer_types(ffi):
231 return [x for x in all_integer_types if int(ffi.cast(x, -1)) < 0]
232
233 def all_unsigned_integer_types(ffi):
234 return [x for x in all_integer_types if int(ffi.cast(x, -1)) > 0]
235
236
237 def test_primitive_category():
238 for typename in all_primitive_types:
239 tp = model.PrimitiveType(typename)
240 C = tp.is_char_type()
241 F = tp.is_float_type()
242 X = tp.is_complex_type()
243 I = tp.is_integer_type()
244 assert C == (typename in ('char', 'wchar_t', 'char16_t', 'char32_t'))
245 assert F == (typename in ('float', 'double', 'long double'))
246 assert X == (typename in ('float _Complex', 'double _Complex'))
247 assert I + F + C + X == 1 # one and only one of them is true
248
249 def test_all_integer_and_float_types():
250 typenames = []
251 for typename in all_primitive_types:
252 if (all_primitive_types[typename] == 'c' or
253 all_primitive_types[typename] == 'j' or # complex
254 typename == '_Bool' or typename == 'long double'):
255 pass
256 else:
257 typenames.append(typename)
258 #
259 ffi = FFI()
260 ffi.cdef('\n'.join(["%s foo_%s(%s);" % (tp, tp.replace(' ', '_'), tp)
261 for tp in typenames]))
262 lib = ffi.verify('\n'.join(["%s foo_%s(%s x) { return (%s)(x+1); }" %
263 (tp, tp.replace(' ', '_'), tp, tp)
264 for tp in typenames]))
265 for typename in typenames:
266 foo = getattr(lib, 'foo_%s' % typename.replace(' ', '_'))
267 assert foo(42) == 43
268 if sys.version < '3':
269 assert foo(long(44)) == 45
270 assert foo(ffi.cast(typename, 46)) == 47
271 py.test.raises(TypeError, foo, ffi.NULL)
272 #
273 # check for overflow cases
274 if all_primitive_types[typename] == 'f':
275 continue
276 for value in [-2**80, -2**40, -2**20, -2**10, -2**5, -1,
277 2**5, 2**10, 2**20, 2**40, 2**80]:
278 overflows = int(ffi.cast(typename, value)) != value
279 if overflows:
280 py.test.raises(OverflowError, foo, value)
281 else:
282 assert foo(value) == value + 1
283
284 def test_var_signed_integer_types():
285 ffi = FFI()
286 lst = all_signed_integer_types(ffi)
287 csource = "\n".join(["%s somevar_%s;" % (tp, tp.replace(' ', '_'))
288 for tp in lst])
289 ffi.cdef(csource)
290 lib = ffi.verify(csource)
291 for tp in lst:
292 varname = 'somevar_%s' % tp.replace(' ', '_')
293 sz = ffi.sizeof(tp)
294 max = (1 << (8*sz-1)) - 1
295 min = -(1 << (8*sz-1))
296 setattr(lib, varname, max)
297 assert getattr(lib, varname) == max
298 setattr(lib, varname, min)
299 assert getattr(lib, varname) == min
300 py.test.raises(OverflowError, setattr, lib, varname, max+1)
301 py.test.raises(OverflowError, setattr, lib, varname, min-1)
302
303 def test_var_unsigned_integer_types():
304 ffi = FFI()
305 lst = all_unsigned_integer_types(ffi)
306 csource = "\n".join(["%s somevar_%s;" % (tp, tp.replace(' ', '_'))
307 for tp in lst])
308 ffi.cdef(csource)
309 lib = ffi.verify(csource)
310 for tp in lst:
311 varname = 'somevar_%s' % tp.replace(' ', '_')
312 sz = ffi.sizeof(tp)
313 if tp != '_Bool':
314 max = (1 << (8*sz)) - 1
315 else:
316 max = 1
317 setattr(lib, varname, max)
318 assert getattr(lib, varname) == max
319 setattr(lib, varname, 0)
320 assert getattr(lib, varname) == 0
321 py.test.raises(OverflowError, setattr, lib, varname, max+1)
322 py.test.raises(OverflowError, setattr, lib, varname, -1)
323
324 def test_fn_signed_integer_types():
325 ffi = FFI()
326 lst = all_signed_integer_types(ffi)
327 cdefsrc = "\n".join(["%s somefn_%s(%s);" % (tp, tp.replace(' ', '_'), tp)
328 for tp in lst])
329 ffi.cdef(cdefsrc)
330 verifysrc = "\n".join(["%s somefn_%s(%s x) { return x; }" %
331 (tp, tp.replace(' ', '_'), tp) for tp in lst])
332 lib = ffi.verify(verifysrc)
333 for tp in lst:
334 fnname = 'somefn_%s' % tp.replace(' ', '_')
335 sz = ffi.sizeof(tp)
336 max = (1 << (8*sz-1)) - 1
337 min = -(1 << (8*sz-1))
338 fn = getattr(lib, fnname)
339 assert fn(max) == max
340 assert fn(min) == min
341 py.test.raises(OverflowError, fn, max + 1)
342 py.test.raises(OverflowError, fn, min - 1)
343
344 def test_fn_unsigned_integer_types():
345 ffi = FFI()
346 lst = all_unsigned_integer_types(ffi)
347 cdefsrc = "\n".join(["%s somefn_%s(%s);" % (tp, tp.replace(' ', '_'), tp)
348 for tp in lst])
349 ffi.cdef(cdefsrc)
350 verifysrc = "\n".join(["%s somefn_%s(%s x) { return x; }" %
351 (tp, tp.replace(' ', '_'), tp) for tp in lst])
352 lib = ffi.verify(verifysrc)
353 for tp in lst:
354 fnname = 'somefn_%s' % tp.replace(' ', '_')
355 sz = ffi.sizeof(tp)
356 if tp != '_Bool':
357 max = (1 << (8*sz)) - 1
358 else:
359 max = 1
360 fn = getattr(lib, fnname)
361 assert fn(max) == max
362 assert fn(0) == 0
363 py.test.raises(OverflowError, fn, max + 1)
364 py.test.raises(OverflowError, fn, -1)
365
366 def test_char_type():
367 ffi = FFI()
368 ffi.cdef("char foo(char);")
369 lib = ffi.verify("char foo(char x) { return ++x; }")
370 assert lib.foo(b"A") == b"B"
371 py.test.raises(TypeError, lib.foo, b"bar")
372 py.test.raises(TypeError, lib.foo, "bar")
373
374 def test_wchar_type():
375 ffi = FFI()
376 if ffi.sizeof('wchar_t') == 2:
377 uniexample1 = u+'\u1234'
378 uniexample2 = u+'\u1235'
379 else:
380 uniexample1 = u+'\U00012345'
381 uniexample2 = u+'\U00012346'
382 #
383 ffi.cdef("wchar_t foo(wchar_t);")
384 lib = ffi.verify("wchar_t foo(wchar_t x) { return x+1; }")
385 assert lib.foo(uniexample1) == uniexample2
386
387 def test_char16_char32_type():
388 py.test.skip("XXX test or fully prevent char16_t and char32_t from "
389 "working in ffi.verify() mode")
390
391 def test_no_argument():
392 ffi = FFI()
393 ffi.cdef("int foo(void);")
394 lib = ffi.verify("int foo(void) { return 42; }")
395 assert lib.foo() == 42
396
397 def test_two_arguments():
398 ffi = FFI()
399 ffi.cdef("int foo(int, int);")
400 lib = ffi.verify("int foo(int a, int b) { return a - b; }")
401 assert lib.foo(40, -2) == 42
402
403 def test_macro():
404 ffi = FFI()
405 ffi.cdef("int foo(int, int);")
406 lib = ffi.verify("#define foo(a, b) ((a) * (b))")
407 assert lib.foo(-6, -7) == 42
408
409 def test_ptr():
410 ffi = FFI()
411 ffi.cdef("int *foo(int *);")
412 lib = ffi.verify("int *foo(int *a) { return a; }")
413 assert lib.foo(ffi.NULL) == ffi.NULL
414 p = ffi.new("int *", 42)
415 q = ffi.new("int *", 42)
416 assert lib.foo(p) == p
417 assert lib.foo(q) != p
418
419 def test_bogus_ptr():
420 ffi = FFI()
421 ffi.cdef("int *foo(int *);")
422 lib = ffi.verify("int *foo(int *a) { return a; }")
423 py.test.raises(TypeError, lib.foo, ffi.new("short *", 42))
424
425
426 def test_verify_typedefs():
427 py.test.skip("ignored so far")
428 types = ['signed char', 'unsigned char', 'int', 'long']
429 for cdefed in types:
430 for real in types:
431 ffi = FFI()
432 ffi.cdef("typedef %s foo_t;" % cdefed)
433 if cdefed == real:
434 ffi.verify("typedef %s foo_t;" % real)
435 else:
436 py.test.raises(VerificationError, ffi.verify,
437 "typedef %s foo_t;" % real)
438
439 def test_nondecl_struct():
440 ffi = FFI()
441 ffi.cdef("typedef struct foo_s foo_t; int bar(foo_t *);")
442 lib = ffi.verify("typedef struct foo_s foo_t;\n"
443 "int bar(foo_t *f) { (void)f; return 42; }\n")
444 assert lib.bar(ffi.NULL) == 42
445
446 def test_ffi_full_struct():
447 ffi = FFI()
448 ffi.cdef("struct foo_s { char x; int y; long *z; };")
449 ffi.verify("struct foo_s { char x; int y; long *z; };")
450 #
451 if sys.platform != 'win32': # XXX fixme: only gives warnings
452 py.test.raises(VerificationError, ffi.verify,
453 "struct foo_s { char x; int y; int *z; };")
454 #
455 py.test.raises(VerificationError, ffi.verify,
456 "struct foo_s { int y; long *z; };")
457 #
458 e = py.test.raises(VerificationError, ffi.verify,
459 "struct foo_s { int y; char x; long *z; };")
460 assert str(e.value) == (
461 "struct foo_s: wrong offset for field 'x'"
462 " (we have 0, but C compiler says 4)")
463 #
464 e = py.test.raises(VerificationError, ffi.verify,
465 "struct foo_s { char x; int y; long *z; char extra; };")
466 assert str(e.value) == (
467 "struct foo_s: wrong total size"
468 " (we have %d, but C compiler says %d)" % (
469 ffi.sizeof("struct foo_s"),
470 ffi.sizeof("struct foo_s") + ffi.sizeof("long*")))
471 #
472 # a corner case that we cannot really detect, but where it has no
473 # bad consequences: the size is the same, but there is an extra field
474 # that replaces what is just padding in our declaration above
475 ffi.verify("struct foo_s { char x, extra; int y; long *z; };")
476 #
477 e = py.test.raises(VerificationError, ffi.verify,
478 "struct foo_s { char x; short pad; short y; long *z; };")
479 assert str(e.value) == (
480 "struct foo_s: wrong size for field 'y'"
481 " (we have 4, but C compiler says 2)")
482
483 def test_ffi_nonfull_struct():
484 ffi = FFI()
485 ffi.cdef("""
486 struct foo_s {
487 int x;
488 ...;
489 };
490 """)
491 py.test.raises(VerificationMissing, ffi.sizeof, 'struct foo_s')
492 py.test.raises(VerificationMissing, ffi.offsetof, 'struct foo_s', 'x')
493 py.test.raises(VerificationMissing, ffi.new, 'struct foo_s *')
494 ffi.verify("""
495 struct foo_s {
496 int a, b, x, c, d, e;
497 };
498 """)
499 assert ffi.sizeof('struct foo_s') == 6 * ffi.sizeof('int')
500 assert ffi.offsetof('struct foo_s', 'x') == 2 * ffi.sizeof('int')
501
502 def test_ffi_nonfull_alignment():
503 ffi = FFI()
504 ffi.cdef("struct foo_s { char x; ...; };")
505 ffi.verify("struct foo_s { int a, b; char x; };")
506 assert ffi.sizeof('struct foo_s') == 3 * ffi.sizeof('int')
507 assert ffi.alignof('struct foo_s') == ffi.sizeof('int')
508
509 def _check_field_match(typename, real, expect_mismatch):
510 ffi = FFI()
511 testing_by_size = (expect_mismatch == 'by_size')
512 if testing_by_size:
513 expect_mismatch = ffi.sizeof(typename) != ffi.sizeof(real)
514 ffi.cdef("struct foo_s { %s x; ...; };" % typename)
515 try:
516 ffi.verify("struct foo_s { %s x; };" % real)
517 except VerificationError:
518 if not expect_mismatch:
519 if testing_by_size and typename != real:
520 print("ignoring mismatch between %s* and %s* even though "
521 "they have the same size" % (typename, real))
522 return
523 raise AssertionError("unexpected mismatch: %s should be accepted "
524 "as equal to %s" % (typename, real))
525 else:
526 if expect_mismatch:
527 raise AssertionError("mismatch not detected: "
528 "%s != %s" % (typename, real))
529
530 def test_struct_bad_sized_integer():
531 for typename in ['int8_t', 'int16_t', 'int32_t', 'int64_t']:
532 for real in ['int8_t', 'int16_t', 'int32_t', 'int64_t']:
533 _check_field_match(typename, real, "by_size")
534
535 def test_struct_bad_sized_float():
536 for typename in all_float_types:
537 for real in all_float_types:
538 _check_field_match(typename, real, "by_size")
539
540 def test_struct_signedness_ignored():
541 _check_field_match("int", "unsigned int", expect_mismatch=False)
542 _check_field_match("unsigned short", "signed short", expect_mismatch=False)
543
544 def test_struct_float_vs_int():
545 if sys.platform == 'win32':
546 py.test.skip("XXX fixme: only gives warnings")
547 ffi = FFI()
548 for typename in all_signed_integer_types(ffi):
549 for real in all_float_types:
550 _check_field_match(typename, real, expect_mismatch=True)
551 for typename in all_float_types:
552 for real in all_signed_integer_types(ffi):
553 _check_field_match(typename, real, expect_mismatch=True)
554
555 def test_struct_array_field():
556 ffi = FFI()
557 ffi.cdef("struct foo_s { int a[17]; ...; };")
558 ffi.verify("struct foo_s { int x; int a[17]; int y; };")
559 assert ffi.sizeof('struct foo_s') == 19 * ffi.sizeof('int')
560 s = ffi.new("struct foo_s *")
561 assert ffi.sizeof(s.a) == 17 * ffi.sizeof('int')
562
563 def test_struct_array_no_length():
564 ffi = FFI()
565 ffi.cdef("struct foo_s { int a[]; int y; ...; };\n"
566 "int bar(struct foo_s *);\n")
567 lib = ffi.verify("struct foo_s { int x; int a[17]; int y; };\n"
568 "int bar(struct foo_s *f) { return f->a[14]; }\n")
569 assert ffi.sizeof('struct foo_s') == 19 * ffi.sizeof('int')
570 s = ffi.new("struct foo_s *")
571 assert ffi.typeof(s.a) is ffi.typeof('int[]') # implicit max length
572 assert len(s.a) == 18 # max length, computed from the size and start offset
573 s.a[14] = 4242
574 assert lib.bar(s) == 4242
575 # with no declared length, out-of-bound accesses are not detected
576 s.a[17] = -521
577 assert s.y == s.a[17] == -521
578 #
579 s = ffi.new("struct foo_s *", {'a': list(range(17))})
580 assert s.a[16] == 16
581 # overflows at construction time not detected either
582 s = ffi.new("struct foo_s *", {'a': list(range(18))})
583 assert s.y == s.a[17] == 17
584
585 def test_struct_array_guess_length():
586 ffi = FFI()
587 ffi.cdef("struct foo_s { int a[...]; };")
588 ffi.verify("struct foo_s { int x; int a[17]; int y; };")
589 assert ffi.sizeof('struct foo_s') == 19 * ffi.sizeof('int')
590 s = ffi.new("struct foo_s *")
591 assert ffi.sizeof(s.a) == 17 * ffi.sizeof('int')
592 py.test.raises(IndexError, 's.a[17]')
593
594 def test_struct_array_c99_1():
595 if sys.platform == 'win32':
596 py.test.skip("requires C99")
597 ffi = FFI()
598 ffi.cdef("struct foo_s { int x; int a[]; };")
599 ffi.verify("struct foo_s { int x; int a[]; };")
600 assert ffi.sizeof('struct foo_s') == 1 * ffi.sizeof('int')
601 s = ffi.new("struct foo_s *", [424242, 4])
602 assert ffi.sizeof(ffi.typeof(s[0])) == 1 * ffi.sizeof('int')
603 assert ffi.sizeof(s[0]) == 5 * ffi.sizeof('int')
604 # ^^^ explanation: if you write in C: "char x[5];", then
605 # "sizeof(x)" will evaluate to 5. The behavior above is
606 # a generalization of that to "struct foo_s[len(a)=5] x;"
607 # if you could do that in C.
608 assert s.a[3] == 0
609 s = ffi.new("struct foo_s *", [424242, [-40, -30, -20, -10]])
610 assert ffi.sizeof(s[0]) == 5 * ffi.sizeof('int')
611 assert s.a[3] == -10
612 s = ffi.new("struct foo_s *")
613 assert ffi.sizeof(s[0]) == 1 * ffi.sizeof('int')
614 s = ffi.new("struct foo_s *", [424242])
615 assert ffi.sizeof(s[0]) == 1 * ffi.sizeof('int')
616
617 def test_struct_array_c99_2():
618 if sys.platform == 'win32':
619 py.test.skip("requires C99")
620 ffi = FFI()
621 ffi.cdef("struct foo_s { int x; int a[]; ...; };")
622 ffi.verify("struct foo_s { int x, y; int a[]; };")
623 assert ffi.sizeof('struct foo_s') == 2 * ffi.sizeof('int')
624 s = ffi.new("struct foo_s *", [424242, 4])
625 assert ffi.sizeof(s[0]) == 6 * ffi.sizeof('int')
626 assert s.a[3] == 0
627 s = ffi.new("struct foo_s *", [424242, [-40, -30, -20, -10]])
628 assert ffi.sizeof(s[0]) == 6 * ffi.sizeof('int')
629 assert s.a[3] == -10
630 s = ffi.new("struct foo_s *")
631 assert ffi.sizeof(s[0]) == 2 * ffi.sizeof('int')
632 s = ffi.new("struct foo_s *", [424242])
633 assert ffi.sizeof(s[0]) == 2 * ffi.sizeof('int')
634
635 def test_struct_ptr_to_array_field():
636 ffi = FFI()
637 ffi.cdef("struct foo_s { int (*a)[17]; ...; }; struct bar_s { ...; };")
638 ffi.verify("struct foo_s { int x; int (*a)[17]; int y; };\n"
639 "struct bar_s { int x; int *a; int y; };")
640 assert ffi.sizeof('struct foo_s') == ffi.sizeof("struct bar_s")
641 s = ffi.new("struct foo_s *")
642 assert ffi.sizeof(s.a) == ffi.sizeof('int(*)[17]') == ffi.sizeof("int *")
643
644 def test_struct_with_bitfield_exact():
645 ffi = FFI()
646 ffi.cdef("struct foo_s { int a:2, b:3; };")
647 ffi.verify("struct foo_s { int a:2, b:3; };")
648 s = ffi.new("struct foo_s *")
649 s.b = 3
650 py.test.raises(OverflowError, "s.b = 4")
651 assert s.b == 3
652
653 def test_struct_with_bitfield_enum():
654 ffi = FFI()
655 code = """
656 typedef enum { AA, BB, CC } foo_e;
657 typedef struct { foo_e f:2; } foo_s;
658 """
659 ffi.cdef(code)
660 ffi.verify(code)
661 s = ffi.new("foo_s *")
662 s.f = 2
663 assert s.f == 2
664
665 def test_unsupported_struct_with_bitfield_ellipsis():
666 ffi = FFI()
667 py.test.raises(NotImplementedError, ffi.cdef,
668 "struct foo_s { int a:2, b:3; ...; };")
669
670 def test_global_constants():
671 ffi = FFI()
672 # use 'static const int', as generally documented, although in this
673 # case the 'static' is completely ignored.
674 ffi.cdef("static const int AA, BB, CC, DD;")
675 lib = ffi.verify("#define AA 42\n"
676 "#define BB (-43) // blah\n"
677 "#define CC (22*2) /* foobar */\n"
678 "#define DD ((unsigned int)142) /* foo\nbar */\n")
679 assert lib.AA == 42
680 assert lib.BB == -43
681 assert lib.CC == 44
682 assert lib.DD == 142
683
684 def test_global_const_int_size():
685 # integer constants: ignore the declared type, always just use the value
686 for value in [-2**63, -2**31, -2**15,
687 2**15-1, 2**15, 2**31-1, 2**31, 2**32-1, 2**32,
688 2**63-1, 2**63, 2**64-1]:
689 ffi = FFI()
690 if value == int(ffi.cast("long long", value)):
691 if value < 0:
692 vstr = '(-%dLL-1)' % (~value,)
693 else:
694 vstr = '%dLL' % value
695 elif value == int(ffi.cast("unsigned long long", value)):
696 vstr = '%dULL' % value
697 else:
698 raise AssertionError(value)
699 ffi.cdef("static const unsigned short AA;")
700 lib = ffi.verify("#define AA %s\n" % vstr)
701 assert lib.AA == value
702 assert type(lib.AA) is type(int(lib.AA))
703
704 def test_global_constants_non_int():
705 ffi = FFI()
706 ffi.cdef("static char *const PP;")
707 lib = ffi.verify('static char *const PP = "testing!";\n')
708 assert ffi.typeof(lib.PP) == ffi.typeof("char *")
709 assert ffi.string(lib.PP) == b"testing!"
710
711 def test_nonfull_enum():
712 ffi = FFI()
713 ffi.cdef("enum ee { EE1, EE2, EE3, ... \n \t };")
714 py.test.raises(VerificationMissing, ffi.cast, 'enum ee', 'EE2')
715 ffi.verify("enum ee { EE1=10, EE2, EE3=-10, EE4 };")
716 assert ffi.string(ffi.cast('enum ee', 11)) == "EE2"
717 assert ffi.string(ffi.cast('enum ee', -10)) == "EE3"
718 #
719 # try again
720 ffi.verify("enum ee { EE1=10, EE2, EE3=-10, EE4 };")
721 assert ffi.string(ffi.cast('enum ee', 11)) == "EE2"
722 #
723 assert ffi.typeof("enum ee").relements == {'EE1': 10, 'EE2': 11, 'EE3': -10}
724 assert ffi.typeof("enum ee").elements == {10: 'EE1', 11: 'EE2', -10: 'EE3'}
725
726 def test_full_enum():
727 ffi = FFI()
728 ffi.cdef("enum ee { EE1, EE2, EE3 };")
729 ffi.verify("enum ee { EE1, EE2, EE3 };")
730 py.test.raises(VerificationError, ffi.verify, "enum ee { EE1, EE2 };")
731 e = py.test.raises(VerificationError, ffi.verify,
732 "enum ee { EE1, EE3, EE2 };")
733 assert str(e.value) == 'enum ee: EE2 has the real value 2, not 1'
734 # extra items cannot be seen and have no bad consequence anyway
735 lib = ffi.verify("enum ee { EE1, EE2, EE3, EE4 };")
736 assert lib.EE3 == 2
737
738 def test_enum_usage():
739 ffi = FFI()
740 ffi.cdef("enum ee { EE1,EE2 }; typedef struct { enum ee x; } *sp;")
741 lib = ffi.verify("enum ee { EE1,EE2 }; typedef struct { enum ee x; } *sp;")
742 assert lib.EE2 == 1
743 s = ffi.new("sp", [lib.EE2])
744 assert s.x == 1
745 s.x = 17
746 assert s.x == 17
747
748 def test_anonymous_enum():
749 ffi = FFI()
750 ffi.cdef("enum { EE1 }; enum { EE2, EE3 };")
751 lib = ffi.verify("enum { EE1 }; enum { EE2, EE3 };")
752 assert lib.EE1 == 0
753 assert lib.EE2 == 0
754 assert lib.EE3 == 1
755
756 def test_nonfull_anonymous_enum():
757 ffi = FFI()
758 ffi.cdef("enum { EE1, ... }; enum { EE3, ... };")
759 lib = ffi.verify("enum { EE2, EE1 }; enum { EE3 };")
760 assert lib.EE1 == 1
761 assert lib.EE3 == 0
762
763 def test_nonfull_enum_syntax2():
764 ffi = FFI()
765 ffi.cdef("enum ee { EE1, EE2=\t..., EE3 };")
766 py.test.raises(VerificationMissing, ffi.cast, 'enum ee', 'EE1')
767 ffi.verify("enum ee { EE1=10, EE2, EE3=-10, EE4 };")
768 assert ffi.string(ffi.cast('enum ee', 11)) == 'EE2'
769 assert ffi.string(ffi.cast('enum ee', -10)) == 'EE3'
770 #
771 ffi = FFI()
772 ffi.cdef("enum ee { EE1, EE2=\t... };")
773 py.test.raises(VerificationMissing, ffi.cast, 'enum ee', 'EE1')
774 ffi.verify("enum ee { EE1=10, EE2, EE3=-10, EE4 };")
775 assert ffi.string(ffi.cast('enum ee', 11)) == 'EE2'
776 #
777 ffi = FFI()
778 ffi.cdef("enum ee2 { EE4=..., EE5=..., ... };")
779 ffi.verify("enum ee2 { EE4=-1234-5, EE5 }; ")
780 assert ffi.string(ffi.cast('enum ee2', -1239)) == 'EE4'
781 assert ffi.string(ffi.cast('enum ee2', -1238)) == 'EE5'
782
783 def test_nonfull_enum_bug3():
784 ffi = FFI()
785 ffi.cdef("enum ee2 { EE4=..., EE5=... };")
786 ffi.cdef("enum ee6 { EE7=10, EE8=..., EE9=... };")
787
788 def test_get_set_errno():
789 ffi = FFI()
790 ffi.cdef("int foo(int);")
791 lib = ffi.verify("""
792 static int foo(int x)
793 {
794 errno += 1;
795 return x * 7;
796 }
797 """)
798 ffi.errno = 15
799 assert lib.foo(6) == 42
800 assert ffi.errno == 16
801
802 def test_define_int():
803 ffi = FFI()
804 ffi.cdef("#define FOO ...\n"
805 "\t#\tdefine\tBAR\t...\t\n"
806 "#define BAZ ...\n")
807 lib = ffi.verify("#define FOO 42\n"
808 "#define BAR (-44)\n"
809 "#define BAZ 0xffffffffffffffffULL\n")
810 assert lib.FOO == 42
811 assert lib.BAR == -44
812 assert lib.BAZ == 0xffffffffffffffff
813
814 def test_access_variable():
815 ffi = FFI()
816 ffi.cdef("int foo(void);\n"
817 "int somenumber;")
818 lib = ffi.verify("""
819 static int somenumber = 2;
820 static int foo(void) {
821 return somenumber * 7;
822 }
823 """)
824 assert lib.somenumber == 2
825 assert lib.foo() == 14
826 lib.somenumber = -6
827 assert lib.foo() == -42
828 assert lib.somenumber == -6
829 lib.somenumber = 2 # reset for the next run, if any
830
831 def test_access_address_of_variable():
832 # access the address of 'somenumber': need a trick
833 ffi = FFI()
834 ffi.cdef("int somenumber; static int *const somenumberptr;")
835 lib = ffi.verify("""
836 static int somenumber = 2;
837 #define somenumberptr (&somenumber)
838 """)
839 assert lib.somenumber == 2
840 lib.somenumberptr[0] = 42
841 assert lib.somenumber == 42
842 lib.somenumber = 2 # reset for the next run, if any
843
844 def test_access_array_variable(length=5):
845 ffi = FFI()
846 ffi.cdef("int foo(int);\n"
847 "int somenumber[%s];" % (length,))
848 lib = ffi.verify("""
849 static int somenumber[] = {2, 2, 3, 4, 5};
850 static int foo(int i) {
851 return somenumber[i] * 7;
852 }
853 """)
854 if length == '':
855 # a global variable of an unknown array length is implicitly
856 # transformed into a global pointer variable, because we can only
857 # work with array instances whose length we know. using a pointer
858 # instead of an array gives the correct effects.
859 assert repr(lib.somenumber).startswith("<cdata 'int *' 0x")
860 py.test.raises(TypeError, len, lib.somenumber)
861 else:
862 assert repr(lib.somenumber).startswith("<cdata 'int[%s]' 0x" % length)
863 assert len(lib.somenumber) == 5
864 assert lib.somenumber[3] == 4
865 assert lib.foo(3) == 28
866 lib.somenumber[3] = -6
867 assert lib.foo(3) == -42
868 assert lib.somenumber[3] == -6
869 assert lib.somenumber[4] == 5
870 lib.somenumber[3] = 4 # reset for the next run, if any
871
872 def test_access_array_variable_length_hidden():
873 test_access_array_variable(length='')
874
875 def test_access_struct_variable():
876 ffi = FFI()
877 ffi.cdef("struct foo { int x; ...; };\n"
878 "int foo(int);\n"
879 "struct foo stuff;")
880 lib = ffi.verify("""
881 struct foo { int x, y, z; };
882 static struct foo stuff = {2, 5, 8};
883 static int foo(int i) {
884 switch (i) {
885 case 0: return stuff.x * 7;
886 case 1: return stuff.y * 7;
887 case 2: return stuff.z * 7;
888 }
889 return -1;
890 }
891 """)
892 assert lib.stuff.x == 2
893 assert lib.foo(0) == 14
894 assert lib.foo(1) == 35
895 assert lib.foo(2) == 56
896 lib.stuff.x = -6
897 assert lib.foo(0) == -42
898 assert lib.foo(1) == 35
899 lib.stuff.x = 2 # reset for the next run, if any
900
901 def test_access_callback():
902 ffi = FFI()
903 ffi.cdef("int (*cb)(int);\n"
904 "int foo(int);\n"
905 "void reset_cb(void);")
906 lib = ffi.verify("""
907 static int g(int x) { return x * 7; }
908 static int (*cb)(int);
909 static int foo(int i) { return cb(i) - 1; }
910 static void reset_cb(void) { cb = g; }
911 """)
912 lib.reset_cb()
913 assert lib.foo(6) == 41
914 my_callback = ffi.callback("int(*)(int)", lambda n: n * 222)
915 lib.cb = my_callback
916 assert lib.foo(4) == 887
917
918 def test_access_callback_function_typedef():
919 ffi = FFI()
920 ffi.cdef("typedef int mycallback_t(int);\n"
921 "mycallback_t *cb;\n"
922 "int foo(int);\n"
923 "void reset_cb(void);")
924 lib = ffi.verify("""
925 static int g(int x) { return x * 7; }
926 static int (*cb)(int);
927 static int foo(int i) { return cb(i) - 1; }
928 static void reset_cb(void) { cb = g; }
929 """)
930 lib.reset_cb()
931 assert lib.foo(6) == 41
932 my_callback = ffi.callback("int(*)(int)", lambda n: n * 222)
933 lib.cb = my_callback
934 assert lib.foo(4) == 887
935
936 def test_ctypes_backend_forces_generic_engine():
937 from cffi.backend_ctypes import CTypesBackend
938 ffi = FFI(backend=CTypesBackend())
939 ffi.cdef("int func(int a);")
940 lib = ffi.verify("int func(int a) { return a * 42; }")
941 assert not hasattr(lib, '_cffi_python_module')
942 assert hasattr(lib, '_cffi_generic_module')
943 assert lib.func(100) == 4200
944
945 def test_call_with_struct_ptr():
946 ffi = FFI()
947 ffi.cdef("typedef struct { int x; ...; } foo_t; int foo(foo_t *);")
948 lib = ffi.verify("""
949 typedef struct { int y, x; } foo_t;
950 static int foo(foo_t *f) { return f->x * 7; }
951 """)
952 f = ffi.new("foo_t *")
953 f.x = 6
954 assert lib.foo(f) == 42
955
956 def test_unknown_type():
957 ffi = FFI()
958 ffi.cdef("""
959 typedef ... token_t;
960 int foo(token_t *);
961 #define TOKEN_SIZE ...
962 """)
963 lib = ffi.verify("""
964 typedef float token_t;
965 static int foo(token_t *tk) {
966 if (!tk)
967 return -42;
968 *tk += 1.601f;
969 return (int)*tk;
970 }
971 #define TOKEN_SIZE sizeof(token_t)
972 """)
973 # we cannot let ffi.new("token_t *") work, because we don't know ahead of
974 # time if it's ok to ask 'sizeof(token_t)' in the C code or not.
975 # See test_unknown_type_2. Workaround.
976 tkmem = ffi.new("char[]", lib.TOKEN_SIZE) # zero-initialized
977 tk = ffi.cast("token_t *", tkmem)
978 results = [lib.foo(tk) for i in range(6)]
979 assert results == [1, 3, 4, 6, 8, 9]
980 assert lib.foo(ffi.NULL) == -42
981
982 def test_unknown_type_2():
983 ffi = FFI()
984 ffi.cdef("typedef ... token_t;")
985 lib = ffi.verify("typedef struct token_s token_t;")
986 # assert did not crash, even though 'sizeof(token_t)' is not valid in C.
987
988 def test_unknown_type_3():
989 ffi = FFI()
990 ffi.cdef("""
991 typedef ... *token_p;
992 token_p foo(token_p);
993 """)
994 lib = ffi.verify("""
995 typedef struct _token_s *token_p;
996 token_p foo(token_p arg) {
997 if (arg)
998 return (token_p)0x12347;
999 else
1000 return (token_p)0x12345;
1001 }
1002 """)
1003 p = lib.foo(ffi.NULL)
1004 assert int(ffi.cast("intptr_t", p)) == 0x12345
1005 q = lib.foo(p)
1006 assert int(ffi.cast("intptr_t", q)) == 0x12347
1007
1008 def test_varargs():
1009 ffi = FFI()
1010 ffi.cdef("int foo(int x, ...);")
1011 lib = ffi.verify("""
1012 int foo(int x, ...) {
1013 va_list vargs;
1014 va_start(vargs, x);
1015 x -= va_arg(vargs, int);
1016 x -= va_arg(vargs, int);
1017 va_end(vargs);
1018 return x;
1019 }
1020 """)
1021 assert lib.foo(50, ffi.cast("int", 5), ffi.cast("int", 3)) == 42
1022
1023 def test_varargs_exact():
1024 if sys.platform == 'win32':
1025 py.test.skip("XXX fixme: only gives warnings")
1026 ffi = FFI()
1027 ffi.cdef("int foo(int x, ...);")
1028 py.test.raises(VerificationError, ffi.verify, """
1029 int foo(long long x, ...) {
1030 return x;
1031 }
1032 """)
1033
1034 def test_varargs_struct():
1035 ffi = FFI()
1036 ffi.cdef("struct foo_s { char a; int b; }; int foo(int x, ...);")
1037 lib = ffi.verify("""
1038 struct foo_s {
1039 char a; int b;
1040 };
1041 int foo(int x, ...) {
1042 va_list vargs;
1043 struct foo_s s;
1044 va_start(vargs, x);
1045 s = va_arg(vargs, struct foo_s);
1046 va_end(vargs);
1047 return s.a - s.b;
1048 }
1049 """)
1050 s = ffi.new("struct foo_s *", [b'B', 1])
1051 assert lib.foo(50, s[0]) == ord('A')
1052
1053 def test_autofilled_struct_as_argument():
1054 ffi = FFI()
1055 ffi.cdef("struct foo_s { long a; double b; ...; };\n"
1056 "int foo(struct foo_s);")
1057 lib = ffi.verify("""
1058 struct foo_s {
1059 double b;
1060 long a;
1061 };
1062 int foo(struct foo_s s) {
1063 return (int)s.a - (int)s.b;
1064 }
1065 """)
1066 s = ffi.new("struct foo_s *", [100, 1])
1067 assert lib.foo(s[0]) == 99
1068 assert lib.foo([100, 1]) == 99
1069
1070 def test_autofilled_struct_as_argument_dynamic():
1071 ffi = FFI()
1072 ffi.cdef("struct foo_s { long a; ...; };\n"
1073 "int (*foo)(struct foo_s);")
1074 lib = ffi.verify("""
1075 struct foo_s {
1076 double b;
1077 long a;
1078 };
1079 int foo1(struct foo_s s) {
1080 return (int)s.a - (int)s.b;
1081 }
1082 int (*foo)(struct foo_s s) = &foo1;
1083 """)
1084 e = py.test.raises(NotImplementedError, lib.foo, "?")
1085 msg = ("ctype 'struct foo_s' not supported as argument. It is a struct "
1086 'declared with "...;", but the C calling convention may depend on '
1087 "the missing fields; or, it contains anonymous struct/unions. "
1088 "Such structs are only supported as argument "
1089 "if the function is 'API mode' and non-variadic (i.e. declared "
1090 "inside ffibuilder.cdef()+ffibuilder.set_source() and not taking "
1091 "a final '...' argument)")
1092 assert str(e.value) == msg
1093
1094 def test_func_returns_struct():
1095 ffi = FFI()
1096 ffi.cdef("""
1097 struct foo_s { int aa, bb; };
1098 struct foo_s foo(int a, int b);
1099 """)
1100 lib = ffi.verify("""
1101 struct foo_s { int aa, bb; };
1102 struct foo_s foo(int a, int b) {
1103 struct foo_s r;
1104 r.aa = a*a;
1105 r.bb = b*b;
1106 return r;
1107 }
1108 """)
1109 s = lib.foo(6, 7)
1110 assert repr(s) == "<cdata 'struct foo_s' owning 8 bytes>"
1111 assert s.aa == 36
1112 assert s.bb == 49
1113
1114 def test_func_as_funcptr():
1115 ffi = FFI()
1116 ffi.cdef("int *(*const fooptr)(void);")
1117 lib = ffi.verify("""
1118 int *foo(void) {
1119 return (int*)"foobar";
1120 }
1121 int *(*fooptr)(void) = foo;
1122 """)
1123 foochar = ffi.cast("char *(*)(void)", lib.fooptr)
1124 s = foochar()
1125 assert ffi.string(s) == b"foobar"
1126
1127 def test_funcptr_as_argument():
1128 ffi = FFI()
1129 ffi.cdef("""
1130 void qsort(void *base, size_t nel, size_t width,
1131 int (*compar)(const void *, const void *));
1132 """)
1133 ffi.verify("#include <stdlib.h>")
1134
1135 def test_func_as_argument():
1136 ffi = FFI()
1137 ffi.cdef("""
1138 void qsort(void *base, size_t nel, size_t width,
1139 int compar(const void *, const void *));
1140 """)
1141 ffi.verify("#include <stdlib.h>")
1142
1143 def test_array_as_argument():
1144 ffi = FFI()
1145 ffi.cdef("""
1146 size_t strlen(char string[]);
1147 """)
1148 ffi.verify("#include <string.h>")
1149
1150 def test_enum_as_argument():
1151 ffi = FFI()
1152 ffi.cdef("""
1153 enum foo_e { AA, BB, ... };
1154 int foo_func(enum foo_e);
1155 """)
1156 lib = ffi.verify("""
1157 enum foo_e { AA, CC, BB };
1158 int foo_func(enum foo_e e) { return (int)e; }
1159 """)
1160 assert lib.foo_func(lib.BB) == 2
1161 py.test.raises(TypeError, lib.foo_func, "BB")
1162
1163 def test_enum_as_function_result():
1164 ffi = FFI()
1165 ffi.cdef("""
1166 enum foo_e { AA, BB, ... };
1167 enum foo_e foo_func(int x);
1168 """)
1169 lib = ffi.verify("""
1170 enum foo_e { AA, CC, BB };
1171 enum foo_e foo_func(int x) { return (enum foo_e)x; }
1172 """)
1173 assert lib.foo_func(lib.BB) == lib.BB == 2
1174
1175 def test_enum_values():
1176 ffi = FFI()
1177 ffi.cdef("enum enum1_e { AA, BB };")
1178 lib = ffi.verify("enum enum1_e { AA, BB };")
1179 assert lib.AA == 0
1180 assert lib.BB == 1
1181 assert ffi.string(ffi.cast("enum enum1_e", 1)) == 'BB'
1182
1183 def test_typedef_complete_enum():
1184 ffi = FFI()
1185 ffi.cdef("typedef enum { AA, BB } enum1_t;")
1186 lib = ffi.verify("typedef enum { AA, BB } enum1_t;")
1187 assert ffi.string(ffi.cast("enum1_t", 1)) == 'BB'
1188 assert lib.AA == 0
1189 assert lib.BB == 1
1190
1191 def test_typedef_broken_complete_enum():
1192 ffi = FFI()
1193 ffi.cdef("typedef enum { AA, BB } enum1_t;")
1194 py.test.raises(VerificationError, ffi.verify,
1195 "typedef enum { AA, CC, BB } enum1_t;")
1196
1197 def test_typedef_incomplete_enum():
1198 ffi = FFI()
1199 ffi.cdef("typedef enum { AA, BB, ... } enum1_t;")
1200 lib = ffi.verify("typedef enum { AA, CC, BB } enum1_t;")
1201 assert ffi.string(ffi.cast("enum1_t", 1)) == '1'
1202 assert ffi.string(ffi.cast("enum1_t", 2)) == 'BB'
1203 assert lib.AA == 0
1204 assert lib.BB == 2
1205
1206 def test_typedef_enum_as_argument():
1207 ffi = FFI()
1208 ffi.cdef("""
1209 typedef enum { AA, BB, ... } foo_t;
1210 int foo_func(foo_t);
1211 """)
1212 lib = ffi.verify("""
1213 typedef enum { AA, CC, BB } foo_t;
1214 int foo_func(foo_t e) { return (int)e; }
1215 """)
1216 assert lib.foo_func(lib.BB) == lib.BB == 2
1217 py.test.raises(TypeError, lib.foo_func, "BB")
1218
1219 def test_typedef_enum_as_function_result():
1220 ffi = FFI()
1221 ffi.cdef("""
1222 typedef enum { AA, BB, ... } foo_t;
1223 foo_t foo_func(int x);
1224 """)
1225 lib = ffi.verify("""
1226 typedef enum { AA, CC, BB } foo_t;
1227 foo_t foo_func(int x) { return (foo_t)x; }
1228 """)
1229 assert lib.foo_func(lib.BB) == lib.BB == 2
1230
1231 def test_function_typedef():
1232 ffi = FFI()
1233 ffi.cdef("""
1234 typedef double func_t(double);
1235 func_t sin;
1236 """)
1237 lib = ffi.verify('#include <math.h>', libraries=lib_m)
1238 assert lib.sin(1.23) == math.sin(1.23)
1239
1240 def test_opaque_integer_as_function_result():
1241 #import platform
1242 #if platform.machine().startswith('sparc'):
1243 # py.test.skip('Breaks horribly on sparc (SIGILL + corrupted stack)')
1244 #elif platform.machine() == 'mips64' and sys.maxsize > 2**32:
1245 # py.test.skip('Segfaults on mips64el')
1246 # XXX bad abuse of "struct { ...; }". It only works a bit by chance
1247 # anyway. XXX think about something better :-(
1248 ffi = FFI()
1249 ffi.cdef("""
1250 typedef struct { ...; } myhandle_t;
1251 myhandle_t foo(void);
1252 """)
1253 lib = ffi.verify("""
1254 typedef short myhandle_t;
1255 myhandle_t foo(void) { return 42; }
1256 """)
1257 h = lib.foo()
1258 assert ffi.sizeof(h) == ffi.sizeof("short")
1259
1260 def test_return_partial_struct():
1261 ffi = FFI()
1262 ffi.cdef("""
1263 typedef struct { int x; ...; } foo_t;
1264 foo_t foo(void);
1265 """)
1266 lib = ffi.verify("""
1267 typedef struct { int y, x; } foo_t;
1268 foo_t foo(void) { foo_t r = { 45, 81 }; return r; }
1269 """)
1270 h = lib.foo()
1271 assert ffi.sizeof(h) == 2 * ffi.sizeof("int")
1272 assert h.x == 81
1273
1274 def test_take_and_return_partial_structs():
1275 ffi = FFI()
1276 ffi.cdef("""
1277 typedef struct { int x; ...; } foo_t;
1278 foo_t foo(foo_t, foo_t);
1279 """)
1280 lib = ffi.verify("""
1281 typedef struct { int y, x; } foo_t;
1282 foo_t foo(foo_t a, foo_t b) {
1283 foo_t r = { 100, a.x * 5 + b.x * 7 };
1284 return r;
1285 }
1286 """)
1287 args = ffi.new("foo_t[3]")
1288 args[0].x = 1000
1289 args[2].x = -498
1290 h = lib.foo(args[0], args[2])
1291 assert ffi.sizeof(h) == 2 * ffi.sizeof("int")
1292 assert h.x == 1000 * 5 - 498 * 7
1293
1294 def test_cannot_name_struct_type():
1295 ffi = FFI()
1296 ffi.cdef("typedef struct { int x; } **sp; void foo(sp);")
1297 e = py.test.raises(VerificationError, ffi.verify,
1298 "typedef struct { int x; } **sp; void foo(sp x) { }")
1299 assert 'in argument of foo: unknown type name' in str(e.value)
1300
1301 def test_dont_check_unnamable_fields():
1302 ffi = FFI()
1303 ffi.cdef("struct foo_s { struct { int x; } someone; };")
1304 ffi.verify("struct foo_s { struct { int x; } someone; };")
1305 # assert did not crash
1306
1307 def test_nested_anonymous_struct_exact():
1308 if sys.platform == 'win32':
1309 py.test.skip("nested anonymous struct/union")
1310 ffi = FFI()
1311 ffi.cdef("""
1312 struct foo_s { struct { int a; char b; }; union { char c, d; }; };
1313 """)
1314 ffi.verify("""
1315 struct foo_s { struct { int a; char b; }; union { char c, d; }; };
1316 """)
1317 p = ffi.new("struct foo_s *")
1318 assert ffi.sizeof(p[0]) == 3 * ffi.sizeof("int") # with alignment
1319 p.a = 1234567
1320 p.b = b'X'
1321 p.c = b'Y'
1322 assert p.a == 1234567
1323 assert p.b == b'X'
1324 assert p.c == b'Y'
1325 assert p.d == b'Y'
1326
1327 def test_nested_anonymous_struct_exact_error():
1328 if sys.platform == 'win32':
1329 py.test.skip("nested anonymous struct/union")
1330 ffi = FFI()
1331 ffi.cdef("""
1332 struct foo_s { struct { int a; char b; }; union { char c, d; }; };
1333 """)
1334 py.test.raises(VerificationError, ffi.verify, """
1335 struct foo_s { struct { int a; short b; }; union { char c, d; }; };
1336 """)
1337 py.test.raises(VerificationError, ffi.verify, """
1338 struct foo_s { struct { int a; char e, b; }; union { char c, d; }; };
1339 """)
1340
1341 def test_nested_anonymous_struct_inexact_1():
1342 ffi = FFI()
1343 ffi.cdef("""
1344 struct foo_s { struct { char b; ...; }; union { char c, d; }; };
1345 """)
1346 ffi.verify("""
1347 struct foo_s { int a, padding; char c, d, b; };
1348 """)
1349 assert ffi.sizeof("struct foo_s") == 3 * ffi.sizeof("int")
1350
1351 def test_nested_anonymous_struct_inexact_2():
1352 ffi = FFI()
1353 ffi.cdef("""
1354 struct foo_s { union { char c, d; }; struct { int a; char b; }; ...; };
1355 """)
1356 ffi.verify("""
1357 struct foo_s { int a, padding; char c, d, b; };
1358 """)
1359 assert ffi.sizeof("struct foo_s") == 3 * ffi.sizeof("int")
1360
1361 def test_ffi_union():
1362 ffi = FFI()
1363 ffi.cdef("union foo_u { char x; long *z; };")
1364 ffi.verify("union foo_u { char x; int y; long *z; };")
1365
1366 def test_ffi_union_partial():
1367 ffi = FFI()
1368 ffi.cdef("union foo_u { char x; ...; };")
1369 ffi.verify("union foo_u { char x; int y; };")
1370 assert ffi.sizeof("union foo_u") == 4
1371
1372 def test_ffi_union_with_partial_struct():
1373 ffi = FFI()
1374 ffi.cdef("struct foo_s { int x; ...; }; union foo_u { struct foo_s s; };")
1375 ffi.verify("struct foo_s { int a; int x; }; "
1376 "union foo_u { char b[32]; struct foo_s s; };")
1377 assert ffi.sizeof("struct foo_s") == 8
1378 assert ffi.sizeof("union foo_u") == 32
1379
1380 def test_ffi_union_partial_2():
1381 ffi = FFI()
1382 ffi.cdef("typedef union { char x; ...; } u1;")
1383 ffi.verify("typedef union { char x; int y; } u1;")
1384 assert ffi.sizeof("u1") == 4
1385
1386 def test_ffi_union_with_partial_struct_2():
1387 ffi = FFI()
1388 ffi.cdef("typedef struct { int x; ...; } s1;"
1389 "typedef union { s1 s; } u1;")
1390 ffi.verify("typedef struct { int a; int x; } s1; "
1391 "typedef union { char b[32]; s1 s; } u1;")
1392 assert ffi.sizeof("s1") == 8
1393 assert ffi.sizeof("u1") == 32
1394 assert ffi.offsetof("u1", "s") == 0
1395
1396 def test_ffi_struct_packed():
1397 if sys.platform == 'win32':
1398 py.test.skip("needs a GCC extension")
1399 ffi = FFI()
1400 ffi.cdef("struct foo_s { int b; ...; };")
1401 ffi.verify("""
1402 struct foo_s {
1403 char a;
1404 int b;
1405 } __attribute__((packed));
1406 """)
1407
1408 def test_tmpdir():
1409 import tempfile, os
1410 from pypy.module.test_lib_pypy.cffi_tests.udir import udir
1411 tmpdir = tempfile.mkdtemp(dir=str(udir))
1412 ffi = FFI()
1413 ffi.cdef("int foo(int);")
1414 lib = ffi.verify("int foo(int a) { return a + 42; }", tmpdir=tmpdir)
1415 assert os.listdir(tmpdir)
1416 assert lib.foo(100) == 142
1417
1418 def test_relative_to():
1419 import tempfile, os
1420 from pypy.module.test_lib_pypy.cffi_tests.udir import udir
1421 tmpdir = tempfile.mkdtemp(dir=str(udir))
1422 ffi = FFI()
1423 ffi.cdef("int foo(int);")
1424 f = open(os.path.join(tmpdir, 'foo.h'), 'w')
1425 f.write("int foo(int a) { return a + 42; }\n")
1426 f.close()
1427 lib = ffi.verify('#include "foo.h"',
1428 include_dirs=['.'],
1429 relative_to=os.path.join(tmpdir, 'x'))
1430 assert lib.foo(100) == 142
1431
1432 def test_bug1():
1433 ffi = FFI()
1434 ffi.cdef("""
1435 typedef struct tdlhandle_s { ...; } *tdl_handle_t;
1436 typedef struct my_error_code_ {
1437 tdl_handle_t *rh;
1438 } my_error_code_t;
1439 """)
1440 ffi.verify("""
1441 typedef struct tdlhandle_s { int foo; } *tdl_handle_t;
1442 typedef struct my_error_code_ {
1443 tdl_handle_t *rh;
1444 } my_error_code_t;
1445 """)
1446
1447 def test_bool():
1448 if sys.platform == 'win32':
1449 py.test.skip("_Bool not in MSVC")
1450 ffi = FFI()
1451 ffi.cdef("struct foo_s { _Bool x; };"
1452 "_Bool foo(_Bool); _Bool (*foop)(_Bool);")
1453 lib = ffi.verify("""
1454 struct foo_s { _Bool x; };
1455 int foo(int arg) {
1456 return !arg;
1457 }
1458 _Bool _foofunc(_Bool x) {
1459 return !x;
1460 }
1461 _Bool (*foop)(_Bool) = _foofunc;
1462 """)
1463 p = ffi.new("struct foo_s *")
1464 p.x = 1
1465 assert p.x is True
1466 py.test.raises(OverflowError, "p.x = -1")
1467 py.test.raises(TypeError, "p.x = 0.0")
1468 assert lib.foop(1) is False
1469 assert lib.foop(True) is False
1470 assert lib.foop(0) is True
1471 py.test.raises(OverflowError, lib.foop, 42)
1472 py.test.raises(TypeError, lib.foop, 0.0)
1473 assert lib.foo(1) is False
1474 assert lib.foo(True) is False
1475 assert lib.foo(0) is True
1476 py.test.raises(OverflowError, lib.foo, 42)
1477 py.test.raises(TypeError, lib.foo, 0.0)
1478 assert int(ffi.cast("_Bool", long(1))) == 1
1479 assert int(ffi.cast("_Bool", long(0))) == 0
1480 assert int(ffi.cast("_Bool", long(-1))) == 1
1481 assert int(ffi.cast("_Bool", 10**200)) == 1
1482 assert int(ffi.cast("_Bool", 10**40000)) == 1
1483 #
1484 class Foo(object):
1485 def __int__(self):
1486 self.seen = 1
1487 return result
1488 f = Foo()
1489 f.seen = 0
1490 result = 42
1491 assert int(ffi.cast("_Bool", f)) == 1
1492 assert f.seen
1493 f.seen = 0
1494 result = 0
1495 assert int(ffi.cast("_Bool", f)) == 0
1496 assert f.seen
1497 #
1498 py.test.raises(TypeError, ffi.cast, "_Bool", [])
1499
1500 def test_bool_on_long_double():
1501 if sys.platform == 'win32':
1502 py.test.skip("_Bool not in MSVC")
1503 f = 1E-250
1504 if f == 0.0 or f*f != 0.0:
1505 py.test.skip("unexpected precision")
1506 ffi = FFI()
1507 ffi.cdef("long double square(long double f); _Bool opposite(_Bool);")
1508 lib = ffi.verify("long double square(long double f) { return f*f; }\n"
1509 "_Bool opposite(_Bool x) { return !x; }")
1510 f0 = lib.square(0.0)
1511 f2 = lib.square(f)
1512 f3 = lib.square(f * 2.0)
1513 if repr(f2) == repr(f3):
1514 py.test.skip("long double doesn't have enough precision")
1515 assert float(f0) == float(f2) == float(f3) == 0.0 # too tiny for 'double'
1516 assert int(ffi.cast("_Bool", f2)) == 1
1517 assert int(ffi.cast("_Bool", f3)) == 1
1518 assert int(ffi.cast("_Bool", f0)) == 0
1519 py.test.raises(TypeError, lib.opposite, f2)
1520
1521 def test_cannot_pass_float():
1522 for basetype in ['char', 'short', 'int', 'long', 'long long']:
1523 for sign in ['signed', 'unsigned']:
1524 type = '%s %s' % (sign, basetype)
1525 ffi = FFI()
1526 ffi.cdef("struct foo_s { %s x; };\n"
1527 "int foo(%s);" % (type, type))
1528 lib = ffi.verify("""
1529 struct foo_s { %s x; };
1530 int foo(%s arg) {
1531 return !arg;
1532 }
1533 """ % (type, type))
1534 p = ffi.new("struct foo_s *")
1535 py.test.raises(TypeError, "p.x = 0.0")
1536 assert lib.foo(42) == 0
1537 assert lib.foo(0) == 1
1538 py.test.raises(TypeError, lib.foo, 0.0)
1539
1540 def test_cast_from_int_type_to_bool():
1541 ffi = FFI()
1542 for basetype in ['char', 'short', 'int', 'long', 'long long']:
1543 for sign in ['signed', 'unsigned']:
1544 type = '%s %s' % (sign, basetype)
1545 assert int(ffi.cast("_Bool", ffi.cast(type, 42))) == 1
1546 assert int(ffi.cast("bool", ffi.cast(type, 42))) == 1
1547 assert int(ffi.cast("_Bool", ffi.cast(type, 0))) == 0
1548
1549 def test_addressof():
1550 ffi = FFI()
1551 ffi.cdef("""
1552 struct point_s { int x, y; };
1553 struct foo_s { int z; struct point_s point; };
1554 struct point_s sum_coord(struct point_s *);
1555 """)
1556 lib = ffi.verify("""
1557 struct point_s { int x, y; };
1558 struct foo_s { int z; struct point_s point; };
1559 struct point_s sum_coord(struct point_s *point) {
1560 struct point_s r;
1561 r.x = point->x + point->y;
1562 r.y = point->x - point->y;
1563 return r;
1564 }
1565 """)
1566 p = ffi.new("struct foo_s *")
1567 p.point.x = 16
1568 p.point.y = 9
1569 py.test.raises(TypeError, lib.sum_coord, p.point)
1570 res = lib.sum_coord(ffi.addressof(p.point))
1571 assert res.x == 25
1572 assert res.y == 7
1573 res2 = lib.sum_coord(ffi.addressof(res))
1574 assert res2.x == 32
1575 assert res2.y == 18
1576 py.test.raises(TypeError, lib.sum_coord, res2)
1577
1578 def test_callback_in_thread():
1579 if sys.platform == 'win32':
1580 py.test.skip("pthread only")
1581 import os, subprocess, imp
1582 arg = os.path.join(os.path.dirname(__file__), 'callback_in_thread.py')
1583 g = subprocess.Popen([sys.executable, arg,
1584 os.path.dirname(imp.find_module('cffi')[1])])
1585 result = g.wait()
1586 assert result == 0
1587
1588 def test_keepalive_lib():
1589 ffi = FFI()
1590 ffi.cdef("int foobar(void);")
1591 lib = ffi.verify("int foobar(void) { return 42; }")
1592 func = lib.foobar
1593 ffi_r = weakref.ref(ffi)
1594 lib_r = weakref.ref(lib)
1595 del ffi
1596 import gc; gc.collect() # lib stays alive
1597 assert lib_r() is not None
1598 assert ffi_r() is not None
1599 assert func() == 42
1600
1601 def test_keepalive_ffi():
1602 ffi = FFI()
1603 ffi.cdef("int foobar(void);")
1604 lib = ffi.verify("int foobar(void) { return 42; }")
1605 func = lib.foobar
1606 ffi_r = weakref.ref(ffi)
1607 lib_r = weakref.ref(lib)
1608 del lib
1609 import gc; gc.collect() # ffi stays alive
1610 assert ffi_r() is not None
1611 assert lib_r() is not None
1612 assert func() == 42
1613
1614 def test_FILE_stored_in_stdout():
1615 if not sys.platform.startswith('linux'):
1616 py.test.skip("likely, we cannot assign to stdout")
1617 ffi = FFI()
1618 ffi.cdef("int printf(const char *, ...); FILE *setstdout(FILE *);")
1619 lib = ffi.verify("""
1620 #include <stdio.h>
1621 FILE *setstdout(FILE *f) {
1622 FILE *result = stdout;
1623 stdout = f;
1624 return result;
1625 }
1626 """)
1627 import os
1628 fdr, fdw = os.pipe()
1629 fw1 = os.fdopen(fdw, 'wb', 256)
1630 old_stdout = lib.setstdout(fw1)
1631 try:
1632 #
1633 fw1.write(b"X")
1634 r = lib.printf(b"hello, %d!\n", ffi.cast("int", 42))
1635 fw1.close()
1636 assert r == len("hello, 42!\n")
1637 #
1638 finally:
1639 lib.setstdout(old_stdout)
1640 #
1641 result = os.read(fdr, 256)
1642 os.close(fdr)
1643 # the 'X' might remain in the user-level buffer of 'fw1' and
1644 # end up showing up after the 'hello, 42!\n'
1645 assert result == b"Xhello, 42!\n" or result == b"hello, 42!\nX"
1646
1647 def test_FILE_stored_explicitly():
1648 ffi = FFI()
1649 ffi.cdef("int myprintf11(const char *, int); FILE *myfile;")
1650 lib = ffi.verify("""
1651 #include <stdio.h>
1652 FILE *myfile;
1653 int myprintf11(const char *out, int value) {
1654 return fprintf(myfile, out, value);
1655 }
1656 """)
1657 import os
1658 fdr, fdw = os.pipe()
1659 fw1 = os.fdopen(fdw, 'wb', 256)
1660 lib.myfile = ffi.cast("FILE *", fw1)
1661 #
1662 fw1.write(b"X")
1663 r = lib.myprintf11(b"hello, %d!\n", ffi.cast("int", 42))
1664 fw1.close()
1665 assert r == len("hello, 42!\n")
1666 #
1667 result = os.read(fdr, 256)
1668 os.close(fdr)
1669 # the 'X' might remain in the user-level buffer of 'fw1' and
1670 # end up showing up after the 'hello, 42!\n'
1671 assert result == b"Xhello, 42!\n" or result == b"hello, 42!\nX"
1672
1673 def test_global_array_with_missing_length():
1674 ffi = FFI()
1675 ffi.cdef("int fooarray[];")
1676 lib = ffi.verify("int fooarray[50];")
1677 assert repr(lib.fooarray).startswith("<cdata 'int *'")
1678
1679 def test_global_array_with_dotdotdot_length():
1680 ffi = FFI()
1681 ffi.cdef("int fooarray[...];")
1682 lib = ffi.verify("int fooarray[50];")
1683 assert repr(lib.fooarray).startswith("<cdata 'int[50]'")
1684
1685 def test_bad_global_array_with_dotdotdot_length():
1686 ffi = FFI()
1687 ffi.cdef("int fooarray[...];")
1688 py.test.raises(VerificationError, ffi.verify, "char fooarray[23];")
1689
1690 def test_struct_containing_struct():
1691 ffi = FFI()
1692 ffi.cdef("struct foo_s { ...; }; struct bar_s { struct foo_s f; ...; };")
1693 ffi.verify("struct foo_s { int x; }; struct bar_s { struct foo_s f; };")
1694 #
1695 ffi = FFI()
1696 ffi.cdef("struct foo_s { struct bar_s f; ...; }; struct bar_s { ...; };")
1697 ffi.verify("struct bar_s { int x; }; struct foo_s { struct bar_s f; };")
1698
1699 def test_struct_returned_by_func():
1700 ffi = FFI()
1701 ffi.cdef("typedef ... foo_t; foo_t myfunc(void);")
1702 e = py.test.raises(TypeError, ffi.verify,
1703 "typedef struct { int x; } foo_t; "
1704 "foo_t myfunc(void) { foo_t x = { 42 }; return x; }")
1705 assert str(e.value) == (
1706 "function myfunc: 'foo_t' is used as result type, but is opaque")
1707
1708 def test_include():
1709 ffi1 = FFI()
1710 ffi1.cdef("typedef struct { int x; ...; } foo_t;")
1711 ffi1.verify("typedef struct { int y, x; } foo_t;")
1712 ffi2 = FFI()
1713 ffi2.include(ffi1)
1714 ffi2.cdef("int myfunc(foo_t *);")
1715 lib = ffi2.verify("typedef struct { int y, x; } foo_t;"
1716 "int myfunc(foo_t *p) { return 42 * p->x; }")
1717 res = lib.myfunc(ffi2.new("foo_t *", {'x': 10}))
1718 assert res == 420
1719 res = lib.myfunc(ffi1.new("foo_t *", {'x': -10}))
1720 assert res == -420
1721
1722 def test_include_enum():
1723 ffi1 = FFI()
1724 ffi1.cdef("enum foo_e { AA, ... };")
1725 lib1 = ffi1.verify("enum foo_e { CC, BB, AA };")
1726 ffi2 = FFI()
1727 ffi2.include(ffi1)
1728 ffi2.cdef("int myfunc(enum foo_e);")
1729 lib2 = ffi2.verify("enum foo_e { CC, BB, AA };"
1730 "int myfunc(enum foo_e x) { return (int)x; }")
1731 res = lib2.myfunc(lib2.AA)
1732 assert res == 2
1733
1734 def test_named_pointer_as_argument():
1735 ffi = FFI()
1736 ffi.cdef("typedef struct { int x; } *mystruct_p;\n"
1737 "mystruct_p ff5a(mystruct_p);")
1738 lib = ffi.verify("typedef struct { int x; } *mystruct_p;\n"
1739 "mystruct_p ff5a(mystruct_p p) { p->x += 40; return p; }")
1740 p = ffi.new("mystruct_p", [-2])
1741 q = lib.ff5a(p)
1742 assert q == p
1743 assert p.x == 38
1744
1745 def test_enum_size():
1746 cases = [('123', 4, 4294967295),
1747 ('4294967295U', 4, 4294967295),
1748 ('-123', 4, -1),
1749 ('-2147483647-1', 4, -1),
1750 ]
1751 if FFI().sizeof("long") == 8:
1752 cases += [('4294967296L', 8, 2**64-1),
1753 ('%dUL' % (2**64-1), 8, 2**64-1),
1754 ('-2147483649L', 8, -1),
1755 ('%dL-1L' % (1-2**63), 8, -1)]
1756 for hidden_value, expected_size, expected_minus1 in cases:
1757 if sys.platform == 'win32' and 'U' in hidden_value:
1758 continue # skipped on Windows
1759 ffi = FFI()
1760 ffi.cdef("enum foo_e { AA, BB, ... };")
1761 lib = ffi.verify("enum foo_e { AA, BB=%s };" % hidden_value)
1762 assert lib.AA == 0
1763 assert lib.BB == eval(hidden_value.replace('U', '').replace('L', ''))
1764 assert ffi.sizeof("enum foo_e") == expected_size
1765 assert int(ffi.cast("enum foo_e", -1)) == expected_minus1
1766 # test with the large value hidden:
1767 # disabled so far, doesn't work
1768 ## for hidden_value, expected_size, expected_minus1 in cases:
1769 ## ffi = FFI()
1770 ## ffi.cdef("enum foo_e { AA, BB, ... };")
1771 ## lib = ffi.verify("enum foo_e { AA, BB=%s };" % hidden_value)
1772 ## assert lib.AA == 0
1773 ## assert ffi.sizeof("enum foo_e") == expected_size
1774 ## assert int(ffi.cast("enum foo_e", -1)) == expected_minus1
1775
1776 def test_enum_bug118():
1777 maxulong = 256 ** FFI().sizeof("unsigned long") - 1
1778 for c1, c2, c2c in [(0xffffffff, -1, ''),
1779 (maxulong, -1, ''),
1780 (-1, 0xffffffff, 'U'),
1781 (-1, maxulong, 'UL')]:
1782 if c2c and sys.platform == 'win32':
1783 continue # enums may always be signed with MSVC
1784 ffi = FFI()
1785 ffi.cdef("enum foo_e { AA=%s };" % c1)
1786 e = py.test.raises(VerificationError, ffi.verify,
1787 "enum foo_e { AA=%s%s };" % (c2, c2c))
1788 assert str(e.value) == ('enum foo_e: AA has the real value %d, not %d'
1789 % (c2, c1))
1790
1791 def test_string_to_voidp_arg():
1792 ffi = FFI()
1793 ffi.cdef("int myfunc(void *);")
1794 lib = ffi.verify("int myfunc(void *p) { return ((signed char *)p)[0]; }")
1795 res = lib.myfunc(b"hi!")
1796 assert res == ord(b"h")
1797 p = ffi.new("char[]", b"gah")
1798 res = lib.myfunc(p)
1799 assert res == ord(b"g")
1800 res = lib.myfunc(ffi.cast("void *", p))
1801 assert res == ord(b"g")
1802 res = lib.myfunc(ffi.cast("int *", p))
1803 assert res == ord(b"g")
1804
1805 def test_callback_indirection():
1806 ffi = FFI()
1807 ffi.cdef("""
1808 int (*python_callback)(int how_many, int *values);
1809 int (*const c_callback)(int,...); /* pass this ptr to C routines */
1810 int some_c_function(int(*cb)(int,...));
1811 """)
1812 lib = ffi.verify("""
1813 #include <stdarg.h>
1814 #ifdef _WIN32
1815 #include <malloc.h>
1816 #define alloca _alloca
1817 #else
1818 # ifdef __FreeBSD__
1819 # include <stdlib.h>
1820 # else
1821 # include <alloca.h>
1822 # endif
1823 #endif
1824 static int (*python_callback)(int how_many, int *values);
1825 static int c_callback(int how_many, ...) {
1826 va_list ap;
1827 /* collect the "..." arguments into the values[] array */
1828 int i, *values = alloca((size_t)how_many * sizeof(int));
1829 va_start(ap, how_many);
1830 for (i=0; i<how_many; i++)
1831 values[i] = va_arg(ap, int);
1832 va_end(ap);
1833 return python_callback(how_many, values);
1834 }
1835 int some_c_function(int(*cb)(int,...)) {
1836 int result = cb(2, 10, 20);
1837 result += cb(3, 30, 40, 50);
1838 return result;
1839 }
1840 """)
1841 seen = []
1842 @ffi.callback("int(int, int*)")
1843 def python_callback(how_many, values):
1844 seen.append([values[i] for i in range(how_many)])
1845 return 42
1846 lib.python_callback = python_callback
1847
1848 res = lib.some_c_function(lib.c_callback)
1849 assert res == 84
1850 assert seen == [[10, 20], [30, 40, 50]]
1851
1852 def test_floatstar_argument():
1853 ffi = FFI()
1854 ffi.cdef("float sum3floats(float *);")
1855 lib = ffi.verify("""
1856 float sum3floats(float *f) {
1857 return f[0] + f[1] + f[2];
1858 }
1859 """)
1860 assert lib.sum3floats((1.5, 2.5, 3.5)) == 7.5
1861 p = ffi.new("float[]", (1.5, 2.5, 3.5))
1862 assert lib.sum3floats(p) == 7.5
1863
1864 def test_charstar_argument():
1865 ffi = FFI()
1866 ffi.cdef("char sum3chars(char *);")
1867 lib = ffi.verify("""
1868 char sum3chars(char *f) {
1869 return (char)(f[0] + f[1] + f[2]);
1870 }
1871 """)
1872 assert lib.sum3chars((b'\x10', b'\x20', b'\x30')) == b'\x60'
1873 p = ffi.new("char[]", b'\x10\x20\x30')
1874 assert lib.sum3chars(p) == b'\x60'
1875
1876 def test_passing_string_or_NULL():
1877 ffi = FFI()
1878 ffi.cdef("int seeme1(char *); int seeme2(int *);")
1879 lib = ffi.verify("""
1880 int seeme1(char *x) {
1881 return (x == NULL);
1882 }
1883 int seeme2(int *x) {
1884 return (x == NULL);
1885 }
1886 """)
1887 assert lib.seeme1(b"foo") == 0
1888 assert lib.seeme1(ffi.NULL) == 1
1889 assert lib.seeme2([42, 43]) == 0
1890 assert lib.seeme2(ffi.NULL) == 1
1891 py.test.raises(TypeError, lib.seeme1, None)
1892 py.test.raises(TypeError, lib.seeme2, None)
1893 py.test.raises(TypeError, lib.seeme1, 0.0)
1894 py.test.raises(TypeError, lib.seeme2, 0.0)
1895 py.test.raises(TypeError, lib.seeme1, 0)
1896 py.test.raises(TypeError, lib.seeme2, 0)
1897 zeroL = 99999999999999999999
1898 zeroL -= 99999999999999999999
1899 py.test.raises(TypeError, lib.seeme2, zeroL)
1900
1901 def test_typeof_function():
1902 ffi = FFI()
1903 ffi.cdef("int foo(int, char);")
1904 lib = ffi.verify("int foo(int x, char y) { (void)x; (void)y; return 42; }")
1905 ctype = ffi.typeof(lib.foo)
1906 assert len(ctype.args) == 2
1907 assert ctype.result == ffi.typeof("int")
1908
1909 def test_call_with_voidstar_arg():
1910 ffi = FFI()
1911 ffi.cdef("int f(void *);")
1912 lib = ffi.verify("int f(void *x) { return ((char*)x)[0]; }")
1913 assert lib.f(b"foobar") == ord(b"f")
1914
1915 def test_dir():
1916 ffi = FFI()
1917 ffi.cdef("""void somefunc(void);
1918 extern int somevar, somearray[2];
1919 static char *const sv2;
1920 enum my_e { AA, BB, ... };
1921 #define FOO ...""")
1922 lib = ffi.verify("""void somefunc(void) { }
1923 int somevar, somearray[2];
1924 #define sv2 "text"
1925 enum my_e { AA, BB };
1926 #define FOO 42""")
1927 assert dir(lib) == ['AA', 'BB', 'FOO', 'somearray',
1928 'somefunc', 'somevar', 'sv2']
1929
1930 def test_typeof_func_with_struct_argument():
1931 ffi = FFI()
1932 ffi.cdef("""struct s { int a; }; int foo(struct s);""")
1933 lib = ffi.verify("""struct s { int a; };
1934 int foo(struct s x) { return x.a; }""")
1935 s = ffi.new("struct s *", [-1234])
1936 m = lib.foo(s[0])
1937 assert m == -1234
1938 assert repr(ffi.typeof(lib.foo)) == "<ctype 'int(*)(struct s)'>"
1939
1940 def test_bug_const_char_ptr_array_1():
1941 ffi = FFI()
1942 ffi.cdef("""const char *a[...];""")
1943 lib = ffi.verify("""const char *a[5];""")
1944 assert repr(ffi.typeof(lib.a)) == "<ctype 'char *[5]'>"
1945
1946 def test_bug_const_char_ptr_array_2():
1947 from cffi import FFI # ignore warnings
1948 ffi = FFI()
1949 ffi.cdef("""const int a[];""")
1950 lib = ffi.verify("""const int a[5];""")
1951 assert repr(ffi.typeof(lib.a)) == "<ctype 'int *'>"
1952
1953 def _test_various_calls(force_libffi):
1954 cdef_source = """
1955 int xvalue;
1956 long long ivalue, rvalue;
1957 float fvalue;
1958 double dvalue;
1959 long double Dvalue;
1960 signed char tf_bb(signed char x, signed char c);
1961 unsigned char tf_bB(signed char x, unsigned char c);
1962 short tf_bh(signed char x, short c);
1963 unsigned short tf_bH(signed char x, unsigned short c);
1964 int tf_bi(signed char x, int c);
1965 unsigned int tf_bI(signed char x, unsigned int c);
1966 long tf_bl(signed char x, long c);
1967 unsigned long tf_bL(signed char x, unsigned long c);
1968 long long tf_bq(signed char x, long long c);
1969 unsigned long long tf_bQ(signed char x, unsigned long long c);
1970 float tf_bf(signed char x, float c);
1971 double tf_bd(signed char x, double c);
1972 long double tf_bD(signed char x, long double c);
1973 """
1974 if force_libffi:
1975 cdef_source = (cdef_source
1976 .replace('tf_', '(*const tf_')
1977 .replace('(signed char x', ')(signed char x'))
1978 ffi = FFI()
1979 ffi.cdef(cdef_source)
1980 lib = ffi.verify("""
1981 int xvalue;
1982 long long ivalue, rvalue;
1983 float fvalue;
1984 double dvalue;
1985 long double Dvalue;
1986
1987 typedef signed char b_t;
1988 typedef unsigned char B_t;
1989 typedef short h_t;
1990 typedef unsigned short H_t;
1991 typedef int i_t;
1992 typedef unsigned int I_t;
1993 typedef long l_t;
1994 typedef unsigned long L_t;
1995 typedef long long q_t;
1996 typedef unsigned long long Q_t;
1997 typedef float f_t;
1998 typedef double d_t;
1999 typedef long double D_t;
2000 #define S(letter) xvalue = (int)x; letter##value = (letter##_t)c;
2001 #define R(letter) return (letter##_t)rvalue;
2002
2003 signed char tf_bb(signed char x, signed char c) { S(i) R(b) }
2004 unsigned char tf_bB(signed char x, unsigned char c) { S(i) R(B) }
2005 short tf_bh(signed char x, short c) { S(i) R(h) }
2006 unsigned short tf_bH(signed char x, unsigned short c) { S(i) R(H) }
2007 int tf_bi(signed char x, int c) { S(i) R(i) }
2008 unsigned int tf_bI(signed char x, unsigned int c) { S(i) R(I) }
2009 long tf_bl(signed char x, long c) { S(i) R(l) }
2010 unsigned long tf_bL(signed char x, unsigned long c) { S(i) R(L) }
2011 long long tf_bq(signed char x, long long c) { S(i) R(q) }
2012 unsigned long long tf_bQ(signed char x, unsigned long long c) { S(i) R(Q) }
2013 float tf_bf(signed char x, float c) { S(f) R(f) }
2014 double tf_bd(signed char x, double c) { S(d) R(d) }
2015 long double tf_bD(signed char x, long double c) { S(D) R(D) }
2016 """)
2017 lib.rvalue = 0x7182838485868788
2018 for kind, cname in [('b', 'signed char'),
2019 ('B', 'unsigned char'),
2020 ('h', 'short'),
2021 ('H', 'unsigned short'),
2022 ('i', 'int'),
2023 ('I', 'unsigned int'),
2024 ('l', 'long'),
2025 ('L', 'unsigned long'),
2026 ('q', 'long long'),
2027 ('Q', 'unsigned long long'),
2028 ('f', 'float'),
2029 ('d', 'double'),
2030 ('D', 'long double')]:
2031 sign = +1 if 'unsigned' in cname else -1
2032 lib.xvalue = 0
2033 lib.ivalue = 0
2034 lib.fvalue = 0
2035 lib.dvalue = 0
2036 lib.Dvalue = 0
2037 fun = getattr(lib, 'tf_b' + kind)
2038 res = fun(-42, sign * 99)
2039 if kind == 'D':
2040 res = float(res)
2041 assert res == int(ffi.cast(cname, 0x7182838485868788))
2042 assert lib.xvalue == -42
2043 if kind in 'fdD':
2044 assert float(getattr(lib, kind + 'value')) == -99.0
2045 else:
2046 assert lib.ivalue == sign * 99
2047
2048 def test_various_calls_direct():
2049 _test_various_calls(force_libffi=False)
2050
2051 def test_various_calls_libffi():
2052 _test_various_calls(force_libffi=True)
2053
2054 def test_ptr_to_opaque():
2055 ffi = FFI()
2056 ffi.cdef("typedef ... foo_t; int f1(foo_t*); foo_t *f2(int);")
2057 lib = ffi.verify("""
2058 #include <stdlib.h>
2059 typedef struct { int x; } foo_t;
2060 int f1(foo_t* p) {
2061 int x = p->x;
2062 free(p);
2063 return x;
2064 }
2065 foo_t *f2(int x) {
2066 foo_t *p = malloc(sizeof(foo_t));
2067 p->x = x;
2068 return p;
2069 }
2070 """)
2071 p = lib.f2(42)
2072 x = lib.f1(p)
2073 assert x == 42
2074
2075 def _run_in_multiple_threads(test1):
2076 test1()
2077 import sys
2078 try:
2079 import thread
2080 except ImportError:
2081 import _thread as thread
2082 errors = []
2083 def wrapper(lock):
2084 try:
2085 test1()
2086 except:
2087 errors.append(sys.exc_info())
2088 lock.release()
2089 locks = []
2090 for i in range(10):
2091 _lock = thread.allocate_lock()
2092 _lock.acquire()
2093 thread.start_new_thread(wrapper, (_lock,))
2094 locks.append(_lock)
2095 for _lock in locks:
2096 _lock.acquire()
2097 if errors:
2098 raise errors[0][1]
2099
2100 def test_errno_working_even_with_pypys_jit():
2101 ffi = FFI()
2102 ffi.cdef("int f(int);")
2103 lib = ffi.verify("""
2104 #include <errno.h>
2105 int f(int x) { return (errno = errno + x); }
2106 """)
2107 @_run_in_multiple_threads
2108 def test1():
2109 ffi.errno = 0
2110 for i in range(10000):
2111 e = lib.f(1)
2112 assert e == i + 1
2113 assert ffi.errno == e
2114 for i in range(10000):
2115 ffi.errno = i
2116 e = lib.f(42)
2117 assert e == i + 42
2118
2119 def test_getlasterror_working_even_with_pypys_jit():
2120 if sys.platform != 'win32':
2121 py.test.skip("win32-only test")
2122 ffi = FFI()
2123 ffi.cdef("void SetLastError(DWORD);")
2124 lib = ffi.dlopen("Kernel32.dll")
2125 @_run_in_multiple_threads
2126 def test1():
2127 for i in range(10000):
2128 n = (1 << 29) + i
2129 lib.SetLastError(n)
2130 assert ffi.getwinerror()[0] == n
2131
2132 def test_verify_dlopen_flags():
2133 # Careful with RTLD_GLOBAL. If by chance the FFI is not deleted
2134 # promptly, like on PyPy, then other tests may see the same
2135 # exported symbols as well. So we must not export a simple name
2136 # like 'foo'!
2137 ffi1 = FFI()
2138 ffi1.cdef("int foo_verify_dlopen_flags;")
2139
2140 lib1 = ffi1.verify("int foo_verify_dlopen_flags;",
2141 flags=ffi1.RTLD_GLOBAL | ffi1.RTLD_LAZY)
2142 lib2 = get_second_lib()
2143
2144 lib1.foo_verify_dlopen_flags = 42
2145 assert lib2.foo_verify_dlopen_flags == 42
2146 lib2.foo_verify_dlopen_flags += 1
2147 assert lib1.foo_verify_dlopen_flags == 43
2148
2149 def get_second_lib():
2150 # Hack, using modulename makes the test fail
2151 ffi2 = FFI()
2152 ffi2.cdef("int foo_verify_dlopen_flags;")
2153 lib2 = ffi2.verify("int foo_verify_dlopen_flags;",
2154 flags=ffi2.RTLD_GLOBAL | ffi2.RTLD_LAZY)
2155 return lib2
2156
2157 def test_consider_not_implemented_function_type():
2158 ffi = FFI()
2159 ffi.cdef("typedef union { int a; float b; } Data;"
2160 "typedef struct { int a:2; } MyStr;"
2161 "typedef void (*foofunc_t)(Data);"
2162 "typedef Data (*bazfunc_t)(void);"
2163 "typedef MyStr (*barfunc_t)(void);")
2164 fooptr = ffi.cast("foofunc_t", 123)
2165 bazptr = ffi.cast("bazfunc_t", 123)
2166 barptr = ffi.cast("barfunc_t", 123)
2167 # assert did not crash so far
2168 e = py.test.raises(NotImplementedError, fooptr, ffi.new("Data *"))
2169 assert str(e.value) == (
2170 "ctype 'Data' not supported as argument by libffi. Unions are only "
2171 "supported as argument if the function is 'API mode' and "
2172 "non-variadic (i.e. declared inside ffibuilder.cdef()+"
2173 "ffibuilder.set_source() and not taking a final '...' argument)")
2174 e = py.test.raises(NotImplementedError, bazptr)
2175 assert str(e.value) == (
2176 "ctype 'Data' not supported as return value by libffi. Unions are "
2177 "only supported as return value if the function is 'API mode' and "
2178 "non-variadic (i.e. declared inside ffibuilder.cdef()+"
2179 "ffibuilder.set_source() and not taking a final '...' argument)")
2180 e = py.test.raises(NotImplementedError, barptr)
2181 assert str(e.value) == (
2182 "ctype 'MyStr' not supported as return value. It is a struct with "
2183 "bit fields, which libffi does not support. Such structs are only "
2184 "supported as return value if the function is 'API mode' and non-"
2185 "variadic (i.e. declared inside ffibuilder.cdef()+ffibuilder."
2186 "set_source() and not taking a final '...' argument)")
2187
2188 def test_verify_extra_arguments():
2189 ffi = FFI()
2190 ffi.cdef("#define ABA ...")
2191 lib = ffi.verify("", define_macros=[('ABA', '42')])
2192 assert lib.ABA == 42
2193
2194 def test_implicit_unicode_on_windows():
2195 if sys.platform != 'win32':
2196 py.test.skip("win32-only test")
2197 ffi = FFI()
2198 e = py.test.raises(FFIError, ffi.cdef, "int foo(LPTSTR);")
2199 assert str(e.value) == ("The Windows type 'LPTSTR' is only available after"
2200 " you call ffi.set_unicode()")
2201 for with_unicode in [True, False]:
2202 ffi = FFI()
2203 ffi.set_unicode(with_unicode)
2204 ffi.cdef("""
2205 DWORD GetModuleFileName(HMODULE hModule, LPTSTR lpFilename,
2206 DWORD nSize);
2207 """)
2208 lib = ffi.verify("""
2209 #include <windows.h>
2210 """, libraries=['Kernel32'])
2211 outbuf = ffi.new("TCHAR[]", 200)
2212 n = lib.GetModuleFileName(ffi.NULL, outbuf, 500)
2213 assert 0 < n < 500
2214 for i in range(n):
2215 #print repr(outbuf[i])
2216 assert ord(outbuf[i]) != 0
2217 assert ord(outbuf[n]) == 0
2218 assert ord(outbuf[0]) < 128 # should be a letter, or '\'
2219
2220 def test_use_local_dir():
2221 ffi = FFI()
2222 lib = ffi.verify("", modulename="test_use_local_dir")
2223 this_dir = os.path.dirname(__file__)
2224 pycache_files = os.listdir(os.path.join(this_dir, '__pycache__'))
2225 assert any('test_use_local_dir' in s for s in pycache_files)
2226
2227 def test_define_known_value():
2228 ffi = FFI()
2229 ffi.cdef("#define FOO 0x123")
2230 lib = ffi.verify("#define FOO 0x123")
2231 assert lib.FOO == 0x123
2232
2233 def test_define_wrong_value():
2234 ffi = FFI()
2235 ffi.cdef("#define FOO 123")
2236 e = py.test.raises(VerificationError, ffi.verify, "#define FOO 124")
2237 assert str(e.value).endswith("FOO has the real value 124, not 123")
2238
2239 def test_static_const_int_known_value():
2240 ffi = FFI()
2241 ffi.cdef("static const int FOO = 0x123;")
2242 lib = ffi.verify("#define FOO 0x123")
2243 assert lib.FOO == 0x123
2244
2245 def test_static_const_int_wrong_value():
2246 ffi = FFI()
2247 ffi.cdef("static const int FOO = 123;")
2248 e = py.test.raises(VerificationError, ffi.verify, "#define FOO 124")
2249 assert str(e.value).endswith("FOO has the real value 124, not 123")
2250
2251 def test_const_struct_global():
2252 ffi = FFI()
2253 ffi.cdef("typedef struct { int x; ...; } T; const T myglob;")
2254 lib = ffi.verify("typedef struct { double y; int x; } T;"
2255 "const T myglob = { 0.1, 42 };")
2256 assert ffi.typeof(lib.myglob) == ffi.typeof("T")
2257 assert lib.myglob.x == 42
2258
2259 def test_dont_support_int_dotdotdot():
2260 ffi = FFI()
2261 ffi.cdef("typedef int... t1;")
2262 e = py.test.raises(VerificationError, ffi.verify, "")
2263 assert str(e.value) == ("feature not supported with ffi.verify(), but only "
2264 "with ffi.set_source(): 'typedef int... t1'")
2265 ffi = FFI()
2266 ffi.cdef("typedef double ... t1;")
2267 e = py.test.raises(VerificationError, ffi.verify, "")
2268 assert str(e.value) == ("feature not supported with ffi.verify(), but only "
2269 "with ffi.set_source(): 'typedef float... t1'")
2270
2271 def test_const_fields():
2272 ffi = FFI()
2273 ffi.cdef("""struct foo_s { const int a; void *const b; };""")
2274 ffi.verify("""struct foo_s { const int a; void *const b; };""")
2275 foo_s = ffi.typeof("struct foo_s")
2276 assert foo_s.fields[0][0] == 'a'
2277 assert foo_s.fields[0][1].type is ffi.typeof("int")
2278 assert foo_s.fields[1][0] == 'b'
2279 assert foo_s.fields[1][1].type is ffi.typeof("void *")
2280
2281 def test_win32_calling_convention_0():
2282 ffi = FFI()
2283 ffi.cdef("""
2284 int call1(int(__cdecl *cb)(int));
2285 int (*const call2)(int(__stdcall *cb)(int));
2286 """)
2287 lib = ffi.verify(r"""
2288 #ifndef _MSC_VER
2289 # define __stdcall /* nothing */
2290 #endif
2291 int call1(int(*cb)(int)) {
2292 int i, result = 0;
2293 //printf("call1: cb = %p\n", cb);
2294 for (i = 0; i < 1000; i++)
2295 result += cb(i);
2296 //printf("result = %d\n", result);
2297 return result;
2298 }
2299 int call2(int(__stdcall *cb)(int)) {
2300 int i, result = 0;
2301 //printf("call2: cb = %p\n", cb);
2302 for (i = 0; i < 1000; i++)
2303 result += cb(-i);
2304 //printf("result = %d\n", result);
2305 return result;
2306 }
2307 """)
2308 @ffi.callback("int(int)")
2309 def cb1(x):
2310 return x * 2
2311 @ffi.callback("int __stdcall(int)")
2312 def cb2(x):
2313 return x * 3
2314 #print 'cb1 =', cb1
2315 res = lib.call1(cb1)
2316 assert res == 500*999*2
2317 #print 'cb2 =', cb2
2318 #print ffi.typeof(lib.call2)
2319 #print 'call2 =', lib.call2
2320 res = lib.call2(cb2)
2321 #print '...'
2322 assert res == -500*999*3
2323 #print 'done'
2324 if sys.platform == 'win32' and sys.maxsize < 2**32:
2325 assert '__stdcall' in str(ffi.typeof(cb2))
2326 assert '__stdcall' not in str(ffi.typeof(cb1))
2327 py.test.raises(TypeError, lib.call1, cb2)
2328 py.test.raises(TypeError, lib.call2, cb1)
2329 else:
2330 assert '__stdcall' not in str(ffi.typeof(cb2))
2331 assert ffi.typeof(cb2) is ffi.typeof(cb1)
2332
2333 def test_win32_calling_convention_1():
2334 ffi = FFI()
2335 ffi.cdef("""
2336 int __cdecl call1(int(__cdecl *cb)(int));
2337 int __stdcall call2(int(__stdcall *cb)(int));
2338 int (__cdecl *const cb1)(int);
2339 int (__stdcall *const cb2)(int);
2340 """)
2341 lib = ffi.verify(r"""
2342 #ifndef _MSC_VER
2343 # define __cdecl
2344 # define __stdcall
2345 #endif
2346 int __cdecl cb1(int x) { return x * 2; }
2347 int __stdcall cb2(int x) { return x * 3; }
2348
2349 int __cdecl call1(int(__cdecl *cb)(int)) {
2350 int i, result = 0;
2351 //printf("here1\n");
2352 //printf("cb = %p, cb1 = %p\n", cb, (void *)cb1);
2353 for (i = 0; i < 1000; i++)
2354 result += cb(i);
2355 //printf("result = %d\n", result);
2356 return result;
2357 }
2358 int __stdcall call2(int(__stdcall *cb)(int)) {
2359 int i, result = 0;
2360 //printf("here1\n");
2361 //printf("cb = %p, cb2 = %p\n", cb, (void *)cb2);
2362 for (i = 0; i < 1000; i++)
2363 result += cb(-i);
2364 //printf("result = %d\n", result);
2365 return result;
2366 }
2367 """)
2368 assert lib.call1(lib.cb1) == 500*999*2
2369 assert lib.call2(lib.cb2) == -500*999*3
2370
2371 def test_win32_calling_convention_2():
2372 # any mistake in the declaration of plain function (including the
2373 # precise argument types and, here, the calling convention) are
2374 # automatically corrected. But this does not apply to the 'cb'
2375 # function pointer argument.
2376 ffi = FFI()
2377 ffi.cdef("""
2378 int __stdcall call1(int(__cdecl *cb)(int));
2379 int __cdecl call2(int(__stdcall *cb)(int));
2380 int (__cdecl *const cb1)(int);
2381 int (__stdcall *const cb2)(int);
2382 """)
2383 lib = ffi.verify(r"""
2384 #ifndef _MSC_VER
2385 # define __cdecl
2386 # define __stdcall
2387 #endif
2388 int __cdecl call1(int(__cdecl *cb)(int)) {
2389 int i, result = 0;
2390 for (i = 0; i < 1000; i++)
2391 result += cb(i);
2392 return result;
2393 }
2394 int __stdcall call2(int(__stdcall *cb)(int)) {
2395 int i, result = 0;
2396 for (i = 0; i < 1000; i++)
2397 result += cb(-i);
2398 return result;
2399 }
2400 int __cdecl cb1(int x) { return x * 2; }
2401 int __stdcall cb2(int x) { return x * 3; }
2402 """)
2403 assert lib.call1(lib.cb1) == 500*999*2
2404 assert lib.call2(lib.cb2) == -500*999*3
2405
2406 def test_win32_calling_convention_3():
2407 ffi = FFI()
2408 ffi.cdef("""
2409 struct point { int x, y; };
2410
2411 int (*const cb1)(struct point);
2412 int (__stdcall *const cb2)(struct point);
2413
2414 struct point __stdcall call1(int(*cb)(struct point));
2415 struct point call2(int(__stdcall *cb)(struct point));
2416 """)
2417 lib = ffi.verify(r"""
2418 #ifndef _MSC_VER
2419 # define __cdecl
2420 # define __stdcall
2421 #endif
2422 struct point { int x, y; };
2423 int cb1(struct point pt) { return pt.x + 10 * pt.y; }
2424 int __stdcall cb2(struct point pt) { return pt.x + 100 * pt.y; }
2425 struct point __stdcall call1(int(__cdecl *cb)(struct point)) {
2426 int i;
2427 struct point result = { 0, 0 };
2428 //printf("here1\n");
2429 //printf("cb = %p, cb1 = %p\n", cb, (void *)cb1);
2430 for (i = 0; i < 1000; i++) {
2431 struct point p = { i, -i };
2432 int r = cb(p);
2433 result.x += r;
2434 result.y -= r;
2435 }
2436 return result;
2437 }
2438 struct point __cdecl call2(int(__stdcall *cb)(struct point)) {
2439 int i;
2440 struct point result = { 0, 0 };
2441 for (i = 0; i < 1000; i++) {
2442 struct point p = { -i, i };
2443 int r = cb(p);
2444 result.x += r;
2445 result.y -= r;
2446 }
2447 return result;
2448 }
2449 """)
2450 if sys.platform == 'win32' and sys.maxsize < 2**32:
2451 py.test.raises(TypeError, lib.call1, lib.cb2)
2452 py.test.raises(TypeError, lib.call2, lib.cb1)
2453 pt = lib.call1(lib.cb1)
2454 assert (pt.x, pt.y) == (-9*500*999, 9*500*999)
2455 pt = lib.call2(lib.cb2)
2456 assert (pt.x, pt.y) == (99*500*999, -99*500*999)
2457
2458 def _only_test_on_linux_intel():
2459 if not sys.platform.startswith('linux'):
2460 py.test.skip('only running the memory-intensive test on Linux')
2461 import platform
2462 machine = platform.machine()
2463 if 'x86' not in machine and 'x64' not in machine:
2464 py.test.skip('only running the memory-intensive test on x86/x64')
2465
2466 def test_ffi_gc_size_arg():
2467 # with PyPy's GC, these calls to ffi.gc() would rapidly consume
2468 # 40 GB of RAM without the third argument
2469 _only_test_on_linux_intel()
2470 ffi = FFI()
2471 ffi.cdef("void *malloc(size_t); void free(void *);")
2472 lib = ffi.verify(r"""
2473 #include <stdlib.h>
2474 """)
2475 for i in range(2000):
2476 p = lib.malloc(20*1024*1024) # 20 MB
2477 p1 = ffi.cast("char *", p)
2478 for j in range(0, 20*1024*1024, 4096):
2479 p1[j] = b'!'
2480 p = ffi.gc(p, lib.free, 20*1024*1024)
2481 del p
2482
2483 def test_ffi_gc_size_arg_2():
2484 # a variant of the above: this "attack" works on cpython's cyclic gc too
2485 # and I found no obvious way to prevent that. So for now, this test
2486 # is skipped on CPython, where it eats all the memory.
2487 if '__pypy__' not in sys.builtin_module_names:
2488 py.test.skip("find a way to tweak the cyclic GC of CPython")
2489 _only_test_on_linux_intel()
2490 ffi = FFI()
2491 ffi.cdef("void *malloc(size_t); void free(void *);")
2492 lib = ffi.verify(r"""
2493 #include <stdlib.h>
2494 """)
2495 class X(object):
2496 pass
2497 for i in range(2000):
2498 p = lib.malloc(50*1024*1024) # 50 MB
2499 p1 = ffi.cast("char *", p)
2500 for j in range(0, 50*1024*1024, 4096):
2501 p1[j] = b'!'
2502 p = ffi.gc(p, lib.free, 50*1024*1024)
2503 x = X()
2504 x.p = p
2505 x.cyclic = x
2506 del p, x
2507
2508 def test_ffi_new_with_cycles():
2509 # still another variant, with ffi.new()
2510 if '__pypy__' not in sys.builtin_module_names:
2511 py.test.skip("find a way to tweak the cyclic GC of CPython")
2512 ffi = FFI()
2513 ffi.cdef("")
2514 lib = ffi.verify("")
2515 class X(object):
2516 pass
2517 for i in range(2000):
2518 p = ffi.new("char[]", 50*1024*1024) # 50 MB
2519 for j in range(0, 50*1024*1024, 4096):
2520 p[j] = b'!'
2521 x = X()
2522 x.p = p
2523 x.cyclic = x
2524 del p, x
+0
-10
pypy/module/test_lib_pypy/cffi_tests/cffi0/test_verify2.py less more
0 # Generated by pypy/tool/import_cffi.py
1 from .test_verify import *
2
3 # This test file runs normally after test_verify. We only clean up the .c
4 # sources, to check that it also works when we have only the .so. The
5 # tests should run much faster than test_verify.
6
7 def setup_module():
8 import cffi.verifier
9 cffi.verifier.cleanup_tmpdir(keep_so=True)
+0
-63
pypy/module/test_lib_pypy/cffi_tests/cffi0/test_version.py less more
0 # Generated by pypy/tool/import_cffi.py
1 import py, os, sys
2 import cffi, _cffi_backend
3
4 def setup_module(mod):
5 if '_cffi_backend' in sys.builtin_module_names:
6 py.test.skip("this is embedded version")
7
8 #BACKEND_VERSIONS = {
9 # '0.4.2': '0.4', # did not change
10 # '0.7.1': '0.7', # did not change
11 # '0.7.2': '0.7', # did not change
12 # '0.8.1': '0.8', # did not change (essentially)
13 # '0.8.4': '0.8.3', # did not change
14 # }
15
16 def test_version():
17 v = cffi.__version__
18 version_info = '.'.join(str(i) for i in cffi.__version_info__)
19 version_info = version_info.replace('.beta.', 'b')
20 version_info = version_info.replace('.plus', '+')
21 assert v == version_info
22 #v = BACKEND_VERSIONS.get(v, v)
23 assert v == _cffi_backend.__version__
24
25 def test_doc_version():
26 parent = os.path.dirname(os.path.dirname(cffi.__file__))
27 p = os.path.join(parent, 'doc', 'source', 'conf.py')
28 content = open(p).read()
29 #
30 v = cffi.__version__
31 assert ("version = '%s'\n" % v[:4]) in content
32 assert ("release = '%s'\n" % v) in content
33
34 def test_doc_version_file():
35 parent = os.path.dirname(os.path.dirname(cffi.__file__))
36 v = cffi.__version__.replace('+', '')
37 p = os.path.join(parent, 'doc', 'source', 'installation.rst')
38 content = open(p).read()
39 assert (" package version %s:" % v) in content
40
41 def test_setup_version():
42 parent = os.path.dirname(os.path.dirname(cffi.__file__))
43 p = os.path.join(parent, 'setup.py')
44 content = open(p).read()
45 #
46 v = cffi.__version__.replace('+', '')
47 assert ("version='%s'" % v) in content
48
49 def test_c_version():
50 parent = os.path.dirname(os.path.dirname(cffi.__file__))
51 v = cffi.__version__
52 p = os.path.join(parent, 'c', 'test_c.py')
53 content = open(p).read()
54 #v = BACKEND_VERSIONS.get(v, v)
55 assert (('assert __version__ == "%s"' % v) in content)
56
57 def test_embedding_h():
58 parent = os.path.dirname(os.path.dirname(cffi.__file__))
59 v = cffi.__version__
60 p = os.path.join(parent, 'cffi', '_embedding.h')
61 content = open(p).read()
62 assert ('cffi version: %s"' % (v,)) in content
+0
-13
pypy/module/test_lib_pypy/cffi_tests/cffi0/test_vgen.py less more
0 # Generated by pypy/tool/import_cffi.py
1 import cffi.verifier
2 from .test_verify import *
3
4
5 def setup_module():
6 cffi.verifier.cleanup_tmpdir()
7 cffi.verifier._FORCE_GENERIC_ENGINE = True
8 # Runs all tests with _FORCE_GENERIC_ENGINE = True, to make sure we
9 # also test vengine_gen.py.
10
11 def teardown_module():
12 cffi.verifier._FORCE_GENERIC_ENGINE = False
+0
-14
pypy/module/test_lib_pypy/cffi_tests/cffi0/test_vgen2.py less more
0 # Generated by pypy/tool/import_cffi.py
1 import cffi.verifier
2 from .test_vgen import *
3
4 # This test file runs normally after test_vgen. We only clean up the .c
5 # sources, to check that it also works when we have only the .so. The
6 # tests should run much faster than test_vgen.
7
8 def setup_module():
9 cffi.verifier.cleanup_tmpdir(keep_so=True)
10 cffi.verifier._FORCE_GENERIC_ENGINE = True
11
12 def teardown_module():
13 cffi.verifier._FORCE_GENERIC_ENGINE = False
+0
-289
pypy/module/test_lib_pypy/cffi_tests/cffi0/test_zdistutils.py less more
0 # Generated by pypy/tool/import_cffi.py
1 import sys, os, imp, math, shutil
2 import py
3 from cffi import FFI, FFIError
4 from cffi.verifier import Verifier, _locate_engine_class, _get_so_suffixes
5 from cffi.ffiplatform import maybe_relative_path
6 from pypy.module.test_lib_pypy.cffi_tests.udir import udir
7
8
9 class DistUtilsTest(object):
10 def setup_class(self):
11 self.lib_m = "m"
12 if sys.platform == 'win32':
13 #there is a small chance this fails on Mingw via environ $CC
14 import distutils.ccompiler
15 if distutils.ccompiler.get_default_compiler() == 'msvc':
16 self.lib_m = 'msvcrt'
17
18 def teardown_class(self):
19 if udir.isdir():
20 udir.remove(ignore_errors=True)
21 udir.ensure(dir=1)
22
23 def test_locate_engine_class(self):
24 cls = _locate_engine_class(FFI(), self.generic)
25 if self.generic:
26 # asked for the generic engine, which must not generate a
27 # CPython extension module
28 assert not cls._gen_python_module
29 else:
30 # asked for the CPython engine: check that we got it, unless
31 # we are running on top of PyPy, where the generic engine is
32 # always better
33 if '__pypy__' not in sys.builtin_module_names:
34 assert cls._gen_python_module
35
36 def test_write_source(self):
37 ffi = FFI()
38 ffi.cdef("double sin(double x);")
39 csrc = '/*hi there %s!*/\n#include <math.h>\n' % self
40 v = Verifier(ffi, csrc, force_generic_engine=self.generic,
41 libraries=[self.lib_m])
42 v.write_source()
43 with open(v.sourcefilename, 'r') as f:
44 data = f.read()
45 assert csrc in data
46
47 def test_write_source_explicit_filename(self):
48 ffi = FFI()
49 ffi.cdef("double sin(double x);")
50 csrc = '/*hi there %s!*/\n#include <math.h>\n' % self
51 v = Verifier(ffi, csrc, force_generic_engine=self.generic,
52 libraries=[self.lib_m])
53 v.sourcefilename = filename = str(udir.join('write_source.c'))
54 v.write_source()
55 assert filename == v.sourcefilename
56 with open(filename, 'r') as f:
57 data = f.read()
58 assert csrc in data
59
60 def test_write_source_to_file_obj(self):
61 ffi = FFI()
62 ffi.cdef("double sin(double x);")
63 csrc = '/*hi there %s!*/\n#include <math.h>\n' % self
64 v = Verifier(ffi, csrc, force_generic_engine=self.generic,
65 libraries=[self.lib_m])
66 try:
67 from StringIO import StringIO
68 except ImportError:
69 from io import StringIO
70 f = StringIO()
71 v.write_source(file=f)
72 assert csrc in f.getvalue()
73
74 def test_compile_module(self):
75 ffi = FFI()
76 ffi.cdef("double sin(double x);")
77 csrc = '/*hi there %s!*/\n#include <math.h>\n' % self
78 v = Verifier(ffi, csrc, force_generic_engine=self.generic,
79 libraries=[self.lib_m])
80 v.compile_module()
81 assert v.get_module_name().startswith('_cffi_')
82 if v.generates_python_module():
83 mod = imp.load_dynamic(v.get_module_name(), v.modulefilename)
84 assert hasattr(mod, '_cffi_setup')
85
86 def test_compile_module_explicit_filename(self):
87 ffi = FFI()
88 ffi.cdef("double sin(double x);")
89 csrc = '/*hi there %s!2*/\n#include <math.h>\n' % self
90 v = Verifier(ffi, csrc, force_generic_engine=self.generic,
91 libraries=[self.lib_m])
92 basename = self.__class__.__name__ + 'test_compile_module'
93 v.modulefilename = filename = str(udir.join(basename + '.so'))
94 v.compile_module()
95 assert filename == v.modulefilename
96 assert v.get_module_name() == basename
97 if v.generates_python_module():
98 mod = imp.load_dynamic(v.get_module_name(), v.modulefilename)
99 assert hasattr(mod, '_cffi_setup')
100
101 def test_name_from_checksum_of_cdef(self):
102 names = []
103 for csrc in ['double', 'double', 'float']:
104 ffi = FFI()
105 ffi.cdef("%s sin(double x);" % csrc)
106 v = Verifier(ffi, "#include <math.h>",
107 force_generic_engine=self.generic,
108 libraries=[self.lib_m])
109 names.append(v.get_module_name())
110 assert names[0] == names[1] != names[2]
111
112 def test_name_from_checksum_of_csrc(self):
113 names = []
114 for csrc in ['123', '123', '1234']:
115 ffi = FFI()
116 ffi.cdef("double sin(double x);")
117 v = Verifier(ffi, csrc, force_generic_engine=self.generic)
118 names.append(v.get_module_name())
119 assert names[0] == names[1] != names[2]
120
121 def test_load_library(self):
122 ffi = FFI()
123 ffi.cdef("double sin(double x);")
124 csrc = '/*hi there %s!3*/\n#include <math.h>\n' % self
125 v = Verifier(ffi, csrc, force_generic_engine=self.generic,
126 libraries=[self.lib_m])
127 library = v.load_library()
128 assert library.sin(12.3) == math.sin(12.3)
129
130 def test_verifier_args(self):
131 ffi = FFI()
132 ffi.cdef("double sin(double x);")
133 csrc = '/*hi there %s!4*/#include "test_verifier_args.h"\n' % self
134 udir.join('test_verifier_args.h').write('#include <math.h>\n')
135 v = Verifier(ffi, csrc, include_dirs=[str(udir)],
136 force_generic_engine=self.generic,
137 libraries=[self.lib_m])
138 library = v.load_library()
139 assert library.sin(12.3) == math.sin(12.3)
140
141 def test_verifier_object_from_ffi(self):
142 ffi = FFI()
143 ffi.cdef("double sin(double x);")
144 csrc = "/*6%s*/\n#include <math.h>" % self
145 lib = ffi.verify(csrc, force_generic_engine=self.generic,
146 libraries=[self.lib_m])
147 assert lib.sin(12.3) == math.sin(12.3)
148 assert isinstance(ffi.verifier, Verifier)
149 with open(ffi.verifier.sourcefilename, 'r') as f:
150 data = f.read()
151 assert csrc in data
152
153 def test_extension_object(self):
154 ffi = FFI()
155 ffi.cdef("double sin(double x);")
156 csrc = '/*7%s*/' % self + '''
157 #include <math.h>
158 #ifndef TEST_EXTENSION_OBJECT
159 # error "define_macros missing"
160 #endif
161 '''
162 lib = ffi.verify(csrc, define_macros=[('TEST_EXTENSION_OBJECT', '1')],
163 force_generic_engine=self.generic,
164 libraries=[self.lib_m])
165 assert lib.sin(12.3) == math.sin(12.3)
166 v = ffi.verifier
167 ext = v.get_extension()
168 assert 'distutils.extension.Extension' in str(ext.__class__) or \
169 'setuptools.extension.Extension' in str(ext.__class__)
170 assert ext.sources == [maybe_relative_path(v.sourcefilename)]
171 assert ext.name == v.get_module_name()
172 assert ext.define_macros == [('TEST_EXTENSION_OBJECT', '1')]
173
174 def test_extension_forces_write_source(self):
175 ffi = FFI()
176 ffi.cdef("double sin(double x);")
177 csrc = '/*hi there9!%s*/\n#include <math.h>\n' % self
178 v = Verifier(ffi, csrc, force_generic_engine=self.generic,
179 libraries=[self.lib_m])
180 assert not os.path.exists(v.sourcefilename)
181 v.get_extension()
182 assert os.path.exists(v.sourcefilename)
183
184 def test_extension_object_extra_sources(self):
185 ffi = FFI()
186 ffi.cdef("double test1eoes(double x);")
187 extra_source = str(udir.join('extension_extra_sources.c'))
188 with open(extra_source, 'w') as f:
189 f.write('double test1eoes(double x) { return x * 6.0; }\n')
190 csrc = '/*9%s*/' % self + '''
191 double test1eoes(double x); /* or #include "extra_sources.h" */
192 '''
193 lib = ffi.verify(csrc, sources=[extra_source],
194 force_generic_engine=self.generic)
195 assert lib.test1eoes(7.0) == 42.0
196 v = ffi.verifier
197 ext = v.get_extension()
198 assert 'distutils.extension.Extension' in str(ext.__class__) or \
199 'setuptools.extension.Extension' in str(ext.__class__)
200 assert ext.sources == [maybe_relative_path(v.sourcefilename),
201 extra_source]
202 assert ext.name == v.get_module_name()
203
204 def test_install_and_reload_module(self, targetpackage='', ext_package=''):
205 KEY = repr(self)
206 if not hasattr(os, 'fork'):
207 py.test.skip("test requires os.fork()")
208
209 if targetpackage:
210 udir.ensure(targetpackage, dir=1).ensure('__init__.py')
211 sys.path.insert(0, str(udir))
212
213 def make_ffi(**verifier_args):
214 ffi = FFI()
215 ffi.cdef("/* %s, %s, %s */" % (KEY, targetpackage, ext_package))
216 ffi.cdef("double test1iarm(double x);")
217 csrc = "double test1iarm(double x) { return x * 42.0; }"
218 lib = ffi.verify(csrc, force_generic_engine=self.generic,
219 ext_package=ext_package,
220 **verifier_args)
221 return ffi, lib
222
223 childpid = os.fork()
224 if childpid == 0:
225 # in the child
226 ffi, lib = make_ffi()
227 assert lib.test1iarm(1.5) == 63.0
228 # "install" the module by moving it into udir (/targetpackage)
229 if targetpackage:
230 target = udir.join(targetpackage)
231 else:
232 target = udir
233 shutil.move(ffi.verifier.modulefilename, str(target))
234 os._exit(0)
235 # in the parent
236 _, status = os.waitpid(childpid, 0)
237 if not (os.WIFEXITED(status) and os.WEXITSTATUS(status) == 0):
238 raise AssertionError # see error above in subprocess
239
240 from cffi import ffiplatform
241 prev_compile = ffiplatform.compile
242 try:
243 if targetpackage == ext_package:
244 ffiplatform.compile = lambda *args: dont_call_me_any_more
245 # won't find it in tmpdir, but should find it correctly
246 # installed in udir
247 ffi, lib = make_ffi()
248 assert lib.test1iarm(0.5) == 21.0
249 finally:
250 ffiplatform.compile = prev_compile
251
252 def test_install_and_reload_module_package(self):
253 self.test_install_and_reload_module(targetpackage='foo_iarmp',
254 ext_package='foo_iarmp')
255
256 def test_install_and_reload_module_ext_package_not_found(self):
257 self.test_install_and_reload_module(targetpackage='foo_epnf',
258 ext_package='not_found')
259
260 def test_tag(self):
261 ffi = FFI()
262 ffi.cdef("/* %s test_tag */ double test1tag(double x);" % self)
263 csrc = "double test1tag(double x) { return x - 42.0; }"
264 lib = ffi.verify(csrc, force_generic_engine=self.generic,
265 tag='xxtest_tagxx')
266 assert lib.test1tag(143) == 101.0
267 assert '_cffi_xxtest_tagxx_' in ffi.verifier.modulefilename
268
269 def test_modulename(self):
270 ffi = FFI()
271 ffi.cdef("/* %s test_modulename */ double test1foo(double x);" % self)
272 csrc = "double test1foo(double x) { return x - 63.0; }"
273 modname = 'xxtest_modulenamexx%d' % (self.generic,)
274 lib = ffi.verify(csrc, force_generic_engine=self.generic,
275 modulename=modname)
276 assert lib.test1foo(143) == 80.0
277 suffix = _get_so_suffixes()[0]
278 fn1 = os.path.join(ffi.verifier.tmpdir, modname + '.c')
279 fn2 = os.path.join(ffi.verifier.tmpdir, modname + suffix)
280 assert ffi.verifier.sourcefilename == fn1
281 assert ffi.verifier.modulefilename == fn2
282
283
284 class TestDistUtilsCPython(DistUtilsTest):
285 generic = False
286
287 class TestDistUtilsGeneric(DistUtilsTest):
288 generic = True
+0
-177
pypy/module/test_lib_pypy/cffi_tests/cffi0/test_zintegration.py less more
0 # Generated by pypy/tool/import_cffi.py
1 import py, os, sys, shutil
2 import subprocess
3 from pypy.module.test_lib_pypy.cffi_tests.udir import udir
4
5 if sys.platform == 'win32':
6 py.test.skip('snippets do not run on win32')
7 if sys.version_info < (2, 7):
8 py.test.skip('fails e.g. on a Debian/Ubuntu which patches virtualenv'
9 ' in a non-2.6-friendly way')
10
11 def create_venv(name):
12 tmpdir = udir.join(name)
13 try:
14 subprocess.check_call(['virtualenv',
15 #'--never-download', <= could be added, but causes failures
16 # in random cases on random machines
17 '-p', os.path.abspath(sys.executable),
18 str(tmpdir)])
19 except OSError as e:
20 py.test.skip("Cannot execute virtualenv: %s" % (e,))
21
22 site_packages = None
23 for dirpath, dirnames, filenames in os.walk(str(tmpdir)):
24 if os.path.basename(dirpath) == 'site-packages':
25 site_packages = dirpath
26 break
27 paths = ""
28 if site_packages:
29 try:
30 from cffi import _pycparser
31 modules = ('cffi', '_cffi_backend')
32 except ImportError:
33 modules = ('cffi', '_cffi_backend', 'pycparser')
34 try:
35 import ply
36 except ImportError:
37 pass
38 else:
39 modules += ('ply',) # needed for older versions of pycparser
40 paths = []
41 for module in modules:
42 target = __import__(module, None, None, [])
43 if not hasattr(target, '__file__'): # for _cffi_backend on pypy
44 continue
45 src = os.path.abspath(target.__file__)
46 for end in ['__init__.pyc', '__init__.pyo', '__init__.py']:
47 if src.lower().endswith(end):
48 src = src[:-len(end)-1]
49 break
50 paths.append(os.path.dirname(src))
51 paths = os.pathsep.join(paths)
52 return tmpdir, paths
53
54 SNIPPET_DIR = py.path.local(__file__).join('..', 'snippets')
55
56 def really_run_setup_and_program(dirname, venv_dir_and_paths, python_snippet):
57 venv_dir, paths = venv_dir_and_paths
58 def remove(dir):
59 dir = str(SNIPPET_DIR.join(dirname, dir))
60 shutil.rmtree(dir, ignore_errors=True)
61 remove('build')
62 remove('__pycache__')
63 for basedir in os.listdir(str(SNIPPET_DIR.join(dirname))):
64 remove(os.path.join(basedir, '__pycache__'))
65 olddir = os.getcwd()
66 python_f = udir.join('x.py')
67 python_f.write(py.code.Source(python_snippet))
68 try:
69 os.chdir(str(SNIPPET_DIR.join(dirname)))
70 if os.name == 'nt':
71 bindir = 'Scripts'
72 else:
73 bindir = 'bin'
74 vp = str(venv_dir.join(bindir).join('python'))
75 env = os.environ.copy()
76 env['PYTHONPATH'] = paths
77 subprocess.check_call((vp, 'setup.py', 'clean'), env=env)
78 subprocess.check_call((vp, 'setup.py', 'install'), env=env)
79 subprocess.check_call((vp, str(python_f)), env=env)
80 finally:
81 os.chdir(olddir)
82
83 def run_setup_and_program(dirname, python_snippet):
84 venv_dir = create_venv(dirname + '-cpy')
85 really_run_setup_and_program(dirname, venv_dir, python_snippet)
86 #
87 sys._force_generic_engine_ = True
88 try:
89 venv_dir = create_venv(dirname + '-gen')
90 really_run_setup_and_program(dirname, venv_dir, python_snippet)
91 finally:
92 del sys._force_generic_engine_
93 # the two files lextab.py and yacctab.py are created by not-correctly-
94 # installed versions of pycparser.
95 assert not os.path.exists(str(SNIPPET_DIR.join(dirname, 'lextab.py')))
96 assert not os.path.exists(str(SNIPPET_DIR.join(dirname, 'yacctab.py')))
97
98 class TestZIntegration(object):
99 def teardown_class(self):
100 if udir.isdir():
101 udir.remove(ignore_errors=True)
102 udir.ensure(dir=1)
103
104 def test_infrastructure(self):
105 run_setup_and_program('infrastructure', '''
106 import snip_infrastructure
107 assert snip_infrastructure.func() == 42
108 ''')
109
110 def test_distutils_module(self):
111 run_setup_and_program("distutils_module", '''
112 import snip_basic_verify
113 p = snip_basic_verify.C.getpwuid(0)
114 assert snip_basic_verify.ffi.string(p.pw_name) == b"root"
115 ''')
116
117 def test_distutils_package_1(self):
118 run_setup_and_program("distutils_package_1", '''
119 import snip_basic_verify1
120 p = snip_basic_verify1.C.getpwuid(0)
121 assert snip_basic_verify1.ffi.string(p.pw_name) == b"root"
122 ''')
123
124 def test_distutils_package_2(self):
125 run_setup_and_program("distutils_package_2", '''
126 import snip_basic_verify2
127 p = snip_basic_verify2.C.getpwuid(0)
128 assert snip_basic_verify2.ffi.string(p.pw_name) == b"root"
129 ''')
130
131 def test_setuptools_module(self):
132 run_setup_and_program("setuptools_module", '''
133 import snip_setuptools_verify
134 p = snip_setuptools_verify.C.getpwuid(0)
135 assert snip_setuptools_verify.ffi.string(p.pw_name) == b"root"
136 ''')
137
138 def test_setuptools_package_1(self):
139 run_setup_and_program("setuptools_package_1", '''
140 import snip_setuptools_verify1
141 p = snip_setuptools_verify1.C.getpwuid(0)
142 assert snip_setuptools_verify1.ffi.string(p.pw_name) == b"root"
143 ''')
144
145 def test_setuptools_package_2(self):
146 run_setup_and_program("setuptools_package_2", '''
147 import snip_setuptools_verify2
148 p = snip_setuptools_verify2.C.getpwuid(0)
149 assert snip_setuptools_verify2.ffi.string(p.pw_name) == b"root"
150 ''')
151
152 def test_set_py_limited_api(self):
153 from cffi.setuptools_ext import _set_py_limited_api
154 try:
155 import setuptools
156 except ImportError as e:
157 py.test.skip(str(e))
158 orig_version = setuptools.__version__
159 expecting_limited_api = not hasattr(sys, 'gettotalrefcount')
160 try:
161 setuptools.__version__ = '26.0.0'
162 from setuptools import Extension
163
164 kwds = _set_py_limited_api(Extension, {})
165 assert kwds.get('py_limited_api', False) == expecting_limited_api
166
167 setuptools.__version__ = '25.0'
168 kwds = _set_py_limited_api(Extension, {})
169 assert kwds.get('py_limited_api', False) == False
170
171 setuptools.__version__ = 'development'
172 kwds = _set_py_limited_api(Extension, {})
173 assert kwds.get('py_limited_api', False) == expecting_limited_api
174
175 finally:
176 setuptools.__version__ = orig_version
+0
-1
pypy/module/test_lib_pypy/cffi_tests/cffi1/__init__.py less more
0 # Generated by pypy/tool/import_cffi.py
+0
-21
pypy/module/test_lib_pypy/cffi_tests/cffi1/test_cffi_binary.py less more
0 # Generated by pypy/tool/import_cffi.py
1 import py, sys, os
2 import _cffi_backend
3
4 def test_no_unknown_exported_symbols():
5 if not hasattr(_cffi_backend, '__file__'):
6 py.test.skip("_cffi_backend module is built-in")
7 if not sys.platform.startswith('linux'):
8 py.test.skip("linux-only")
9 g = os.popen("objdump -T '%s'" % _cffi_backend.__file__, 'r')
10 for line in g:
11 if not line.startswith('0'):
12 continue
13 if '*UND*' in line:
14 continue
15 name = line.split()[-1]
16 if name.startswith('_') or name.startswith('.'):
17 continue
18 if name not in ('init_cffi_backend', 'PyInit__cffi_backend'):
19 raise Exception("Unexpected exported name %r" % (name,))
20 g.close()
+0
-35
pypy/module/test_lib_pypy/cffi_tests/cffi1/test_commontypes.py less more
0 # Generated by pypy/tool/import_cffi.py
1 import py, os, cffi, re
2 import _cffi_backend
3
4
5 def getlines():
6 try:
7 f = open(os.path.join(os.path.dirname(cffi.__file__),
8 '..', 'c', 'commontypes.c'))
9 except IOError:
10 py.test.skip("cannot find ../c/commontypes.c")
11 lines = [line for line in f.readlines() if line.strip().startswith('EQ(')]
12 f.close()
13 return lines
14
15 def test_alphabetical_order():
16 lines = getlines()
17 assert lines == sorted(lines)
18
19 def test_dependencies():
20 r = re.compile(r'EQ[(]"([^"]+)",(?:\s*"([A-Z0-9_]+)\s*[*]*"[)])?')
21 lines = getlines()
22 d = {}
23 for line in lines:
24 match = r.search(line)
25 if match is not None:
26 d[match.group(1)] = match.group(2)
27 for value in d.values():
28 if value:
29 assert value in d
30
31 def test_get_common_types():
32 d = {}
33 _cffi_backend._get_common_types(d)
34 assert d["bool"] == "_Bool"
+0
-226
pypy/module/test_lib_pypy/cffi_tests/cffi1/test_dlopen.py less more
0 # Generated by pypy/tool/import_cffi.py
1 import py
2 from cffi import FFI, VerificationError, CDefError
3 from cffi.recompiler import make_py_source
4 from pypy.module.test_lib_pypy.cffi_tests.udir import udir
5
6
7 def test_simple():
8 ffi = FFI()
9 ffi.cdef("int close(int); static const int BB = 42; int somevar;")
10 target = udir.join('test_simple.py')
11 make_py_source(ffi, 'test_simple', str(target))
12 assert target.read() == r"""# auto-generated file
13 import _cffi_backend
14
15 ffi = _cffi_backend.FFI('test_simple',
16 _version = 0x2601,
17 _types = b'\x00\x00\x01\x0D\x00\x00\x07\x01\x00\x00\x00\x0F',
18 _globals = (b'\xFF\xFF\xFF\x1FBB',42,b'\x00\x00\x00\x23close',0,b'\x00\x00\x01\x21somevar',0),
19 )
20 """
21
22 def test_global_constant():
23 ffi = FFI()
24 ffi.cdef("static const long BB; static const float BF = 12;")
25 target = udir.join('test_valid_global_constant.py')
26 make_py_source(ffi, 'test_valid_global_constant', str(target))
27 assert target.read() == r"""# auto-generated file
28 import _cffi_backend
29
30 ffi = _cffi_backend.FFI('test_valid_global_constant',
31 _version = 0x2601,
32 _types = b'\x00\x00\x0D\x01\x00\x00\x09\x01',
33 _globals = (b'\x00\x00\x01\x25BB',0,b'\x00\x00\x00\x25BF',0),
34 )
35 """
36
37 def test_invalid_global_constant_3():
38 ffi = FFI()
39 e = py.test.raises(CDefError, ffi.cdef, "#define BB 12.34")
40 assert str(e.value).startswith(
41 "only supports one of the following syntax:")
42
43 def test_invalid_dotdotdot_in_macro():
44 ffi = FFI()
45 ffi.cdef("#define FOO ...")
46 target = udir.join('test_invalid_dotdotdot_in_macro.py')
47 e = py.test.raises(VerificationError, make_py_source, ffi,
48 'test_invalid_dotdotdot_in_macro', str(target))
49 assert str(e.value) == ("macro FOO: cannot use the syntax '...' in "
50 "'#define FOO ...' when using the ABI mode")
51
52 def test_typename():
53 ffi = FFI()
54 ffi.cdef("typedef int foobar_t;")
55 target = udir.join('test_typename.py')
56 make_py_source(ffi, 'test_typename', str(target))
57 assert target.read() == r"""# auto-generated file
58 import _cffi_backend
59
60 ffi = _cffi_backend.FFI('test_typename',
61 _version = 0x2601,
62 _types = b'\x00\x00\x07\x01',
63 _typenames = (b'\x00\x00\x00\x00foobar_t',),
64 )
65 """
66
67 def test_enum():
68 ffi = FFI()
69 ffi.cdef("enum myenum_e { AA, BB, CC=-42 };")
70 target = udir.join('test_enum.py')
71 make_py_source(ffi, 'test_enum', str(target))
72 assert target.read() == r"""# auto-generated file
73 import _cffi_backend
74
75 ffi = _cffi_backend.FFI('test_enum',
76 _version = 0x2601,
77 _types = b'\x00\x00\x00\x0B',
78 _globals = (b'\xFF\xFF\xFF\x0BAA',0,b'\xFF\xFF\xFF\x0BBB',1,b'\xFF\xFF\xFF\x0BCC',-42),
79 _enums = (b'\x00\x00\x00\x00\x00\x00\x00\x15myenum_e\x00AA,BB,CC',),
80 )
81 """
82
83 def test_struct():
84 ffi = FFI()
85 ffi.cdef("struct foo_s { int a; signed char b[]; }; struct bar_s;")
86 target = udir.join('test_struct.py')
87 make_py_source(ffi, 'test_struct', str(target))
88 assert target.read() == r"""# auto-generated file
89 import _cffi_backend
90
91 ffi = _cffi_backend.FFI('test_struct',
92 _version = 0x2601,
93 _types = b'\x00\x00\x07\x01\x00\x00\x03\x01\x00\x00\x01\x07\x00\x00\x00\x09\x00\x00\x01\x09',
94 _struct_unions = ((b'\x00\x00\x00\x03\x00\x00\x00\x10bar_s',),(b'\x00\x00\x00\x04\x00\x00\x00\x02foo_s',b'\x00\x00\x00\x11a',b'\x00\x00\x02\x11b')),
95 )
96 """
97
98 def test_include():
99 ffi = FFI()
100 ffi.cdef("#define ABC 123")
101 ffi.set_source('test_include', None)
102 target = udir.join('test_include.py')
103 make_py_source(ffi, 'test_include', str(target))
104 assert target.read() == r"""# auto-generated file
105 import _cffi_backend
106
107 ffi = _cffi_backend.FFI('test_include',
108 _version = 0x2601,
109 _types = b'',
110 _globals = (b'\xFF\xFF\xFF\x1FABC',123,),
111 )
112 """
113 #
114 ffi2 = FFI()
115 ffi2.include(ffi)
116 target2 = udir.join('test2_include.py')
117 make_py_source(ffi2, 'test2_include', str(target2))
118 assert target2.read() == r"""# auto-generated file
119 import _cffi_backend
120 from test_include import ffi as _ffi0
121
122 ffi = _cffi_backend.FFI('test2_include',
123 _version = 0x2601,
124 _types = b'',
125 _includes = (_ffi0,),
126 )
127 """
128
129 def test_negative_constant():
130 ffi = FFI()
131 ffi.cdef("static const int BB = -42;")
132 target = udir.join('test_negative_constant.py')
133 make_py_source(ffi, 'test_negative_constant', str(target))
134 assert target.read() == r"""# auto-generated file
135 import _cffi_backend
136
137 ffi = _cffi_backend.FFI('test_negative_constant',
138 _version = 0x2601,
139 _types = b'',
140 _globals = (b'\xFF\xFF\xFF\x1FBB',-42,),
141 )
142 """
143
144 def test_struct_included():
145 baseffi = FFI()
146 baseffi.cdef("struct foo_s { int x; };")
147 baseffi.set_source('test_struct_included_base', None)
148 #
149 ffi = FFI()
150 ffi.include(baseffi)
151 target = udir.join('test_struct_included.py')
152 make_py_source(ffi, 'test_struct_included', str(target))
153 assert target.read() == r"""# auto-generated file
154 import _cffi_backend
155 from test_struct_included_base import ffi as _ffi0
156
157 ffi = _cffi_backend.FFI('test_struct_included',
158 _version = 0x2601,
159 _types = b'\x00\x00\x00\x09',
160 _struct_unions = ((b'\x00\x00\x00\x00\x00\x00\x00\x08foo_s',),),
161 _includes = (_ffi0,),
162 )
163 """
164
165 def test_no_cross_include():
166 baseffi = FFI()
167 baseffi.set_source('test_no_cross_include_base', "..source..")
168 #
169 ffi = FFI()
170 ffi.include(baseffi)
171 target = udir.join('test_no_cross_include.py')
172 py.test.raises(VerificationError, make_py_source,
173 ffi, 'test_no_cross_include', str(target))
174
175 def test_array():
176 ffi = FFI()
177 ffi.cdef("typedef int32_t my_array_t[42];")
178 target = udir.join('test_array.py')
179 make_py_source(ffi, 'test_array', str(target))
180 assert target.read() == r"""# auto-generated file
181 import _cffi_backend
182
183 ffi = _cffi_backend.FFI('test_array',
184 _version = 0x2601,
185 _types = b'\x00\x00\x15\x01\x00\x00\x00\x05\x00\x00\x00\x2A',
186 _typenames = (b'\x00\x00\x00\x01my_array_t',),
187 )
188 """
189
190 def test_array_overflow():
191 ffi = FFI()
192 ffi.cdef("typedef int32_t my_array_t[3000000000];")
193 target = udir.join('test_array_overflow.py')
194 py.test.raises(OverflowError, make_py_source,
195 ffi, 'test_array_overflow', str(target))
196
197 def test_global_var():
198 ffi = FFI()
199 ffi.cdef("int myglob;")
200 target = udir.join('test_global_var.py')
201 make_py_source(ffi, 'test_global_var', str(target))
202 assert target.read() == r"""# auto-generated file
203 import _cffi_backend
204
205 ffi = _cffi_backend.FFI('test_global_var',
206 _version = 0x2601,
207 _types = b'\x00\x00\x07\x01',
208 _globals = (b'\x00\x00\x00\x21myglob',0,),
209 )
210 """
211
212 def test_bitfield():
213 ffi = FFI()
214 ffi.cdef("struct foo_s { int y:10; short x:5; };")
215 target = udir.join('test_bitfield.py')
216 make_py_source(ffi, 'test_bitfield', str(target))
217 assert target.read() == r"""# auto-generated file
218 import _cffi_backend
219
220 ffi = _cffi_backend.FFI('test_bitfield',
221 _version = 0x2601,
222 _types = b'\x00\x00\x07\x01\x00\x00\x05\x01\x00\x00\x00\x09',
223 _struct_unions = ((b'\x00\x00\x00\x02\x00\x00\x00\x02foo_s',b'\x00\x00\x00\x13\x00\x00\x00\x0Ay',b'\x00\x00\x01\x13\x00\x00\x00\x05x'),),
224 )
225 """
+0
-10
pypy/module/test_lib_pypy/cffi_tests/cffi1/test_dlopen_unicode_literals.py less more
0 # Generated by pypy/tool/import_cffi.py
1 import py, os
2
3 s = """from __future__ import unicode_literals
4 """
5
6 with open(os.path.join(os.path.dirname(__file__), 'test_dlopen.py')) as f:
7 s += f.read()
8
9 exec(py.code.compile(s))
+0
-511
pypy/module/test_lib_pypy/cffi_tests/cffi1/test_ffi_obj.py less more
0 # Generated by pypy/tool/import_cffi.py
1 import py, sys
2 import _cffi_backend as _cffi1_backend
3
4
5 def test_ffi_new():
6 ffi = _cffi1_backend.FFI()
7 p = ffi.new("int *")
8 p[0] = -42
9 assert p[0] == -42
10 assert type(ffi) is ffi.__class__ is _cffi1_backend.FFI
11
12 def test_ffi_subclass():
13 class FOO(_cffi1_backend.FFI):
14 def __init__(self, x):
15 self.x = x
16 foo = FOO(42)
17 assert foo.x == 42
18 p = foo.new("int *")
19 assert p[0] == 0
20 assert type(foo) is foo.__class__ is FOO
21
22 def test_ffi_no_argument():
23 py.test.raises(TypeError, _cffi1_backend.FFI, 42)
24
25 def test_ffi_cache_type():
26 ffi = _cffi1_backend.FFI()
27 t1 = ffi.typeof("int **")
28 t2 = ffi.typeof("int *")
29 assert t2.item is t1.item.item
30 assert t2 is t1.item
31 assert ffi.typeof("int[][10]") is ffi.typeof("int[][10]")
32 assert ffi.typeof("int(*)()") is ffi.typeof("int(*)()")
33
34 def test_ffi_type_not_immortal():
35 import weakref, gc
36 ffi = _cffi1_backend.FFI()
37 t1 = ffi.typeof("int **")
38 t2 = ffi.typeof("int *")
39 w1 = weakref.ref(t1)
40 w2 = weakref.ref(t2)
41 del t1, ffi
42 gc.collect()
43 assert w1() is None
44 assert w2() is t2
45 ffi = _cffi1_backend.FFI()
46 assert ffi.typeof(ffi.new("int **")[0]) is t2
47 #
48 ffi = _cffi1_backend.FFI()
49 t1 = ffi.typeof("int ***")
50 t2 = ffi.typeof("int **")
51 w1 = weakref.ref(t1)
52 w2 = weakref.ref(t2)
53 del t2, ffi
54 gc.collect()
55 assert w1() is t1
56 assert w2() is not None # kept alive by t1
57 ffi = _cffi1_backend.FFI()
58 assert ffi.typeof("int * *") is t1.item
59
60 def test_ffi_cache_type_globally():
61 ffi1 = _cffi1_backend.FFI()
62 ffi2 = _cffi1_backend.FFI()
63 t1 = ffi1.typeof("int *")
64 t2 = ffi2.typeof("int *")
65 assert t1 is t2
66
67 def test_ffi_invalid():
68 ffi = _cffi1_backend.FFI()
69 # array of 10 times an "int[]" is invalid
70 py.test.raises(ValueError, ffi.typeof, "int[10][]")
71
72 def test_ffi_docstrings():
73 # check that all methods of the FFI class have a docstring.
74 check_type = type(_cffi1_backend.FFI.new)
75 for methname in dir(_cffi1_backend.FFI):
76 if not methname.startswith('_'):
77 method = getattr(_cffi1_backend.FFI, methname)
78 if isinstance(method, check_type):
79 assert method.__doc__, "method FFI.%s() has no docstring" % (
80 methname,)
81
82 def test_ffi_NULL():
83 NULL = _cffi1_backend.FFI.NULL
84 assert _cffi1_backend.FFI().typeof(NULL).cname == "void *"
85
86 def test_ffi_no_attr():
87 ffi = _cffi1_backend.FFI()
88 py.test.raises(AttributeError, "ffi.no_such_name")
89 py.test.raises(AttributeError, "ffi.no_such_name = 42")
90 py.test.raises(AttributeError, "del ffi.no_such_name")
91
92 def test_ffi_string():
93 ffi = _cffi1_backend.FFI()
94 p = ffi.new("char[]", init=b"foobar\x00baz")
95 assert ffi.string(p) == b"foobar"
96 assert ffi.string(cdata=p, maxlen=3) == b"foo"
97
98 def test_ffi_errno():
99 # xxx not really checking errno, just checking that we can read/write it
100 ffi = _cffi1_backend.FFI()
101 ffi.errno = 42
102 assert ffi.errno == 42
103
104 def test_ffi_alignof():
105 ffi = _cffi1_backend.FFI()
106 assert ffi.alignof("int") == 4
107 assert ffi.alignof("int[]") == 4
108 assert ffi.alignof("int[41]") == 4
109 assert ffi.alignof("short[41]") == 2
110 assert ffi.alignof(ffi.new("int[41]")) == 4
111 assert ffi.alignof(ffi.new("int[]", 41)) == 4
112
113 def test_ffi_sizeof():
114 ffi = _cffi1_backend.FFI()
115 assert ffi.sizeof("int") == 4
116 py.test.raises(ffi.error, ffi.sizeof, "int[]")
117 assert ffi.sizeof("int[41]") == 41 * 4
118 assert ffi.sizeof(ffi.new("int[41]")) == 41 * 4
119 assert ffi.sizeof(ffi.new("int[]", 41)) == 41 * 4
120
121 def test_ffi_callback():
122 ffi = _cffi1_backend.FFI()
123 assert ffi.callback("int(int)", lambda x: x + 42)(10) == 52
124 assert ffi.callback("int(*)(int)", lambda x: x + 42)(10) == 52
125 assert ffi.callback("int(int)", lambda x: x + "", -66)(10) == -66
126 assert ffi.callback("int(int)", lambda x: x + "", error=-66)(10) == -66
127
128 def test_ffi_callback_decorator():
129 ffi = _cffi1_backend.FFI()
130 assert ffi.callback(ffi.typeof("int(*)(int)"))(lambda x: x + 42)(10) == 52
131 deco = ffi.callback("int(int)", error=-66)
132 assert deco(lambda x: x + "")(10) == -66
133 assert deco(lambda x: x + 42)(10) == 52
134
135 def test_ffi_callback_onerror():
136 ffi = _cffi1_backend.FFI()
137 seen = []
138 def oops(*args):
139 seen.append(args)
140
141 @ffi.callback("int(int)", onerror=oops)
142 def fn1(x):
143 return x + ""
144 assert fn1(10) == 0
145
146 @ffi.callback("int(int)", onerror=oops, error=-66)
147 def fn2(x):
148 return x + ""
149 assert fn2(10) == -66
150
151 assert len(seen) == 2
152 exc, val, tb = seen[0]
153 assert exc is TypeError
154 assert isinstance(val, TypeError)
155 assert tb.tb_frame.f_code.co_name == "fn1"
156 exc, val, tb = seen[1]
157 assert exc is TypeError
158 assert isinstance(val, TypeError)
159 assert tb.tb_frame.f_code.co_name == "fn2"
160 #
161 py.test.raises(TypeError, ffi.callback, "int(int)",
162 lambda x: x, onerror=42) # <- not callable
163
164 def test_ffi_getctype():
165 ffi = _cffi1_backend.FFI()
166 assert ffi.getctype("int") == "int"
167 assert ffi.getctype("int", 'x') == "int x"
168 assert ffi.getctype("int*") == "int *"
169 assert ffi.getctype("int*", '') == "int *"
170 assert ffi.getctype("int*", 'x') == "int * x"
171 assert ffi.getctype("int", '*') == "int *"
172 assert ffi.getctype("int", replace_with=' * x ') == "int * x"
173 assert ffi.getctype(ffi.typeof("int*"), '*') == "int * *"
174 assert ffi.getctype("int", '[5]') == "int[5]"
175 assert ffi.getctype("int[5]", '[6]') == "int[6][5]"
176 assert ffi.getctype("int[5]", '(*)') == "int(*)[5]"
177 # special-case for convenience: automatically put '()' around '*'
178 assert ffi.getctype("int[5]", '*') == "int(*)[5]"
179 assert ffi.getctype("int[5]", '*foo') == "int(*foo)[5]"
180 assert ffi.getctype("int[5]", ' ** foo ') == "int(** foo)[5]"
181
182 def test_addressof():
183 ffi = _cffi1_backend.FFI()
184 a = ffi.new("int[10]")
185 b = ffi.addressof(a, 5)
186 b[2] = -123
187 assert a[7] == -123
188
189 def test_handle():
190 ffi = _cffi1_backend.FFI()
191 x = [2, 4, 6]
192 xp = ffi.new_handle(x)
193 assert ffi.typeof(xp) == ffi.typeof("void *")
194 assert ffi.from_handle(xp) is x
195 yp = ffi.new_handle([6, 4, 2])
196 assert ffi.from_handle(yp) == [6, 4, 2]
197
198 def test_handle_unique():
199 ffi = _cffi1_backend.FFI()
200 assert ffi.new_handle(None) is not ffi.new_handle(None)
201 assert ffi.new_handle(None) != ffi.new_handle(None)
202
203 def test_ffi_cast():
204 ffi = _cffi1_backend.FFI()
205 assert ffi.cast("int(*)(int)", 0) == ffi.NULL
206 ffi.callback("int(int)") # side-effect of registering this string
207 py.test.raises(ffi.error, ffi.cast, "int(int)", 0)
208
209 def test_ffi_invalid_type():
210 ffi = _cffi1_backend.FFI()
211 e = py.test.raises(ffi.error, ffi.cast, "", 0)
212 assert str(e.value) == ("identifier expected\n"
213 "\n"
214 "^")
215 e = py.test.raises(ffi.error, ffi.cast, "struct struct", 0)
216 assert str(e.value) == ("struct or union name expected\n"
217 "struct struct\n"
218 " ^")
219 e = py.test.raises(ffi.error, ffi.cast, "struct never_heard_of_s", 0)
220 assert str(e.value) == ("undefined struct/union name\n"
221 "struct never_heard_of_s\n"
222 " ^")
223 e = py.test.raises(ffi.error, ffi.cast, "\t\n\x01\x1f~\x7f\x80\xff", 0)
224 marks = "?" if sys.version_info < (3,) else "??"
225 assert str(e.value) == ("identifier expected\n"
226 " ??~?%s%s\n"
227 " ^" % (marks, marks))
228 e = py.test.raises(ffi.error, ffi.cast, "X" * 600, 0)
229 assert str(e.value) == ("undefined type name")
230
231 def test_ffi_buffer():
232 ffi = _cffi1_backend.FFI()
233 a = ffi.new("signed char[]", [5, 6, 7])
234 assert ffi.buffer(a)[:] == b'\x05\x06\x07'
235 assert ffi.buffer(cdata=a, size=2)[:] == b'\x05\x06'
236 assert type(ffi.buffer(a)) is ffi.buffer
237
238 def test_ffi_from_buffer():
239 import array
240 ffi = _cffi1_backend.FFI()
241 a = array.array('H', [10000, 20000, 30000])
242 c = ffi.from_buffer(a)
243 assert ffi.typeof(c) is ffi.typeof("char[]")
244 ffi.cast("unsigned short *", c)[1] += 500
245 assert list(a) == [10000, 20500, 30000]
246
247 def test_memmove():
248 ffi = _cffi1_backend.FFI()
249 p = ffi.new("short[]", [-1234, -2345, -3456, -4567, -5678])
250 ffi.memmove(p, p + 1, 4)
251 assert list(p) == [-2345, -3456, -3456, -4567, -5678]
252 p[2] = 999
253 ffi.memmove(p + 2, p, 6)
254 assert list(p) == [-2345, -3456, -2345, -3456, 999]
255 ffi.memmove(p + 4, ffi.new("char[]", b"\x71\x72"), 2)
256 if sys.byteorder == 'little':
257 assert list(p) == [-2345, -3456, -2345, -3456, 0x7271]
258 else:
259 assert list(p) == [-2345, -3456, -2345, -3456, 0x7172]
260
261 def test_memmove_buffer():
262 import array
263 ffi = _cffi1_backend.FFI()
264 a = array.array('H', [10000, 20000, 30000])
265 p = ffi.new("short[]", 5)
266 ffi.memmove(p, a, 6)
267 assert list(p) == [10000, 20000, 30000, 0, 0]
268 ffi.memmove(p + 1, a, 6)
269 assert list(p) == [10000, 10000, 20000, 30000, 0]
270 b = array.array('h', [-1000, -2000, -3000])
271 ffi.memmove(b, a, 4)
272 assert b.tolist() == [10000, 20000, -3000]
273 assert a.tolist() == [10000, 20000, 30000]
274 p[0] = 999
275 p[1] = 998
276 p[2] = 997
277 p[3] = 996
278 p[4] = 995
279 ffi.memmove(b, p, 2)
280 assert b.tolist() == [999, 20000, -3000]
281 ffi.memmove(b, p + 2, 4)
282 assert b.tolist() == [997, 996, -3000]
283 p[2] = -p[2]
284 p[3] = -p[3]
285 ffi.memmove(b, p + 2, 6)
286 assert b.tolist() == [-997, -996, 995]
287
288 def test_memmove_readonly_readwrite():
289 ffi = _cffi1_backend.FFI()
290 p = ffi.new("signed char[]", 5)
291 ffi.memmove(p, b"abcde", 3)
292 assert list(p) == [ord("a"), ord("b"), ord("c"), 0, 0]
293 ffi.memmove(p, bytearray(b"ABCDE"), 2)
294 assert list(p) == [ord("A"), ord("B"), ord("c"), 0, 0]
295 py.test.raises((TypeError, BufferError), ffi.memmove, b"abcde", p, 3)
296 ba = bytearray(b"xxxxx")
297 ffi.memmove(dest=ba, src=p, n=3)
298 assert ba == bytearray(b"ABcxx")
299
300 def test_ffi_types():
301 CData = _cffi1_backend.FFI.CData
302 CType = _cffi1_backend.FFI.CType
303 ffi = _cffi1_backend.FFI()
304 assert isinstance(ffi.cast("int", 42), CData)
305 assert isinstance(ffi.typeof("int"), CType)
306
307 def test_ffi_getwinerror():
308 if sys.platform != "win32":
309 py.test.skip("for windows")
310 ffi = _cffi1_backend.FFI()
311 n = (1 << 29) + 42
312 code, message = ffi.getwinerror(code=n)
313 assert code == n
314
315 def test_ffi_new_allocator_1():
316 ffi = _cffi1_backend.FFI()
317 alloc1 = ffi.new_allocator()
318 alloc2 = ffi.new_allocator(should_clear_after_alloc=False)
319 for retry in range(100):
320 p1 = alloc1("int[10]")
321 p2 = alloc2("int[10]")
322 combination = 0
323 for i in range(10):
324 assert p1[i] == 0
325 combination |= p2[i]
326 p1[i] = -42
327 p2[i] = -43
328 if combination != 0:
329 break
330 del p1, p2
331 import gc; gc.collect()
332 else:
333 raise AssertionError("cannot seem to get an int[10] not "
334 "completely cleared")
335
336 def test_ffi_new_allocator_2():
337 ffi = _cffi1_backend.FFI()
338 seen = []
339 def myalloc(size):
340 seen.append(size)
341 return ffi.new("char[]", b"X" * size)
342 def myfree(raw):
343 seen.append(raw)
344 alloc1 = ffi.new_allocator(myalloc, myfree)
345 alloc2 = ffi.new_allocator(alloc=myalloc, free=myfree,
346 should_clear_after_alloc=False)
347 p1 = alloc1("int[10]")
348 p2 = alloc2("int[]", 10)
349 assert seen == [40, 40]
350 assert ffi.typeof(p1) == ffi.typeof("int[10]")
351 assert ffi.sizeof(p1) == 40
352 assert ffi.typeof(p2) == ffi.typeof("int[]")
353 assert ffi.sizeof(p2) == 40
354 assert p1[5] == 0
355 assert p2[6] == ord('X') * 0x01010101
356 raw1 = ffi.cast("char *", p1)
357 raw2 = ffi.cast("char *", p2)
358 del p1, p2
359 retries = 0
360 while len(seen) != 4:
361 retries += 1
362 assert retries <= 5
363 import gc; gc.collect()
364 assert (seen == [40, 40, raw1, raw2] or
365 seen == [40, 40, raw2, raw1])
366 assert repr(seen[2]) == "<cdata 'char[]' owning 41 bytes>"
367 assert repr(seen[3]) == "<cdata 'char[]' owning 41 bytes>"
368
369 def test_ffi_new_allocator_3():
370 ffi = _cffi1_backend.FFI()
371 seen = []
372 def myalloc(size):
373 seen.append(size)
374 return ffi.new("char[]", b"X" * size)
375 alloc1 = ffi.new_allocator(myalloc) # no 'free'
376 p1 = alloc1("int[10]")
377 assert seen == [40]
378 assert ffi.typeof(p1) == ffi.typeof("int[10]")
379 assert ffi.sizeof(p1) == 40
380 assert p1[5] == 0
381
382 def test_ffi_new_allocator_4():
383 ffi = _cffi1_backend.FFI()
384 py.test.raises(TypeError, ffi.new_allocator, free=lambda x: None)
385 #
386 def myalloc2(size):
387 raise LookupError
388 alloc2 = ffi.new_allocator(myalloc2)
389 py.test.raises(LookupError, alloc2, "int[5]")
390 #
391 def myalloc3(size):
392 return 42
393 alloc3 = ffi.new_allocator(myalloc3)
394 e = py.test.raises(TypeError, alloc3, "int[5]")
395 assert str(e.value) == "alloc() must return a cdata object (got int)"
396 #
397 def myalloc4(size):
398 return ffi.cast("int", 42)
399 alloc4 = ffi.new_allocator(myalloc4)
400 e = py.test.raises(TypeError, alloc4, "int[5]")
401 assert str(e.value) == "alloc() must return a cdata pointer, not 'int'"
402 #
403 def myalloc5(size):
404 return ffi.NULL
405 alloc5 = ffi.new_allocator(myalloc5)
406 py.test.raises(MemoryError, alloc5, "int[5]")
407
408 def test_bool_issue228():
409 ffi = _cffi1_backend.FFI()
410 fntype = ffi.typeof("int(*callback)(bool is_valid)")
411 assert repr(fntype.args[0]) == "<ctype '_Bool'>"
412
413 def test_FILE_issue228():
414 fntype1 = _cffi1_backend.FFI().typeof("FILE *")
415 fntype2 = _cffi1_backend.FFI().typeof("FILE *")
416 assert repr(fntype1) == "<ctype 'FILE *'>"
417 assert fntype1 is fntype2
418
419 def test_cast_from_int_type_to_bool():
420 ffi = _cffi1_backend.FFI()
421 for basetype in ['char', 'short', 'int', 'long', 'long long']:
422 for sign in ['signed', 'unsigned']:
423 type = '%s %s' % (sign, basetype)
424 assert int(ffi.cast("_Bool", ffi.cast(type, 42))) == 1
425 assert int(ffi.cast("bool", ffi.cast(type, 42))) == 1
426 assert int(ffi.cast("_Bool", ffi.cast(type, 0))) == 0
427
428 def test_init_once():
429 def do_init():
430 seen.append(1)
431 return 42
432 ffi = _cffi1_backend.FFI()
433 seen = []
434 for i in range(3):
435 res = ffi.init_once(do_init, "tag1")
436 assert res == 42
437 assert seen == [1]
438 for i in range(3):
439 res = ffi.init_once(do_init, "tag2")
440 assert res == 42
441 assert seen == [1, 1]
442
443 def test_init_once_multithread():
444 if sys.version_info < (3,):
445 import thread
446 else:
447 import _thread as thread
448 import time
449 #
450 def do_init():
451 print('init!')
452 seen.append('init!')
453 time.sleep(1)
454 seen.append('init done')
455 print('init done')
456 return 7
457 ffi = _cffi1_backend.FFI()
458 seen = []
459 for i in range(6):
460 def f():
461 res = ffi.init_once(do_init, "tag")
462 seen.append(res)
463 thread.start_new_thread(f, ())
464 time.sleep(1.5)
465 assert seen == ['init!', 'init done'] + 6 * [7]
466
467 def test_init_once_failure():
468 def do_init():
469 seen.append(1)
470 raise ValueError
471 ffi = _cffi1_backend.FFI()
472 seen = []
473 for i in range(5):
474 py.test.raises(ValueError, ffi.init_once, do_init, "tag")
475 assert seen == [1] * (i + 1)
476
477 def test_init_once_multithread_failure():
478 if sys.version_info < (3,):
479 import thread
480 else:
481 import _thread as thread
482 import time
483 def do_init():
484 seen.append('init!')
485 time.sleep(1)
486 seen.append('oops')
487 raise ValueError
488 ffi = _cffi1_backend.FFI()
489 seen = []
490 for i in range(3):
491 def f():
492 py.test.raises(ValueError, ffi.init_once, do_init, "tag")
493 thread.start_new_thread(f, ())
494 i = 0
495 while len(seen) < 6:
496 i += 1
497 assert i < 20
498 time.sleep(0.51)
499 assert seen == ['init!', 'oops'] * 3
500
501 def test_unpack():
502 ffi = _cffi1_backend.FFI()
503 p = ffi.new("char[]", b"abc\x00def")
504 assert ffi.unpack(p+1, 7) == b"bc\x00def\x00"
505 p = ffi.new("int[]", [-123456789])
506 assert ffi.unpack(p, 1) == [-123456789]
507
508 def test_negative_array_size():
509 ffi = _cffi1_backend.FFI()
510 py.test.raises(ffi.error, ffi.cast, "int[-5]", 0)
+0
-1773
pypy/module/test_lib_pypy/cffi_tests/cffi1/test_new_ffi_1.py less more
0 # Generated by pypy/tool/import_cffi.py
1 import py
2 import platform, imp
3 import sys, os, ctypes
4 import cffi
5 from pypy.module.test_lib_pypy.cffi_tests.udir import udir
6 from pypy.module.test_lib_pypy.cffi_tests.support import *
7 from cffi.recompiler import recompile
8 from cffi.cffi_opcode import PRIMITIVE_TO_INDEX
9
10 SIZE_OF_INT = ctypes.sizeof(ctypes.c_int)
11 SIZE_OF_LONG = ctypes.sizeof(ctypes.c_long)
12 SIZE_OF_SHORT = ctypes.sizeof(ctypes.c_short)
13 SIZE_OF_PTR = ctypes.sizeof(ctypes.c_void_p)
14 SIZE_OF_WCHAR = ctypes.sizeof(ctypes.c_wchar)
15
16
17 def setup_module():
18 global ffi, construction_params
19 ffi1 = cffi.FFI()
20 DEFS = r"""
21 struct repr { short a, b, c; };
22 struct simple { int a; short b, c; };
23 struct array { int a[2]; char b[3]; };
24 struct recursive { int value; struct recursive *next; };
25 union simple_u { int a; short b, c; };
26 union init_u { char a; int b; };
27 struct four_s { int a; short b, c, d; };
28 union four_u { int a; short b, c, d; };
29 struct string { const char *name; };
30 struct ustring { const wchar_t *name; };
31 struct voidp { void *p; int *q; short *r; };
32 struct ab { int a, b; };
33 struct abc { int a, b, c; };
34
35 /* don't use A0, B0, CC0, D0 because termios.h might be included
36 and it has its own #defines for these names */
37 enum foq { cffiA0, cffiB0, cffiCC0, cffiD0 };
38 enum bar { A1, B1=-2, CC1, D1, E1 };
39 enum baz { A2=0x1000, B2=0x2000 };
40 enum foo2 { A3, B3, C3, D3 };
41 struct bar_with_e { enum foo2 e; };
42 enum noncont { A4, B4=42, C4 };
43 enum etypes {A5='!', B5='\'', C5=0x10, D5=010, E5=- 0x10, F5=-010};
44 typedef enum { Value0 = 0 } e_t, *pe_t;
45 enum e_noninj { AA3=0, BB3=0, CC3=0, DD3=0 };
46 enum e_prev { AA4, BB4=2, CC4=4, DD4=BB4, EE4, FF4=CC4, GG4=FF4 };
47
48 struct nesting { struct abc d, e; };
49 struct array2 { int a, b; int c[99]; };
50 struct align { char a; short b; char c; };
51 struct bitfield { int a:10, b:20, c:3; };
52 typedef enum { AA2, BB2, CC2 } foo_e_t;
53 typedef struct { foo_e_t f:2; } bfenum_t;
54 typedef struct { int a; } anon_foo_t;
55 typedef struct { char b, c; } anon_bar_t;
56 typedef struct named_foo_s { int a; } named_foo_t, *named_foo_p;
57 typedef struct { int a; } unnamed_foo_t, *unnamed_foo_p;
58 struct nonpacked { char a; int b; };
59 struct array0 { int len; short data[0]; };
60 struct array_no_length { int x; int a[]; };
61
62 struct nested_anon {
63 struct { int a, b; };
64 union { int c, d; };
65 };
66 struct nested_field_ofs_s {
67 struct { int a; char b; };
68 union { char c; };
69 };
70 union nested_anon_u {
71 struct { int a, b; };
72 union { int c, d; };
73 };
74 struct abc50 { int a, b; int c[50]; };
75 struct ints_and_bitfield { int a,b,c,d,e; int x:1; };
76 """
77 DEFS_PACKED = """
78 struct is_packed { char a; int b; } /*here*/;
79 """
80 if sys.platform == "win32":
81 DEFS = DEFS.replace('data[0]', 'data[1]') # not supported
82 CCODE = (DEFS + "\n#pragma pack(push,1)\n" + DEFS_PACKED +
83 "\n#pragma pack(pop)\n")
84 else:
85 CCODE = (DEFS +
86 DEFS_PACKED.replace('/*here*/', '__attribute__((packed))'))
87
88 ffi1.cdef(DEFS)
89 ffi1.cdef(DEFS_PACKED, packed=True)
90 ffi1.set_source("test_new_ffi_1", CCODE)
91
92 outputfilename = recompile(ffi1, "test_new_ffi_1", CCODE,
93 tmpdir=str(udir))
94 module = imp.load_dynamic("test_new_ffi_1", outputfilename)
95 ffi = module.ffi
96 construction_params = (ffi1, CCODE)
97
98
99 class TestNewFFI1:
100
101 def test_integer_ranges(self):
102 for (c_type, size) in [('char', 1),
103 ('short', 2),
104 ('short int', 2),
105 ('', 4),
106 ('int', 4),
107 ('long', SIZE_OF_LONG),
108 ('long int', SIZE_OF_LONG),
109 ('long long', 8),
110 ('long long int', 8),
111 ]:
112 for unsigned in [None, False, True]:
113 c_decl = {None: '',
114 False: 'signed ',
115 True: 'unsigned '}[unsigned] + c_type
116 if c_decl == 'char' or c_decl == '':
117 continue
118 self._test_int_type(ffi, c_decl, size, unsigned)
119
120 def test_fixedsize_int(self):
121 for size in [1, 2, 4, 8]:
122 self._test_int_type(ffi, 'int%d_t' % (8*size), size, False)
123 self._test_int_type(ffi, 'uint%d_t' % (8*size), size, True)
124 self._test_int_type(ffi, 'intptr_t', SIZE_OF_PTR, False)
125 self._test_int_type(ffi, 'uintptr_t', SIZE_OF_PTR, True)
126 self._test_int_type(ffi, 'ptrdiff_t', SIZE_OF_PTR, False)
127 self._test_int_type(ffi, 'size_t', SIZE_OF_PTR, True)
128 self._test_int_type(ffi, 'ssize_t', SIZE_OF_PTR, False)
129
130 def _test_int_type(self, ffi, c_decl, size, unsigned):
131 if unsigned:
132 min = 0
133 max = (1 << (8*size)) - 1
134 else:
135 min = -(1 << (8*size-1))
136 max = (1 << (8*size-1)) - 1
137 min = int(min)
138 max = int(max)
139 p = ffi.cast(c_decl, min)
140 assert p == min
141 assert bool(p) is bool(min)
142 assert int(p) == min
143 p = ffi.cast(c_decl, max)
144 assert int(p) == max
145 p = ffi.cast(c_decl, long(max))
146 assert int(p) == max
147 q = ffi.cast(c_decl, min - 1)
148 assert ffi.typeof(q) is ffi.typeof(p) and int(q) == max
149 q = ffi.cast(c_decl, long(min - 1))
150 assert ffi.typeof(q) is ffi.typeof(p) and int(q) == max
151 assert q == p
152 assert int(q) == int(p)
153 assert hash(q) == hash(p)
154 c_decl_ptr = '%s *' % c_decl
155 py.test.raises(OverflowError, ffi.new, c_decl_ptr, min - 1)
156 py.test.raises(OverflowError, ffi.new, c_decl_ptr, max + 1)
157 py.test.raises(OverflowError, ffi.new, c_decl_ptr, long(min - 1))
158 py.test.raises(OverflowError, ffi.new, c_decl_ptr, long(max + 1))
159 assert ffi.new(c_decl_ptr, min)[0] == min
160 assert ffi.new(c_decl_ptr, max)[0] == max
161 assert ffi.new(c_decl_ptr, long(min))[0] == min
162 assert ffi.new(c_decl_ptr, long(max))[0] == max
163
164 def test_new_unsupported_type(self):
165 e = py.test.raises(TypeError, ffi.new, "int")
166 assert str(e.value) == "expected a pointer or array ctype, got 'int'"
167
168 def test_new_single_integer(self):
169 p = ffi.new("int *") # similar to ffi.new("int[1]")
170 assert p[0] == 0
171 p[0] = -123
172 assert p[0] == -123
173 p = ffi.new("int *", -42)
174 assert p[0] == -42
175 assert repr(p) == "<cdata 'int *' owning %d bytes>" % SIZE_OF_INT
176
177 def test_new_array_no_arg(self):
178 p = ffi.new("int[10]")
179 # the object was zero-initialized:
180 for i in range(10):
181 assert p[i] == 0
182
183 def test_array_indexing(self):
184 p = ffi.new("int[10]")
185 p[0] = 42
186 p[9] = 43
187 assert p[0] == 42
188 assert p[9] == 43
189 py.test.raises(IndexError, "p[10]")
190 py.test.raises(IndexError, "p[10] = 44")
191 py.test.raises(IndexError, "p[-1]")
192 py.test.raises(IndexError, "p[-1] = 44")
193
194 def test_new_array_args(self):
195 # this tries to be closer to C: where we say "int x[5] = {10, 20, ..}"
196 # then here we must enclose the items in a list
197 p = ffi.new("int[5]", [10, 20, 30, 40, 50])
198 assert p[0] == 10
199 assert p[1] == 20
200 assert p[2] == 30
201 assert p[3] == 40
202 assert p[4] == 50
203 p = ffi.new("int[4]", [25])
204 assert p[0] == 25
205 assert p[1] == 0 # follow C convention rather than LuaJIT's
206 assert p[2] == 0
207 assert p[3] == 0
208 p = ffi.new("int[4]", [ffi.cast("int", -5)])
209 assert p[0] == -5
210 assert repr(p) == "<cdata 'int[4]' owning %d bytes>" % (4*SIZE_OF_INT)
211
212 def test_new_array_varsize(self):
213 p = ffi.new("int[]", 10) # a single integer is the length
214 assert p[9] == 0
215 py.test.raises(IndexError, "p[10]")
216 #
217 py.test.raises(TypeError, ffi.new, "int[]")
218 #
219 p = ffi.new("int[]", [-6, -7]) # a list is all the items, like C
220 assert p[0] == -6
221 assert p[1] == -7
222 py.test.raises(IndexError, "p[2]")
223 assert repr(p) == "<cdata 'int[]' owning %d bytes>" % (2*SIZE_OF_INT)
224 #
225 p = ffi.new("int[]", 0)
226 py.test.raises(IndexError, "p[0]")
227 py.test.raises(ValueError, ffi.new, "int[]", -1)
228 assert repr(p) == "<cdata 'int[]' owning 0 bytes>"
229
230 def test_pointer_init(self):
231 n = ffi.new("int *", 24)
232 a = ffi.new("int *[10]", [ffi.NULL, ffi.NULL, n, n, ffi.NULL])
233 for i in range(10):
234 if i not in (2, 3):
235 assert a[i] == ffi.NULL
236 assert a[2] == a[3] == n
237
238 def test_cannot_cast(self):
239 a = ffi.new("short int[10]")
240 e = py.test.raises(TypeError, ffi.new, "long int **", a)
241 msg = str(e.value)
242 assert "'short[10]'" in msg and "'long *'" in msg
243
244 def test_new_pointer_to_array(self):
245 a = ffi.new("int[4]", [100, 102, 104, 106])
246 p = ffi.new("int **", a)
247 assert p[0] == ffi.cast("int *", a)
248 assert p[0][2] == 104
249 p = ffi.cast("int *", a)
250 assert p[0] == 100
251 assert p[1] == 102
252 assert p[2] == 104
253 assert p[3] == 106
254 # keepalive: a
255
256 def test_pointer_direct(self):
257 p = ffi.cast("int*", 0)
258 assert p is not None
259 assert bool(p) is False
260 assert p == ffi.cast("int*", 0)
261 assert p != None
262 assert repr(p) == "<cdata 'int *' NULL>"
263 a = ffi.new("int[]", [123, 456])
264 p = ffi.cast("int*", a)
265 assert bool(p) is True
266 assert p == ffi.cast("int*", a)
267 assert p != ffi.cast("int*", 0)
268 assert p[0] == 123
269 assert p[1] == 456
270
271 def test_repr(self):
272 typerepr = "<ctype '%s'>"
273 p = ffi.cast("short unsigned int", 0)
274 assert repr(p) == "<cdata 'unsigned short' 0>"
275 assert repr(ffi.typeof(p)) == typerepr % "unsigned short"
276 p = ffi.cast("unsigned short int", 0)
277 assert repr(p) == "<cdata 'unsigned short' 0>"
278 assert repr(ffi.typeof(p)) == typerepr % "unsigned short"
279 p = ffi.cast("int*", 0)
280 assert repr(p) == "<cdata 'int *' NULL>"
281 assert repr(ffi.typeof(p)) == typerepr % "int *"
282 #
283 p = ffi.new("int*")
284 assert repr(p) == "<cdata 'int *' owning %d bytes>" % SIZE_OF_INT
285 assert repr(ffi.typeof(p)) == typerepr % "int *"
286 p = ffi.new("int**")
287 assert repr(p) == "<cdata 'int * *' owning %d bytes>" % SIZE_OF_PTR
288 assert repr(ffi.typeof(p)) == typerepr % "int * *"
289 p = ffi.new("int [2]")
290 assert repr(p) == "<cdata 'int[2]' owning %d bytes>" % (2*SIZE_OF_INT)
291 assert repr(ffi.typeof(p)) == typerepr % "int[2]"
292 p = ffi.new("int*[2][3]")
293 assert repr(p) == "<cdata 'int *[2][3]' owning %d bytes>" % (
294 6*SIZE_OF_PTR)
295 assert repr(ffi.typeof(p)) == typerepr % "int *[2][3]"
296 p = ffi.new("struct repr *")
297 assert repr(p) == "<cdata 'struct repr *' owning %d bytes>" % (
298 3*SIZE_OF_SHORT)
299 assert repr(ffi.typeof(p)) == typerepr % "struct repr *"
300 #
301 q = ffi.cast("short", -123)
302 assert repr(q) == "<cdata 'short' -123>"
303 assert repr(ffi.typeof(q)) == typerepr % "short"
304 p = ffi.new("int*")
305 q = ffi.cast("short*", p)
306 assert repr(q).startswith("<cdata 'short *' 0x")
307 assert repr(ffi.typeof(q)) == typerepr % "short *"
308 p = ffi.new("int [2]")
309 q = ffi.cast("int*", p)
310 assert repr(q).startswith("<cdata 'int *' 0x")
311 assert repr(ffi.typeof(q)) == typerepr % "int *"
312 p = ffi.new("struct repr*")
313 q = ffi.cast("struct repr *", p)
314 assert repr(q).startswith("<cdata 'struct repr *' 0x")
315 assert repr(ffi.typeof(q)) == typerepr % "struct repr *"
316 prevrepr = repr(q)
317 q = q[0]
318 assert repr(q) == prevrepr.replace(' *', ' &')
319 assert repr(ffi.typeof(q)) == typerepr % "struct repr"
320
321 def test_new_array_of_array(self):
322 p = ffi.new("int[3][4]")
323 p[0][0] = 10
324 p[2][3] = 33
325 assert p[0][0] == 10
326 assert p[2][3] == 33
327 py.test.raises(IndexError, "p[1][-1]")
328
329 def test_constructor_array_of_array(self):
330 p = ffi.new("int[3][2]", [[10, 11], [12, 13], [14, 15]])
331 assert p[2][1] == 15
332
333 def test_new_array_of_pointer_1(self):
334 n = ffi.new("int*", 99)
335 p = ffi.new("int*[4]")
336 p[3] = n
337 a = p[3]
338 assert repr(a).startswith("<cdata 'int *' 0x")
339 assert a[0] == 99
340
341 def test_new_array_of_pointer_2(self):
342 n = ffi.new("int[1]", [99])
343 p = ffi.new("int*[4]")
344 p[3] = n
345 a = p[3]
346 assert repr(a).startswith("<cdata 'int *' 0x")
347 assert a[0] == 99
348
349 def test_char(self):
350 assert ffi.new("char*", b"\xff")[0] == b'\xff'
351 assert ffi.new("char*")[0] == b'\x00'
352 assert int(ffi.cast("char", 300)) == 300 - 256
353 assert not bool(ffi.cast("char", 0))
354 assert bool(ffi.cast("char", 1))
355 assert bool(ffi.cast("char", 255))
356 py.test.raises(TypeError, ffi.new, "char*", 32)
357 py.test.raises(TypeError, ffi.new, "char*", u+"x")
358 py.test.raises(TypeError, ffi.new, "char*", b"foo")
359 #
360 p = ffi.new("char[]", [b'a', b'b', b'\x9c'])
361 assert len(p) == 3
362 assert p[0] == b'a'
363 assert p[1] == b'b'
364 assert p[2] == b'\x9c'
365 p[0] = b'\xff'
366 assert p[0] == b'\xff'
367 p = ffi.new("char[]", b"abcd")
368 assert len(p) == 5
369 assert p[4] == b'\x00' # like in C, with: char[] p = "abcd";
370 #
371 p = ffi.new("char[4]", b"ab")
372 assert len(p) == 4
373 assert [p[i] for i in range(4)] == [b'a', b'b', b'\x00', b'\x00']
374 p = ffi.new("char[2]", b"ab")
375 assert len(p) == 2
376 assert [p[i] for i in range(2)] == [b'a', b'b']
377 py.test.raises(IndexError, ffi.new, "char[2]", b"abc")
378
379 def check_wchar_t(self, ffi):
380 try:
381 ffi.cast("wchar_t", 0)
382 except NotImplementedError:
383 py.test.skip("NotImplementedError: wchar_t")
384
385 def test_wchar_t(self):
386 self.check_wchar_t(ffi)
387 assert ffi.new("wchar_t*", u+'x')[0] == u+'x'
388 assert ffi.new("wchar_t*", u+'\u1234')[0] == u+'\u1234'
389 if SIZE_OF_WCHAR > 2:
390 assert ffi.new("wchar_t*", u+'\U00012345')[0] == u+'\U00012345'
391 else:
392 py.test.raises(TypeError, ffi.new, "wchar_t*", u+'\U00012345')
393 assert ffi.new("wchar_t*")[0] == u+'\x00'
394 assert int(ffi.cast("wchar_t", 300)) == 300
395 assert not bool(ffi.cast("wchar_t", 0))
396 assert bool(ffi.cast("wchar_t", 1))
397 assert bool(ffi.cast("wchar_t", 65535))
398 if SIZE_OF_WCHAR > 2:
399 assert bool(ffi.cast("wchar_t", 65536))
400 py.test.raises(TypeError, ffi.new, "wchar_t*", 32)
401 py.test.raises(TypeError, ffi.new, "wchar_t*", "foo")
402 #
403 p = ffi.new("wchar_t[]", [u+'a', u+'b', u+'\u1234'])
404 assert len(p) == 3
405 assert p[0] == u+'a'
406 assert p[1] == u+'b' and type(p[1]) is unicode
407 assert p[2] == u+'\u1234'
408 p[0] = u+'x'
409 assert p[0] == u+'x' and type(p[0]) is unicode
410 p[1] = u+'\u1357'
411 assert p[1] == u+'\u1357'
412 p = ffi.new("wchar_t[]", u+"abcd")
413 assert len(p) == 5
414 assert p[4] == u+'\x00'
415 p = ffi.new("wchar_t[]", u+"a\u1234b")
416 assert len(p) == 4
417 assert p[1] == u+'\u1234'
418 #
419 p = ffi.new("wchar_t[]", u+'\U00023456')
420 if SIZE_OF_WCHAR == 2:
421 assert len(p) == 3
422 assert p[0] == u+'\ud84d'
423 assert p[1] == u+'\udc56'
424 assert p[2] == u+'\x00'
425 else:
426 assert len(p) == 2
427 assert p[0] == u+'\U00023456'
428 assert p[1] == u+'\x00'
429 #
430 p = ffi.new("wchar_t[4]", u+"ab")
431 assert len(p) == 4
432 assert [p[i] for i in range(4)] == [u+'a', u+'b', u+'\x00', u+'\x00']
433 p = ffi.new("wchar_t[2]", u+"ab")
434 assert len(p) == 2
435 assert [p[i] for i in range(2)] == [u+'a', u+'b']
436 py.test.raises(IndexError, ffi.new, "wchar_t[2]", u+"abc")
437
438 def test_none_as_null_doesnt_work(self):
439 p = ffi.new("int*[1]")
440 assert p[0] is not None
441 assert p[0] != None
442 assert p[0] == ffi.NULL
443 assert repr(p[0]) == "<cdata 'int *' NULL>"
444 #
445 n = ffi.new("int*", 99)
446 p = ffi.new("int*[]", [n])
447 assert p[0][0] == 99
448 py.test.raises(TypeError, "p[0] = None")
449 p[0] = ffi.NULL
450 assert p[0] == ffi.NULL
451
452 def test_float(self):
453 p = ffi.new("float[]", [-2, -2.5])
454 assert p[0] == -2.0
455 assert p[1] == -2.5
456 p[1] += 17.75
457 assert p[1] == 15.25
458 #
459 p = ffi.new("float*", 15.75)
460 assert p[0] == 15.75
461 py.test.raises(TypeError, int, p)
462 py.test.raises(TypeError, float, p)
463 p[0] = 0.0
464 assert bool(p) is True
465 #
466 p = ffi.new("float*", 1.1)
467 f = p[0]
468 assert f != 1.1 # because of rounding effect
469 assert abs(f - 1.1) < 1E-7
470 #
471 INF = 1E200 * 1E200
472 assert 1E200 != INF
473 p[0] = 1E200
474 assert p[0] == INF # infinite, not enough precision
475
476 def test_struct_simple(self):
477 s = ffi.new("struct simple*")
478 assert s.a == s.b == s.c == 0
479 s.b = -23
480 assert s.b == -23
481 py.test.raises(OverflowError, "s.b = 32768")
482 #
483 s = ffi.new("struct simple*", [-2, -3])
484 assert s.a == -2
485 assert s.b == -3
486 assert s.c == 0
487 py.test.raises((AttributeError, TypeError), "del s.a")
488 assert repr(s) == "<cdata 'struct simple *' owning %d bytes>" % (
489 SIZE_OF_INT + 2 * SIZE_OF_SHORT)
490 #
491 py.test.raises(ValueError, ffi.new, "struct simple*", [1, 2, 3, 4])
492
493 def test_constructor_struct_from_dict(self):
494 s = ffi.new("struct simple*", {'b': 123, 'c': 456})
495 assert s.a == 0
496 assert s.b == 123
497 assert s.c == 456
498 py.test.raises(KeyError, ffi.new, "struct simple*", {'d': 456})
499
500 def test_struct_pointer(self):
501 s = ffi.new("struct simple*")
502 assert s[0].a == s[0].b == s[0].c == 0
503 s[0].b = -23
504 assert s[0].b == s.b == -23
505 py.test.raises(OverflowError, "s[0].b = -32769")
506 py.test.raises(IndexError, "s[1]")
507
508 def test_struct_opaque(self):
509 py.test.raises(ffi.error, ffi.new, "struct baz*")
510 # should 'ffi.new("struct baz **") work? it used to, but it was
511 # not particularly useful...
512 py.test.raises(ffi.error, ffi.new, "struct baz**")
513
514 def test_pointer_to_struct(self):
515 s = ffi.new("struct simple *")
516 s.a = -42
517 assert s[0].a == -42
518 p = ffi.new("struct simple **", s)
519 assert p[0].a == -42
520 assert p[0][0].a == -42
521 p[0].a = -43
522 assert s.a == -43
523 assert s[0].a == -43
524 p[0][0].a = -44
525 assert s.a == -44
526 assert s[0].a == -44
527 s.a = -45
528 assert p[0].a == -45
529 assert p[0][0].a == -45
530 s[0].a = -46
531 assert p[0].a == -46
532 assert p[0][0].a == -46
533
534 def test_constructor_struct_of_array(self):
535 s = ffi.new("struct array *", [[10, 11], [b'a', b'b', b'c']])
536 assert s.a[1] == 11
537 assert s.b[2] == b'c'
538 s.b[1] = b'X'
539 assert s.b[0] == b'a'
540 assert s.b[1] == b'X'
541 assert s.b[2] == b'c'
542
543 def test_recursive_struct(self):
544 s = ffi.new("struct recursive*")
545 t = ffi.new("struct recursive*")
546 s.value = 123
547 s.next = t
548 t.value = 456
549 assert s.value == 123
550 assert s.next.value == 456
551
552 def test_union_simple(self):
553 u = ffi.new("union simple_u*")
554 assert u.a == u.b == u.c == 0
555 u.b = -23
556 assert u.b == -23
557 assert u.a != 0
558 py.test.raises(OverflowError, "u.b = 32768")
559 #
560 u = ffi.new("union simple_u*", [-2])
561 assert u.a == -2
562 py.test.raises((AttributeError, TypeError), "del u.a")
563 assert repr(u) == "<cdata 'union simple_u *' owning %d bytes>" % (
564 SIZE_OF_INT,)
565
566 def test_union_opaque(self):
567 py.test.raises(ffi.error, ffi.new, "union baz*")
568 # should 'ffi.new("union baz **") work? it used to, but it was
569 # not particularly useful...
570 py.test.raises(ffi.error, ffi.new, "union baz**")
571
572 def test_union_initializer(self):
573 py.test.raises(TypeError, ffi.new, "union init_u*", b'A')
574 py.test.raises(TypeError, ffi.new, "union init_u*", 5)
575 py.test.raises(ValueError, ffi.new, "union init_u*", [b'A', 5])
576 u = ffi.new("union init_u*", [b'A'])
577 assert u.a == b'A'
578 py.test.raises(TypeError, ffi.new, "union init_u*", [1005])
579 u = ffi.new("union init_u*", {'b': 12345})
580 assert u.b == 12345
581 u = ffi.new("union init_u*", [])
582 assert u.a == b'\x00'
583 assert u.b == 0
584
585 def test_sizeof_type(self):
586 for c_type, expected_size in [
587 ('char', 1),
588 ('unsigned int', 4),
589 ('char *', SIZE_OF_PTR),
590 ('int[5]', 20),
591 ('struct four_s', 12),
592 ('union four_u', 4),
593 ]:
594 size = ffi.sizeof(c_type)
595 assert size == expected_size, (size, expected_size, ctype)
596
597 def test_sizeof_cdata(self):
598 assert ffi.sizeof(ffi.new("short*")) == SIZE_OF_PTR
599 assert ffi.sizeof(ffi.cast("short", 123)) == SIZE_OF_SHORT
600 #
601 a = ffi.new("int[]", [10, 11, 12, 13, 14])
602 assert len(a) == 5
603 assert ffi.sizeof(a) == 5 * SIZE_OF_INT
604
605 def test_string_from_char_pointer(self):
606 x = ffi.new("char*", b"x")
607 assert str(x) == repr(x)
608 assert ffi.string(x) == b"x"
609 assert ffi.string(ffi.new("char*", b"\x00")) == b""
610 py.test.raises(TypeError, ffi.new, "char*", unicode("foo"))
611
612 def test_unicode_from_wchar_pointer(self):
613 self.check_wchar_t(ffi)
614 x = ffi.new("wchar_t*", u+"x")
615 assert unicode(x) == unicode(repr(x))
616 assert ffi.string(x) == u+"x"
617 assert ffi.string(ffi.new("wchar_t*", u+"\x00")) == u+""
618
619 def test_string_from_char_array(self):
620 p = ffi.new("char[]", b"hello.")
621 p[5] = b'!'
622 assert ffi.string(p) == b"hello!"
623 p[6] = b'?'
624 assert ffi.string(p) == b"hello!?"
625 p[3] = b'\x00'
626 assert ffi.string(p) == b"hel"
627 assert ffi.string(p, 2) == b"he"
628 py.test.raises(IndexError, "p[7] = b'X'")
629 #
630 a = ffi.new("char[]", b"hello\x00world")
631 assert len(a) == 12
632 p = ffi.cast("char *", a)
633 assert ffi.string(p) == b'hello'
634
635 def test_string_from_wchar_array(self):
636 self.check_wchar_t(ffi)
637 assert ffi.string(ffi.cast("wchar_t", "x")) == u+"x"
638 assert ffi.string(ffi.cast("wchar_t", u+"x")) == u+"x"
639 x = ffi.cast("wchar_t", "x")
640 assert str(x) == repr(x)
641 assert ffi.string(x) == u+"x"
642 #
643 p = ffi.new("wchar_t[]", u+"hello.")
644 p[5] = u+'!'
645 assert ffi.string(p) == u+"hello!"
646 p[6] = u+'\u04d2'
647 assert ffi.string(p) == u+"hello!\u04d2"
648 p[3] = u+'\x00'
649 assert ffi.string(p) == u+"hel"
650 assert ffi.string(p, 123) == u+"hel"
651 py.test.raises(IndexError, "p[7] = u+'X'")
652 #
653 a = ffi.new("wchar_t[]", u+"hello\x00world")
654 assert len(a) == 12
655 p = ffi.cast("wchar_t *", a)
656 assert ffi.string(p) == u+'hello'
657 assert ffi.string(p, 123) == u+'hello'
658 assert ffi.string(p, 5) == u+'hello'
659 assert ffi.string(p, 2) == u+'he'
660
661 def test_fetch_const_char_p_field(self):
662 # 'const' is ignored so far, in the declaration of 'struct string'
663 t = ffi.new("const char[]", b"testing")
664 s = ffi.new("struct string*", [t])
665 assert type(s.name) not in (bytes, str, unicode)
666 assert ffi.string(s.name) == b"testing"
667 py.test.raises(TypeError, "s.name = None")
668 s.name = ffi.NULL
669 assert s.name == ffi.NULL
670
671 def test_fetch_const_wchar_p_field(self):
672 # 'const' is ignored so far
673 self.check_wchar_t(ffi)
674 t = ffi.new("const wchar_t[]", u+"testing")
675 s = ffi.new("struct ustring*", [t])
676 assert type(s.name) not in (bytes, str, unicode)
677 assert ffi.string(s.name) == u+"testing"
678 s.name = ffi.NULL
679 assert s.name == ffi.NULL
680
681 def test_voidp(self):
682 py.test.raises(TypeError, ffi.new, "void*")
683 p = ffi.new("void **")
684 assert p[0] == ffi.NULL
685 a = ffi.new("int[]", [10, 11, 12])
686 p = ffi.new("void **", a)
687 vp = p[0]
688 py.test.raises(TypeError, "vp[0]")
689 py.test.raises(TypeError, ffi.new, "short **", a)
690 #
691 s = ffi.new("struct voidp *")
692 s.p = a # works
693 s.q = a # works
694 py.test.raises(TypeError, "s.r = a") # fails
695 b = ffi.cast("int *", a)
696 s.p = b # works
697 s.q = b # works
698 py.test.raises(TypeError, "s.r = b") # fails
699
700 def test_functionptr_simple(self):
701 py.test.raises(TypeError, ffi.callback, "int(*)(int)", 0)
702 def cb(n):
703 return n + 1
704 cb.__qualname__ = 'cb'
705 p = ffi.callback("int(*)(int)", cb)
706 res = p(41) # calling an 'int(*)(int)', i.e. a function pointer
707 assert res == 42 and type(res) is int
708 res = p(ffi.cast("int", -41))
709 assert res == -40 and type(res) is int
710 assert repr(p).startswith(
711 "<cdata 'int(*)(int)' calling <function cb at 0x")
712 assert ffi.typeof(p) is ffi.typeof("int(*)(int)")
713 q = ffi.new("int(**)(int)", p)
714 assert repr(q) == "<cdata 'int(* *)(int)' owning %d bytes>" % (
715 SIZE_OF_PTR)
716 py.test.raises(TypeError, "q(43)")
717 res = q[0](43)
718 assert res == 44
719 q = ffi.cast("int(*)(int)", p)
720 assert repr(q).startswith("<cdata 'int(*)(int)' 0x")
721 res = q(45)
722 assert res == 46
723
724 def test_functionptr_advanced(self):
725 t = ffi.typeof("int(*(*)(int))(int)")
726 assert repr(t) == "<ctype '%s'>" % "int(*(*)(int))(int)"
727
728 def test_functionptr_voidptr_return(self):
729 def cb():
730 return ffi.NULL
731 p = ffi.callback("void*(*)()", cb)
732 res = p()
733 assert res is not None
734 assert res == ffi.NULL
735 int_ptr = ffi.new('int*')
736 void_ptr = ffi.cast('void*', int_ptr)
737 def cb():
738 return void_ptr
739 p = ffi.callback("void*(*)()", cb)
740 res = p()
741 assert res == void_ptr
742
743 def test_functionptr_intptr_return(self):
744 def cb():
745 return ffi.NULL
746 p = ffi.callback("int*(*)()", cb)
747 res = p()
748 assert res == ffi.NULL
749 int_ptr = ffi.new('int*')
750 def cb():
751 return int_ptr
752 p = ffi.callback("int*(*)()", cb)
753 res = p()
754 assert repr(res).startswith("<cdata 'int *' 0x")
755 assert res == int_ptr
756 int_array_ptr = ffi.new('int[1]')
757 def cb():
758 return int_array_ptr
759 p = ffi.callback("int*(*)()", cb)
760 res = p()
761 assert repr(res).startswith("<cdata 'int *' 0x")
762 assert res == int_array_ptr
763
764 def test_functionptr_void_return(self):
765 def foo():
766 pass
767 foo_cb = ffi.callback("void foo()", foo)
768 result = foo_cb()
769 assert result is None
770
771 def test_char_cast(self):
772 p = ffi.cast("int", b'\x01')
773 assert ffi.typeof(p) is ffi.typeof("int")
774 assert int(p) == 1
775 p = ffi.cast("int", ffi.cast("char", b"a"))
776 assert int(p) == ord("a")
777 p = ffi.cast("int", ffi.cast("char", b"\x80"))
778 assert int(p) == 0x80 # "char" is considered unsigned in this case
779 p = ffi.cast("int", b"\x81")
780 assert int(p) == 0x81
781
782 def test_wchar_cast(self):
783 self.check_wchar_t(ffi)
784 p = ffi.cast("int", ffi.cast("wchar_t", u+'\u1234'))
785 assert int(p) == 0x1234
786 p = ffi.cast("long long", ffi.cast("wchar_t", -1))
787 if SIZE_OF_WCHAR == 2: # 2 bytes, unsigned
788 assert int(p) == 0xffff
789 elif (sys.platform.startswith('linux') and
790 platform.machine().startswith('x86')): # known to be signed
791 assert int(p) == -1
792 else: # in general, it can be either signed or not
793 assert int(p) in [-1, 0xffffffff] # e.g. on arm, both cases occur
794 p = ffi.cast("int", u+'\u1234')
795 assert int(p) == 0x1234
796
797 def test_cast_array_to_charp(self):
798 a = ffi.new("short int[]", [0x1234, 0x5678])
799 p = ffi.cast("char*", a)
800 data = b''.join([p[i] for i in range(4)])
801 if sys.byteorder == 'little':
802 assert data == b'\x34\x12\x78\x56'
803 else:
804 assert data == b'\x12\x34\x56\x78'
805
806 def test_cast_between_pointers(self):
807 a = ffi.new("short int[]", [0x1234, 0x5678])
808 p = ffi.cast("short*", a)
809 p2 = ffi.cast("int*", p)
810 q = ffi.cast("char*", p2)
811 data = b''.join([q[i] for i in range(4)])
812 if sys.byteorder == 'little':
813 assert data == b'\x34\x12\x78\x56'
814 else:
815 assert data == b'\x12\x34\x56\x78'
816
817 def test_cast_pointer_and_int(self):
818 a = ffi.new("short int[]", [0x1234, 0x5678])
819 l1 = ffi.cast("intptr_t", a)
820 p = ffi.cast("short*", a)
821 l2 = ffi.cast("intptr_t", p)
822 assert int(l1) == int(l2) != 0
823 q = ffi.cast("short*", l1)
824 assert q == ffi.cast("short*", int(l1))
825 assert q[0] == 0x1234
826 assert int(ffi.cast("intptr_t", ffi.NULL)) == 0
827
828 def test_cast_functionptr_and_int(self):
829 def cb(n):
830 return n + 1
831 a = ffi.callback("int(*)(int)", cb)
832 p = ffi.cast("void *", a)
833 assert p
834 b = ffi.cast("int(*)(int)", p)
835 assert b(41) == 42
836 assert a == b
837 assert hash(a) == hash(b)
838
839 def test_callback_crash(self):
840 def cb(n):
841 raise Exception
842 a = ffi.callback("int(*)(int)", cb, error=42)
843 res = a(1) # and the error reported to stderr
844 assert res == 42
845
846 def test_structptr_argument(self):
847 def cb(p):
848 return p[0].a * 1000 + p[0].b * 100 + p[1].a * 10 + p[1].b
849 a = ffi.callback("int(*)(struct ab[])", cb)
850 res = a([[5, 6], {'a': 7, 'b': 8}])
851 assert res == 5678
852 res = a([[5], {'b': 8}])
853 assert res == 5008
854
855 def test_array_argument_as_list(self):
856 seen = []
857 def cb(argv):
858 seen.append(ffi.string(argv[0]))
859 seen.append(ffi.string(argv[1]))
860 a = ffi.callback("void(*)(char *[])", cb)
861 a([ffi.new("char[]", b"foobar"), ffi.new("char[]", b"baz")])
862 assert seen == [b"foobar", b"baz"]
863
864 def test_cast_float(self):
865 a = ffi.cast("float", 12)
866 assert float(a) == 12.0
867 a = ffi.cast("float", 12.5)
868 assert float(a) == 12.5
869 a = ffi.cast("float", b"A")
870 assert float(a) == ord("A")
871 a = ffi.cast("int", 12.9)
872 assert int(a) == 12
873 a = ffi.cast("char", 66.9 + 256)
874 assert ffi.string(a) == b"B"
875 #
876 a = ffi.cast("float", ffi.cast("int", 12))
877 assert float(a) == 12.0
878 a = ffi.cast("float", ffi.cast("double", 12.5))
879 assert float(a) == 12.5
880 a = ffi.cast("float", ffi.cast("char", b"A"))
881 assert float(a) == ord("A")
882 a = ffi.cast("int", ffi.cast("double", 12.9))
883 assert int(a) == 12
884 a = ffi.cast("char", ffi.cast("double", 66.9 + 256))
885 assert ffi.string(a) == b"B"
886
887 def test_enum(self):
888 # enum foq { A0, B0, CC0, D0 };
889 assert ffi.string(ffi.cast("enum foq", 0)) == "cffiA0"
890 assert ffi.string(ffi.cast("enum foq", 2)) == "cffiCC0"
891 assert ffi.string(ffi.cast("enum foq", 3)) == "cffiD0"
892 assert ffi.string(ffi.cast("enum foq", 4)) == "4"
893 # enum bar { A1, B1=-2, CC1, D1, E1 };
894 assert ffi.string(ffi.cast("enum bar", 0)) == "A1"
895 assert ffi.string(ffi.cast("enum bar", -2)) == "B1"
896 assert ffi.string(ffi.cast("enum bar", -1)) == "CC1"
897 assert ffi.string(ffi.cast("enum bar", 1)) == "E1"
898 assert ffi.cast("enum bar", -2) == ffi.cast("enum bar", -2)
899 assert ffi.cast("enum foq", 0) == ffi.cast("enum bar", 0)
900 assert ffi.cast("enum bar", 0) == ffi.cast("int", 0)
901 assert repr(ffi.cast("enum bar", -1)) == "<cdata 'enum bar' -1: CC1>"
902 assert repr(ffi.cast("enum foq", -1)) == ( # enums are unsigned, if
903 "<cdata 'enum foq' 4294967295>") or ( # they contain no neg value
904 sys.platform == "win32") # (but not on msvc)
905 # enum baz { A2=0x1000, B2=0x2000 };
906 assert ffi.string(ffi.cast("enum baz", 0x1000)) == "A2"
907 assert ffi.string(ffi.cast("enum baz", 0x2000)) == "B2"
908
909 def test_enum_in_struct(self):
910 # enum foo2 { A3, B3, C3, D3 };
911 # struct bar_with_e { enum foo2 e; };
912 s = ffi.new("struct bar_with_e *")
913 s.e = 0
914 assert s.e == 0
915 s.e = 3
916 assert s.e == 3
917 assert s[0].e == 3
918 s[0].e = 2
919 assert s.e == 2
920 assert s[0].e == 2
921 s.e = ffi.cast("enum foo2", -1)
922 assert s.e in (4294967295, -1) # two choices
923 assert s[0].e in (4294967295, -1)
924 s.e = s.e
925 py.test.raises(TypeError, "s.e = 'B3'")
926 py.test.raises(TypeError, "s.e = '2'")
927 py.test.raises(TypeError, "s.e = '#2'")
928 py.test.raises(TypeError, "s.e = '#7'")
929
930 def test_enum_non_contiguous(self):
931 # enum noncont { A4, B4=42, C4 };
932 assert ffi.string(ffi.cast("enum noncont", 0)) == "A4"
933 assert ffi.string(ffi.cast("enum noncont", 42)) == "B4"
934 assert ffi.string(ffi.cast("enum noncont", 43)) == "C4"
935 invalid_value = ffi.cast("enum noncont", 2)
936 assert int(invalid_value) == 2
937 assert ffi.string(invalid_value) == "2"
938
939 def test_enum_char_hex_oct(self):
940 # enum etypes {A5='!', B5='\'', C5=0x10, D5=010, E5=- 0x10, F5=-010};
941 assert ffi.string(ffi.cast("enum etypes", ord('!'))) == "A5"
942 assert ffi.string(ffi.cast("enum etypes", ord("'"))) == "B5"
943 assert ffi.string(ffi.cast("enum etypes", 16)) == "C5"
944 assert ffi.string(ffi.cast("enum etypes", 8)) == "D5"
945 assert ffi.string(ffi.cast("enum etypes", -16)) == "E5"
946 assert ffi.string(ffi.cast("enum etypes", -8)) == "F5"
947
948 def test_array_of_struct(self):
949 s = ffi.new("struct ab[1]")
950 py.test.raises(AttributeError, 's.b')
951 py.test.raises(AttributeError, 's.b = 412')
952 s[0].b = 412
953 assert s[0].b == 412
954 py.test.raises(IndexError, 's[1]')
955
956 def test_pointer_to_array(self):
957 p = ffi.new("int(**)[5]")
958 assert repr(p) == "<cdata 'int(* *)[5]' owning %d bytes>" % SIZE_OF_PTR
959
960 def test_iterate_array(self):
961 a = ffi.new("char[]", b"hello")
962 assert list(a) == [b"h", b"e", b"l", b"l", b"o", b"\0"]
963 assert list(iter(a)) == [b"h", b"e", b"l", b"l", b"o", b"\0"]
964 #
965 py.test.raises(TypeError, iter, ffi.cast("char *", a))
966 py.test.raises(TypeError, list, ffi.cast("char *", a))
967 py.test.raises(TypeError, iter, ffi.new("int *"))
968 py.test.raises(TypeError, list, ffi.new("int *"))
969
970 def test_offsetof(self):
971 # struct abc { int a, b, c; };
972 assert ffi.offsetof("struct abc", "a") == 0
973 assert ffi.offsetof("struct abc", "b") == 4
974 assert ffi.offsetof("struct abc", "c") == 8
975
976 def test_offsetof_nested(self):
977 # struct nesting { struct abc d, e; };
978 assert ffi.offsetof("struct nesting", "e") == 12
979 py.test.raises(KeyError, ffi.offsetof, "struct nesting", "e.a")
980 assert ffi.offsetof("struct nesting", "e", "a") == 12
981 assert ffi.offsetof("struct nesting", "e", "b") == 16
982 assert ffi.offsetof("struct nesting", "e", "c") == 20
983
984 def test_offsetof_array(self):
985 assert ffi.offsetof("int[]", 51) == 51 * ffi.sizeof("int")
986 assert ffi.offsetof("int *", 51) == 51 * ffi.sizeof("int")
987 # struct array2 { int a, b; int c[99]; };
988 assert ffi.offsetof("struct array2", "c") == 2 * ffi.sizeof("int")
989 assert ffi.offsetof("struct array2", "c", 0) == 2 * ffi.sizeof("int")
990 assert ffi.offsetof("struct array2", "c", 51) == 53 * ffi.sizeof("int")
991
992 def test_alignof(self):
993 # struct align { char a; short b; char c; };
994 assert ffi.alignof("int") == 4
995 assert ffi.alignof("double") in (4, 8)
996 assert ffi.alignof("struct align") == 2
997
998 def test_bitfield(self):
999 # struct bitfield { int a:10, b:20, c:3; };
1000 assert ffi.sizeof("struct bitfield") == 8
1001 s = ffi.new("struct bitfield *")
1002 s.a = 511
1003 py.test.raises(OverflowError, "s.a = 512")
1004 py.test.raises(OverflowError, "s[0].a = 512")
1005 assert s.a == 511
1006 s.a = -512
1007 py.test.raises(OverflowError, "s.a = -513")
1008 py.test.raises(OverflowError, "s[0].a = -513")
1009 assert s.a == -512
1010 s.c = 3
1011 assert s.c == 3
1012 py.test.raises(OverflowError, "s.c = 4")
1013 py.test.raises(OverflowError, "s[0].c = 4")
1014 s.c = -4
1015 assert s.c == -4
1016
1017 def test_bitfield_enum(self):
1018 # typedef enum { AA1, BB1, CC1 } foo_e_t;
1019 # typedef struct { foo_e_t f:2; } bfenum_t;
1020 if sys.platform == "win32":
1021 py.test.skip("enums are not unsigned")
1022 s = ffi.new("bfenum_t *")
1023 s.f = 2
1024 assert s.f == 2
1025
1026 def test_anonymous_struct(self):
1027 # typedef struct { int a; } anon_foo_t;
1028 # typedef struct { char b, c; } anon_bar_t;
1029 f = ffi.new("anon_foo_t *", [12345])
1030 b = ffi.new("anon_bar_t *", [b"B", b"C"])
1031 assert f.a == 12345
1032 assert b.b == b"B"
1033 assert b.c == b"C"
1034 assert repr(b).startswith("<cdata 'anon_bar_t *'")
1035
1036 def test_struct_with_two_usages(self):
1037 # typedef struct named_foo_s { int a; } named_foo_t, *named_foo_p;
1038 # typedef struct { int a; } unnamed_foo_t, *unnamed_foo_p;
1039 f = ffi.new("named_foo_t *", [12345])
1040 ps = ffi.new("named_foo_p[]", [f])
1041 f = ffi.new("unnamed_foo_t *", [12345])
1042 ps = ffi.new("unnamed_foo_p[]", [f])
1043
1044 def test_pointer_arithmetic(self):
1045 s = ffi.new("short[]", list(range(100, 110)))
1046 p = ffi.cast("short *", s)
1047 assert p[2] == 102
1048 assert p+1 == p+1
1049 assert p+1 != p+0
1050 assert p == p+0 == p-0
1051 assert (p+1)[0] == 101
1052 assert (p+19)[-10] == 109
1053 assert (p+5) - (p+1) == 4
1054 assert p == s+0
1055 assert p+1 == s+1
1056
1057 def test_pointer_comparison(self):
1058 s = ffi.new("short[]", list(range(100)))
1059 p = ffi.cast("short *", s)
1060 assert (p < s) is False
1061 assert (p <= s) is True
1062 assert (p == s) is True
1063 assert (p != s) is False
1064 assert (p > s) is False
1065 assert (p >= s) is True
1066 assert (s < p) is False
1067 assert (s <= p) is True
1068 assert (s == p) is True
1069 assert (s != p) is False
1070 assert (s > p) is False
1071 assert (s >= p) is True
1072 q = p + 1
1073 assert (q < s) is False
1074 assert (q <= s) is False
1075 assert (q == s) is False
1076 assert (q != s) is True
1077 assert (q > s) is True
1078 assert (q >= s) is True
1079 assert (s < q) is True
1080 assert (s <= q) is True
1081 assert (s == q) is False
1082 assert (s != q) is True
1083 assert (s > q) is False
1084 assert (s >= q) is False
1085 assert (q < p) is False
1086 assert (q <= p) is False
1087 assert (q == p) is False
1088 assert (q != p) is True
1089 assert (q > p) is True
1090 assert (q >= p) is True
1091 assert (p < q) is True
1092 assert (p <= q) is True
1093 assert (p == q) is False
1094 assert (p != q) is True
1095 assert (p > q) is False
1096 assert (p >= q) is False
1097 #
1098 assert (None == s) is False
1099 assert (None != s) is True
1100 assert (s == None) is False
1101 assert (s != None) is True
1102 assert (None == q) is False
1103 assert (None != q) is True
1104 assert (q == None) is False
1105 assert (q != None) is True
1106
1107 def test_integer_comparison(self):
1108 x = ffi.cast("int", 123)
1109 y = ffi.cast("int", 456)
1110 assert x < y
1111 #
1112 z = ffi.cast("double", 78.9)
1113 assert x > z
1114 assert y > z
1115
1116 def test_ffi_buffer_ptr(self):
1117 a = ffi.new("short *", 100)
1118 try:
1119 b = ffi.buffer(a)
1120 except NotImplementedError as e:
1121 py.test.skip(str(e))
1122 content = b[:]
1123 assert len(content) == len(b) == 2
1124 if sys.byteorder == 'little':
1125 assert content == b'\x64\x00'
1126 assert b[0] == b'\x64'
1127 b[0] = b'\x65'
1128 else:
1129 assert content == b'\x00\x64'
1130 assert b[1] == b'\x64'
1131 b[1] = b'\x65'
1132 assert a[0] == 101
1133
1134 def test_ffi_buffer_array(self):
1135 a = ffi.new("int[]", list(range(100, 110)))
1136 try:
1137 b = ffi.buffer(a)
1138 except NotImplementedError as e:
1139 py.test.skip(str(e))
1140 content = b[:]
1141 if sys.byteorder == 'little':
1142 assert content.startswith(b'\x64\x00\x00\x00\x65\x00\x00\x00')
1143 b[4] = b'\x45'
1144 else:
1145 assert content.startswith(b'\x00\x00\x00\x64\x00\x00\x00\x65')
1146 b[7] = b'\x45'
1147 assert len(content) == 4 * 10
1148 assert a[1] == 0x45
1149
1150 def test_ffi_buffer_ptr_size(self):
1151 a = ffi.new("short *", 0x4243)
1152 try:
1153 b = ffi.buffer(a, 1)
1154 except NotImplementedError as e:
1155 py.test.skip(str(e))
1156 content = b[:]
1157 assert len(content) == 1
1158 if sys.byteorder == 'little':
1159 assert content == b'\x43'
1160 b[0] = b'\x62'
1161 assert a[0] == 0x4262
1162 else:
1163 assert content == b'\x42'
1164 b[0] = b'\x63'
1165 assert a[0] == 0x6343
1166
1167 def test_ffi_buffer_array_size(self):
1168 a1 = ffi.new("int[]", list(range(100, 110)))
1169 a2 = ffi.new("int[]", list(range(100, 115)))
1170 try:
1171 ffi.buffer(a1)
1172 except NotImplementedError as e:
1173 py.test.skip(str(e))
1174 assert ffi.buffer(a1)[:] == ffi.buffer(a2, 4*10)[:]
1175
1176 def test_ffi_buffer_with_file(self):
1177 import tempfile, os, array
1178 fd, filename = tempfile.mkstemp()
1179 f = os.fdopen(fd, 'r+b')
1180 a = ffi.new("int[]", list(range(1005)))
1181 try:
1182 ffi.buffer(a, 512)
1183 except NotImplementedError as e:
1184 py.test.skip(str(e))
1185 f.write(ffi.buffer(a, 1000 * ffi.sizeof("int")))
1186 f.seek(0)
1187 assert f.read() == array.array('i', range(1000)).tostring()
1188 f.seek(0)
1189 b = ffi.new("int[]", 1005)
1190 f.readinto(ffi.buffer(b, 1000 * ffi.sizeof("int")))
1191 assert list(a)[:1000] + [0] * (len(a)-1000) == list(b)
1192 f.close()
1193 os.unlink(filename)
1194
1195 def test_ffi_buffer_with_io(self):
1196 import io, array
1197 f = io.BytesIO()
1198 a = ffi.new("int[]", list(range(1005)))
1199 try:
1200 ffi.buffer(a, 512)
1201 except NotImplementedError as e:
1202 py.test.skip(str(e))
1203 f.write(ffi.buffer(a, 1000 * ffi.sizeof("int")))
1204 f.seek(0)
1205 assert f.read() == array.array('i', range(1000)).tostring()
1206 f.seek(0)
1207 b = ffi.new("int[]", 1005)
1208 f.readinto(ffi.buffer(b, 1000 * ffi.sizeof("int")))
1209 assert list(a)[:1000] + [0] * (len(a)-1000) == list(b)
1210 f.close()
1211
1212 def test_array_in_struct(self):
1213 # struct array { int a[2]; char b[3]; };
1214 p = ffi.new("struct array *")
1215 p.a[1] = 5
1216 assert p.a[1] == 5
1217 assert repr(p.a).startswith("<cdata 'int[2]' 0x")
1218
1219 def test_struct_containing_array_varsize_workaround(self):
1220 if sys.platform == "win32":
1221 py.test.skip("array of length 0 not supported")
1222 # struct array0 { int len; short data[0]; };
1223 p = ffi.new("char[]", ffi.sizeof("struct array0") + 7 * SIZE_OF_SHORT)
1224 q = ffi.cast("struct array0 *", p)
1225 assert q.len == 0
1226 # 'q.data' gets not a 'short[0]', but just a 'short *' instead
1227 assert repr(q.data).startswith("<cdata 'short *' 0x")
1228 assert q.data[6] == 0
1229 q.data[6] = 15
1230 assert q.data[6] == 15
1231
1232 def test_new_struct_containing_array_varsize(self):
1233 py.test.skip("later?")
1234 ffi.cdef("struct foo_s { int len; short data[]; };")
1235 p = ffi.new("struct foo_s *", 10) # a single integer is the length
1236 assert p.len == 0
1237 assert p.data[9] == 0
1238 py.test.raises(IndexError, "p.data[10]")
1239
1240 def test_ffi_typeof_getcname(self):
1241 assert ffi.getctype("int") == "int"
1242 assert ffi.getctype("int", 'x') == "int x"
1243 assert ffi.getctype("int*") == "int *"
1244 assert ffi.getctype("int*", '') == "int *"
1245 assert ffi.getctype("int*", 'x') == "int * x"
1246 assert ffi.getctype("int", '*') == "int *"
1247 assert ffi.getctype("int", ' * x ') == "int * x"
1248 assert ffi.getctype(ffi.typeof("int*"), '*') == "int * *"
1249 assert ffi.getctype("int", '[5]') == "int[5]"
1250 assert ffi.getctype("int[5]", '[6]') == "int[6][5]"
1251 assert ffi.getctype("int[5]", '(*)') == "int(*)[5]"
1252 # special-case for convenience: automatically put '()' around '*'
1253 assert ffi.getctype("int[5]", '*') == "int(*)[5]"
1254 assert ffi.getctype("int[5]", '*foo') == "int(*foo)[5]"
1255 assert ffi.getctype("int[5]", ' ** foo ') == "int(** foo)[5]"
1256
1257 def test_array_of_func_ptr(self):
1258 f = ffi.cast("int(*)(int)", 42)
1259 assert f != ffi.NULL
1260 py.test.raises(ffi.error, ffi.cast, "int(int)", 42)
1261 py.test.raises(ffi.error, ffi.new, "int([5])(int)")
1262 a = ffi.new("int(*[5])(int)", [f])
1263 assert ffi.getctype(ffi.typeof(a)) == "int(*[5])(int)"
1264 assert len(a) == 5
1265 assert a[0] == f
1266 assert a[1] == ffi.NULL
1267 py.test.raises(TypeError, ffi.cast, "int(*)(int)[5]", 0)
1268 #
1269 def cb(n):
1270 return n + 1
1271 f = ffi.callback("int(*)(int)", cb)
1272 a = ffi.new("int(*[5])(int)", [f, f])
1273 assert a[1](42) == 43
1274
1275 def test_callback_as_function_argument(self):
1276 # In C, function arguments can be declared with a function type,
1277 # which is automatically replaced with the ptr-to-function type.
1278 def cb(a, b):
1279 return chr(ord(a) + ord(b)).encode()
1280 f = ffi.callback("char cb(char, char)", cb)
1281 assert f(b'A', b'\x01') == b'B'
1282 def g(callback):
1283 return callback(b'A', b'\x01')
1284 g = ffi.callback("char g(char cb(char, char))", g)
1285 assert g(f) == b'B'
1286
1287 def test_vararg_callback(self):
1288 py.test.skip("callback with '...'")
1289 def cb(i, va_list):
1290 j = ffi.va_arg(va_list, "int")
1291 k = ffi.va_arg(va_list, "long long")
1292 return i * 2 + j * 3 + k * 5
1293 f = ffi.callback("long long cb(long i, ...)", cb)
1294 res = f(10, ffi.cast("int", 100), ffi.cast("long long", 1000))
1295 assert res == 20 + 300 + 5000
1296
1297 def test_callback_decorator(self):
1298 #
1299 @ffi.callback("long(long, long)", error=42)
1300 def cb(a, b):
1301 return a - b
1302 #
1303 assert cb(-100, -10) == -90
1304 sz = ffi.sizeof("long")
1305 assert cb((1 << (sz*8-1)) - 1, -10) == 42
1306
1307 def test_anonymous_enum(self):
1308 # typedef enum { Value0 = 0 } e_t, *pe_t;
1309 assert ffi.getctype("e_t*") == 'e_t *'
1310 assert ffi.getctype("pe_t") == 'e_t *'
1311 assert ffi.getctype("foo_e_t*") == 'foo_e_t *'
1312
1313 def test_new_ctype(self):
1314 p = ffi.new("int *")
1315 py.test.raises(TypeError, ffi.new, p)
1316 p = ffi.new(ffi.typeof("int *"), 42)
1317 assert p[0] == 42
1318
1319 def test_enum_with_non_injective_mapping(self):
1320 # enum e_noninj { AA3=0, BB3=0, CC3=0, DD3=0 };
1321 e = ffi.cast("enum e_noninj", 0)
1322 assert ffi.string(e) == "AA3" # pick the first one arbitrarily
1323
1324 def test_enum_refer_previous_enum_value(self):
1325 # enum e_prev { AA4, BB4=2, CC4=4, DD4=BB4, EE4, FF4=CC4, GG4=FF4 };
1326 assert ffi.string(ffi.cast("enum e_prev", 2)) == "BB4"
1327 assert ffi.string(ffi.cast("enum e_prev", 3)) == "EE4"
1328 assert ffi.sizeof("char[DD4]") == 2
1329 assert ffi.sizeof("char[EE4]") == 3
1330 assert ffi.sizeof("char[FF4]") == 4
1331 assert ffi.sizeof("char[GG4]") == 4
1332
1333 def test_nested_anonymous_struct(self):
1334 # struct nested_anon {
1335 # struct { int a, b; };
1336 # union { int c, d; };
1337 # };
1338 assert ffi.sizeof("struct nested_anon") == 3 * SIZE_OF_INT
1339 p = ffi.new("struct nested_anon *", [1, 2, 3])
1340 assert p.a == 1
1341 assert p.b == 2
1342 assert p.c == 3
1343 assert p.d == 3
1344 p.d = 17
1345 assert p.c == 17
1346 p.b = 19
1347 assert p.a == 1
1348 assert p.b == 19
1349 assert p.c == 17
1350 assert p.d == 17
1351 p = ffi.new("struct nested_anon *", {'b': 12, 'd': 14})
1352 assert p.a == 0
1353 assert p.b == 12
1354 assert p.c == 14
1355 assert p.d == 14
1356
1357 def test_nested_field_offset_align(self):
1358 # struct nested_field_ofs_s {
1359 # struct { int a; char b; };
1360 # union { char c; };
1361 # };
1362 assert ffi.offsetof("struct nested_field_ofs_s", "c") == 2 * SIZE_OF_INT
1363 assert ffi.sizeof("struct nested_field_ofs_s") == 3 * SIZE_OF_INT
1364
1365 def test_nested_anonymous_union(self):
1366 # union nested_anon_u {
1367 # struct { int a, b; };
1368 # union { int c, d; };
1369 # };
1370 assert ffi.sizeof("union nested_anon_u") == 2 * SIZE_OF_INT
1371 p = ffi.new("union nested_anon_u *", [5])
1372 assert p.a == 5
1373 assert p.b == 0
1374 assert p.c == 5
1375 assert p.d == 5
1376 p.d = 17
1377 assert p.c == 17
1378 assert p.a == 17
1379 p.b = 19
1380 assert p.a == 17
1381 assert p.b == 19
1382 assert p.c == 17
1383 assert p.d == 17
1384 p = ffi.new("union nested_anon_u *", {'d': 14})
1385 assert p.a == 14
1386 assert p.b == 0
1387 assert p.c == 14
1388 assert p.d == 14
1389 p = ffi.new("union nested_anon_u *", {'b': 12})
1390 assert p.a == 0
1391 assert p.b == 12
1392 assert p.c == 0
1393 assert p.d == 0
1394 # we cannot specify several items in the dict, even though
1395 # in theory in this particular case it would make sense
1396 # to give both 'a' and 'b'
1397
1398 def test_cast_to_array_type(self):
1399 p = ffi.new("int[4]", [-5])
1400 q = ffi.cast("int[3]", p)
1401 assert q[0] == -5
1402 assert repr(q).startswith("<cdata 'int[3]' 0x")
1403
1404 def test_gc(self):
1405 p = ffi.new("int *", 123)
1406 seen = []
1407 def destructor(p1):
1408 assert p1 is p
1409 assert p1[0] == 123
1410 seen.append(1)
1411 q = ffi.gc(p, destructor=destructor)
1412 import gc; gc.collect()
1413 assert seen == []
1414 del q
1415 import gc; gc.collect(); gc.collect(); gc.collect()
1416 assert seen == [1]
1417
1418 def test_gc_2(self):
1419 p = ffi.new("int *", 123)
1420 seen = []
1421 q1 = ffi.gc(p, lambda p: seen.append(1))
1422 q2 = ffi.gc(q1, lambda p: seen.append(2))
1423 import gc; gc.collect()
1424 assert seen == []
1425 del q1, q2
1426 import gc; gc.collect(); gc.collect(); gc.collect(); gc.collect()
1427 assert seen == [2, 1]
1428
1429 def test_gc_3(self):
1430 p = ffi.new("int *", 123)
1431 r = ffi.new("int *", 123)
1432 seen = []
1433 seen_r = []
1434 q1 = ffi.gc(p, lambda p: seen.append(1))
1435 s1 = ffi.gc(r, lambda r: seen_r.append(4))
1436 q2 = ffi.gc(q1, lambda p: seen.append(2))
1437 s2 = ffi.gc(s1, lambda r: seen_r.append(5))
1438 q3 = ffi.gc(q2, lambda p: seen.append(3))
1439 import gc; gc.collect()
1440 assert seen == []
1441 assert seen_r == []
1442 del q1, q2, q3, s2, s1
1443 import gc; gc.collect(); gc.collect(); gc.collect(); gc.collect()
1444 assert seen == [3, 2, 1]
1445 assert seen_r == [5, 4]
1446
1447 def test_gc_4(self):
1448 p = ffi.new("int *", 123)
1449 seen = []
1450 q1 = ffi.gc(p, lambda p: seen.append(1))
1451 q2 = ffi.gc(q1, lambda p: seen.append(2))
1452 q3 = ffi.gc(q2, lambda p: seen.append(3))
1453 import gc; gc.collect()
1454 assert seen == []
1455 del q1, q3 # q2 remains, and has a hard ref to q1
1456 import gc; gc.collect(); gc.collect(); gc.collect()
1457 assert seen == [3]
1458
1459 def test_CData_CType(self):
1460 assert isinstance(ffi.cast("int", 0), ffi.CData)
1461 assert isinstance(ffi.new("int *"), ffi.CData)
1462 assert not isinstance(ffi.typeof("int"), ffi.CData)
1463 assert not isinstance(ffi.cast("int", 0), ffi.CType)
1464 assert not isinstance(ffi.new("int *"), ffi.CType)
1465
1466 def test_CData_CType_2(self):
1467 assert isinstance(ffi.typeof("int"), ffi.CType)
1468
1469 def test_bool(self):
1470 assert int(ffi.cast("_Bool", 0.1)) == 1
1471 assert int(ffi.cast("_Bool", -0.0)) == 0
1472 assert int(ffi.cast("_Bool", b'\x02')) == 1
1473 assert int(ffi.cast("_Bool", b'\x00')) == 0
1474 assert int(ffi.cast("_Bool", b'\x80')) == 1
1475 assert ffi.new("_Bool *", False)[0] == 0
1476 assert ffi.new("_Bool *", 1)[0] == 1
1477 py.test.raises(OverflowError, ffi.new, "_Bool *", 2)
1478 py.test.raises(TypeError, ffi.string, ffi.cast("_Bool", 2))
1479
1480 def test_addressof(self):
1481 p = ffi.new("struct ab *")
1482 a = ffi.addressof(p[0])
1483 assert repr(a).startswith("<cdata 'struct ab *' 0x")
1484 assert a == p
1485 py.test.raises(TypeError, ffi.addressof, p)
1486 py.test.raises((AttributeError, TypeError), ffi.addressof, 5)
1487 py.test.raises(TypeError, ffi.addressof, ffi.cast("int", 5))
1488
1489 def test_addressof_field(self):
1490 p = ffi.new("struct ab *")
1491 b = ffi.addressof(p[0], 'b')
1492 assert repr(b).startswith("<cdata 'int *' 0x")
1493 assert int(ffi.cast("uintptr_t", b)) == (
1494 int(ffi.cast("uintptr_t", p)) + ffi.sizeof("int"))
1495 assert b == ffi.addressof(p, 'b')
1496 assert b != ffi.addressof(p, 'a')
1497
1498 def test_addressof_field_nested(self):
1499 # struct nesting { struct abc d, e; };
1500 p = ffi.new("struct nesting *")
1501 py.test.raises(KeyError, ffi.addressof, p[0], 'e.b')
1502 a = ffi.addressof(p[0], 'e', 'b')
1503 assert int(ffi.cast("uintptr_t", a)) == (
1504 int(ffi.cast("uintptr_t", p)) +
1505 ffi.sizeof("struct abc") + ffi.sizeof("int"))
1506
1507 def test_addressof_anonymous_struct(self):
1508 # typedef struct { int a; } anon_foo_t;
1509 p = ffi.new("anon_foo_t *")
1510 a = ffi.addressof(p[0])
1511 assert a == p
1512
1513 def test_addressof_array(self):
1514 p = ffi.new("int[52]")
1515 p0 = ffi.addressof(p)
1516 assert p0 == p
1517 assert ffi.typeof(p0) is ffi.typeof("int(*)[52]")
1518 py.test.raises(TypeError, ffi.addressof, p0)
1519 #
1520 p1 = ffi.addressof(p, 25)
1521 assert ffi.typeof(p1) is ffi.typeof("int *")
1522 assert (p1 - p) == 25
1523 assert ffi.addressof(p, 0) == p
1524
1525 def test_addressof_pointer(self):
1526 array = ffi.new("int[50]")
1527 p = ffi.cast("int *", array)
1528 py.test.raises(TypeError, ffi.addressof, p)
1529 assert ffi.addressof(p, 0) == p
1530 assert ffi.addressof(p, 25) == p + 25
1531 assert ffi.typeof(ffi.addressof(p, 25)) == ffi.typeof(p)
1532 #
1533 array = ffi.new("struct ab[50]")
1534 p = ffi.cast("int *", array)
1535 py.test.raises(TypeError, ffi.addressof, p)
1536 assert ffi.addressof(p, 0) == p
1537 assert ffi.addressof(p, 25) == p + 25
1538 assert ffi.typeof(ffi.addressof(p, 25)) == ffi.typeof(p)
1539
1540 def test_addressof_array_in_struct(self):
1541 # struct abc50 { int a, b; int c[50]; };
1542 p = ffi.new("struct abc50 *")
1543 p1 = ffi.addressof(p, "c", 25)
1544 assert ffi.typeof(p1) is ffi.typeof("int *")
1545 assert p1 == ffi.cast("int *", p) + 27
1546 assert ffi.addressof(p, "c") == ffi.cast("int *", p) + 2
1547 assert ffi.addressof(p, "c", 0) == ffi.cast("int *", p) + 2
1548 p2 = ffi.addressof(p, 1)
1549 assert ffi.typeof(p2) is ffi.typeof("struct abc50 *")
1550 assert p2 == p + 1
1551
1552 def test_multiple_independent_structs(self):
1553 CDEF2 = "struct ab { int x; };"
1554 ffi2 = cffi.FFI(); ffi2.cdef(CDEF2)
1555 outputfilename = recompile(ffi2, "test_multiple_independent_structs",
1556 CDEF2, tmpdir=str(udir))
1557 module = imp.load_dynamic("test_multiple_independent_structs",
1558 outputfilename)
1559 ffi1 = module.ffi
1560 foo1 = ffi1.new("struct ab *", [10])
1561 foo2 = ffi .new("struct ab *", [20, 30])
1562 assert foo1.x == 10
1563 assert foo2.a == 20
1564 assert foo2.b == 30
1565
1566 def test_include_struct_union_enum_typedef(self):
1567 ffi1, CCODE = construction_params
1568 ffi2 = cffi.FFI()
1569 ffi2.include(ffi1)
1570 outputfilename = recompile(ffi2,
1571 "test_include_struct_union_enum_typedef",
1572 CCODE, tmpdir=str(udir))
1573 module = imp.load_dynamic("test_include_struct_union_enum_typedef",
1574 outputfilename)
1575 ffi2 = module.ffi
1576 #
1577 p = ffi2.new("struct nonpacked *", [b'A', -43141])
1578 assert p.a == b'A'
1579 assert p.b == -43141
1580 #
1581 p = ffi.new("union simple_u *", [-52525])
1582 assert p.a == -52525
1583 #
1584 p = ffi.cast("enum foq", 2)
1585 assert ffi.string(p) == "cffiCC0"
1586 assert ffi2.sizeof("char[cffiCC0]") == 2
1587 #
1588 p = ffi.new("anon_foo_t *", [-52526])
1589 assert p.a == -52526
1590 p = ffi.new("named_foo_p", [-52527])
1591 assert p.a == -52527
1592
1593 def test_struct_packed(self):
1594 # struct nonpacked { char a; int b; };
1595 # struct is_packed { char a; int b; } __attribute__((packed));
1596 assert ffi.sizeof("struct nonpacked") == 8
1597 assert ffi.sizeof("struct is_packed") == 5
1598 assert ffi.alignof("struct nonpacked") == 4
1599 assert ffi.alignof("struct is_packed") == 1
1600 s = ffi.new("struct is_packed[2]")
1601 s[0].b = 42623381
1602 s[0].a = b'X'
1603 s[1].b = -4892220
1604 s[1].a = b'Y'
1605 assert s[0].b == 42623381
1606 assert s[0].a == b'X'
1607 assert s[1].b == -4892220
1608 assert s[1].a == b'Y'
1609
1610 def test_not_supported_bitfield_in_result(self):
1611 # struct ints_and_bitfield { int a,b,c,d,e; int x:1; };
1612 e = py.test.raises(NotImplementedError, ffi.callback,
1613 "struct ints_and_bitfield foo(void)", lambda: 42)
1614 assert str(e.value) == ("struct ints_and_bitfield(*)(): "
1615 "callback with unsupported argument or return type or with '...'")
1616
1617 def test_inspecttype(self):
1618 assert ffi.typeof("long").kind == "primitive"
1619 assert ffi.typeof("long(*)(long, long**, ...)").cname == (
1620 "long(*)(long, long * *, ...)")
1621 assert ffi.typeof("long(*)(long, long**, ...)").ellipsis is True
1622
1623 def test_new_handle(self):
1624 o = [2, 3, 4]
1625 p = ffi.new_handle(o)
1626 assert ffi.typeof(p) == ffi.typeof("void *")
1627 assert ffi.from_handle(p) is o
1628 assert ffi.from_handle(ffi.cast("char *", p)) is o
1629 py.test.raises(RuntimeError, ffi.from_handle, ffi.NULL)
1630
1631 def test_struct_array_no_length(self):
1632 # struct array_no_length { int x; int a[]; };
1633 p = ffi.new("struct array_no_length *", [100, [200, 300, 400]])
1634 assert p.x == 100
1635 assert ffi.typeof(p.a) is ffi.typeof("int[]") # length available
1636 assert p.a[0] == 200
1637 assert p.a[1] == 300
1638 assert p.a[2] == 400
1639 assert len(p.a) == 3
1640 assert list(p.a) == [200, 300, 400]
1641 q = ffi.cast("struct array_no_length *", p)
1642 assert ffi.typeof(q.a) is ffi.typeof("int *") # no length available
1643 assert q.a[0] == 200
1644 assert q.a[1] == 300
1645 assert q.a[2] == 400
1646 py.test.raises(TypeError, len, q.a)
1647 py.test.raises(TypeError, list, q.a)
1648
1649 def test_from_buffer(self):
1650 import array
1651 a = array.array('H', [10000, 20000, 30000])
1652 c = ffi.from_buffer(a)
1653 assert ffi.typeof(c) is ffi.typeof("char[]")
1654 ffi.cast("unsigned short *", c)[1] += 500
1655 assert list(a) == [10000, 20500, 30000]
1656
1657 def test_all_primitives(self):
1658 assert set(PRIMITIVE_TO_INDEX) == set([
1659 "char",
1660 "short",
1661 "int",
1662 "long",
1663 "long long",
1664 "signed char",
1665 "unsigned char",
1666 "unsigned short",
1667 "unsigned int",
1668 "unsigned long",
1669 "unsigned long long",
1670 "float",
1671 "double",
1672 "long double",
1673 "wchar_t",
1674 "char16_t",
1675 "char32_t",
1676 "_Bool",
1677 "int8_t",
1678 "uint8_t",
1679 "int16_t",
1680 "uint16_t",
1681 "int32_t",
1682 "uint32_t",
1683 "int64_t",
1684 "uint64_t",
1685 "int_least8_t",
1686 "uint_least8_t",
1687 "int_least16_t",
1688 "uint_least16_t",
1689 "int_least32_t",
1690 "uint_least32_t",
1691 "int_least64_t",
1692 "uint_least64_t",
1693 "int_fast8_t",
1694 "uint_fast8_t",
1695 "int_fast16_t",
1696 "uint_fast16_t",
1697 "int_fast32_t",
1698 "uint_fast32_t",
1699 "int_fast64_t",
1700 "uint_fast64_t",
1701 "intptr_t",
1702 "uintptr_t",
1703 "intmax_t",
1704 "uintmax_t",
1705 "ptrdiff_t",
1706 "size_t",
1707 "ssize_t",
1708 'float _Complex',
1709 'double _Complex',
1710 ])
1711 for name in PRIMITIVE_TO_INDEX:
1712 x = ffi.sizeof(name)
1713 assert 1 <= x <= 16
1714
1715 def test_emit_c_code(self):
1716 ffi = cffi.FFI()
1717 ffi.set_source("foobar", "??")
1718 c_file = str(udir.join('test_emit_c_code'))
1719 ffi.emit_c_code(c_file)
1720 assert os.path.isfile(c_file)
1721
1722 def test_import_from_lib(self):
1723 ffi2 = cffi.FFI()
1724 ffi2.cdef("int myfunc(int); int myvar;\n#define MYFOO ...\n")
1725 outputfilename = recompile(ffi2, "_test_import_from_lib",
1726 "int myfunc(int x) { return x + 1; }\n"
1727 "int myvar = -5;\n"
1728 "#define MYFOO 42", tmpdir=str(udir))
1729 imp.load_dynamic("_test_import_from_lib", outputfilename)
1730 from _test_import_from_lib.lib import myfunc, myvar, MYFOO
1731 assert MYFOO == 42
1732 assert myfunc(43) == 44
1733 assert myvar == -5 # but can't be changed, so not very useful
1734 py.test.raises(ImportError, "from _test_import_from_lib.lib import bar")
1735 d = {}
1736 exec("from _test_import_from_lib.lib import *", d)
1737 assert (set(key for key in d if not key.startswith('_')) ==
1738 set(['myfunc', 'MYFOO']))
1739 #
1740 # also test "import *" on the module itself, which should be
1741 # equivalent to "import ffi, lib"
1742 d = {}
1743 exec("from _test_import_from_lib import *", d)
1744 assert (sorted([x for x in d.keys() if not x.startswith('__')]) ==
1745 ['ffi', 'lib'])
1746
1747 def test_char16_t(self):
1748 x = ffi.new("char16_t[]", 5)
1749 assert len(x) == 5 and ffi.sizeof(x) == 10
1750 x[2] = u+'\u1324'
1751 assert x[2] == u+'\u1324'
1752 y = ffi.new("char16_t[]", u+'\u1234\u5678')
1753 assert len(y) == 3
1754 assert list(y) == [u+'\u1234', u+'\u5678', u+'\x00']
1755 assert ffi.string(y) == u+'\u1234\u5678'
1756 z = ffi.new("char16_t[]", u+'\U00012345')
1757 assert len(z) == 3
1758 assert list(z) == [u+'\ud808', u+'\udf45', u+'\x00']
1759 assert ffi.string(z) == u+'\U00012345'
1760
1761 def test_char32_t(self):
1762 x = ffi.new("char32_t[]", 5)
1763 assert len(x) == 5 and ffi.sizeof(x) == 20
1764 x[3] = u+'\U00013245'
1765 assert x[3] == u+'\U00013245'
1766 y = ffi.new("char32_t[]", u+'\u1234\u5678')
1767 assert len(y) == 3
1768 assert list(y) == [u+'\u1234', u+'\u5678', u+'\x00']
1769 z = ffi.new("char32_t[]", u+'\U00012345')
1770 assert len(z) == 2
1771 assert list(z) == [u+'\U00012345', u+'\x00'] # maybe a 2-unichars strin
1772 assert ffi.string(z) == u+'\U00012345'
+0
-368
pypy/module/test_lib_pypy/cffi_tests/cffi1/test_parse_c_type.py less more
0 # Generated by pypy/tool/import_cffi.py
1 import sys, re, os, py
2 import cffi
3 from cffi import cffi_opcode
4
5 if '__pypy__' in sys.builtin_module_names:
6 py.test.skip("not available on pypy")
7
8 cffi_dir = os.path.dirname(cffi_opcode.__file__)
9
10 r_macro = re.compile(r"#define \w+[(][^\n]*|#include [^\n]*")
11 r_define = re.compile(r"(#define \w+) [^\n]*")
12 r_ifdefs = re.compile(r"(#ifdef |#endif)[^\n]*")
13 header = open(os.path.join(cffi_dir, 'parse_c_type.h')).read()
14 header = r_macro.sub(r"", header)
15 header = r_define.sub(r"\1 ...", header)
16 header = r_ifdefs.sub(r"", header)
17
18 ffi = cffi.FFI()
19 ffi.cdef(header)
20
21 lib = ffi.verify(
22 open(os.path.join(cffi_dir, '..', 'c', 'parse_c_type.c')).read() + """
23 static const char *get_common_type(const char *search, size_t search_len) {
24 return NULL;
25 }
26 """, include_dirs=[cffi_dir])
27
28 class ParseError(Exception):
29 pass
30
31 struct_names = ["bar_s", "foo", "foo_", "foo_s", "foo_s1", "foo_s12"]
32 assert struct_names == sorted(struct_names)
33
34 enum_names = ["ebar_s", "efoo", "efoo_", "efoo_s", "efoo_s1", "efoo_s12"]
35 assert enum_names == sorted(enum_names)
36
37 identifier_names = ["id", "id0", "id05", "id05b", "tail"]
38 assert identifier_names == sorted(identifier_names)
39
40 global_names = ["FIVE", "NEG", "ZERO"]
41 assert global_names == sorted(global_names)
42
43 ctx = ffi.new("struct _cffi_type_context_s *")
44 c_struct_names = [ffi.new("char[]", _n.encode('ascii')) for _n in struct_names]
45 ctx_structs = ffi.new("struct _cffi_struct_union_s[]", len(struct_names))
46 for _i in range(len(struct_names)):
47 ctx_structs[_i].name = c_struct_names[_i]
48 ctx_structs[3].flags = lib._CFFI_F_UNION
49 ctx.struct_unions = ctx_structs
50 ctx.num_struct_unions = len(struct_names)
51
52 c_enum_names = [ffi.new("char[]", _n.encode('ascii')) for _n in enum_names]
53 ctx_enums = ffi.new("struct _cffi_enum_s[]", len(enum_names))
54 for _i in range(len(enum_names)):
55 ctx_enums[_i].name = c_enum_names[_i]
56 ctx.enums = ctx_enums
57 ctx.num_enums = len(enum_names)
58
59 c_identifier_names = [ffi.new("char[]", _n.encode('ascii'))
60 for _n in identifier_names]
61 ctx_identifiers = ffi.new("struct _cffi_typename_s[]", len(identifier_names))
62 for _i in range(len(identifier_names)):
63 ctx_identifiers[_i].name = c_identifier_names[_i]
64 ctx_identifiers[_i].type_index = 100 + _i
65 ctx.typenames = ctx_identifiers
66 ctx.num_typenames = len(identifier_names)
67
68 @ffi.callback("int(unsigned long long *)")
69 def fetch_constant_five(p):
70 p[0] = 5
71 return 0
72 @ffi.callback("int(unsigned long long *)")
73 def fetch_constant_zero(p):
74 p[0] = 0
75 return 1
76 @ffi.callback("int(unsigned long long *)")
77 def fetch_constant_neg(p):
78 p[0] = 123321
79 return 1
80
81 ctx_globals = ffi.new("struct _cffi_global_s[]", len(global_names))
82 c_glob_names = [ffi.new("char[]", _n.encode('ascii')) for _n in global_names]
83 for _i, _fn in enumerate([fetch_constant_five,
84 fetch_constant_neg,
85 fetch_constant_zero]):
86 ctx_globals[_i].name = c_glob_names[_i]
87 ctx_globals[_i].address = _fn
88 ctx_globals[_i].type_op = ffi.cast("_cffi_opcode_t",
89 cffi_opcode.OP_CONSTANT_INT if _i != 1
90 else cffi_opcode.OP_ENUM)
91 ctx.globals = ctx_globals
92 ctx.num_globals = len(global_names)
93
94
95 def parse(input):
96 out = ffi.new("_cffi_opcode_t[]", 100)
97 info = ffi.new("struct _cffi_parse_info_s *")
98 info.ctx = ctx
99 info.output = out
100 info.output_size = len(out)
101 for j in range(len(out)):
102 out[j] = ffi.cast("void *", -424242)
103 res = lib.parse_c_type(info, input.encode('ascii'))
104 if res < 0:
105 raise ParseError(ffi.string(info.error_message).decode('ascii'),
106 info.error_location)
107 assert 0 <= res < len(out)
108 result = []
109 for j in range(len(out)):
110 if out[j] == ffi.cast("void *", -424242):
111 assert res < j
112 break
113 i = int(ffi.cast("intptr_t", out[j]))
114 if j == res:
115 result.append('->')
116 result.append(i)
117 return result
118
119 def parsex(input):
120 result = parse(input)
121 def str_if_int(x):
122 if isinstance(x, str):
123 return x
124 return '%d,%d' % (x & 255, x >> 8)
125 return ' '.join(map(str_if_int, result))
126
127 def parse_error(input, expected_msg, expected_location):
128 e = py.test.raises(ParseError, parse, input)
129 assert e.value.args[0] == expected_msg
130 assert e.value.args[1] == expected_location
131
132 def make_getter(name):
133 opcode = getattr(lib, '_CFFI_OP_' + name)
134 def getter(value):
135 return opcode | (value << 8)
136 return getter
137
138 Prim = make_getter('PRIMITIVE')
139 Pointer = make_getter('POINTER')
140 Array = make_getter('ARRAY')
141 OpenArray = make_getter('OPEN_ARRAY')
142 NoOp = make_getter('NOOP')
143 Func = make_getter('FUNCTION')
144 FuncEnd = make_getter('FUNCTION_END')
145 Struct = make_getter('STRUCT_UNION')
146 Enum = make_getter('ENUM')
147 Typename = make_getter('TYPENAME')
148
149
150 def test_simple():
151 for simple_type, expected in [
152 ("int", lib._CFFI_PRIM_INT),
153 ("signed int", lib._CFFI_PRIM_INT),
154 (" long ", lib._CFFI_PRIM_LONG),
155 ("long int", lib._CFFI_PRIM_LONG),
156 ("unsigned short", lib._CFFI_PRIM_USHORT),
157 ("long double", lib._CFFI_PRIM_LONGDOUBLE),
158 (" float _Complex", lib._CFFI_PRIM_FLOATCOMPLEX),
159 ("double _Complex ", lib._CFFI_PRIM_DOUBLECOMPLEX),
160 ]:
161 assert parse(simple_type) == ['->', Prim(expected)]
162
163 def test_array():
164 assert parse("int[5]") == [Prim(lib._CFFI_PRIM_INT), '->', Array(0), 5]
165 assert parse("int[]") == [Prim(lib._CFFI_PRIM_INT), '->', OpenArray(0)]
166 assert parse("int[5][8]") == [Prim(lib._CFFI_PRIM_INT),
167 '->', Array(3),
168 5,
169 Array(0),
170 8]
171 assert parse("int[][8]") == [Prim(lib._CFFI_PRIM_INT),
172 '->', OpenArray(2),
173 Array(0),
174 8]
175
176 def test_pointer():
177 assert parse("int*") == [Prim(lib._CFFI_PRIM_INT), '->', Pointer(0)]
178 assert parse("int***") == [Prim(lib._CFFI_PRIM_INT),
179 Pointer(0), Pointer(1), '->', Pointer(2)]
180
181 def test_grouping():
182 assert parse("int*[]") == [Prim(lib._CFFI_PRIM_INT),
183 Pointer(0), '->', OpenArray(1)]
184 assert parse("int**[][8]") == [Prim(lib._CFFI_PRIM_INT),
185 Pointer(0), Pointer(1),
186 '->', OpenArray(4), Array(2), 8]
187 assert parse("int(*)[]") == [Prim(lib._CFFI_PRIM_INT),
188 NoOp(3), '->', Pointer(1), OpenArray(0)]
189 assert parse("int(*)[][8]") == [Prim(lib._CFFI_PRIM_INT),
190 NoOp(3), '->', Pointer(1),
191 OpenArray(4), Array(0), 8]
192 assert parse("int**(**)") == [Prim(lib._CFFI_PRIM_INT),
193 Pointer(0), Pointer(1),
194 NoOp(2), Pointer(3), '->', Pointer(4)]
195 assert parse("int**(**)[]") == [Prim(lib._CFFI_PRIM_INT),
196 Pointer(0), Pointer(1),
197 NoOp(6), Pointer(3), '->', Pointer(4),
198 OpenArray(2)]
199
200 def test_simple_function():
201 assert parse("int()") == [Prim(lib._CFFI_PRIM_INT),
202 '->', Func(0), FuncEnd(0), 0]
203 assert parse("int(int)") == [Prim(lib._CFFI_PRIM_INT),
204 '->', Func(0), NoOp(4), FuncEnd(0),
205 Prim(lib._CFFI_PRIM_INT)]
206 assert parse("int(long, char)") == [
207 Prim(lib._CFFI_PRIM_INT),
208 '->', Func(0), NoOp(5), NoOp(6), FuncEnd(0),
209 Prim(lib._CFFI_PRIM_LONG),
210 Prim(lib._CFFI_PRIM_CHAR)]
211 assert parse("int(int*)") == [Prim(lib._CFFI_PRIM_INT),
212 '->', Func(0), NoOp(5), FuncEnd(0),
213 Prim(lib._CFFI_PRIM_INT),
214 Pointer(4)]
215 assert parse("int*(void)") == [Prim(lib._CFFI_PRIM_INT),
216 Pointer(0),
217 '->', Func(1), FuncEnd(0), 0]
218 assert parse("int(int, ...)") == [Prim(lib._CFFI_PRIM_INT),
219 '->', Func(0), NoOp(5), FuncEnd(1), 0,
220 Prim(lib._CFFI_PRIM_INT)]
221
222 def test_internal_function():
223 assert parse("int(*)()") == [Prim(lib._CFFI_PRIM_INT),
224 NoOp(3), '->', Pointer(1),
225 Func(0), FuncEnd(0), 0]
226 assert parse("int(*())[]") == [Prim(lib._CFFI_PRIM_INT),
227 NoOp(6), Pointer(1),
228 '->', Func(2), FuncEnd(0), 0,
229 OpenArray(0)]
230 assert parse("int(char(*)(long, short))") == [
231 Prim(lib._CFFI_PRIM_INT),
232 '->', Func(0), NoOp(6), FuncEnd(0),
233 Prim(lib._CFFI_PRIM_CHAR),
234 NoOp(7), Pointer(5),
235 Func(4), NoOp(11), NoOp(12), FuncEnd(0),
236 Prim(lib._CFFI_PRIM_LONG),
237 Prim(lib._CFFI_PRIM_SHORT)]
238
239 def test_fix_arg_types():
240 assert parse("int(char(long, short))") == [
241 Prim(lib._CFFI_PRIM_INT),
242 '->', Func(0), Pointer(5), FuncEnd(0),
243 Prim(lib._CFFI_PRIM_CHAR),
244 Func(4), NoOp(9), NoOp(10), FuncEnd(0),
245 Prim(lib._CFFI_PRIM_LONG),
246 Prim(lib._CFFI_PRIM_SHORT)]
247 assert parse("int(char[])") == [
248 Prim(lib._CFFI_PRIM_INT),
249 '->', Func(0), Pointer(4), FuncEnd(0),
250 Prim(lib._CFFI_PRIM_CHAR),
251 OpenArray(4)]
252
253 def test_enum():
254 for i in range(len(enum_names)):
255 assert parse("enum %s" % (enum_names[i],)) == ['->', Enum(i)]
256 assert parse("enum %s*" % (enum_names[i],)) == [Enum(i),
257 '->', Pointer(0)]
258
259 def test_error():
260 parse_error("short short int", "'short' after another 'short' or 'long'", 6)
261 parse_error("long long long", "'long long long' is too long", 10)
262 parse_error("short long", "'long' after 'short'", 6)
263 parse_error("signed unsigned int", "multiple 'signed' or 'unsigned'", 7)
264 parse_error("unsigned signed int", "multiple 'signed' or 'unsigned'", 9)
265 parse_error("long char", "invalid combination of types", 5)
266 parse_error("short char", "invalid combination of types", 6)
267 parse_error("signed void", "invalid combination of types", 7)
268 parse_error("unsigned struct", "invalid combination of types", 9)
269 #
270 parse_error("", "identifier expected", 0)
271 parse_error("]", "identifier expected", 0)
272 parse_error("*", "identifier expected", 0)
273 parse_error("int ]**", "unexpected symbol", 4)
274 parse_error("char char", "unexpected symbol", 5)
275 parse_error("int(int]", "expected ')'", 7)
276 parse_error("int(*]", "expected ')'", 5)
277 parse_error("int(]", "identifier expected", 4)
278 parse_error("int[?]", "expected a positive integer constant", 4)
279 parse_error("int[24)", "expected ']'", 6)
280 parse_error("struct", "struct or union name expected", 6)
281 parse_error("struct 24", "struct or union name expected", 7)
282 parse_error("int[5](*)", "unexpected symbol", 6)
283 parse_error("int a(*)", "identifier expected", 6)
284 parse_error("int[123456789012345678901234567890]", "number too large", 4)
285 #
286 parse_error("_Complex", "identifier expected", 0)
287 parse_error("int _Complex", "_Complex type combination unsupported", 4)
288 parse_error("long double _Complex", "_Complex type combination unsupported",
289 12)
290
291 def test_number_too_large():
292 num_max = sys.maxsize
293 assert parse("char[%d]" % num_max) == [Prim(lib._CFFI_PRIM_CHAR),
294 '->', Array(0), num_max]
295 parse_error("char[%d]" % (num_max + 1), "number too large", 5)
296
297 def test_complexity_limit():
298 parse_error("int" + "[]" * 2500, "internal type complexity limit reached",
299 202)
300
301 def test_struct():
302 for i in range(len(struct_names)):
303 if i == 3:
304 tag = "union"
305 else:
306 tag = "struct"
307 assert parse("%s %s" % (tag, struct_names[i])) == ['->', Struct(i)]
308 assert parse("%s %s*" % (tag, struct_names[i])) == [Struct(i),
309 '->', Pointer(0)]
310
311 def test_exchanging_struct_union():
312 parse_error("union %s" % (struct_names[0],),
313 "wrong kind of tag: struct vs union", 6)
314 parse_error("struct %s" % (struct_names[3],),
315 "wrong kind of tag: struct vs union", 7)
316
317 def test_identifier():
318 for i in range(len(identifier_names)):
319 assert parse("%s" % (identifier_names[i])) == ['->', Typename(i)]
320 assert parse("%s*" % (identifier_names[i])) == [Typename(i),
321 '->', Pointer(0)]
322
323 def test_cffi_opcode_sync():
324 import cffi.model
325 for name in dir(lib):
326 if name.startswith('_CFFI_'):
327 assert getattr(cffi_opcode, name[6:]) == getattr(lib, name)
328 assert sorted(cffi_opcode.PRIMITIVE_TO_INDEX.keys()) == (
329 sorted(cffi.model.PrimitiveType.ALL_PRIMITIVE_TYPES.keys()))
330
331 def test_array_length_from_constant():
332 parse_error("int[UNKNOWN]", "expected a positive integer constant", 4)
333 assert parse("int[FIVE]") == [Prim(lib._CFFI_PRIM_INT), '->', Array(0), 5]
334 assert parse("int[ZERO]") == [Prim(lib._CFFI_PRIM_INT), '->', Array(0), 0]
335 parse_error("int[NEG]", "expected a positive integer constant", 4)
336
337 def test_various_constant_exprs():
338 def array(n):
339 return [Prim(lib._CFFI_PRIM_CHAR), '->', Array(0), n]
340 assert parse("char[21]") == array(21)
341 assert parse("char[0x10]") == array(16)
342 assert parse("char[0X21]") == array(33)
343 assert parse("char[0Xb]") == array(11)
344 assert parse("char[0x1C]") == array(0x1C)
345 assert parse("char[0xc6]") == array(0xC6)
346 assert parse("char[010]") == array(8)
347 assert parse("char[021]") == array(17)
348 parse_error("char[08]", "invalid number", 5)
349 parse_error("char[1C]", "invalid number", 5)
350 parse_error("char[0C]", "invalid number", 5)
351 # not supported (really obscure):
352 # "char[+5]"
353 # "char['A']"
354
355 def test_stdcall_cdecl():
356 assert parse("int __stdcall(int)") == [Prim(lib._CFFI_PRIM_INT),
357 '->', Func(0), NoOp(4), FuncEnd(2),
358 Prim(lib._CFFI_PRIM_INT)]
359 assert parse("int __stdcall func(int)") == parse("int __stdcall(int)")
360 assert parse("int (__stdcall *)()") == [Prim(lib._CFFI_PRIM_INT),
361 NoOp(3), '->', Pointer(1),
362 Func(0), FuncEnd(2), 0]
363 assert parse("int (__stdcall *p)()") == parse("int (__stdcall*)()")
364 parse_error("__stdcall int", "identifier expected", 0)
365 parse_error("__cdecl int", "identifier expected", 0)
366 parse_error("int __stdcall", "expected '('", 13)
367 parse_error("int __cdecl", "expected '('", 11)
+0
-248
pypy/module/test_lib_pypy/cffi_tests/cffi1/test_re_python.py less more
0 # Generated by pypy/tool/import_cffi.py
1 import sys, os
2 import py
3 from cffi import FFI
4 from cffi import recompiler, ffiplatform, VerificationMissing
5 from pypy.module.test_lib_pypy.cffi_tests.udir import udir
6 from pypy.module.test_lib_pypy.cffi_tests.support import u
7
8
9 def setup_module(mod):
10 SRC = """
11 #include <string.h>
12 #define FOOBAR (-42)
13 static const int FOOBAZ = -43;
14 #define BIGPOS 420000000000L
15 #define BIGNEG -420000000000L
16 int add42(int x) { return x + 42; }
17 int add43(int x, ...) { return x; }
18 int globalvar42 = 1234;
19 const int globalconst42 = 4321;
20 const char *const globalconsthello = "hello";
21 struct foo_s;
22 typedef struct bar_s { int x; signed char a[]; } bar_t;
23 enum foo_e { AA, BB, CC };
24
25 void init_test_re_python(void) { } /* windows hack */
26 void PyInit__test_re_python(void) { } /* windows hack */
27 """
28 tmpdir = udir.join('test_re_python')
29 tmpdir.ensure(dir=1)
30 c_file = tmpdir.join('_test_re_python.c')
31 c_file.write(SRC)
32 ext = ffiplatform.get_extension(
33 str(c_file),
34 '_test_re_python',
35 export_symbols=['add42', 'add43', 'globalvar42',
36 'globalconst42', 'globalconsthello']
37 )
38 outputfilename = ffiplatform.compile(str(tmpdir), ext)
39 if sys.platform == "win32":
40 # test with a non-ascii char
41 outputfn1 = outputfilename
42 ofn, oext = os.path.splitext(outputfn1)
43 outputfilename = ofn + (u+'\u03be') + oext
44 #print(repr(outputfn1) + ' ==> ' + repr(outputfilename))
45 os.rename(outputfn1, outputfilename)
46 mod.extmod = outputfilename
47 mod.tmpdir = tmpdir
48 #
49 ffi = FFI()
50 ffi.cdef("""
51 #define FOOBAR -42
52 static const int FOOBAZ = -43;
53 #define BIGPOS 420000000000L
54 #define BIGNEG -420000000000L
55 int add42(int);
56 int add43(int, ...);
57 int globalvar42;
58 const int globalconst42;
59 const char *const globalconsthello = "hello";
60 int no_such_function(int);
61 int no_such_globalvar;
62 struct foo_s;
63 typedef struct bar_s { int x; signed char a[]; } bar_t;
64 enum foo_e { AA, BB, CC };
65 int strlen(const char *);
66 struct with_union { union { int a; char b; }; };
67 union with_struct { struct { int a; char b; }; };
68 struct NVGcolor { union { float rgba[4]; struct { float r,g,b,a; }; }; };
69 """)
70 ffi.set_source('re_python_pysrc', None)
71 ffi.emit_python_code(str(tmpdir.join('re_python_pysrc.py')))
72 mod.original_ffi = ffi
73 #
74 sys.path.insert(0, str(tmpdir))
75
76
77 def test_constant():
78 from re_python_pysrc import ffi
79 assert ffi.integer_const('FOOBAR') == -42
80 assert ffi.integer_const('FOOBAZ') == -43
81
82 def test_large_constant():
83 from re_python_pysrc import ffi
84 assert ffi.integer_const('BIGPOS') == 420000000000
85 assert ffi.integer_const('BIGNEG') == -420000000000
86
87 def test_function():
88 import _cffi_backend
89 from re_python_pysrc import ffi
90 lib = ffi.dlopen(extmod)
91 assert lib.add42(-10) == 32
92 assert type(lib.add42) is _cffi_backend.FFI.CData
93
94 def test_function_with_varargs():
95 import _cffi_backend
96 from re_python_pysrc import ffi
97 lib = ffi.dlopen(extmod, 0)
98 assert lib.add43(45, ffi.cast("int", -5)) == 45
99 assert type(lib.add43) is _cffi_backend.FFI.CData
100
101 def test_dlopen_none():
102 import _cffi_backend
103 from re_python_pysrc import ffi
104 name = None
105 if sys.platform == 'win32':
106 import ctypes.util
107 name = ctypes.util.find_msvcrt()
108 if name is None:
109 py.test.skip("dlopen(None) cannot work on Windows with Python 3")
110 lib = ffi.dlopen(name)
111 assert lib.strlen(b"hello") == 5
112
113 def test_dlclose():
114 import _cffi_backend
115 from re_python_pysrc import ffi
116 lib = ffi.dlopen(extmod)
117 ffi.dlclose(lib)
118 if type(extmod) is not str: # unicode, on python 2
119 str_extmod = extmod.encode('utf-8')
120 else:
121 str_extmod = extmod
122 e = py.test.raises(ffi.error, getattr, lib, 'add42')
123 assert str(e.value) == (
124 "library '%s' has been closed" % (str_extmod,))
125 ffi.dlclose(lib) # does not raise
126
127 def test_constant_via_lib():
128 from re_python_pysrc import ffi
129 lib = ffi.dlopen(extmod)
130 assert lib.FOOBAR == -42
131 assert lib.FOOBAZ == -43
132
133 def test_opaque_struct():
134 from re_python_pysrc import ffi
135 ffi.cast("struct foo_s *", 0)
136 py.test.raises(TypeError, ffi.new, "struct foo_s *")
137
138 def test_nonopaque_struct():
139 from re_python_pysrc import ffi
140 for p in [ffi.new("struct bar_s *", [5, b"foobar"]),
141 ffi.new("bar_t *", [5, b"foobar"])]:
142 assert p.x == 5
143 assert p.a[0] == ord('f')
144 assert p.a[5] == ord('r')
145
146 def test_enum():
147 from re_python_pysrc import ffi
148 assert ffi.integer_const("BB") == 1
149 e = ffi.cast("enum foo_e", 2)
150 assert ffi.string(e) == "CC"
151
152 def test_include_1():
153 sub_ffi = FFI()
154 sub_ffi.cdef("static const int k2 = 121212;")
155 sub_ffi.include(original_ffi)
156 assert 'macro FOOBAR' in original_ffi._parser._declarations
157 assert 'macro FOOBAZ' in original_ffi._parser._declarations
158 sub_ffi.set_source('re_python_pysrc', None)
159 sub_ffi.emit_python_code(str(tmpdir.join('_re_include_1.py')))
160 #
161 if sys.version_info[:2] >= (3, 3):
162 import importlib
163 importlib.invalidate_caches() # issue 197 (but can't reproduce myself)
164 #
165 from _re_include_1 import ffi
166 assert ffi.integer_const('FOOBAR') == -42
167 assert ffi.integer_const('FOOBAZ') == -43
168 assert ffi.integer_const('k2') == 121212
169 lib = ffi.dlopen(extmod) # <- a random unrelated library would be fine
170 assert lib.FOOBAR == -42
171 assert lib.FOOBAZ == -43
172 assert lib.k2 == 121212
173 #
174 p = ffi.new("bar_t *", [5, b"foobar"])
175 assert p.a[4] == ord('a')
176
177 def test_global_var():
178 from re_python_pysrc import ffi
179 lib = ffi.dlopen(extmod)
180 assert lib.globalvar42 == 1234
181 p = ffi.addressof(lib, 'globalvar42')
182 lib.globalvar42 += 5
183 assert p[0] == 1239
184 p[0] -= 1
185 assert lib.globalvar42 == 1238
186
187 def test_global_const_int():
188 from re_python_pysrc import ffi
189 lib = ffi.dlopen(extmod)
190 assert lib.globalconst42 == 4321
191 py.test.raises(AttributeError, ffi.addressof, lib, 'globalconst42')
192
193 def test_global_const_nonint():
194 from re_python_pysrc import ffi
195 lib = ffi.dlopen(extmod)
196 assert ffi.string(lib.globalconsthello, 8) == b"hello"
197 py.test.raises(AttributeError, ffi.addressof, lib, 'globalconsthello')
198
199 def test_rtld_constants():
200 from re_python_pysrc import ffi
201 ffi.RTLD_NOW # check that we have the attributes
202 ffi.RTLD_LAZY
203 ffi.RTLD_GLOBAL
204
205 def test_no_such_function_or_global_var():
206 from re_python_pysrc import ffi
207 lib = ffi.dlopen(extmod)
208 e = py.test.raises(ffi.error, getattr, lib, 'no_such_function')
209 assert str(e.value).startswith(
210 "symbol 'no_such_function' not found in library '")
211 e = py.test.raises(ffi.error, getattr, lib, 'no_such_globalvar')
212 assert str(e.value).startswith(
213 "symbol 'no_such_globalvar' not found in library '")
214
215 def test_check_version():
216 import _cffi_backend
217 e = py.test.raises(ImportError, _cffi_backend.FFI,
218 "foobar", _version=0x2594)
219 assert str(e.value).startswith(
220 "cffi out-of-line Python module 'foobar' has unknown version")
221
222 def test_partial_enum():
223 ffi = FFI()
224 ffi.cdef("enum foo { A, B, ... };")
225 ffi.set_source('test_partial_enum', None)
226 py.test.raises(VerificationMissing, ffi.emit_python_code,
227 str(tmpdir.join('test_partial_enum.py')))
228
229 def test_anonymous_union_inside_struct():
230 # based on issue #357
231 from re_python_pysrc import ffi
232 INT = ffi.sizeof("int")
233 assert ffi.offsetof("struct with_union", "a") == 0
234 assert ffi.offsetof("struct with_union", "b") == 0
235 assert ffi.sizeof("struct with_union") == INT
236 #
237 assert ffi.offsetof("union with_struct", "a") == 0
238 assert ffi.offsetof("union with_struct", "b") == INT
239 assert ffi.sizeof("union with_struct") >= INT + 1
240 #
241 FLOAT = ffi.sizeof("float")
242 assert ffi.sizeof("struct NVGcolor") == FLOAT * 4
243 assert ffi.offsetof("struct NVGcolor", "rgba") == 0
244 assert ffi.offsetof("struct NVGcolor", "r") == 0
245 assert ffi.offsetof("struct NVGcolor", "g") == FLOAT
246 assert ffi.offsetof("struct NVGcolor", "b") == FLOAT * 2
247 assert ffi.offsetof("struct NVGcolor", "a") == FLOAT * 3
+0
-74
pypy/module/test_lib_pypy/cffi_tests/cffi1/test_realize_c_type.py less more
0 # Generated by pypy/tool/import_cffi.py
1 import py, sys
2 from cffi import cffi_opcode
3
4
5 def check(input, expected_output=None, expected_ffi_error=False):
6 import _cffi_backend
7 ffi = _cffi_backend.FFI()
8 if not expected_ffi_error:
9 ct = ffi.typeof(input)
10 assert isinstance(ct, ffi.CType)
11 assert ct.cname == (expected_output or input)
12 else:
13 e = py.test.raises(ffi.error, ffi.typeof, input)
14 if isinstance(expected_ffi_error, str):
15 assert str(e.value) == expected_ffi_error
16
17 def test_void():
18 check("void", "void")
19 check(" void ", "void")
20
21 def test_int_star():
22 check("int")
23 check("int *")
24 check("int*", "int *")
25 check("long int", "long")
26 check("long")
27
28 def test_noop():
29 check("int(*)", "int *")
30
31 def test_array():
32 check("int[6]")
33
34 def test_funcptr():
35 check("int(*)(long)")
36 check("int(long)", expected_ffi_error="the type 'int(long)' is a"
37 " function type, not a pointer-to-function type")
38 check("int(void)", expected_ffi_error="the type 'int()' is a"
39 " function type, not a pointer-to-function type")
40
41 def test_funcptr_rewrite_args():
42 check("int(*)(int(int))", "int(*)(int(*)(int))")
43 check("int(*)(long[])", "int(*)(long *)")
44 check("int(*)(long[5])", "int(*)(long *)")
45
46 def test_all_primitives():
47 for name in cffi_opcode.PRIMITIVE_TO_INDEX:
48 check(name, name)
49
50 def check_func(input, expected_output=None):
51 import _cffi_backend
52 ffi = _cffi_backend.FFI()
53 ct = ffi.typeof(ffi.callback(input, lambda: None))
54 assert isinstance(ct, ffi.CType)
55 if sys.platform != 'win32' or sys.maxsize > 2**32:
56 expected_output = expected_output.replace('__stdcall *', '*')
57 assert ct.cname == expected_output
58
59 def test_funcptr_stdcall():
60 check_func("int(int)", "int(*)(int)")
61 check_func("int foobar(int)", "int(*)(int)")
62 check_func("int __stdcall(int)", "int(__stdcall *)(int)")
63 check_func("int __stdcall foobar(int)", "int(__stdcall *)(int)")
64 check_func("void __cdecl(void)", "void(*)()")
65 check_func("void __cdecl foobar(void)", "void(*)()")
66 check_func("void __stdcall(void)", "void(__stdcall *)()")
67 check_func("void __stdcall foobar(long, short)",
68 "void(__stdcall *)(long, short)")
69 check_func("void(void __cdecl(void), void __stdcall(void))",
70 "void(*)(void(*)(), void(__stdcall *)())")
71
72 def test_variadic_overrides_stdcall():
73 check("void (__stdcall*)(int, ...)", "void(*)(int, ...)")
+0
-2308
pypy/module/test_lib_pypy/cffi_tests/cffi1/test_recompiler.py less more
0 # Generated by pypy/tool/import_cffi.py
1
2 import sys, os, py
3 from cffi import FFI, VerificationError, FFIError, CDefError
4 from cffi import recompiler
5 from pypy.module.test_lib_pypy.cffi_tests.udir import udir
6 from pypy.module.test_lib_pypy.cffi_tests.support import u, long
7 from pypy.module.test_lib_pypy.cffi_tests.support import FdWriteCapture, StdErrCapture
8
9 try:
10 import importlib
11 except ImportError:
12 importlib = None
13
14
15 def check_type_table(input, expected_output, included=None):
16 ffi = FFI()
17 if included:
18 ffi1 = FFI()
19 ffi1.cdef(included)
20 ffi.include(ffi1)
21 ffi.cdef(input)
22 recomp = recompiler.Recompiler(ffi, 'testmod')
23 recomp.collect_type_table()
24 assert ''.join(map(str, recomp.cffi_types)) == expected_output
25
26 def verify(ffi, module_name, source, *args, **kwds):
27 no_cpp = kwds.pop('no_cpp', False)
28 kwds.setdefault('undef_macros', ['NDEBUG'])
29 module_name = '_CFFI_' + module_name
30 ffi.set_source(module_name, source)
31 if not os.environ.get('NO_CPP') and not no_cpp: # test the .cpp mode too
32 kwds.setdefault('source_extension', '.cpp')
33 source = 'extern "C" {\n%s\n}' % (source,)
34 elif sys.platform != 'win32':
35 # add '-Werror' to the existing 'extra_compile_args' flags
36 kwds['extra_compile_args'] = (kwds.get('extra_compile_args', []) +
37 ['-Werror'])
38 return recompiler._verify(ffi, module_name, source, *args, **kwds)
39
40 def test_set_source_no_slashes():
41 ffi = FFI()
42 py.test.raises(ValueError, ffi.set_source, "abc/def", None)
43 py.test.raises(ValueError, ffi.set_source, "abc/def", "C code")
44
45
46 def test_type_table_func():
47 check_type_table("double sin(double);",
48 "(FUNCTION 1)(PRIMITIVE 14)(FUNCTION_END 0)")
49 check_type_table("float sin(double);",
50 "(FUNCTION 3)(PRIMITIVE 14)(FUNCTION_END 0)(PRIMITIVE 13)")
51 check_type_table("float sin(void);",
52 "(FUNCTION 2)(FUNCTION_END 0)(PRIMITIVE 13)")
53 check_type_table("double sin(float); double cos(float);",
54 "(FUNCTION 3)(PRIMITIVE 13)(FUNCTION_END 0)(PRIMITIVE 14)")
55 check_type_table("double sin(float); double cos(double);",
56 "(FUNCTION 1)(PRIMITIVE 14)(FUNCTION_END 0)" # cos
57 "(FUNCTION 1)(PRIMITIVE 13)(FUNCTION_END 0)") # sin
58 check_type_table("float sin(double); float cos(float);",
59 "(FUNCTION 4)(PRIMITIVE 14)(FUNCTION_END 0)" # sin
60 "(FUNCTION 4)(PRIMITIVE 13)(FUNCTION_END 0)") # cos
61
62 def test_type_table_use_noop_for_repeated_args():
63 check_type_table("double sin(double *, double *);",
64 "(FUNCTION 4)(POINTER 4)(NOOP 1)(FUNCTION_END 0)"
65 "(PRIMITIVE 14)")
66 check_type_table("double sin(double *, double *, double);",
67 "(FUNCTION 3)(POINTER 3)(NOOP 1)(PRIMITIVE 14)"
68 "(FUNCTION_END 0)")
69
70 def test_type_table_dont_use_noop_for_primitives():
71 check_type_table("double sin(double, double);",
72 "(FUNCTION 1)(PRIMITIVE 14)(PRIMITIVE 14)(FUNCTION_END 0)")
73
74 def test_type_table_funcptr_as_argument():
75 check_type_table("int sin(double(float));",
76 "(FUNCTION 6)(PRIMITIVE 13)(FUNCTION_END 0)"
77 "(FUNCTION 7)(POINTER 0)(FUNCTION_END 0)"
78 "(PRIMITIVE 14)(PRIMITIVE 7)")
79
80 def test_type_table_variadic_function():
81 check_type_table("int sin(int, ...);",
82 "(FUNCTION 1)(PRIMITIVE 7)(FUNCTION_END 1)(POINTER 0)")
83
84 def test_type_table_array():
85 check_type_table("int a[100];",
86 "(PRIMITIVE 7)(ARRAY 0)(None 100)")
87
88 def test_type_table_typedef():
89 check_type_table("typedef int foo_t;",
90 "(PRIMITIVE 7)")
91
92 def test_type_table_prebuilt_type():
93 check_type_table("int32_t f(void);",
94 "(FUNCTION 2)(FUNCTION_END 0)(PRIMITIVE 21)")
95
96 def test_type_table_struct_opaque():
97 check_type_table("struct foo_s;",
98 "(STRUCT_UNION 0)")
99
100 def test_type_table_struct():
101 check_type_table("struct foo_s { int a; long b; };",
102 "(PRIMITIVE 7)(PRIMITIVE 9)(STRUCT_UNION 0)")
103
104 def test_type_table_union():
105 check_type_table("union foo_u { int a; long b; };",
106 "(PRIMITIVE 7)(PRIMITIVE 9)(STRUCT_UNION 0)")
107
108 def test_type_table_struct_used():
109 check_type_table("struct foo_s { int a; long b; }; int f(struct foo_s*);",
110 "(FUNCTION 3)(POINTER 5)(FUNCTION_END 0)"
111 "(PRIMITIVE 7)(PRIMITIVE 9)"
112 "(STRUCT_UNION 0)")
113
114 def test_type_table_anonymous_struct_with_typedef():
115 check_type_table("typedef struct { int a; long b; } foo_t;",
116 "(STRUCT_UNION 0)(PRIMITIVE 7)(PRIMITIVE 9)")
117
118 def test_type_table_enum():
119 check_type_table("enum foo_e { AA, BB, ... };",
120 "(ENUM 0)")
121
122 def test_type_table_include_1():
123 check_type_table("foo_t sin(foo_t);",
124 "(FUNCTION 1)(PRIMITIVE 14)(FUNCTION_END 0)",
125 included="typedef double foo_t;")
126
127 def test_type_table_include_2():
128 check_type_table("struct foo_s *sin(struct foo_s *);",
129 "(FUNCTION 1)(POINTER 3)(FUNCTION_END 0)(STRUCT_UNION 0)",
130 included="struct foo_s { int x, y; };")
131
132
133 def test_math_sin():
134 import math
135 ffi = FFI()
136 ffi.cdef("float sin(double); double cos(double);")
137 lib = verify(ffi, 'test_math_sin', '#include <math.h>')
138 assert lib.cos(1.43) == math.cos(1.43)
139
140 def test_repr_lib():
141 ffi = FFI()
142 lib = verify(ffi, 'test_repr_lib', '')
143 assert repr(lib) == "<Lib object for '_CFFI_test_repr_lib'>"
144
145 def test_funcarg_ptr():
146 ffi = FFI()
147 ffi.cdef("int foo(int *);")
148 lib = verify(ffi, 'test_funcarg_ptr', 'int foo(int *p) { return *p; }')
149 assert lib.foo([-12345]) == -12345
150
151 def test_funcres_ptr():
152 ffi = FFI()
153 ffi.cdef("int *foo(void);")
154 lib = verify(ffi, 'test_funcres_ptr',
155 'int *foo(void) { static int x=-12345; return &x; }')
156 assert lib.foo()[0] == -12345
157
158 def test_global_var_array():
159 ffi = FFI()
160 ffi.cdef("int a[100];")
161 lib = verify(ffi, 'test_global_var_array', 'int a[100] = { 9999 };')
162 lib.a[42] = 123456
163 assert lib.a[42] == 123456
164 assert lib.a[0] == 9999
165
166 def test_verify_typedef():
167 ffi = FFI()
168 ffi.cdef("typedef int **foo_t;")
169 lib = verify(ffi, 'test_verify_typedef', 'typedef int **foo_t;')
170 assert ffi.sizeof("foo_t") == ffi.sizeof("void *")
171
172 def test_verify_typedef_dotdotdot():
173 ffi = FFI()
174 ffi.cdef("typedef ... foo_t;")
175 verify(ffi, 'test_verify_typedef_dotdotdot', 'typedef int **foo_t;')
176
177 def test_verify_typedef_star_dotdotdot():
178 ffi = FFI()
179 ffi.cdef("typedef ... *foo_t;")
180 verify(ffi, 'test_verify_typedef_star_dotdotdot', 'typedef int **foo_t;')
181
182 def test_global_var_int():
183 ffi = FFI()
184 ffi.cdef("int a, b, c;")
185 lib = verify(ffi, 'test_global_var_int', 'int a = 999, b, c;')
186 assert lib.a == 999
187 lib.a -= 1001
188 assert lib.a == -2
189 lib.a = -2147483648
190 assert lib.a == -2147483648
191 py.test.raises(OverflowError, "lib.a = 2147483648")
192 py.test.raises(OverflowError, "lib.a = -2147483649")
193 lib.b = 525 # try with the first access being in setattr, too
194 assert lib.b == 525
195 py.test.raises(AttributeError, "del lib.a")
196 py.test.raises(AttributeError, "del lib.c")
197 py.test.raises(AttributeError, "del lib.foobarbaz")
198
199 def test_macro():
200 ffi = FFI()
201 ffi.cdef("#define FOOBAR ...")
202 lib = verify(ffi, 'test_macro', "#define FOOBAR (-6912)")
203 assert lib.FOOBAR == -6912
204 py.test.raises(AttributeError, "lib.FOOBAR = 2")
205
206 def test_macro_check_value():
207 # the value '-0x80000000' in C sources does not have a clear meaning
208 # to me; it appears to have a different effect than '-2147483648'...
209 # Moreover, on 32-bits, -2147483648 is actually equal to
210 # -2147483648U, which in turn is equal to 2147483648U and so positive.
211 vals = ['42', '-42', '0x80000000', '-2147483648',
212 '0', '9223372036854775809ULL',
213 '-9223372036854775807LL']
214 if sys.maxsize <= 2**32 or sys.platform == 'win32':
215 vals.remove('-2147483648')
216 ffi = FFI()
217 cdef_lines = ['#define FOO_%d_%d %s' % (i, j, vals[i])
218 for i in range(len(vals))
219 for j in range(len(vals))]
220 ffi.cdef('\n'.join(cdef_lines))
221
222 verify_lines = ['#define FOO_%d_%d %s' % (i, j, vals[j]) # [j], not [i]
223 for i in range(len(vals))
224 for j in range(len(vals))]
225 lib = verify(ffi, 'test_macro_check_value_ok',
226 '\n'.join(verify_lines))
227 #
228 for j in range(len(vals)):
229 c_got = int(vals[j].replace('U', '').replace('L', ''), 0)
230 c_compiler_msg = str(c_got)
231 if c_got > 0:
232 c_compiler_msg += ' (0x%x)' % (c_got,)
233 #
234 for i in range(len(vals)):
235 attrname = 'FOO_%d_%d' % (i, j)
236 if i == j:
237 x = getattr(lib, attrname)
238 assert x == c_got
239 else:
240 e = py.test.raises(ffi.error, getattr, lib, attrname)
241 assert str(e.value) == (
242 "the C compiler says '%s' is equal to "
243 "%s, but the cdef disagrees" % (attrname, c_compiler_msg))
244
245 def test_constant():
246 ffi = FFI()
247 ffi.cdef("static const int FOOBAR;")
248 lib = verify(ffi, 'test_constant', "#define FOOBAR (-6912)")
249 assert lib.FOOBAR == -6912
250 py.test.raises(AttributeError, "lib.FOOBAR = 2")
251
252 def test_check_value_of_static_const():
253 ffi = FFI()
254 ffi.cdef("static const int FOOBAR = 042;")
255 lib = verify(ffi, 'test_check_value_of_static_const',
256 "#define FOOBAR (-6912)")
257 e = py.test.raises(ffi.error, getattr, lib, 'FOOBAR')
258 assert str(e.value) == (
259 "the C compiler says 'FOOBAR' is equal to -6912, but the cdef disagrees")
260
261 def test_constant_nonint():
262 ffi = FFI()
263 ffi.cdef("static const double FOOBAR;")
264 lib = verify(ffi, 'test_constant_nonint', "#define FOOBAR (-6912.5)")
265 assert lib.FOOBAR == -6912.5
266 py.test.raises(AttributeError, "lib.FOOBAR = 2")
267
268 def test_constant_ptr():
269 ffi = FFI()
270 ffi.cdef("static double *const FOOBAR;")
271 lib = verify(ffi, 'test_constant_ptr', "#define FOOBAR NULL")
272 assert lib.FOOBAR == ffi.NULL
273 assert ffi.typeof(lib.FOOBAR) == ffi.typeof("double *")
274
275 def test_dir():
276 ffi = FFI()
277 ffi.cdef("int ff(int); int aa; static const int my_constant;")
278 lib = verify(ffi, 'test_dir', """
279 #define my_constant (-45)
280 int aa;
281 int ff(int x) { return x+aa; }
282 """)
283 lib.aa = 5
284 assert dir(lib) == ['aa', 'ff', 'my_constant']
285 #
286 aaobj = lib.__dict__['aa']
287 assert not isinstance(aaobj, int) # some internal object instead
288 assert lib.__dict__ == {
289 'ff': lib.ff,
290 'aa': aaobj,
291 'my_constant': -45}
292 lib.__dict__['ff'] = "??"
293 assert lib.ff(10) == 15
294
295 def test_verify_opaque_struct():
296 ffi = FFI()
297 ffi.cdef("struct foo_s;")
298 lib = verify(ffi, 'test_verify_opaque_struct', "struct foo_s;")
299 assert ffi.typeof("struct foo_s").cname == "struct foo_s"
300
301 def test_verify_opaque_union():
302 ffi = FFI()
303 ffi.cdef("union foo_s;")
304 lib = verify(ffi, 'test_verify_opaque_union', "union foo_s;")
305 assert ffi.typeof("union foo_s").cname == "union foo_s"
306
307 def test_verify_struct():
308 ffi = FFI()
309 ffi.cdef("""struct foo_s { int b; short a; ...; };
310 struct bar_s { struct foo_s *f; };""")
311 lib = verify(ffi, 'test_verify_struct',
312 """struct foo_s { short a; int b; };
313 struct bar_s { struct foo_s *f; };""")
314 ffi.typeof("struct bar_s *")
315 p = ffi.new("struct foo_s *", {'a': -32768, 'b': -2147483648})
316 assert p.a == -32768
317 assert p.b == -2147483648
318 py.test.raises(OverflowError, "p.a -= 1")
319 py.test.raises(OverflowError, "p.b -= 1")
320 q = ffi.new("struct bar_s *", {'f': p})
321 assert q.f == p
322 #
323 assert ffi.offsetof("struct foo_s", "a") == 0
324 assert ffi.offsetof("struct foo_s", "b") == 4
325 assert ffi.offsetof(u+"struct foo_s", u+"b") == 4
326 #
327 py.test.raises(TypeError, ffi.addressof, p)
328 assert ffi.addressof(p[0]) == p
329 assert ffi.typeof(ffi.addressof(p[0])) is ffi.typeof("struct foo_s *")
330 assert ffi.typeof(ffi.addressof(p, "b")) is ffi.typeof("int *")
331 assert ffi.addressof(p, "b")[0] == p.b
332
333 def test_verify_exact_field_offset():
334 ffi = FFI()
335 ffi.cdef("""struct foo_s { int b; short a; };""")
336 lib = verify(ffi, 'test_verify_exact_field_offset',
337 """struct foo_s { short a; int b; };""")
338 e = py.test.raises(ffi.error, ffi.new, "struct foo_s *", []) # lazily
339 assert str(e.value) == ("struct foo_s: wrong offset for field 'b' (cdef "
340 'says 0, but C compiler says 4). fix it or use "...;" '
341 "in the cdef for struct foo_s to make it flexible")
342
343 def test_type_caching():
344 ffi1 = FFI(); ffi1.cdef("struct foo_s;")
345 ffi2 = FFI(); ffi2.cdef("struct foo_s;") # different one!
346 lib1 = verify(ffi1, 'test_type_caching_1', 'struct foo_s;')
347 lib2 = verify(ffi2, 'test_type_caching_2', 'struct foo_s;')
348 # shared types
349 assert ffi1.typeof("long") is ffi2.typeof("long")
350 assert ffi1.typeof("long**") is ffi2.typeof("long * *")
351 assert ffi1.typeof("long(*)(int, ...)") is ffi2.typeof("long(*)(int, ...)")
352 # non-shared types
353 assert ffi1.typeof("struct foo_s") is not ffi2.typeof("struct foo_s")
354 assert ffi1.typeof("struct foo_s *") is not ffi2.typeof("struct foo_s *")
355 assert ffi1.typeof("struct foo_s*(*)()") is not (
356 ffi2.typeof("struct foo_s*(*)()"))
357 assert ffi1.typeof("void(*)(struct foo_s*)") is not (
358 ffi2.typeof("void(*)(struct foo_s*)"))
359
360 def test_verify_enum():
361 ffi = FFI()
362 ffi.cdef("""enum e1 { B1, A1, ... }; enum e2 { B2, A2, ... };""")
363 lib = verify(ffi, 'test_verify_enum',
364 "enum e1 { A1, B1, C1=%d };" % sys.maxsize +
365 "enum e2 { A2, B2, C2 };")
366 ffi.typeof("enum e1")
367 ffi.typeof("enum e2")
368 assert lib.A1 == 0
369 assert lib.B1 == 1
370 assert lib.A2 == 0
371 assert lib.B2 == 1
372 assert ffi.sizeof("enum e1") == ffi.sizeof("long")
373 assert ffi.sizeof("enum e2") == ffi.sizeof("int")
374 assert repr(ffi.cast("enum e1", 0)) == "<cdata 'enum e1' 0: A1>"
375
376 def test_duplicate_enum():
377 ffi = FFI()
378 ffi.cdef("enum e1 { A1, ... }; enum e2 { A1, ... };")
379 py.test.raises(VerificationError, verify, ffi, 'test_duplicate_enum',
380 "enum e1 { A1 }; enum e2 { B1 };")
381
382 def test_dotdotdot_length_of_array_field():
383 ffi = FFI()
384 ffi.cdef("struct foo_s { int a[...]; int b[...]; };")
385 verify(ffi, 'test_dotdotdot_length_of_array_field',
386 "struct foo_s { int a[42]; int b[11]; };")
387 assert ffi.sizeof("struct foo_s") == (42 + 11) * 4
388 p = ffi.new("struct foo_s *")
389 assert p.a[41] == p.b[10] == 0
390 py.test.raises(IndexError, "p.a[42]")
391 py.test.raises(IndexError, "p.b[11]")
392
393 def test_dotdotdot_global_array():
394 ffi = FFI()
395 ffi.cdef("int aa[...]; int bb[...];")
396 lib = verify(ffi, 'test_dotdotdot_global_array',
397 "int aa[41]; int bb[12];")
398 assert ffi.sizeof(lib.aa) == 41 * 4
399 assert ffi.sizeof(lib.bb) == 12 * 4
400 assert lib.aa[40] == lib.bb[11] == 0
401 py.test.raises(IndexError, "lib.aa[41]")
402 py.test.raises(IndexError, "lib.bb[12]")
403
404 def test_misdeclared_field_1():
405 ffi = FFI()
406 ffi.cdef("struct foo_s { int a[5]; };")
407 try:
408 verify(ffi, 'test_misdeclared_field_1',
409 "struct foo_s { int a[6]; };")
410 except VerificationError:
411 pass # ok, fail during compilation already (e.g. C++)
412 else:
413 assert ffi.sizeof("struct foo_s") == 24 # found by the actual C code
414 try:
415 # lazily build the fields and boom:
416 p = ffi.new("struct foo_s *")
417 p.a
418 assert False, "should have raised"
419 except ffi.error as e:
420 assert str(e).startswith("struct foo_s: wrong size for field 'a' "
421 "(cdef says 20, but C compiler says 24)")
422
423 def test_open_array_in_struct():
424 ffi = FFI()
425 ffi.cdef("struct foo_s { int b; int a[]; };")
426 verify(ffi, 'test_open_array_in_struct',
427 "struct foo_s { int b; int a[]; };")
428 assert ffi.sizeof("struct foo_s") == 4
429 p = ffi.new("struct foo_s *", [5, [10, 20, 30, 40]])
430 assert p.a[2] == 30
431 assert ffi.sizeof(p) == ffi.sizeof("void *")
432 assert ffi.sizeof(p[0]) == 5 * ffi.sizeof("int")
433
434 def test_math_sin_type():
435 ffi = FFI()
436 ffi.cdef("double sin(double); void *xxtestfunc();")
437 lib = verify(ffi, 'test_math_sin_type', """
438 #include <math.h>
439 void *xxtestfunc(void) { return 0; }
440 """)
441 # 'lib.sin' is typed as a <built-in method> object on lib
442 assert ffi.typeof(lib.sin).cname == "double(*)(double)"
443 # 'x' is another <built-in method> object on lib, made very indirectly
444 x = type(lib).__dir__.__get__(lib)
445 py.test.raises(TypeError, ffi.typeof, x)
446 #
447 # present on built-in functions on CPython; must be emulated on PyPy:
448 assert lib.sin.__name__ == 'sin'
449 assert lib.sin.__module__ == '_CFFI_test_math_sin_type'
450 assert lib.sin.__doc__ == (
451 "double sin(double);\n"
452 "\n"
453 "CFFI C function from _CFFI_test_math_sin_type.lib")
454
455 assert ffi.typeof(lib.xxtestfunc).cname == "void *(*)()"
456 assert lib.xxtestfunc.__doc__ == (
457 "void *xxtestfunc();\n"
458 "\n"
459 "CFFI C function from _CFFI_test_math_sin_type.lib")
460
461 def test_verify_anonymous_struct_with_typedef():
462 ffi = FFI()
463 ffi.cdef("typedef struct { int a; long b; ...; } foo_t;")
464 verify(ffi, 'test_verify_anonymous_struct_with_typedef',
465 "typedef struct { long b; int hidden, a; } foo_t;")
466 p = ffi.new("foo_t *", {'b': 42})
467 assert p.b == 42
468 assert repr(p).startswith("<cdata 'foo_t *' ")
469
470 def test_verify_anonymous_struct_with_star_typedef():
471 ffi = FFI()
472 ffi.cdef("typedef struct { int a; long b; } *foo_t;")
473 verify(ffi, 'test_verify_anonymous_struct_with_star_typedef',
474 "typedef struct { int a; long b; } *foo_t;")
475 p = ffi.new("foo_t", {'b': 42})
476 assert p.b == 42
477
478 def test_verify_anonymous_enum_with_typedef():
479 ffi = FFI()
480 ffi.cdef("typedef enum { AA, ... } e1;")
481 lib = verify(ffi, 'test_verify_anonymous_enum_with_typedef1',
482 "typedef enum { BB, CC, AA } e1;")
483 assert lib.AA == 2
484 assert ffi.sizeof("e1") == ffi.sizeof("int")
485 assert repr(ffi.cast("e1", 2)) == "<cdata 'e1' 2: AA>"
486 #
487 ffi = FFI()
488 ffi.cdef("typedef enum { AA=%d } e1;" % sys.maxsize)
489 lib = verify(ffi, 'test_verify_anonymous_enum_with_typedef2',
490 "typedef enum { AA=%d } e1;" % sys.maxsize)
491 assert lib.AA == int(ffi.cast("long", sys.maxsize))
492 assert ffi.sizeof("e1") == ffi.sizeof("long")
493
494 def test_unique_types():
495 CDEF = "struct foo_s; union foo_u; enum foo_e { AA };"
496 ffi1 = FFI(); ffi1.cdef(CDEF); verify(ffi1, "test_unique_types_1", CDEF)
497 ffi2 = FFI(); ffi2.cdef(CDEF); verify(ffi2, "test_unique_types_2", CDEF)
498 #
499 assert ffi1.typeof("char") is ffi2.typeof("char ")
500 assert ffi1.typeof("long") is ffi2.typeof("signed long int")
501 assert ffi1.typeof("double *") is ffi2.typeof("double*")
502 assert ffi1.typeof("int ***") is ffi2.typeof(" int * * *")
503 assert ffi1.typeof("int[]") is ffi2.typeof("signed int[]")
504 assert ffi1.typeof("signed int*[17]") is ffi2.typeof("int *[17]")
505 assert ffi1.typeof("void") is ffi2.typeof("void")
506 assert ffi1.typeof("int(*)(int,int)") is ffi2.typeof("int(*)(int,int)")
507 #
508 # these depend on user-defined data, so should not be shared
509 for name in ["struct foo_s",
510 "union foo_u *",
511 "enum foo_e",
512 "struct foo_s *(*)()",
513 "void(*)(struct foo_s *)",
514 "struct foo_s *(*[5])[8]",
515 ]:
516 assert ffi1.typeof(name) is not ffi2.typeof(name)
517 # sanity check: twice 'ffi1'
518 assert ffi1.typeof("struct foo_s*") is ffi1.typeof("struct foo_s *")
519
520 def test_module_name_in_package():
521 ffi = FFI()
522 ffi.cdef("int foo(int);")
523 recompiler.recompile(ffi, "test_module_name_in_package.mymod",
524 "int foo(int x) { return x + 32; }",
525 tmpdir=str(udir))
526 old_sys_path = sys.path[:]
527 try:
528 package_dir = udir.join('test_module_name_in_package')
529 for name in os.listdir(str(udir)):
530 assert not name.startswith('test_module_name_in_package.')
531 assert os.path.isdir(str(package_dir))
532 assert len(os.listdir(str(package_dir))) > 0
533 assert os.path.exists(str(package_dir.join('mymod.c')))
534 package_dir.join('__init__.py').write('')
535 #
536 getattr(importlib, 'invalidate_caches', object)()
537 #
538 sys.path.insert(0, str(udir))
539 import test_module_name_in_package.mymod
540 assert test_module_name_in_package.mymod.lib.foo(10) == 42
541 assert test_module_name_in_package.mymod.__name__ == (
542 'test_module_name_in_package.mymod')
543 finally:
544 sys.path[:] = old_sys_path
545
546 def test_bad_size_of_global_1():
547 ffi = FFI()
548 ffi.cdef("short glob;")
549 py.test.raises(VerificationError, verify, ffi,
550 "test_bad_size_of_global_1", "long glob;")
551
552 def test_bad_size_of_global_2():
553 ffi = FFI()
554 ffi.cdef("int glob[10];")
555 py.test.raises(VerificationError, verify, ffi,
556 "test_bad_size_of_global_2", "int glob[9];")
557
558 def test_unspecified_size_of_global_1():
559 ffi = FFI()
560 ffi.cdef("int glob[];")
561 lib = verify(ffi, "test_unspecified_size_of_global_1", "int glob[10];")
562 assert ffi.typeof(lib.glob) == ffi.typeof("int *")
563
564 def test_unspecified_size_of_global_2():
565 ffi = FFI()
566 ffi.cdef("int glob[][5];")
567 lib = verify(ffi, "test_unspecified_size_of_global_2", "int glob[10][5];")
568 assert ffi.typeof(lib.glob) == ffi.typeof("int(*)[5]")
569
570 def test_unspecified_size_of_global_3():
571 ffi = FFI()
572 ffi.cdef("int glob[][...];")
573 lib = verify(ffi, "test_unspecified_size_of_global_3", "int glob[10][5];")
574 assert ffi.typeof(lib.glob) == ffi.typeof("int(*)[5]")
575
576 def test_unspecified_size_of_global_4():
577 ffi = FFI()
578 ffi.cdef("int glob[...][...];")
579 lib = verify(ffi, "test_unspecified_size_of_global_4", "int glob[10][5];")
580 assert ffi.typeof(lib.glob) == ffi.typeof("int[10][5]")
581
582 def test_include_1():
583 ffi1 = FFI()
584 ffi1.cdef("typedef double foo_t;")
585 verify(ffi1, "test_include_1_parent", "typedef double foo_t;")
586 ffi = FFI()
587 ffi.include(ffi1)
588 ffi.cdef("foo_t ff1(foo_t);")
589 lib = verify(ffi, "test_include_1", "double ff1(double x) { return 42.5; }")
590 assert lib.ff1(0) == 42.5
591 assert ffi1.typeof("foo_t") is ffi.typeof("foo_t") is ffi.typeof("double")
592
593 def test_include_1b():
594 ffi1 = FFI()
595 ffi1.cdef("int foo1(int);")
596 lib1 = verify(ffi1, "test_include_1b_parent",
597 "int foo1(int x) { return x + 10; }")
598 ffi = FFI()
599 ffi.include(ffi1)
600 ffi.cdef("int foo2(int);")
601 lib = verify(ffi, "test_include_1b", "int foo2(int x) { return x - 5; }")
602 assert lib.foo2(42) == 37
603 assert lib.foo1(42) == 52
604 assert lib.foo1 is lib1.foo1
605
606 def test_include_2():
607 ffi1 = FFI()
608 ffi1.cdef("struct foo_s { int x, y; };")
609 verify(ffi1, "test_include_2_parent", "struct foo_s { int x, y; };")
610 ffi = FFI()
611 ffi.include(ffi1)
612 ffi.cdef("struct foo_s *ff2(struct foo_s *);")
613 lib = verify(ffi, "test_include_2",
614 "struct foo_s { int x, y; }; //usually from a #include\n"
615 "struct foo_s *ff2(struct foo_s *p) { p->y++; return p; }")
616 p = ffi.new("struct foo_s *")
617 p.y = 41
618 q = lib.ff2(p)
619 assert q == p
620 assert p.y == 42
621 assert ffi1.typeof("struct foo_s") is ffi.typeof("struct foo_s")
622
623 def test_include_3():
624 ffi1 = FFI()
625 ffi1.cdef("typedef short sshort_t;")
626 verify(ffi1, "test_include_3_parent", "typedef short sshort_t;")
627 ffi = FFI()
628 ffi.include(ffi1)
629 ffi.cdef("sshort_t ff3(sshort_t);")
630 lib = verify(ffi, "test_include_3",
631 "typedef short sshort_t; //usually from a #include\n"
632 "sshort_t ff3(sshort_t x) { return x + 42; }")
633 assert lib.ff3(10) == 52
634 assert ffi.typeof(ffi.cast("sshort_t", 42)) is ffi.typeof("short")
635 assert ffi1.typeof("sshort_t") is ffi.typeof("sshort_t")
636
637 def test_include_4():
638 ffi1 = FFI()
639 ffi1.cdef("typedef struct { int x; } mystruct_t;")
640 verify(ffi1, "test_include_4_parent",
641 "typedef struct { int x; } mystruct_t;")
642 ffi = FFI()
643 ffi.include(ffi1)
644 ffi.cdef("mystruct_t *ff4(mystruct_t *);")
645 lib = verify(ffi, "test_include_4",
646 "typedef struct {int x; } mystruct_t; //usually from a #include\n"
647 "mystruct_t *ff4(mystruct_t *p) { p->x += 42; return p; }")
648 p = ffi.new("mystruct_t *", [10])
649 q = lib.ff4(p)
650 assert q == p
651 assert p.x == 52
652 assert ffi1.typeof("mystruct_t") is ffi.typeof("mystruct_t")
653
654 def test_include_5():
655 ffi1 = FFI()
656 ffi1.cdef("typedef struct { int x[2]; int y; } *mystruct_p;")
657 verify(ffi1, "test_include_5_parent",
658 "typedef struct { int x[2]; int y; } *mystruct_p;")
659 ffi = FFI()
660 ffi.include(ffi1)
661 ffi.cdef("mystruct_p ff5(mystruct_p);")
662 lib = verify(ffi, "test_include_5",
663 "typedef struct {int x[2]; int y; } *mystruct_p; //usually #include\n"
664 "mystruct_p ff5(mystruct_p p) { p->x[1] += 42; return p; }")
665 assert ffi.alignof(ffi.typeof("mystruct_p").item) == 4
666 assert ffi1.typeof("mystruct_p") is ffi.typeof("mystruct_p")
667 p = ffi.new("mystruct_p", [[5, 10], -17])
668 q = lib.ff5(p)
669 assert q == p
670 assert p.x[0] == 5
671 assert p.x[1] == 52
672 assert p.y == -17
673 assert ffi.alignof(ffi.typeof(p[0])) == 4
674
675 def test_include_6():
676 ffi1 = FFI()
677 ffi1.cdef("typedef ... mystruct_t;")
678 verify(ffi1, "test_include_6_parent",
679 "typedef struct _mystruct_s mystruct_t;")
680 ffi = FFI()
681 ffi.include(ffi1)
682 ffi.cdef("mystruct_t *ff6(void); int ff6b(mystruct_t *);")
683 lib = verify(ffi, "test_include_6",
684 "typedef struct _mystruct_s mystruct_t; //usually from a #include\n"
685 "struct _mystruct_s { int x; };\n"
686 "static mystruct_t result_struct = { 42 };\n"
687 "mystruct_t *ff6(void) { return &result_struct; }\n"
688 "int ff6b(mystruct_t *p) { return p->x; }")
689 p = lib.ff6()
690 assert ffi.cast("int *", p)[0] == 42
691 assert lib.ff6b(p) == 42
692
693 def test_include_7():
694 ffi1 = FFI()
695 ffi1.cdef("typedef ... mystruct_t;\n"
696 "int ff7b(mystruct_t *);")
697 verify(ffi1, "test_include_7_parent",
698 "typedef struct { int x; } mystruct_t;\n"
699 "int ff7b(mystruct_t *p) { return p->x; }")
700 ffi = FFI()
701 ffi.include(ffi1)
702 ffi.cdef("mystruct_t *ff7(void);")
703 lib = verify(ffi, "test_include_7",
704 "typedef struct { int x; } mystruct_t; //usually from a #include\n"
705 "static mystruct_t result_struct = { 42 };"
706 "mystruct_t *ff7(void) { return &result_struct; }")
707 p = lib.ff7()
708 assert ffi.cast("int *", p)[0] == 42
709 assert lib.ff7b(p) == 42
710
711 def test_include_8():
712 ffi1 = FFI()
713 ffi1.cdef("struct foo_s;")
714 verify(ffi1, "test_include_8_parent", "struct foo_s;")
715 ffi = FFI()
716 ffi.include(ffi1)
717 ffi.cdef("struct foo_s { int x, y; };")
718 verify(ffi, "test_include_8", "struct foo_s { int x, y; };")
719 e = py.test.raises(NotImplementedError, ffi.new, "struct foo_s *")
720 assert str(e.value) == (
721 "'struct foo_s' is opaque in the ffi.include(), but no longer in "
722 "the ffi doing the include (workaround: don't use ffi.include() but"
723 " duplicate the declarations of everything using struct foo_s)")
724
725 def test_unicode_libraries():
726 try:
727 unicode
728 except NameError:
729 py.test.skip("for python 2.x")
730 #
731 import math
732 lib_m = "m"
733 if sys.platform == 'win32':
734 #there is a small chance this fails on Mingw via environ $CC
735 import distutils.ccompiler
736 if distutils.ccompiler.get_default_compiler() == 'msvc':
737 lib_m = 'msvcrt'
738 ffi = FFI()
739 ffi.cdef(unicode("float sin(double); double cos(double);"))
740 lib = verify(ffi, 'test_math_sin_unicode', unicode('#include <math.h>'),
741 libraries=[unicode(lib_m)])
742 assert lib.cos(1.43) == math.cos(1.43)
743
744 def test_incomplete_struct_as_arg():
745 ffi = FFI()
746 ffi.cdef("struct foo_s { int x; ...; }; int f(int, struct foo_s);")
747 lib = verify(ffi, "test_incomplete_struct_as_arg",
748 "struct foo_s { int a, x, z; };\n"
749 "int f(int b, struct foo_s s) { return s.x * b; }")
750 s = ffi.new("struct foo_s *", [21])
751 assert s.x == 21
752 assert ffi.sizeof(s[0]) == 12
753 assert ffi.offsetof(ffi.typeof(s), 'x') == 4
754 assert lib.f(2, s[0]) == 42
755 assert ffi.typeof(lib.f) == ffi.typeof("int(*)(int, struct foo_s)")
756
757 def test_incomplete_struct_as_result():
758 ffi = FFI()
759 ffi.cdef("struct foo_s { int x; ...; }; struct foo_s f(int);")
760 lib = verify(ffi, "test_incomplete_struct_as_result",
761 "struct foo_s { int a, x, z; };\n"
762 "struct foo_s f(int x) { struct foo_s r; r.x = x * 2; return r; }")
763 s = lib.f(21)
764 assert s.x == 42
765 assert ffi.typeof(lib.f) == ffi.typeof("struct foo_s(*)(int)")
766
767 def test_incomplete_struct_as_both():
768 ffi = FFI()
769 ffi.cdef("struct foo_s { int x; ...; }; struct bar_s { int y; ...; };\n"
770 "struct foo_s f(int, struct bar_s);")
771 lib = verify(ffi, "test_incomplete_struct_as_both",
772 "struct foo_s { int a, x, z; };\n"
773 "struct bar_s { int b, c, y, d; };\n"
774 "struct foo_s f(int x, struct bar_s b) {\n"
775 " struct foo_s r; r.x = x * b.y; return r;\n"
776 "}")
777 b = ffi.new("struct bar_s *", [7])
778 s = lib.f(6, b[0])
779 assert s.x == 42
780 assert ffi.typeof(lib.f) == ffi.typeof(
781 "struct foo_s(*)(int, struct bar_s)")
782 s = lib.f(14, {'y': -3})
783 assert s.x == -42
784
785 def test_name_of_unnamed_struct():
786 ffi = FFI()
787 ffi.cdef("typedef struct { int x; } foo_t;\n"
788 "typedef struct { int y; } *bar_p;\n"
789 "typedef struct { int y; } **baz_pp;\n")
790 verify(ffi, "test_name_of_unnamed_struct",
791 "typedef struct { int x; } foo_t;\n"
792 "typedef struct { int y; } *bar_p;\n"
793 "typedef struct { int y; } **baz_pp;\n")
794 assert repr(ffi.typeof("foo_t")) == "<ctype 'foo_t'>"
795 assert repr(ffi.typeof("bar_p")) == "<ctype 'struct $1 *'>"
796 assert repr(ffi.typeof("baz_pp")) == "<ctype 'struct $2 * *'>"
797
798 def test_address_of_global_var():
799 ffi = FFI()
800 ffi.cdef("""
801 long bottom, bottoms[2];
802 long FetchRectBottom(void);
803 long FetchRectBottoms1(void);
804 #define FOOBAR 42
805 """)
806 lib = verify(ffi, "test_address_of_global_var", """
807 long bottom, bottoms[2];
808 long FetchRectBottom(void) { return bottom; }
809 long FetchRectBottoms1(void) { return bottoms[1]; }
810 #define FOOBAR 42
811 """)
812 lib.bottom = 300
813 assert lib.FetchRectBottom() == 300
814 lib.bottom += 1
815 assert lib.FetchRectBottom() == 301
816 lib.bottoms[1] = 500
817 assert lib.FetchRectBottoms1() == 500
818 lib.bottoms[1] += 2
819 assert lib.FetchRectBottoms1() == 502
820 #
821 p = ffi.addressof(lib, 'bottom')
822 assert ffi.typeof(p) == ffi.typeof("long *")
823 assert p[0] == 301
824 p[0] += 1
825 assert lib.FetchRectBottom() == 302
826 p = ffi.addressof(lib, 'bottoms')
827 assert ffi.typeof(p) == ffi.typeof("long(*)[2]")
828 assert p[0] == lib.bottoms
829 #
830 py.test.raises(AttributeError, ffi.addressof, lib, 'unknown_var')
831 py.test.raises(AttributeError, ffi.addressof, lib, "FOOBAR")
832
833 def test_defines__CFFI_():
834 # Check that we define the macro _CFFI_ automatically.
835 # It should be done before including Python.h, so that PyPy's Python.h
836 # can check for it.
837 ffi = FFI()
838 ffi.cdef("""
839 #define CORRECT 1
840 """)
841 lib = verify(ffi, "test_defines__CFFI_", """
842 #ifdef _CFFI_
843 # define CORRECT 1
844 #endif
845 """)
846 assert lib.CORRECT == 1
847
848 def test_unpack_args():
849 ffi = FFI()
850 ffi.cdef("void foo0(void); void foo1(int); void foo2(int, int);")
851 lib = verify(ffi, "test_unpack_args", """
852 void foo0(void) { }
853 void foo1(int x) { }
854 void foo2(int x, int y) { }
855 """)
856 assert 'foo0' in repr(lib.foo0)
857 assert 'foo1' in repr(lib.foo1)
858 assert 'foo2' in repr(lib.foo2)
859 lib.foo0()
860 lib.foo1(42)
861 lib.foo2(43, 44)
862 e1 = py.test.raises(TypeError, lib.foo0, 42)
863 e2 = py.test.raises(TypeError, lib.foo0, 43, 44)
864 e3 = py.test.raises(TypeError, lib.foo1)
865 e4 = py.test.raises(TypeError, lib.foo1, 43, 44)
866 e5 = py.test.raises(TypeError, lib.foo2)
867 e6 = py.test.raises(TypeError, lib.foo2, 42)
868 e7 = py.test.raises(TypeError, lib.foo2, 45, 46, 47)
869 assert str(e1.value) == "foo0() takes no arguments (1 given)"
870 assert str(e2.value) == "foo0() takes no arguments (2 given)"
871 assert str(e3.value) == "foo1() takes exactly one argument (0 given)"
872 assert str(e4.value) == "foo1() takes exactly one argument (2 given)"
873 assert str(e5.value) in ["foo2 expected 2 arguments, got 0",
874 "foo2() takes exactly 2 arguments (0 given)"]
875 assert str(e6.value) in ["foo2 expected 2 arguments, got 1",
876 "foo2() takes exactly 2 arguments (1 given)"]
877 assert str(e7.value) in ["foo2 expected 2 arguments, got 3",
878 "foo2() takes exactly 2 arguments (3 given)"]
879
880 def test_address_of_function():
881 ffi = FFI()
882 ffi.cdef("long myfunc(long x);")
883 lib = verify(ffi, "test_addressof_function", """
884 char myfunc(char x) { return (char)(x + 42); }
885 """)
886 assert lib.myfunc(5) == 47
887 assert lib.myfunc(0xABC05) == 47
888 assert not isinstance(lib.myfunc, ffi.CData)
889 assert ffi.typeof(lib.myfunc) == ffi.typeof("long(*)(long)")
890 addr = ffi.addressof(lib, 'myfunc')
891 assert addr(5) == 47
892 assert addr(0xABC05) == 47
893 assert isinstance(addr, ffi.CData)
894 assert ffi.typeof(addr) == ffi.typeof("long(*)(long)")
895
896 def test_address_of_function_with_struct():
897 ffi = FFI()
898 ffi.cdef("struct foo_s { int x; }; long myfunc(struct foo_s);")
899 lib = verify(ffi, "test_addressof_function_with_struct", """
900 struct foo_s { int x; };
901 char myfunc(struct foo_s input) { return (char)(input.x + 42); }
902 """)
903 s = ffi.new("struct foo_s *", [5])[0]
904 assert lib.myfunc(s) == 47
905 assert not isinstance(lib.myfunc, ffi.CData)
906 assert ffi.typeof(lib.myfunc) == ffi.typeof("long(*)(struct foo_s)")
907 addr = ffi.addressof(lib, 'myfunc')
908 assert addr(s) == 47
909 assert isinstance(addr, ffi.CData)
910 assert ffi.typeof(addr) == ffi.typeof("long(*)(struct foo_s)")
911
912 def test_issue198():
913 ffi = FFI()
914 ffi.cdef("""
915 typedef struct{...;} opaque_t;
916 const opaque_t CONSTANT;
917 int toint(opaque_t);
918 """)
919 lib = verify(ffi, 'test_issue198', """
920 typedef int opaque_t;
921 #define CONSTANT ((opaque_t)42)
922 static int toint(opaque_t o) { return o; }
923 """)
924 def random_stuff():
925 pass
926 assert lib.toint(lib.CONSTANT) == 42
927 random_stuff()
928 assert lib.toint(lib.CONSTANT) == 42
929
930 def test_constant_is_not_a_compiler_constant():
931 ffi = FFI()
932 ffi.cdef("static const float almost_forty_two;")
933 lib = verify(ffi, 'test_constant_is_not_a_compiler_constant', """
934 static float f(void) { return 42.25; }
935 #define almost_forty_two (f())
936 """)
937 assert lib.almost_forty_two == 42.25
938
939 def test_constant_of_unknown_size():
940 ffi = FFI()
941 ffi.cdef("""
942 typedef ... opaque_t;
943 const opaque_t CONSTANT;
944 """)
945 lib = verify(ffi, 'test_constant_of_unknown_size',
946 "typedef int opaque_t;"
947 "const int CONSTANT = 42;")
948 e = py.test.raises(ffi.error, getattr, lib, 'CONSTANT')
949 assert str(e.value) == ("constant 'CONSTANT' is of "
950 "type 'opaque_t', whose size is not known")
951
952 def test_variable_of_unknown_size():
953 ffi = FFI()
954 ffi.cdef("""
955 typedef ... opaque_t;
956 opaque_t globvar;
957 """)
958 lib = verify(ffi, 'test_variable_of_unknown_size', """
959 typedef char opaque_t[6];
960 opaque_t globvar = "hello";
961 """)
962 # can't read or write it at all
963 e = py.test.raises(TypeError, getattr, lib, 'globvar')
964 assert str(e.value) in ["cdata 'opaque_t' is opaque",
965 "'opaque_t' is opaque or not completed yet"] #pypy
966 e = py.test.raises(TypeError, setattr, lib, 'globvar', [])
967 assert str(e.value) in ["'opaque_t' is opaque",
968 "'opaque_t' is opaque or not completed yet"] #pypy
969 # but we can get its address
970 p = ffi.addressof(lib, 'globvar')
971 assert ffi.typeof(p) == ffi.typeof('opaque_t *')
972 assert ffi.string(ffi.cast("char *", p), 8) == b"hello"
973
974 def test_constant_of_value_unknown_to_the_compiler():
975 extra_c_source = udir.join(
976 'extra_test_constant_of_value_unknown_to_the_compiler.c')
977 extra_c_source.write('const int external_foo = 42;\n')
978 ffi = FFI()
979 ffi.cdef("const int external_foo;")
980 lib = verify(ffi, 'test_constant_of_value_unknown_to_the_compiler', """
981 extern const int external_foo;
982 """, sources=[str(extra_c_source)])
983 assert lib.external_foo == 42
984
985 def test_dotdot_in_source_file_names():
986 extra_c_source = udir.join(
987 'extra_test_dotdot_in_source_file_names.c')
988 extra_c_source.write('const int external_foo = 42;\n')
989 ffi = FFI()
990 ffi.cdef("const int external_foo;")
991 lib = verify(ffi, 'test_dotdot_in_source_file_names', """
992 extern const int external_foo;
993 """, sources=[os.path.join(os.path.dirname(str(extra_c_source)),
994 'foobar', '..',
995 os.path.basename(str(extra_c_source)))])
996 assert lib.external_foo == 42
997
998 def test_call_with_incomplete_structs():
999 ffi = FFI()
1000 ffi.cdef("typedef struct {...;} foo_t; "
1001 "foo_t myglob; "
1002 "foo_t increment(foo_t s); "
1003 "double getx(foo_t s);")
1004 lib = verify(ffi, 'test_call_with_incomplete_structs', """
1005 typedef double foo_t;
1006 double myglob = 42.5;
1007 double getx(double x) { return x; }
1008 double increment(double x) { return x + 1; }
1009 """)
1010 assert lib.getx(lib.myglob) == 42.5
1011 assert lib.getx(lib.increment(lib.myglob)) == 43.5
1012
1013 def test_struct_array_guess_length_2():
1014 ffi = FFI()
1015 ffi.cdef("struct foo_s { int a[...][...]; };")
1016 lib = verify(ffi, 'test_struct_array_guess_length_2',
1017 "struct foo_s { int x; int a[5][8]; int y; };")
1018 assert ffi.sizeof('struct foo_s') == 42 * ffi.sizeof('int')
1019 s = ffi.new("struct foo_s *")
1020 assert ffi.typeof(s.a) == ffi.typeof("int[5][8]")
1021 assert ffi.sizeof(s.a) == 40 * ffi.sizeof('int')
1022 assert s.a[4][7] == 0
1023 py.test.raises(IndexError, 's.a[4][8]')
1024 py.test.raises(IndexError, 's.a[5][0]')
1025 assert ffi.typeof(s.a) == ffi.typeof("int[5][8]")
1026 assert ffi.typeof(s.a[0]) == ffi.typeof("int[8]")
1027
1028 def test_struct_array_guess_length_3():
1029 ffi = FFI()
1030 ffi.cdef("struct foo_s { int a[][...]; };")
1031 lib = verify(ffi, 'test_struct_array_guess_length_3',
1032 "struct foo_s { int x; int a[5][7]; int y; };")
1033 assert ffi.sizeof('struct foo_s') == 37 * ffi.sizeof('int')
1034 s = ffi.new("struct foo_s *")
1035 assert ffi.typeof(s.a) == ffi.typeof("int[][7]")
1036 assert s.a[4][6] == 0
1037 py.test.raises(IndexError, 's.a[4][7]')
1038 assert ffi.typeof(s.a[0]) == ffi.typeof("int[7]")
1039
1040 def test_global_var_array_2():
1041 ffi = FFI()
1042 ffi.cdef("int a[...][...];")
1043 lib = verify(ffi, 'test_global_var_array_2', 'int a[10][8];')
1044 lib.a[9][7] = 123456
1045 assert lib.a[9][7] == 123456
1046 py.test.raises(IndexError, 'lib.a[0][8]')
1047 py.test.raises(IndexError, 'lib.a[10][0]')
1048 assert ffi.typeof(lib.a) == ffi.typeof("int[10][8]")
1049 assert ffi.typeof(lib.a[0]) == ffi.typeof("int[8]")
1050
1051 def test_global_var_array_3():
1052 ffi = FFI()
1053 ffi.cdef("int a[][...];")
1054 lib = verify(ffi, 'test_global_var_array_3', 'int a[10][8];')
1055 lib.a[9][7] = 123456
1056 assert lib.a[9][7] == 123456
1057 py.test.raises(IndexError, 'lib.a[0][8]')
1058 assert ffi.typeof(lib.a) == ffi.typeof("int(*)[8]")
1059 assert ffi.typeof(lib.a[0]) == ffi.typeof("int[8]")
1060
1061 def test_global_var_array_4():
1062 ffi = FFI()
1063 ffi.cdef("int a[10][...];")
1064 lib = verify(ffi, 'test_global_var_array_4', 'int a[10][8];')
1065 lib.a[9][7] = 123456
1066 assert lib.a[9][7] == 123456
1067 py.test.raises(IndexError, 'lib.a[0][8]')
1068 py.test.raises(IndexError, 'lib.a[10][8]')
1069 assert ffi.typeof(lib.a) == ffi.typeof("int[10][8]")
1070 assert ffi.typeof(lib.a[0]) == ffi.typeof("int[8]")
1071
1072 def test_some_integer_type():
1073 ffi = FFI()
1074 ffi.cdef("""
1075 typedef int... foo_t;
1076 typedef unsigned long... bar_t;
1077 typedef struct { foo_t a, b; } mystruct_t;
1078 foo_t foobar(bar_t, mystruct_t);
1079 static const bar_t mu = -20;
1080 static const foo_t nu = 20;
1081 """)
1082 lib = verify(ffi, 'test_some_integer_type', """
1083 typedef unsigned long long foo_t;
1084 typedef short bar_t;
1085 typedef struct { foo_t a, b; } mystruct_t;
1086 static foo_t foobar(bar_t x, mystruct_t s) {
1087 return (foo_t)x + s.a + s.b;
1088 }
1089 static const bar_t mu = -20;
1090 static const foo_t nu = 20;
1091 """)
1092 assert ffi.sizeof("foo_t") == ffi.sizeof("unsigned long long")
1093 assert ffi.sizeof("bar_t") == ffi.sizeof("short")
1094 maxulonglong = 2 ** 64 - 1
1095 assert int(ffi.cast("foo_t", -1)) == maxulonglong
1096 assert int(ffi.cast("bar_t", -1)) == -1
1097 assert lib.foobar(-1, [0, 0]) == maxulonglong
1098 assert lib.foobar(2 ** 15 - 1, [0, 0]) == 2 ** 15 - 1
1099 assert lib.foobar(10, [20, 31]) == 61
1100 assert lib.foobar(0, [0, maxulonglong]) == maxulonglong
1101 py.test.raises(OverflowError, lib.foobar, 2 ** 15, [0, 0])
1102 py.test.raises(OverflowError, lib.foobar, -(2 ** 15) - 1, [0, 0])
1103 py.test.raises(OverflowError, ffi.new, "mystruct_t *", [0, -1])
1104 assert lib.mu == -20
1105 assert lib.nu == 20
1106
1107 def test_some_float_type():
1108 ffi = FFI()
1109 ffi.cdef("""
1110 typedef double... foo_t;
1111 typedef float... bar_t;
1112 foo_t sum(foo_t[]);
1113 bar_t neg(bar_t);
1114 """)
1115 lib = verify(ffi, 'test_some_float_type', """
1116 typedef float foo_t;
1117 static foo_t sum(foo_t x[]) { return x[0] + x[1]; }
1118 typedef double bar_t;
1119 static double neg(double x) { return -x; }
1120 """)
1121 assert lib.sum([40.0, 2.25]) == 42.25
1122 assert lib.sum([12.3, 45.6]) != 12.3 + 45.6 # precision loss
1123 assert lib.neg(12.3) == -12.3 # no precision loss
1124 assert ffi.sizeof("foo_t") == ffi.sizeof("float")
1125 assert ffi.sizeof("bar_t") == ffi.sizeof("double")
1126
1127 def test_some_float_invalid_1():
1128 ffi = FFI()
1129 py.test.raises((FFIError, # with pycparser <= 2.17
1130 CDefError), # with pycparser >= 2.18
1131 ffi.cdef, "typedef long double... foo_t;")
1132
1133 def test_some_float_invalid_2():
1134 ffi = FFI()
1135 ffi.cdef("typedef double... foo_t; foo_t neg(foo_t);")
1136 lib = verify(ffi, 'test_some_float_invalid_2', """
1137 typedef unsigned long foo_t;
1138 foo_t neg(foo_t x) { return -x; }
1139 """)
1140 e = py.test.raises(ffi.error, getattr, lib, 'neg')
1141 assert str(e.value) == ("primitive floating-point type with an unexpected "
1142 "size (or not a float type at all)")
1143
1144 def test_some_float_invalid_3():
1145 ffi = FFI()
1146 ffi.cdef("typedef double... foo_t; foo_t neg(foo_t);")
1147 lib = verify(ffi, 'test_some_float_invalid_3', """
1148 typedef long double foo_t;
1149 foo_t neg(foo_t x) { return -x; }
1150 """)
1151 if ffi.sizeof("long double") == ffi.sizeof("double"):
1152 assert lib.neg(12.3) == -12.3
1153 else:
1154 e = py.test.raises(ffi.error, getattr, lib, 'neg')
1155 assert str(e.value) == ("primitive floating-point type is "
1156 "'long double', not supported for now with "
1157 "the syntax 'typedef double... xxx;'")
1158
1159 def test_issue200():
1160 ffi = FFI()
1161 ffi.cdef("""
1162 typedef void (function_t)(void*);
1163 void function(void *);
1164 """)
1165 lib = verify(ffi, 'test_issue200', """
1166 static void function(void *p) { (void)p; }
1167 """)
1168 ffi.typeof('function_t*')
1169 lib.function(ffi.NULL)
1170 # assert did not crash
1171
1172 def test_alignment_of_longlong():
1173 ffi = FFI()
1174 x1 = ffi.alignof('unsigned long long')
1175 assert x1 in [4, 8]
1176 ffi.cdef("struct foo_s { unsigned long long x; };")
1177 lib = verify(ffi, 'test_alignment_of_longlong',
1178 "struct foo_s { unsigned long long x; };")
1179 assert ffi.alignof('unsigned long long') == x1
1180 assert ffi.alignof('struct foo_s') == x1
1181
1182 def test_import_from_lib():
1183 ffi = FFI()
1184 ffi.cdef("int mybar(int); int myvar;\n#define MYFOO ...")
1185 lib = verify(ffi, 'test_import_from_lib',
1186 "#define MYFOO 42\n"
1187 "static int mybar(int x) { return x + 1; }\n"
1188 "static int myvar = -5;")
1189 assert sys.modules['_CFFI_test_import_from_lib'].lib is lib
1190 assert sys.modules['_CFFI_test_import_from_lib.lib'] is lib
1191 from _CFFI_test_import_from_lib.lib import MYFOO
1192 assert MYFOO == 42
1193 assert hasattr(lib, '__dict__')
1194 assert lib.__all__ == ['MYFOO', 'mybar'] # but not 'myvar'
1195 assert lib.__name__ == '_CFFI_test_import_from_lib.lib'
1196 assert lib.__class__ is type(sys) # !! hack for help()
1197
1198 def test_macro_var_callback():
1199 ffi = FFI()
1200 ffi.cdef("int my_value; int *(*get_my_value)(void);")
1201 lib = verify(ffi, 'test_macro_var_callback',
1202 "int *(*get_my_value)(void);\n"
1203 "#define my_value (*get_my_value())")
1204 #
1205 values = ffi.new("int[50]")
1206 def it():
1207 for i in range(50):
1208 yield i
1209 it = it()
1210 #
1211 @ffi.callback("int *(*)(void)")
1212 def get_my_value():
1213 for nextvalue in it:
1214 return values + nextvalue
1215 lib.get_my_value = get_my_value
1216 #
1217 values[0] = 41
1218 assert lib.my_value == 41 # [0]
1219 p = ffi.addressof(lib, 'my_value') # [1]
1220 assert p == values + 1
1221 assert p[-1] == 41
1222 assert p[+1] == 0
1223 lib.my_value = 42 # [2]
1224 assert values[2] == 42
1225 assert p[-1] == 41
1226 assert p[+1] == 42
1227 #
1228 # if get_my_value raises or returns nonsense, the exception is printed
1229 # to stderr like with any callback, but then the C expression 'my_value'
1230 # expand to '*NULL'. We assume here that '&my_value' will return NULL
1231 # without segfaulting, and check for NULL when accessing the variable.
1232 @ffi.callback("int *(*)(void)")
1233 def get_my_value():
1234 raise LookupError
1235 lib.get_my_value = get_my_value
1236 py.test.raises(ffi.error, getattr, lib, 'my_value')
1237 py.test.raises(ffi.error, setattr, lib, 'my_value', 50)
1238 py.test.raises(ffi.error, ffi.addressof, lib, 'my_value')
1239 @ffi.callback("int *(*)(void)")
1240 def get_my_value():
1241 return "hello"
1242 lib.get_my_value = get_my_value
1243 py.test.raises(ffi.error, getattr, lib, 'my_value')
1244 e = py.test.raises(ffi.error, setattr, lib, 'my_value', 50)
1245 assert str(e.value) == "global variable 'my_value' is at address NULL"
1246
1247 def test_const_fields():
1248 ffi = FFI()
1249 ffi.cdef("""struct foo_s { const int a; void *const b; };""")
1250 lib = verify(ffi, 'test_const_fields', """
1251 struct foo_s { const int a; void *const b; };""")
1252 foo_s = ffi.typeof("struct foo_s")
1253 assert foo_s.fields[0][0] == 'a'
1254 assert foo_s.fields[0][1].type is ffi.typeof("int")
1255 assert foo_s.fields[1][0] == 'b'
1256 assert foo_s.fields[1][1].type is ffi.typeof("void *")
1257
1258 def test_restrict_fields():
1259 ffi = FFI()
1260 ffi.cdef("""struct foo_s { void * restrict b; };""")
1261 lib = verify(ffi, 'test_restrict_fields', """
1262 struct foo_s { void * __restrict b; };""")
1263 foo_s = ffi.typeof("struct foo_s")
1264 assert foo_s.fields[0][0] == 'b'
1265 assert foo_s.fields[0][1].type is ffi.typeof("void *")
1266
1267 def test_volatile_fields():
1268 ffi = FFI()
1269 ffi.cdef("""struct foo_s { void * volatile b; };""")
1270 lib = verify(ffi, 'test_volatile_fields', """
1271 struct foo_s { void * volatile b; };""")
1272 foo_s = ffi.typeof("struct foo_s")
1273 assert foo_s.fields[0][0] == 'b'
1274 assert foo_s.fields[0][1].type is ffi.typeof("void *")
1275
1276 def test_const_array_fields():
1277 ffi = FFI()
1278 ffi.cdef("""struct foo_s { const int a[4]; };""")
1279 lib = verify(ffi, 'test_const_array_fields', """
1280 struct foo_s { const int a[4]; };""")
1281 foo_s = ffi.typeof("struct foo_s")
1282 assert foo_s.fields[0][0] == 'a'
1283 assert foo_s.fields[0][1].type is ffi.typeof("int[4]")
1284
1285 def test_const_array_fields_varlength():
1286 ffi = FFI()
1287 ffi.cdef("""struct foo_s { const int a[]; ...; };""")
1288 lib = verify(ffi, 'test_const_array_fields_varlength', """
1289 struct foo_s { const int a[4]; };""")
1290 foo_s = ffi.typeof("struct foo_s")
1291 assert foo_s.fields[0][0] == 'a'
1292 assert foo_s.fields[0][1].type is ffi.typeof("int[]")
1293
1294 def test_const_array_fields_unknownlength():
1295 ffi = FFI()
1296 ffi.cdef("""struct foo_s { const int a[...]; ...; };""")
1297 lib = verify(ffi, 'test_const_array_fields_unknownlength', """
1298 struct foo_s { const int a[4]; };""")
1299 foo_s = ffi.typeof("struct foo_s")
1300 assert foo_s.fields[0][0] == 'a'
1301 assert foo_s.fields[0][1].type is ffi.typeof("int[4]")
1302
1303 def test_const_function_args():
1304 ffi = FFI()
1305 ffi.cdef("""int foobar(const int a, const int *b, const int c[]);""")
1306 lib = verify(ffi, 'test_const_function_args', """
1307 int foobar(const int a, const int *b, const int c[]) {
1308 return a + *b + *c;
1309 }
1310 """)
1311 assert lib.foobar(100, ffi.new("int *", 40), ffi.new("int *", 2)) == 142
1312
1313 def test_const_function_type_args():
1314 ffi = FFI()
1315 ffi.cdef("""int (*foobar)(const int a, const int *b, const int c[]);""")
1316 lib = verify(ffi, 'test_const_function_type_args', """
1317 int (*foobar)(const int a, const int *b, const int c[]);
1318 """)
1319 t = ffi.typeof(lib.foobar)
1320 assert t.args[0] is ffi.typeof("int")
1321 assert t.args[1] is ffi.typeof("int *")
1322 assert t.args[2] is ffi.typeof("int *")
1323
1324 def test_const_constant():
1325 ffi = FFI()
1326 ffi.cdef("""struct foo_s { int x,y; }; const struct foo_s myfoo;""")
1327 lib = verify(ffi, 'test_const_constant', """
1328 struct foo_s { int x,y; }; const struct foo_s myfoo = { 40, 2 };
1329 """)
1330 assert lib.myfoo.x == 40
1331 assert lib.myfoo.y == 2
1332
1333 def test_const_via_typedef():
1334 ffi = FFI()
1335 ffi.cdef("""typedef const int const_t; const_t aaa;""")
1336 lib = verify(ffi, 'test_const_via_typedef', """
1337 typedef const int const_t;
1338 #define aaa 42
1339 """)
1340 assert lib.aaa == 42
1341 py.test.raises(AttributeError, "lib.aaa = 43")
1342
1343 def test_win32_calling_convention_0():
1344 ffi = FFI()
1345 ffi.cdef("""
1346 int call1(int(__cdecl *cb)(int));
1347 int (*const call2)(int(__stdcall *cb)(int));
1348 """)
1349 lib = verify(ffi, 'test_win32_calling_convention_0', r"""
1350 #ifndef _MSC_VER
1351 # define __stdcall /* nothing */
1352 #endif
1353 int call1(int(*cb)(int)) {
1354 int i, result = 0;
1355 //printf("call1: cb = %p\n", cb);
1356 for (i = 0; i < 1000; i++)
1357 result += cb(i);
1358 //printf("result = %d\n", result);
1359 return result;
1360 }
1361 int call2(int(__stdcall *cb)(int)) {
1362 int i, result = 0;
1363 //printf("call2: cb = %p\n", cb);
1364 for (i = 0; i < 1000; i++)
1365 result += cb(-i);
1366 //printf("result = %d\n", result);
1367 return result;
1368 }
1369 """)
1370 @ffi.callback("int(int)")
1371 def cb1(x):
1372 return x * 2
1373 @ffi.callback("int __stdcall(int)")
1374 def cb2(x):
1375 return x * 3
1376 res = lib.call1(cb1)
1377 assert res == 500*999*2
1378 assert res == ffi.addressof(lib, 'call1')(cb1)
1379 res = lib.call2(cb2)
1380 assert res == -500*999*3
1381 assert res == ffi.addressof(lib, 'call2')(cb2)
1382 if sys.platform == 'win32' and not sys.maxsize > 2**32:
1383 assert '__stdcall' in str(ffi.typeof(cb2))
1384 assert '__stdcall' not in str(ffi.typeof(cb1))
1385 py.test.raises(TypeError, lib.call1, cb2)
1386 py.test.raises(TypeError, lib.call2, cb1)
1387 else:
1388 assert '__stdcall' not in str(ffi.typeof(cb2))
1389 assert ffi.typeof(cb2) is ffi.typeof(cb1)
1390
1391 def test_win32_calling_convention_1():
1392 ffi = FFI()
1393 ffi.cdef("""
1394 int __cdecl call1(int(__cdecl *cb)(int));
1395 int __stdcall call2(int(__stdcall *cb)(int));
1396 int (__cdecl *const cb1)(int);
1397 int (__stdcall *const cb2)(int);
1398 """)
1399 lib = verify(ffi, 'test_win32_calling_convention_1', r"""
1400 #ifndef _MSC_VER
1401 # define __cdecl
1402 # define __stdcall
1403 #endif
1404 int __cdecl cb1(int x) { return x * 2; }
1405 int __stdcall cb2(int x) { return x * 3; }
1406
1407 int __cdecl call1(int(__cdecl *cb)(int)) {
1408 int i, result = 0;
1409 //printf("here1\n");
1410 //printf("cb = %p, cb1 = %p\n", cb, (void *)cb1);
1411 for (i = 0; i < 1000; i++)
1412 result += cb(i);
1413 //printf("result = %d\n", result);
1414 return result;
1415 }
1416 int __stdcall call2(int(__stdcall *cb)(int)) {
1417 int i, result = 0;
1418 //printf("here1\n");
1419 //printf("cb = %p, cb2 = %p\n", cb, (void *)cb2);
1420 for (i = 0; i < 1000; i++)
1421 result += cb(-i);
1422 //printf("result = %d\n", result);
1423 return result;
1424 }
1425 """)
1426 #print '<<< cb1 =', ffi.addressof(lib, 'cb1')
1427 ptr_call1 = ffi.addressof(lib, 'call1')
1428 assert lib.call1(ffi.addressof(lib, 'cb1')) == 500*999*2
1429 assert ptr_call1(ffi.addressof(lib, 'cb1')) == 500*999*2
1430 #print '<<< cb2 =', ffi.addressof(lib, 'cb2')
1431 ptr_call2 = ffi.addressof(lib, 'call2')
1432 assert lib.call2(ffi.addressof(lib, 'cb2')) == -500*999*3
1433 assert ptr_call2(ffi.addressof(lib, 'cb2')) == -500*999*3
1434 #print '<<< done'
1435
1436 def test_win32_calling_convention_2():
1437 # any mistake in the declaration of plain function (including the
1438 # precise argument types and, here, the calling convention) are
1439 # automatically corrected. But this does not apply to the 'cb'
1440 # function pointer argument.
1441 ffi = FFI()
1442 ffi.cdef("""
1443 int __stdcall call1(int(__cdecl *cb)(int));
1444 int __cdecl call2(int(__stdcall *cb)(int));
1445 int (__cdecl *const cb1)(int);
1446 int (__stdcall *const cb2)(int);
1447 """)
1448 lib = verify(ffi, 'test_win32_calling_convention_2', """
1449 #ifndef _MSC_VER
1450 # define __cdecl
1451 # define __stdcall
1452 #endif
1453 int __cdecl call1(int(__cdecl *cb)(int)) {
1454 int i, result = 0;
1455 for (i = 0; i < 1000; i++)
1456 result += cb(i);
1457 return result;
1458 }
1459 int __stdcall call2(int(__stdcall *cb)(int)) {
1460 int i, result = 0;
1461 for (i = 0; i < 1000; i++)
1462 result += cb(-i);
1463 return result;
1464 }
1465 int __cdecl cb1(int x) { return x * 2; }
1466 int __stdcall cb2(int x) { return x * 3; }
1467 """)
1468 ptr_call1 = ffi.addressof(lib, 'call1')
1469 ptr_call2 = ffi.addressof(lib, 'call2')
1470 if sys.platform == 'win32' and not sys.maxsize > 2**32:
1471 py.test.raises(TypeError, lib.call1, ffi.addressof(lib, 'cb2'))
1472 py.test.raises(TypeError, ptr_call1, ffi.addressof(lib, 'cb2'))
1473 py.test.raises(TypeError, lib.call2, ffi.addressof(lib, 'cb1'))
1474 py.test.raises(TypeError, ptr_call2, ffi.addressof(lib, 'cb1'))
1475 assert lib.call1(ffi.addressof(lib, 'cb1')) == 500*999*2
1476 assert ptr_call1(ffi.addressof(lib, 'cb1')) == 500*999*2
1477 assert lib.call2(ffi.addressof(lib, 'cb2')) == -500*999*3
1478 assert ptr_call2(ffi.addressof(lib, 'cb2')) == -500*999*3
1479
1480 def test_win32_calling_convention_3():
1481 ffi = FFI()
1482 ffi.cdef("""
1483 struct point { int x, y; };
1484
1485 int (*const cb1)(struct point);
1486 int (__stdcall *const cb2)(struct point);
1487
1488 struct point __stdcall call1(int(*cb)(struct point));
1489 struct point call2(int(__stdcall *cb)(struct point));
1490 """)
1491 lib = verify(ffi, 'test_win32_calling_convention_3', r"""
1492 #ifndef _MSC_VER
1493 # define __cdecl
1494 # define __stdcall
1495 #endif
1496 struct point { int x, y; };
1497 int cb1(struct point pt) { return pt.x + 10 * pt.y; }
1498 int __stdcall cb2(struct point pt) { return pt.x + 100 * pt.y; }
1499 struct point __stdcall call1(int(__cdecl *cb)(struct point)) {
1500 int i;
1501 struct point result = { 0, 0 };
1502 //printf("here1\n");
1503 //printf("cb = %p, cb1 = %p\n", cb, (void *)cb1);
1504 for (i = 0; i < 1000; i++) {
1505 struct point p = { i, -i };
1506 int r = cb(p);
1507 result.x += r;
1508 result.y -= r;
1509 }
1510 return result;
1511 }
1512 struct point __cdecl call2(int(__stdcall *cb)(struct point)) {
1513 int i;
1514 struct point result = { 0, 0 };
1515 for (i = 0; i < 1000; i++) {
1516 struct point p = { -i, i };
1517 int r = cb(p);
1518 result.x += r;
1519 result.y -= r;
1520 }
1521 return result;
1522 }
1523 """)
1524 ptr_call1 = ffi.addressof(lib, 'call1')
1525 ptr_call2 = ffi.addressof(lib, 'call2')
1526 if sys.platform == 'win32' and not sys.maxsize > 2**32:
1527 py.test.raises(TypeError, lib.call1, ffi.addressof(lib, 'cb2'))
1528 py.test.raises(TypeError, ptr_call1, ffi.addressof(lib, 'cb2'))
1529 py.test.raises(TypeError, lib.call2, ffi.addressof(lib, 'cb1'))
1530 py.test.raises(TypeError, ptr_call2, ffi.addressof(lib, 'cb1'))
1531 pt = lib.call1(ffi.addressof(lib, 'cb1'))
1532 assert (pt.x, pt.y) == (-9*500*999, 9*500*999)
1533 pt = ptr_call1(ffi.addressof(lib, 'cb1'))
1534 assert (pt.x, pt.y) == (-9*500*999, 9*500*999)
1535 pt = lib.call2(ffi.addressof(lib, 'cb2'))
1536 assert (pt.x, pt.y) == (99*500*999, -99*500*999)
1537 pt = ptr_call2(ffi.addressof(lib, 'cb2'))
1538 assert (pt.x, pt.y) == (99*500*999, -99*500*999)
1539
1540 def test_extern_python_1():
1541 ffi = FFI()
1542 ffi.cdef("""
1543 extern "Python" {
1544 int bar(int, int);
1545 void baz(int, int);
1546 int bok(void);
1547 void boz(void);
1548 }
1549 """)
1550 lib = verify(ffi, 'test_extern_python_1', """
1551 static void baz(int, int); /* forward */
1552 """)
1553 assert ffi.typeof(lib.bar) == ffi.typeof("int(*)(int, int)")
1554 with FdWriteCapture() as f:
1555 res = lib.bar(4, 5)
1556 assert res == 0
1557 assert f.getvalue() == (
1558 b"extern \"Python\": function _CFFI_test_extern_python_1.bar() called, "
1559 b"but no code was attached "
1560 b"to it yet with @ffi.def_extern(). Returning 0.\n")
1561
1562 @ffi.def_extern("bar")
1563 def my_bar(x, y):
1564 seen.append(("Bar", x, y))
1565 return x * y
1566 assert my_bar != lib.bar
1567 seen = []
1568 res = lib.bar(6, 7)
1569 assert seen == [("Bar", 6, 7)]
1570 assert res == 42
1571
1572 def baz(x, y):
1573 seen.append(("Baz", x, y))
1574 baz1 = ffi.def_extern()(baz)
1575 assert baz1 is baz
1576 seen = []
1577 baz(long(40), long(4))
1578 res = lib.baz(long(50), long(8))
1579 assert res is None
1580 assert seen == [("Baz", 40, 4), ("Baz", 50, 8)]
1581 assert type(seen[0][1]) is type(seen[0][2]) is long
1582 assert type(seen[1][1]) is type(seen[1][2]) is int
1583
1584 @ffi.def_extern(name="bok")
1585 def bokk():
1586 seen.append("Bok")
1587 return 42
1588 seen = []
1589 assert lib.bok() == 42
1590 assert seen == ["Bok"]
1591
1592 @ffi.def_extern()
1593 def boz():
1594 seen.append("Boz")
1595 seen = []
1596 assert lib.boz() is None
1597 assert seen == ["Boz"]
1598
1599 def test_extern_python_bogus_name():
1600 ffi = FFI()
1601 ffi.cdef("int abc;")
1602 lib = verify(ffi, 'test_extern_python_bogus_name', "int abc;")
1603 def fn():
1604 pass
1605 py.test.raises(ffi.error, ffi.def_extern("unknown_name"), fn)
1606 py.test.raises(ffi.error, ffi.def_extern("abc"), fn)
1607 assert lib.abc == 0
1608 e = py.test.raises(ffi.error, ffi.def_extern("abc"), fn)
1609 assert str(e.value) == ("ffi.def_extern('abc'): no 'extern \"Python\"' "
1610 "function with this name")
1611 e = py.test.raises(ffi.error, ffi.def_extern(), fn)
1612 assert str(e.value) == ("ffi.def_extern('fn'): no 'extern \"Python\"' "
1613 "function with this name")
1614 #
1615 py.test.raises(TypeError, ffi.def_extern(42), fn)
1616 py.test.raises((TypeError, AttributeError), ffi.def_extern(), "foo")
1617 class X:
1618 pass
1619 x = X()
1620 x.__name__ = x
1621 py.test.raises(TypeError, ffi.def_extern(), x)
1622
1623 def test_extern_python_bogus_result_type():
1624 ffi = FFI()
1625 ffi.cdef("""extern "Python" void bar(int);""")
1626 lib = verify(ffi, 'test_extern_python_bogus_result_type', "")
1627 #
1628 @ffi.def_extern()
1629 def bar(n):
1630 return n * 10
1631 with StdErrCapture() as f:
1632 res = lib.bar(321)
1633 assert res is None
1634 assert f.getvalue() == (
1635 "From cffi callback %r:\n" % (bar,) +
1636 "Trying to convert the result back to C:\n"
1637 "TypeError: callback with the return type 'void' must return None\n")
1638
1639 def test_extern_python_redefine():
1640 ffi = FFI()
1641 ffi.cdef("""extern "Python" int bar(int);""")
1642 lib = verify(ffi, 'test_extern_python_redefine', "")
1643 #
1644 @ffi.def_extern()
1645 def bar(n):
1646 return n * 10
1647 assert lib.bar(42) == 420
1648 #
1649 @ffi.def_extern()
1650 def bar(n):
1651 return -n
1652 assert lib.bar(42) == -42
1653
1654 def test_extern_python_struct():
1655 ffi = FFI()
1656 ffi.cdef("""
1657 struct foo_s { int a, b, c; };
1658 extern "Python" int bar(int, struct foo_s, int);
1659 extern "Python" { struct foo_s baz(int, int);
1660 struct foo_s bok(void); }
1661 """)
1662 lib = verify(ffi, 'test_extern_python_struct',
1663 "struct foo_s { int a, b, c; };")
1664 #
1665 @ffi.def_extern()
1666 def bar(x, s, z):
1667 return x + s.a + s.b + s.c + z
1668 res = lib.bar(1000, [1001, 1002, 1004], 1008)
1669 assert res == 5015
1670 #
1671 @ffi.def_extern()
1672 def baz(x, y):
1673 return [x + y, x - y, x * y]
1674 res = lib.baz(1000, 42)
1675 assert res.a == 1042
1676 assert res.b == 958
1677 assert res.c == 42000
1678 #
1679 @ffi.def_extern()
1680 def bok():
1681 return [10, 20, 30]
1682 res = lib.bok()
1683 assert [res.a, res.b, res.c] == [10, 20, 30]
1684
1685 def test_extern_python_long_double():
1686 ffi = FFI()
1687 ffi.cdef("""
1688 extern "Python" int bar(int, long double, int);
1689 extern "Python" long double baz(int, int);
1690 extern "Python" long double bok(void);
1691 """)
1692 lib = verify(ffi, 'test_extern_python_long_double', "")
1693 #
1694 @ffi.def_extern()
1695 def bar(x, l, z):
1696 seen.append((x, l, z))
1697 return 6
1698 seen = []
1699 lib.bar(10, 3.5, 20)
1700 expected = ffi.cast("long double", 3.5)
1701 assert repr(seen) == repr([(10, expected, 20)])
1702 #
1703 @ffi.def_extern()
1704 def baz(x, z):
1705 assert x == 10 and z == 20
1706 return expected
1707 res = lib.baz(10, 20)
1708 assert repr(res) == repr(expected)
1709 #
1710 @ffi.def_extern()
1711 def bok():
1712 return expected
1713 res = lib.bok()
1714 assert repr(res) == repr(expected)
1715
1716 def test_extern_python_signature():
1717 ffi = FFI()
1718 lib = verify(ffi, 'test_extern_python_signature', "")
1719 py.test.raises(TypeError, ffi.def_extern(425), None)
1720 py.test.raises(TypeError, ffi.def_extern, 'a', 'b', 'c', 'd')
1721
1722 def test_extern_python_errors():
1723 ffi = FFI()
1724 ffi.cdef("""
1725 extern "Python" int bar(int);
1726 """)
1727 lib = verify(ffi, 'test_extern_python_errors', "")
1728
1729 seen = []
1730 def oops(*args):
1731 seen.append(args)
1732
1733 @ffi.def_extern(onerror=oops)
1734 def bar(x):
1735 return x + ""
1736 assert lib.bar(10) == 0
1737
1738 @ffi.def_extern(name="bar", onerror=oops, error=-66)
1739 def bar2(x):
1740 return x + ""
1741 assert lib.bar(10) == -66
1742
1743 assert len(seen) == 2
1744 exc, val, tb = seen[0]
1745 assert exc is TypeError
1746 assert isinstance(val, TypeError)
1747 assert tb.tb_frame.f_code.co_name == "bar"
1748 exc, val, tb = seen[1]
1749 assert exc is TypeError
1750 assert isinstance(val, TypeError)
1751 assert tb.tb_frame.f_code.co_name == "bar2"
1752 #
1753 # a case where 'onerror' is not callable
1754 py.test.raises(TypeError, ffi.def_extern(name='bar', onerror=42),
1755 lambda x: x)
1756
1757 def test_extern_python_stdcall():
1758 ffi = FFI()
1759 ffi.cdef("""
1760 extern "Python" int __stdcall foo(int);
1761 extern "Python" int WINAPI bar(int);
1762 int (__stdcall * mycb1)(int);
1763 int indirect_call(int);
1764 """)
1765 lib = verify(ffi, 'test_extern_python_stdcall', """
1766 #ifndef _MSC_VER
1767 # define __stdcall
1768 #endif
1769 static int (__stdcall * mycb1)(int);
1770 static int indirect_call(int x) {
1771 return mycb1(x);
1772 }
1773 """)
1774 #
1775 @ffi.def_extern()
1776 def foo(x):
1777 return x + 42
1778 @ffi.def_extern()
1779 def bar(x):
1780 return x + 43
1781 assert lib.foo(100) == 142
1782 assert lib.bar(100) == 143
1783 lib.mycb1 = lib.foo
1784 assert lib.mycb1(200) == 242
1785 assert lib.indirect_call(300) == 342
1786
1787 def test_extern_python_plus_c():
1788 ffi = FFI()
1789 ffi.cdef("""
1790 extern "Python+C" int foo(int);
1791 extern "C +\tPython" int bar(int);
1792 int call_me(int);
1793 """)
1794 lib = verify(ffi, 'test_extern_python_plus_c', """
1795 int foo(int);
1796 #ifdef __GNUC__
1797 __attribute__((visibility("hidden")))
1798 #endif
1799 int bar(int);
1800
1801 static int call_me(int x) {
1802 return foo(x) - bar(x);
1803 }
1804 """)
1805 #
1806 @ffi.def_extern()
1807 def foo(x):
1808 return x * 42
1809 @ffi.def_extern()
1810 def bar(x):
1811 return x * 63
1812 assert lib.foo(100) == 4200
1813 assert lib.bar(100) == 6300
1814 assert lib.call_me(100) == -2100
1815
1816 def test_introspect_function():
1817 ffi = FFI()
1818 ffi.cdef("float f1(double);")
1819 lib = verify(ffi, 'test_introspect_function', """
1820 float f1(double x) { return x; }
1821 """)
1822 assert dir(lib) == ['f1']
1823 FUNC = ffi.typeof(lib.f1)
1824 assert FUNC.kind == 'function'
1825 assert FUNC.args[0].cname == 'double'
1826 assert FUNC.result.cname == 'float'
1827 assert ffi.typeof(ffi.addressof(lib, 'f1')) is FUNC
1828
1829 def test_introspect_global_var():
1830 ffi = FFI()
1831 ffi.cdef("float g1;")
1832 lib = verify(ffi, 'test_introspect_global_var', """
1833 float g1;
1834 """)
1835 assert dir(lib) == ['g1']
1836 FLOATPTR = ffi.typeof(ffi.addressof(lib, 'g1'))
1837 assert FLOATPTR.kind == 'pointer'
1838 assert FLOATPTR.item.cname == 'float'
1839
1840 def test_introspect_global_var_array():
1841 ffi = FFI()
1842 ffi.cdef("float g1[100];")
1843 lib = verify(ffi, 'test_introspect_global_var_array', """
1844 float g1[100];
1845 """)
1846 assert dir(lib) == ['g1']
1847 FLOATARRAYPTR = ffi.typeof(ffi.addressof(lib, 'g1'))
1848 assert FLOATARRAYPTR.kind == 'pointer'
1849 assert FLOATARRAYPTR.item.kind == 'array'
1850 assert FLOATARRAYPTR.item.length == 100
1851 assert ffi.typeof(lib.g1) is FLOATARRAYPTR.item
1852
1853 def test_introspect_integer_const():
1854 ffi = FFI()
1855 ffi.cdef("#define FOO 42")
1856 lib = verify(ffi, 'test_introspect_integer_const', """
1857 #define FOO 42
1858 """)
1859 assert dir(lib) == ['FOO']
1860 assert lib.FOO == ffi.integer_const('FOO') == 42
1861
1862 def test_introspect_typedef():
1863 ffi = FFI()
1864 ffi.cdef("typedef int foo_t;")
1865 lib = verify(ffi, 'test_introspect_typedef', """
1866 typedef int foo_t;
1867 """)
1868 assert ffi.list_types() == (['foo_t'], [], [])
1869 assert ffi.typeof('foo_t').kind == 'primitive'
1870 assert ffi.typeof('foo_t').cname == 'int'
1871
1872 def test_introspect_typedef_multiple():
1873 ffi = FFI()
1874 ffi.cdef("typedef signed char a_t, c_t, g_t, b_t;")
1875 lib = verify(ffi, 'test_introspect_typedef_multiple', """
1876 typedef signed char a_t, c_t, g_t, b_t;
1877 """)
1878 assert ffi.list_types() == (['a_t', 'b_t', 'c_t', 'g_t'], [], [])
1879
1880 def test_introspect_struct():
1881 ffi = FFI()
1882 ffi.cdef("struct foo_s { int a; };")
1883 lib = verify(ffi, 'test_introspect_struct', """
1884 struct foo_s { int a; };
1885 """)
1886 assert ffi.list_types() == ([], ['foo_s'], [])
1887 assert ffi.typeof('struct foo_s').kind == 'struct'
1888 assert ffi.typeof('struct foo_s').cname == 'struct foo_s'
1889
1890 def test_introspect_union():
1891 ffi = FFI()
1892 ffi.cdef("union foo_s { int a; };")
1893 lib = verify(ffi, 'test_introspect_union', """
1894 union foo_s { int a; };
1895 """)
1896 assert ffi.list_types() == ([], [], ['foo_s'])
1897 assert ffi.typeof('union foo_s').kind == 'union'
1898 assert ffi.typeof('union foo_s').cname == 'union foo_s'
1899
1900 def test_introspect_struct_and_typedef():
1901 ffi = FFI()
1902 ffi.cdef("typedef struct { int a; } foo_t;")
1903 lib = verify(ffi, 'test_introspect_struct_and_typedef', """
1904 typedef struct { int a; } foo_t;
1905 """)
1906 assert ffi.list_types() == (['foo_t'], [], [])
1907 assert ffi.typeof('foo_t').kind == 'struct'
1908 assert ffi.typeof('foo_t').cname == 'foo_t'
1909
1910 def test_introspect_included_type():
1911 SOURCE = """
1912 typedef signed char schar_t;
1913 struct sint_t { int x; };
1914 """
1915 ffi1 = FFI()
1916 ffi1.cdef(SOURCE)
1917 ffi2 = FFI()
1918 ffi2.include(ffi1)
1919 verify(ffi1, "test_introspect_included_type_parent", SOURCE)
1920 verify(ffi2, "test_introspect_included_type", SOURCE)
1921 assert ffi1.list_types() == ffi2.list_types() == (
1922 ['schar_t'], ['sint_t'], [])
1923
1924 def test_introspect_order():
1925 ffi = FFI()
1926 ffi.cdef("union CFFIaaa { int a; }; typedef struct CFFIccc { int a; } CFFIb;")
1927 ffi.cdef("union CFFIg { int a; }; typedef struct CFFIcc { int a; } CFFIbbb;")
1928 ffi.cdef("union CFFIaa { int a; }; typedef struct CFFIa { int a; } CFFIbb;")
1929 verify(ffi, "test_introspect_order", """
1930 union CFFIaaa { int a; }; typedef struct CFFIccc { int a; } CFFIb;
1931 union CFFIg { int a; }; typedef struct CFFIcc { int a; } CFFIbbb;
1932 union CFFIaa { int a; }; typedef struct CFFIa { int a; } CFFIbb;
1933 """)
1934 assert ffi.list_types() == (['CFFIb', 'CFFIbb', 'CFFIbbb'],
1935 ['CFFIa', 'CFFIcc', 'CFFIccc'],
1936 ['CFFIaa', 'CFFIaaa', 'CFFIg'])
1937
1938 def test_bool_in_cpp():
1939 # this works when compiled as C, but in cffi < 1.7 it fails as C++
1940 ffi = FFI()
1941 ffi.cdef("bool f(void);")
1942 lib = verify(ffi, "test_bool_in_cpp", "char f(void) { return 2; }")
1943 assert lib.f() is True
1944
1945 def test_bool_in_cpp_2():
1946 ffi = FFI()
1947 ffi.cdef('int add(int a, int b);')
1948 lib = verify(ffi, "test_bool_bug_cpp", '''
1949 typedef bool _Bool; /* there is a Windows header with this line */
1950 int add(int a, int b)
1951 {
1952 return a + b;
1953 }''', source_extension='.cpp')
1954 c = lib.add(2, 3)
1955 assert c == 5
1956
1957 def test_struct_field_opaque():
1958 ffi = FFI()
1959 ffi.cdef("struct a { struct b b; };")
1960 e = py.test.raises(TypeError, verify,
1961 ffi, "test_struct_field_opaque", "?")
1962 assert str(e.value) == ("struct a: field 'a.b' is of an opaque"
1963 " type (not declared in cdef())")
1964 ffi = FFI()
1965 ffi.cdef("struct a { struct b b[2]; };")
1966 e = py.test.raises(TypeError, verify,
1967 ffi, "test_struct_field_opaque", "?")
1968 assert str(e.value) == ("struct a: field 'a.b' is of an opaque"
1969 " type (not declared in cdef())")
1970 ffi = FFI()
1971 ffi.cdef("struct a { struct b b[]; };")
1972 e = py.test.raises(TypeError, verify,
1973 ffi, "test_struct_field_opaque", "?")
1974 assert str(e.value) == ("struct a: field 'a.b' is of an opaque"
1975 " type (not declared in cdef())")
1976
1977 def test_function_arg_opaque():
1978 py.test.skip("can currently declare a function with an opaque struct "
1979 "as argument, but AFAICT it's impossible to call it later")
1980
1981 def test_function_returns_opaque():
1982 ffi = FFI()
1983 ffi.cdef("struct a foo(int);")
1984 e = py.test.raises(TypeError, verify,
1985 ffi, "test_function_returns_opaque", "?")
1986 assert str(e.value) == ("function foo: 'struct a' is used as result type,"
1987 " but is opaque")
1988
1989 def test_function_returns_union():
1990 ffi = FFI()
1991 ffi.cdef("union u1 { int a, b; }; union u1 f1(int);")
1992 lib = verify(ffi, "test_function_returns_union", """
1993 union u1 { int a, b; };
1994 static union u1 f1(int x) { union u1 u; u.b = x; return u; }
1995 """)
1996 assert lib.f1(51).a == 51
1997
1998 def test_function_returns_partial_struct():
1999 ffi = FFI()
2000 ffi.cdef("struct aaa { int a; ...; }; struct aaa f1(int);")
2001 lib = verify(ffi, "test_function_returns_partial_struct", """
2002 struct aaa { int b, a, c; };
2003 static struct aaa f1(int x) { struct aaa s = {0}; s.a = x; return s; }
2004 """)
2005 assert lib.f1(52).a == 52
2006
2007 def test_function_returns_float_complex():
2008 if sys.platform == 'win32':
2009 py.test.skip("MSVC may not support _Complex")
2010 ffi = FFI()
2011 ffi.cdef("float _Complex f1(float a, float b);");
2012 lib = verify(ffi, "test_function_returns_float_complex", """
2013 #include <complex.h>
2014 static float _Complex f1(float a, float b) { return a + I*2.0*b; }
2015 """, no_cpp=True) # <complex.h> fails on some systems with C++
2016 result = lib.f1(1.25, 5.1)
2017 assert type(result) == complex
2018 assert result.real == 1.25 # exact
2019 assert (result.imag != 2*5.1) and (abs(result.imag - 2*5.1) < 1e-5) # inexact
2020
2021 def test_function_returns_double_complex():
2022 if sys.platform == 'win32':
2023 py.test.skip("MSVC may not support _Complex")
2024 ffi = FFI()
2025 ffi.cdef("double _Complex f1(double a, double b);");
2026 lib = verify(ffi, "test_function_returns_double_complex", """
2027 #include <complex.h>
2028 static double _Complex f1(double a, double b) { return a + I*2.0*b; }
2029 """, no_cpp=True) # <complex.h> fails on some systems with C++
2030 result = lib.f1(1.25, 5.1)
2031 assert type(result) == complex
2032 assert result.real == 1.25 # exact
2033 assert result.imag == 2*5.1 # exact
2034
2035 def test_function_argument_float_complex():
2036 if sys.platform == 'win32':
2037 py.test.skip("MSVC may not support _Complex")
2038 ffi = FFI()
2039 ffi.cdef("float f1(float _Complex x);");
2040 lib = verify(ffi, "test_function_argument_float_complex", """
2041 #include <complex.h>
2042 static float f1(float _Complex x) { return cabsf(x); }
2043 """, no_cpp=True) # <complex.h> fails on some systems with C++
2044 x = complex(12.34, 56.78)
2045 result = lib.f1(x)
2046 assert abs(result - abs(x)) < 1e-5
2047
2048 def test_function_argument_double_complex():
2049 if sys.platform == 'win32':
2050 py.test.skip("MSVC may not support _Complex")
2051 ffi = FFI()
2052 ffi.cdef("double f1(double _Complex);");
2053 lib = verify(ffi, "test_function_argument_double_complex", """
2054 #include <complex.h>
2055 static double f1(double _Complex x) { return cabs(x); }
2056 """, no_cpp=True) # <complex.h> fails on some systems with C++
2057 x = complex(12.34, 56.78)
2058 result = lib.f1(x)
2059 assert abs(result - abs(x)) < 1e-11
2060
2061 def test_typedef_array_dotdotdot():
2062 ffi = FFI()
2063 ffi.cdef("""
2064 typedef int foo_t[...], bar_t[...];
2065 int gv[...];
2066 typedef int mat_t[...][...];
2067 typedef int vmat_t[][...];
2068 """)
2069 lib = verify(ffi, "test_typedef_array_dotdotdot", """
2070 typedef int foo_t[50], bar_t[50];
2071 int gv[23];
2072 typedef int mat_t[6][7];
2073 typedef int vmat_t[][8];
2074 """)
2075 assert ffi.sizeof("foo_t") == 50 * ffi.sizeof("int")
2076 assert ffi.sizeof("bar_t") == 50 * ffi.sizeof("int")
2077 assert len(ffi.new("foo_t")) == 50
2078 assert len(ffi.new("bar_t")) == 50
2079 assert ffi.sizeof(lib.gv) == 23 * ffi.sizeof("int")
2080 assert ffi.sizeof("mat_t") == 6 * 7 * ffi.sizeof("int")
2081 assert len(ffi.new("mat_t")) == 6
2082 assert len(ffi.new("mat_t")[3]) == 7
2083 py.test.raises(ffi.error, ffi.sizeof, "vmat_t")
2084 p = ffi.new("vmat_t", 4)
2085 assert ffi.sizeof(p[3]) == 8 * ffi.sizeof("int")
2086
2087 def test_call_with_custom_field_pos():
2088 ffi = FFI()
2089 ffi.cdef("""
2090 struct foo { int x; ...; };
2091 struct foo f(void);
2092 struct foo g(int, ...);
2093 """)
2094 lib = verify(ffi, "test_call_with_custom_field_pos", """
2095 struct foo { int y, x; };
2096 struct foo f(void) {
2097 struct foo s = { 40, 200 };
2098 return s;
2099 }
2100 struct foo g(int a, ...) { return f(); }
2101 """)
2102 assert lib.f().x == 200
2103 e = py.test.raises(NotImplementedError, lib.g, 0)
2104 assert str(e.value) == (
2105 'ctype \'struct foo\' not supported as return value. It is a '
2106 'struct declared with "...;", but the C calling convention may '
2107 'depend on the missing fields; or, it contains anonymous '
2108 'struct/unions. Such structs are only supported '
2109 'as return value if the function is \'API mode\' and non-variadic '
2110 '(i.e. declared inside ffibuilder.cdef()+ffibuilder.set_source() '
2111 'and not taking a final \'...\' argument)')
2112
2113 def test_call_with_nested_anonymous_struct():
2114 if sys.platform == 'win32':
2115 py.test.skip("needs a GCC extension")
2116 ffi = FFI()
2117 ffi.cdef("""
2118 struct foo { int a; union { int b, c; }; };
2119 struct foo f(void);
2120 struct foo g(int, ...);
2121 """)
2122 lib = verify(ffi, "test_call_with_nested_anonymous_struct", """
2123 struct foo { int a; union { int b, c; }; };
2124 struct foo f(void) {
2125 struct foo s = { 40 };
2126 s.b = 200;
2127 return s;
2128 }
2129 struct foo g(int a, ...) { return f(); }
2130 """)
2131 assert lib.f().b == 200
2132 e = py.test.raises(NotImplementedError, lib.g, 0)
2133 assert str(e.value) == (
2134 'ctype \'struct foo\' not supported as return value. It is a '
2135 'struct declared with "...;", but the C calling convention may '
2136 'depend on the missing fields; or, it contains anonymous '
2137 'struct/unions. Such structs are only supported '
2138 'as return value if the function is \'API mode\' and non-variadic '
2139 '(i.e. declared inside ffibuilder.cdef()+ffibuilder.set_source() '
2140 'and not taking a final \'...\' argument)')
2141
2142 def test_call_with_bitfield():
2143 ffi = FFI()
2144 ffi.cdef("""
2145 struct foo { int x:5; };
2146 struct foo f(void);
2147 struct foo g(int, ...);
2148 """)
2149 lib = verify(ffi, "test_call_with_bitfield", """
2150 struct foo { int x:5; };
2151 struct foo f(void) {
2152 struct foo s = { 11 };
2153 return s;
2154 }
2155 struct foo g(int a, ...) { return f(); }
2156 """)
2157 assert lib.f().x == 11
2158 e = py.test.raises(NotImplementedError, lib.g, 0)
2159 assert str(e.value) == (
2160 "ctype 'struct foo' not supported as return value. It is a struct "
2161 "with bit fields, which libffi does not support. Such structs are "
2162 "only supported as return value if the function is 'API mode' and "
2163 "non-variadic (i.e. declared inside ffibuilder.cdef()+ffibuilder."
2164 "set_source() and not taking a final '...' argument)")
2165
2166 def test_call_with_zero_length_field():
2167 if sys.platform == 'win32':
2168 py.test.skip("zero-length field not supported by MSVC")
2169 ffi = FFI()
2170 ffi.cdef("""
2171 struct foo { int a; int x[0]; };
2172 struct foo f(void);
2173 struct foo g(int, ...);
2174 """)
2175 lib = verify(ffi, "test_call_with_zero_length_field", """
2176 struct foo { int a; int x[0]; };
2177 struct foo f(void) {
2178 struct foo s = { 42 };
2179 return s;
2180 }
2181 struct foo g(int a, ...) { return f(); }
2182 """)
2183 assert lib.f().a == 42
2184 e = py.test.raises(NotImplementedError, lib.g, 0)
2185 assert str(e.value) == (
2186 "ctype 'struct foo' not supported as return value. It is a "
2187 "struct with a zero-length array, which libffi does not support."
2188 " Such structs are only supported as return value if the function is "
2189 "'API mode' and non-variadic (i.e. declared inside ffibuilder.cdef()"
2190 "+ffibuilder.set_source() and not taking a final '...' argument)")
2191
2192 def test_call_with_union():
2193 ffi = FFI()
2194 ffi.cdef("""
2195 union foo { int a; char b; };
2196 union foo f(void);
2197 union foo g(int, ...);
2198 """)
2199 lib = verify(ffi, "test_call_with_union", """
2200 union foo { int a; char b; };
2201 union foo f(void) {
2202 union foo s = { 42 };
2203 return s;
2204 }
2205 union foo g(int a, ...) { return f(); }
2206 """)
2207 assert lib.f().a == 42
2208 e = py.test.raises(NotImplementedError, lib.g, 0)
2209 assert str(e.value) == (
2210 "ctype 'union foo' not supported as return value by libffi. "
2211 "Unions are only supported as return value if the function is "
2212 "'API mode' and non-variadic (i.e. declared inside ffibuilder.cdef()"
2213 "+ffibuilder.set_source() and not taking a final '...' argument)")
2214
2215 def test_call_with_packed_struct():
2216 if sys.platform == 'win32':
2217 py.test.skip("needs a GCC extension")
2218 ffi = FFI()
2219 ffi.cdef("""
2220 struct foo { char y; int x; };
2221 struct foo f(void);
2222 struct foo g(int, ...);
2223 """, packed=True)
2224 lib = verify(ffi, "test_call_with_packed_struct", """
2225 struct foo { char y; int x; } __attribute__((packed));
2226 struct foo f(void) {
2227 struct foo s = { 40, 200 };
2228 return s;
2229 }
2230 struct foo g(int a, ...) {
2231 struct foo s = { 41, 201 };
2232 return s;
2233 }
2234 """)
2235 assert ord(lib.f().y) == 40
2236 assert lib.f().x == 200
2237 e = py.test.raises(NotImplementedError, lib.g, 0)
2238 assert str(e.value) == (
2239 "ctype 'struct foo' not supported as return value. It is a "
2240 "'packed' structure, with a different layout than expected by libffi."
2241 " Such structs are only supported as return value if the function is "
2242 "'API mode' and non-variadic (i.e. declared inside ffibuilder.cdef()"
2243 "+ffibuilder.set_source() and not taking a final '...' argument)")
2244
2245 def test_gcc_visibility_hidden():
2246 if sys.platform == 'win32':
2247 py.test.skip("test for gcc/clang")
2248 ffi = FFI()
2249 ffi.cdef("""
2250 int f(int);
2251 """)
2252 lib = verify(ffi, "test_gcc_visibility_hidden", """
2253 int f(int a) { return a + 40; }
2254 """, extra_compile_args=['-fvisibility=hidden'])
2255 assert lib.f(2) == 42
2256
2257 def test_override_default_definition():
2258 ffi = FFI()
2259 ffi.cdef("typedef long int16_t, char16_t;")
2260 lib = verify(ffi, "test_override_default_definition", "")
2261 assert ffi.typeof("int16_t") is ffi.typeof("char16_t") is ffi.typeof("long")
2262
2263 def test_char16_char32_type(no_cpp=False):
2264 if no_cpp is False and sys.platform == "win32":
2265 py.test.skip("aaaaaaa why do modern MSVC compilers still define "
2266 "a very old __cplusplus value")
2267 ffi = FFI()
2268 ffi.cdef("""
2269 char16_t foo_2bytes(char16_t);
2270 char32_t foo_4bytes(char32_t);
2271 """)
2272 lib = verify(ffi, "test_char16_char32_type" + no_cpp * "_nocpp", """
2273 #if !defined(__cplusplus) || (!defined(_LIBCPP_VERSION) && __cplusplus < 201103L)
2274 typedef uint_least16_t char16_t;
2275 typedef uint_least32_t char32_t;
2276 #endif
2277
2278 char16_t foo_2bytes(char16_t a) { return (char16_t)(a + 42); }
2279 char32_t foo_4bytes(char32_t a) { return (char32_t)(a + 42); }
2280 """, no_cpp=no_cpp)
2281 assert lib.foo_2bytes(u+'\u1234') == u+'\u125e'
2282 assert lib.foo_4bytes(u+'\u1234') == u+'\u125e'
2283 assert lib.foo_4bytes(u+'\U00012345') == u+'\U0001236f'
2284 py.test.raises(TypeError, lib.foo_2bytes, u+'\U00012345')
2285 py.test.raises(TypeError, lib.foo_2bytes, 1234)
2286 py.test.raises(TypeError, lib.foo_4bytes, 1234)
2287
2288 def test_char16_char32_plain_c():
2289 test_char16_char32_type(no_cpp=True)
2290
2291 def test_loader_spec():
2292 ffi = FFI()
2293 lib = verify(ffi, "test_loader_spec", "")
2294 if sys.version_info < (3,):
2295 assert not hasattr(lib, '__loader__')
2296 assert not hasattr(lib, '__spec__')
2297 else:
2298 assert lib.__loader__ is None
2299 assert lib.__spec__ is None
2300
2301 def test_realize_struct_error():
2302 ffi = FFI()
2303 ffi.cdef("""typedef ... foo_t; struct foo_s { void (*x)(foo_t); };""")
2304 lib = verify(ffi, "test_realize_struct_error", """
2305 typedef int foo_t; struct foo_s { void (*x)(foo_t); };
2306 """)
2307 py.test.raises(TypeError, ffi.new, "struct foo_s *")
+0
-44
pypy/module/test_lib_pypy/cffi_tests/cffi1/test_unicode_literals.py less more
0 # Generated by pypy/tool/import_cffi.py
1 #
2 # ----------------------------------------------
3 # WARNING, ALL LITERALS IN THIS FILE ARE UNICODE
4 # ----------------------------------------------
5 #
6 from __future__ import unicode_literals
7 #
8 #
9 #
10 from _cffi_backend import FFI
11
12
13 def test_cast():
14 ffi = FFI()
15 assert int(ffi.cast("int", 3.14)) == 3 # unicode literal
16
17 def test_new():
18 ffi = FFI()
19 assert ffi.new("int[]", [3, 4, 5])[2] == 5 # unicode literal
20
21 def test_typeof():
22 ffi = FFI()
23 tp = ffi.typeof("int[51]") # unicode literal
24 assert tp.length == 51
25
26 def test_sizeof():
27 ffi = FFI()
28 assert ffi.sizeof("int[51]") == 51 * 4 # unicode literal
29
30 def test_alignof():
31 ffi = FFI()
32 assert ffi.alignof("int[51]") == 4 # unicode literal
33
34 def test_getctype():
35 ffi = FFI()
36 assert ffi.getctype("int**") == "int * *" # unicode literal
37 assert type(ffi.getctype("int**")) is str
38
39 def test_callback():
40 ffi = FFI()
41 cb = ffi.callback("int(int)", # unicode literal
42 lambda x: x + 42)
43 assert cb(5) == 47
+0
-2364
pypy/module/test_lib_pypy/cffi_tests/cffi1/test_verify1.py less more
0 # Generated by pypy/tool/import_cffi.py
1 import os, sys, math, py
2 from cffi import FFI, FFIError, VerificationError, VerificationMissing, model
3 from cffi import CDefError
4 from cffi import recompiler
5 from pypy.module.test_lib_pypy.cffi_tests.support import *
6 import _cffi_backend
7
8 lib_m = ['m']
9 if sys.platform == 'win32':
10 #there is a small chance this fails on Mingw via environ $CC
11 import distutils.ccompiler
12 if distutils.ccompiler.get_default_compiler() == 'msvc':
13 lib_m = ['msvcrt']
14 extra_compile_args = [] # no obvious -Werror equivalent on MSVC
15 else:
16 if (sys.platform == 'darwin' and
17 [int(x) for x in os.uname()[2].split('.')] >= [11, 0, 0]):
18 # assume a standard clang or gcc
19 extra_compile_args = ['-Werror', '-Wall', '-Wextra', '-Wconversion']
20 # special things for clang
21 extra_compile_args.append('-Qunused-arguments')
22 else:
23 # assume a standard gcc
24 extra_compile_args = ['-Werror', '-Wall', '-Wextra', '-Wconversion']
25
26 class FFI(FFI):
27 error = _cffi_backend.FFI.error
28 _extra_compile_args = extra_compile_args
29 _verify_counter = 0
30
31 def verify(self, preamble='', *args, **kwds):
32 # HACK to reuse the tests from ../cffi0/test_verify.py
33 FFI._verify_counter += 1
34 module_name = 'verify%d' % FFI._verify_counter
35 try:
36 del self._assigned_source
37 except AttributeError:
38 pass
39 self.set_source(module_name, preamble)
40 return recompiler._verify(self, module_name, preamble, *args,
41 extra_compile_args=self._extra_compile_args,
42 **kwds)
43
44 class FFI_warnings_not_error(FFI):
45 _extra_compile_args = []
46
47
48 def test_missing_function(ffi=None):
49 # uses the FFI hacked above with '-Werror'
50 if ffi is None:
51 ffi = FFI()
52 ffi.cdef("void some_completely_unknown_function();")
53 try:
54 lib = ffi.verify()
55 except (VerificationError, OSError, ImportError):
56 pass # expected case: we get a VerificationError
57 else:
58 # but depending on compiler and loader details, maybe
59 # 'lib' could actually be imported but will fail if we
60 # actually try to call the unknown function... Hard
61 # to test anything more.
62 pass
63
64 def test_missing_function_import_error():
65 # uses the original FFI that just gives a warning during compilation
66 test_missing_function(ffi=FFI_warnings_not_error())
67
68 def test_simple_case():
69 ffi = FFI()
70 ffi.cdef("double sin(double x);")
71 lib = ffi.verify('#include <math.h>', libraries=lib_m)
72 assert lib.sin(1.23) == math.sin(1.23)
73
74 def _Wconversion(cdef, source, **kargs):
75 if sys.platform in ('win32', 'darwin'):
76 py.test.skip("needs GCC")
77 ffi = FFI()
78 ffi.cdef(cdef)
79 py.test.raises(VerificationError, ffi.verify, source, **kargs)
80 extra_compile_args_orig = extra_compile_args[:]
81 extra_compile_args.remove('-Wconversion')
82 try:
83 lib = ffi.verify(source, **kargs)
84 finally:
85 extra_compile_args[:] = extra_compile_args_orig
86 return lib
87
88 def test_Wconversion_unsigned():
89 _Wconversion("unsigned foo(void);",
90 "int foo(void) { return -1;}")
91
92 def test_Wconversion_integer():
93 _Wconversion("short foo(void);",
94 "long long foo(void) { return 1<<sizeof(short);}")
95
96 def test_Wconversion_floating():
97 lib = _Wconversion("float sin(double);",
98 "#include <math.h>", libraries=lib_m)
99 res = lib.sin(1.23)
100 assert res != math.sin(1.23) # not exact, because of double->float
101 assert abs(res - math.sin(1.23)) < 1E-5
102
103 def test_Wconversion_float2int():
104 _Wconversion("int sinf(float);",
105 "#include <math.h>", libraries=lib_m)
106
107 def test_Wconversion_double2int():
108 _Wconversion("int sin(double);",
109 "#include <math.h>", libraries=lib_m)
110
111 def test_rounding_1():
112 ffi = FFI()
113 ffi.cdef("double sinf(float x);")
114 lib = ffi.verify('#include <math.h>', libraries=lib_m)
115 res = lib.sinf(1.23)
116 assert res != math.sin(1.23) # not exact, because of double->float
117 assert abs(res - math.sin(1.23)) < 1E-5
118
119 def test_rounding_2():
120 ffi = FFI()
121 ffi.cdef("double sin(float x);")
122 lib = ffi.verify('#include <math.h>', libraries=lib_m)
123 res = lib.sin(1.23)
124 assert res != math.sin(1.23) # not exact, because of double->float
125 assert abs(res - math.sin(1.23)) < 1E-5
126
127 def test_strlen_exact():
128 ffi = FFI()
129 ffi.cdef("size_t strlen(const char *s);")
130 lib = ffi.verify("#include <string.h>")
131 assert lib.strlen(b"hi there!") == 9
132
133 def test_strlen_approximate():
134 lib = _Wconversion("int strlen(char *s);",
135 "#include <string.h>")
136 assert lib.strlen(b"hi there!") == 9
137
138 def test_return_approximate():
139 for typename in ['short', 'int', 'long', 'long long']:
140 ffi = FFI()
141 ffi.cdef("%s foo(signed char x);" % typename)
142 lib = ffi.verify("signed char foo(signed char x) { return x;}")
143 assert lib.foo(-128) == -128
144 assert lib.foo(+127) == +127
145
146 def test_strlen_array_of_char():
147 ffi = FFI()
148 ffi.cdef("size_t strlen(char[]);")
149 lib = ffi.verify("#include <string.h>")
150 assert lib.strlen(b"hello") == 5
151
152 def test_longdouble():
153 ffi = FFI()
154 ffi.cdef("long double sinl(long double x);")
155 lib = ffi.verify('#include <math.h>', libraries=lib_m)
156 for input in [1.23,
157 ffi.cast("double", 1.23),
158 ffi.cast("long double", 1.23)]:
159 x = lib.sinl(input)
160 assert repr(x).startswith("<cdata 'long double'")
161 assert (float(x) - math.sin(1.23)) < 1E-10
162
163 def test_longdouble_precision():
164 # Test that we don't loose any precision of 'long double' when
165 # passing through Python and CFFI.
166 ffi = FFI()
167 ffi.cdef("long double step1(long double x);")
168 SAME_SIZE = ffi.sizeof("long double") == ffi.sizeof("double")
169 lib = ffi.verify("""
170 long double step1(long double x)
171 {
172 return 4*x-x*x;
173 }
174 """)
175 def do(cast_to_double):
176 x = 0.9789
177 for i in range(10000):
178 x = lib.step1(x)
179 if cast_to_double:
180 x = float(x)
181 return float(x)
182
183 more_precise = do(False)
184 less_precise = do(True)
185 if SAME_SIZE:
186 assert more_precise == less_precise
187 else:
188 assert abs(more_precise - less_precise) > 0.1
189 # Check the particular results on Intel
190 import platform
191 if (platform.machine().startswith('i386') or
192 platform.machine().startswith('i486') or
193 platform.machine().startswith('i586') or
194 platform.machine().startswith('i686') or
195 platform.machine().startswith('x86')):
196 assert abs(more_precise - 0.656769) < 0.001
197 assert abs(less_precise - 3.99091) < 0.001
198 else:
199 py.test.skip("don't know the very exact precision of 'long double'")
200
201
202 all_primitive_types = model.PrimitiveType.ALL_PRIMITIVE_TYPES
203 if sys.platform == 'win32':
204 all_primitive_types = all_primitive_types.copy()
205 del all_primitive_types['ssize_t']
206 all_integer_types = sorted(tp for tp in all_primitive_types
207 if all_primitive_types[tp] == 'i')
208 all_float_types = sorted(tp for tp in all_primitive_types
209 if all_primitive_types[tp] == 'f')
210
211 def all_signed_integer_types(ffi):
212 return [x for x in all_integer_types if int(ffi.cast(x, -1)) < 0]
213
214 def all_unsigned_integer_types(ffi):
215 return [x for x in all_integer_types if int(ffi.cast(x, -1)) > 0]
216
217
218 def test_primitive_category():
219 for typename in all_primitive_types:
220 tp = model.PrimitiveType(typename)
221 C = tp.is_char_type()
222 F = tp.is_float_type()
223 X = tp.is_complex_type()
224 I = tp.is_integer_type()
225 assert C == (typename in ('char', 'wchar_t', 'char16_t', 'char32_t'))
226 assert F == (typename in ('float', 'double', 'long double'))
227 assert X == (typename in ('float _Complex', 'double _Complex'))
228 assert I + F + C + X == 1 # one and only one of them is true
229
230 def test_all_integer_and_float_types():
231 typenames = []
232 for typename in all_primitive_types:
233 if (all_primitive_types[typename] == 'c' or
234 all_primitive_types[typename] == 'j' or # complex
235 typename == '_Bool' or typename == 'long double'):
236 pass
237 else:
238 typenames.append(typename)
239 #
240 ffi = FFI()
241 ffi.cdef('\n'.join(["%s foo_%s(%s);" % (tp, tp.replace(' ', '_'), tp)
242 for tp in typenames]))
243 lib = ffi.verify('\n'.join(["%s foo_%s(%s x) { return (%s)(x+1); }" %
244 (tp, tp.replace(' ', '_'), tp, tp)
245 for tp in typenames]))
246 for typename in typenames:
247 foo = getattr(lib, 'foo_%s' % typename.replace(' ', '_'))
248 assert foo(42) == 43
249 if sys.version < '3':
250 assert foo(long(44)) == 45
251 assert foo(ffi.cast(typename, 46)) == 47
252 py.test.raises(TypeError, foo, ffi.NULL)
253 #
254 # check for overflow cases
255 if all_primitive_types[typename] == 'f':
256 continue
257 for value in [-2**80, -2**40, -2**20, -2**10, -2**5, -1,
258 2**5, 2**10, 2**20, 2**40, 2**80]:
259 overflows = int(ffi.cast(typename, value)) != value
260 if overflows:
261 py.test.raises(OverflowError, foo, value)
262 else:
263 assert foo(value) == value + 1
264
265 def test_var_signed_integer_types():
266 ffi = FFI()
267 lst = all_signed_integer_types(ffi)
268 csource = "\n".join(["%s somevar_%s;" % (tp, tp.replace(' ', '_'))
269 for tp in lst])
270 ffi.cdef(csource)
271 lib = ffi.verify(csource)
272 for tp in lst:
273 varname = 'somevar_%s' % tp.replace(' ', '_')
274 sz = ffi.sizeof(tp)
275 max = (1 << (8*sz-1)) - 1
276 min = -(1 << (8*sz-1))
277 setattr(lib, varname, max)
278 assert getattr(lib, varname) == max
279 setattr(lib, varname, min)
280 assert getattr(lib, varname) == min
281 py.test.raises(OverflowError, setattr, lib, varname, max+1)
282 py.test.raises(OverflowError, setattr, lib, varname, min-1)
283
284 def test_var_unsigned_integer_types():
285 ffi = FFI()
286 lst = all_unsigned_integer_types(ffi)
287 csource = "\n".join(["%s somevar_%s;" % (tp, tp.replace(' ', '_'))
288 for tp in lst])
289 ffi.cdef(csource)
290 lib = ffi.verify(csource)
291 for tp in lst:
292 varname = 'somevar_%s' % tp.replace(' ', '_')
293 sz = ffi.sizeof(tp)
294 if tp != '_Bool':
295 max = (1 << (8*sz)) - 1
296 else:
297 max = 1
298 setattr(lib, varname, max)
299 assert getattr(lib, varname) == max
300 setattr(lib, varname, 0)
301 assert getattr(lib, varname) == 0
302 py.test.raises(OverflowError, setattr, lib, varname, max+1)
303 py.test.raises(OverflowError, setattr, lib, varname, -1)
304
305 def test_fn_signed_integer_types():
306 ffi = FFI()
307 lst = all_signed_integer_types(ffi)
308 cdefsrc = "\n".join(["%s somefn_%s(%s);" % (tp, tp.replace(' ', '_'), tp)
309 for tp in lst])
310 ffi.cdef(cdefsrc)
311 verifysrc = "\n".join(["%s somefn_%s(%s x) { return x; }" %
312 (tp, tp.replace(' ', '_'), tp) for tp in lst])
313 lib = ffi.verify(verifysrc)
314 for tp in lst:
315 fnname = 'somefn_%s' % tp.replace(' ', '_')
316 sz = ffi.sizeof(tp)
317 max = (1 << (8*sz-1)) - 1
318 min = -(1 << (8*sz-1))
319 fn = getattr(lib, fnname)
320 assert fn(max) == max
321 assert fn(min) == min
322 py.test.raises(OverflowError, fn, max + 1)
323 py.test.raises(OverflowError, fn, min - 1)
324
325 def test_fn_unsigned_integer_types():
326 ffi = FFI()
327 lst = all_unsigned_integer_types(ffi)
328 cdefsrc = "\n".join(["%s somefn_%s(%s);" % (tp, tp.replace(' ', '_'), tp)
329 for tp in lst])
330 ffi.cdef(cdefsrc)
331 verifysrc = "\n".join(["%s somefn_%s(%s x) { return x; }" %
332 (tp, tp.replace(' ', '_'), tp) for tp in lst])
333 lib = ffi.verify(verifysrc)
334 for tp in lst:
335 fnname = 'somefn_%s' % tp.replace(' ', '_')
336 sz = ffi.sizeof(tp)
337 if tp != '_Bool':
338 max = (1 << (8*sz)) - 1
339 else:
340 max = 1
341 fn = getattr(lib, fnname)
342 assert fn(max) == max
343 assert fn(0) == 0
344 py.test.raises(OverflowError, fn, max + 1)
345 py.test.raises(OverflowError, fn, -1)
346
347 def test_char_type():
348 ffi = FFI()
349 ffi.cdef("char foo(char);")
350 lib = ffi.verify("char foo(char x) { return ++x; }")
351 assert lib.foo(b"A") == b"B"
352 py.test.raises(TypeError, lib.foo, b"bar")
353 py.test.raises(TypeError, lib.foo, "bar")
354
355 def test_wchar_type():
356 ffi = FFI()
357 if ffi.sizeof('wchar_t') == 2:
358 uniexample1 = u+'\u1234'
359 uniexample2 = u+'\u1235'
360 else:
361 uniexample1 = u+'\U00012345'
362 uniexample2 = u+'\U00012346'
363 #
364 ffi.cdef("wchar_t foo(wchar_t);")
365 lib = ffi.verify("wchar_t foo(wchar_t x) { return x+1; }")
366 assert lib.foo(uniexample1) == uniexample2
367
368 def test_no_argument():
369 ffi = FFI()
370 ffi.cdef("int foo(void);")
371 lib = ffi.verify("int foo(void) { return 42; }")
372 assert lib.foo() == 42
373
374 def test_two_arguments():
375 ffi = FFI()
376 ffi.cdef("int foo(int, int);")
377 lib = ffi.verify("int foo(int a, int b) { return a - b; }")
378 assert lib.foo(40, -2) == 42
379
380 def test_macro():
381 ffi = FFI()
382 ffi.cdef("int foo(int, int);")
383 lib = ffi.verify("#define foo(a, b) ((a) * (b))")
384 assert lib.foo(-6, -7) == 42
385
386 def test_ptr():
387 ffi = FFI()
388 ffi.cdef("int *foo(int *);")
389 lib = ffi.verify("int *foo(int *a) { return a; }")
390 assert lib.foo(ffi.NULL) == ffi.NULL
391 p = ffi.new("int *", 42)
392 q = ffi.new("int *", 42)
393 assert lib.foo(p) == p
394 assert lib.foo(q) != p
395
396 def test_bogus_ptr():
397 ffi = FFI()
398 ffi.cdef("int *foo(int *);")
399 lib = ffi.verify("int *foo(int *a) { return a; }")
400 py.test.raises(TypeError, lib.foo, ffi.new("short *", 42))
401
402
403 def test_verify_typedefs():
404 py.test.skip("ignored so far")
405 types = ['signed char', 'unsigned char', 'int', 'long']
406 for cdefed in types:
407 for real in types:
408 ffi = FFI()
409 ffi.cdef("typedef %s foo_t;" % cdefed)
410 if cdefed == real:
411 ffi.verify("typedef %s foo_t;" % real)
412 else:
413 py.test.raises(VerificationError, ffi.verify,
414 "typedef %s foo_t;" % real)
415
416 def test_nondecl_struct():
417 ffi = FFI()
418 ffi.cdef("typedef struct foo_s foo_t; int bar(foo_t *);")
419 lib = ffi.verify("typedef struct foo_s foo_t;\n"
420 "int bar(foo_t *f) { (void)f; return 42; }\n")
421 assert lib.bar(ffi.NULL) == 42
422
423 def test_ffi_full_struct():
424 def check(verified_code):
425 ffi = FFI()
426 ffi.cdef("struct foo_s { char x; int y; long *z; };")
427 ffi.verify(verified_code)
428 ffi.new("struct foo_s *", {})
429
430 check("struct foo_s { char x; int y; long *z; };")
431 #
432 if sys.platform != 'win32': # XXX fixme: only gives warnings
433 py.test.raises(VerificationError, check,
434 "struct foo_s { char x; int y; int *z; };")
435 #
436 py.test.raises(VerificationError, check,
437 "struct foo_s { int y; long *z; };") # cdef'ed field x is missing
438 #
439 e = py.test.raises(FFI.error, check,
440 "struct foo_s { int y; char x; long *z; };")
441 assert str(e.value).startswith(
442 "struct foo_s: wrong offset for field 'x'"
443 " (cdef says 0, but C compiler says 4)")
444 #
445 e = py.test.raises(FFI.error, check,
446 "struct foo_s { char x; int y; long *z; char extra; };")
447 assert str(e.value).startswith(
448 "struct foo_s: wrong total size"
449 " (cdef says %d, but C compiler says %d)" % (
450 8 + FFI().sizeof('long *'),
451 8 + FFI().sizeof('long *') * 2))
452 #
453 # a corner case that we cannot really detect, but where it has no
454 # bad consequences: the size is the same, but there is an extra field
455 # that replaces what is just padding in our declaration above
456 check("struct foo_s { char x, extra; int y; long *z; };")
457 #
458 e = py.test.raises(FFI.error, check,
459 "struct foo_s { char x; short pad; short y; long *z; };")
460 assert str(e.value).startswith(
461 "struct foo_s: wrong size for field 'y'"
462 " (cdef says 4, but C compiler says 2)")
463
464 def test_ffi_nonfull_struct():
465 ffi = FFI()
466 ffi.cdef("""
467 struct foo_s {
468 int x;
469 ...;
470 };
471 """)
472 py.test.raises(VerificationMissing, ffi.sizeof, 'struct foo_s')
473 py.test.raises(VerificationMissing, ffi.offsetof, 'struct foo_s', 'x')
474 py.test.raises(VerificationMissing, ffi.new, 'struct foo_s *')
475 ffi.verify("""
476 struct foo_s {
477 int a, b, x, c, d, e;
478 };
479 """)
480 assert ffi.sizeof('struct foo_s') == 6 * ffi.sizeof('int')
481 assert ffi.offsetof('struct foo_s', 'x') == 2 * ffi.sizeof('int')
482
483 def test_ffi_nonfull_alignment():
484 ffi = FFI()
485 ffi.cdef("struct foo_s { char x; ...; };")
486 ffi.verify("struct foo_s { int a, b; char x; };")
487 assert ffi.sizeof('struct foo_s') == 3 * ffi.sizeof('int')
488 assert ffi.alignof('struct foo_s') == ffi.sizeof('int')
489
490 def _check_field_match(typename, real, expect_mismatch):
491 ffi = FFI()
492 testing_by_size = (expect_mismatch == 'by_size')
493 if testing_by_size:
494 expect_mismatch = ffi.sizeof(typename) != ffi.sizeof(real)
495 ffi.cdef("struct foo_s { %s x; ...; };" % typename)
496 try:
497 ffi.verify("struct foo_s { %s x; };" % real)
498 ffi.new("struct foo_s *", []) # because some mismatches show up lazily
499 except (VerificationError, ffi.error):
500 if not expect_mismatch:
501 if testing_by_size and typename != real:
502 print("ignoring mismatch between %s* and %s* even though "
503 "they have the same size" % (typename, real))
504 return
505 raise AssertionError("unexpected mismatch: %s should be accepted "
506 "as equal to %s" % (typename, real))
507 else:
508 if expect_mismatch:
509 raise AssertionError("mismatch not detected: "
510 "%s != %s" % (typename, real))
511
512 def test_struct_bad_sized_integer():
513 for typename in ['int8_t', 'int16_t', 'int32_t', 'int64_t']:
514 for real in ['int8_t', 'int16_t', 'int32_t', 'int64_t']:
515 _check_field_match(typename, real, "by_size")
516
517 def test_struct_bad_sized_float():
518 for typename in all_float_types:
519 for real in all_float_types:
520 _check_field_match(typename, real, "by_size")
521
522 def test_struct_signedness_ignored():
523 _check_field_match("int", "unsigned int", expect_mismatch=False)
524 _check_field_match("unsigned short", "signed short", expect_mismatch=False)
525
526 def test_struct_float_vs_int():
527 if sys.platform == 'win32':
528 py.test.skip("XXX fixme: only gives warnings")
529 ffi = FFI()
530 for typename in all_signed_integer_types(ffi):
531 for real in all_float_types:
532 _check_field_match(typename, real, expect_mismatch=True)
533 for typename in all_float_types:
534 for real in all_signed_integer_types(ffi):
535 _check_field_match(typename, real, expect_mismatch=True)
536
537 def test_struct_array_field():
538 ffi = FFI()
539 ffi.cdef("struct foo_s { int a[17]; ...; };")
540 ffi.verify("struct foo_s { int x; int a[17]; int y; };")
541 assert ffi.sizeof('struct foo_s') == 19 * ffi.sizeof('int')
542 s = ffi.new("struct foo_s *")
543 assert ffi.sizeof(s.a) == 17 * ffi.sizeof('int')
544
545 def test_struct_array_no_length():
546 ffi = FFI()
547 ffi.cdef("struct foo_s { int a[]; int y; ...; };\n"
548 "int bar(struct foo_s *);\n")
549 lib = ffi.verify("struct foo_s { int x; int a[17]; int y; };\n"
550 "int bar(struct foo_s *f) { return f->a[14]; }\n")
551 assert ffi.sizeof('struct foo_s') == 19 * ffi.sizeof('int')
552 s = ffi.new("struct foo_s *")
553 assert ffi.typeof(s.a) is ffi.typeof('int[]') # implicit max length
554 assert len(s.a) == 18 # max length, computed from the size and start offset
555 s.a[14] = 4242
556 assert lib.bar(s) == 4242
557 # with no declared length, out-of-bound accesses are not detected
558 s.a[17] = -521
559 assert s.y == s.a[17] == -521
560 #
561 s = ffi.new("struct foo_s *", {'a': list(range(17))})
562 assert s.a[16] == 16
563 # overflows at construction time not detected either
564 s = ffi.new("struct foo_s *", {'a': list(range(18))})
565 assert s.y == s.a[17] == 17
566
567 def test_struct_array_guess_length():
568 ffi = FFI()
569 ffi.cdef("struct foo_s { int a[...]; };")
570 ffi.verify("struct foo_s { int x; int a[17]; int y; };")
571 assert ffi.sizeof('struct foo_s') == 19 * ffi.sizeof('int')
572 s = ffi.new("struct foo_s *")
573 assert ffi.sizeof(s.a) == 17 * ffi.sizeof('int')
574 py.test.raises(IndexError, 's.a[17]')
575
576 def test_struct_array_c99_1():
577 if sys.platform == 'win32':
578 py.test.skip("requires C99")
579 ffi = FFI()
580 ffi.cdef("struct foo_s { int x; int a[]; };")
581 ffi.verify("struct foo_s { int x; int a[]; };")
582 assert ffi.sizeof('struct foo_s') == 1 * ffi.sizeof('int')
583 s = ffi.new("struct foo_s *", [424242, 4])
584 assert ffi.sizeof(ffi.typeof(s[0])) == 1 * ffi.sizeof('int')
585 assert ffi.sizeof(s[0]) == 5 * ffi.sizeof('int')
586 # ^^^ explanation: if you write in C: "char x[5];", then
587 # "sizeof(x)" will evaluate to 5. The behavior above is
588 # a generalization of that to "struct foo_s[len(a)=5] x;"
589 # if you could do that in C.
590 assert s.a[3] == 0
591 s = ffi.new("struct foo_s *", [424242, [-40, -30, -20, -10]])
592 assert ffi.sizeof(s[0]) == 5 * ffi.sizeof('int')
593 assert s.a[3] == -10
594 s = ffi.new("struct foo_s *")
595 assert ffi.sizeof(s[0]) == 1 * ffi.sizeof('int')
596 s = ffi.new("struct foo_s *", [424242])
597 assert ffi.sizeof(s[0]) == 1 * ffi.sizeof('int')
598
599 def test_struct_array_c99_2():
600 if sys.platform == 'win32':
601 py.test.skip("requires C99")
602 ffi = FFI()
603 ffi.cdef("struct foo_s { int x; int a[]; ...; };")
604 ffi.verify("struct foo_s { int x, y; int a[]; };")
605 assert ffi.sizeof('struct foo_s') == 2 * ffi.sizeof('int')
606 s = ffi.new("struct foo_s *", [424242, 4])
607 assert ffi.sizeof(s[0]) == 6 * ffi.sizeof('int')
608 assert s.a[3] == 0
609 s = ffi.new("struct foo_s *", [424242, [-40, -30, -20, -10]])
610 assert ffi.sizeof(s[0]) == 6 * ffi.sizeof('int')
611 assert s.a[3] == -10
612 s = ffi.new("struct foo_s *")
613 assert ffi.sizeof(s[0]) == 2 * ffi.sizeof('int')
614 s = ffi.new("struct foo_s *", [424242])
615 assert ffi.sizeof(s[0]) == 2 * ffi.sizeof('int')
616
617 def test_struct_ptr_to_array_field():
618 ffi = FFI()
619 ffi.cdef("struct foo_s { int (*a)[17]; ...; }; struct bar_s { ...; };")
620 ffi.verify("struct foo_s { int x; int (*a)[17]; int y; };\n"
621 "struct bar_s { int x; int *a; int y; };")
622 assert ffi.sizeof('struct foo_s') == ffi.sizeof("struct bar_s")
623 s = ffi.new("struct foo_s *")
624 assert ffi.sizeof(s.a) == ffi.sizeof('int(*)[17]') == ffi.sizeof("int *")
625
626 def test_struct_with_bitfield_exact():
627 ffi = FFI()
628 ffi.cdef("struct foo_s { int a:2, b:3; };")
629 ffi.verify("struct foo_s { int a:2, b:3; };")
630 s = ffi.new("struct foo_s *")
631 s.b = 3
632 py.test.raises(OverflowError, "s.b = 4")
633 assert s.b == 3
634
635 def test_struct_with_bitfield_enum():
636 ffi = FFI()
637 code = """
638 typedef enum { AA, BB, CC } foo_e;
639 typedef struct { foo_e f:2; } foo_s;
640 """
641 ffi.cdef(code)
642 ffi.verify(code)
643 s = ffi.new("foo_s *")
644 s.f = 1
645 assert s.f == 1
646 if int(ffi.cast("foo_e", -1)) < 0:
647 two = -2
648 else:
649 two = 2
650 s.f = two
651 assert s.f == two
652
653 def test_unsupported_struct_with_bitfield_ellipsis():
654 ffi = FFI()
655 py.test.raises(NotImplementedError, ffi.cdef,
656 "struct foo_s { int a:2, b:3; ...; };")
657
658 def test_global_constants():
659 ffi = FFI()
660 # use 'static const int', as generally documented, although in this
661 # case the 'static' is completely ignored.
662 ffi.cdef("static const int AA, BB, CC, DD;")
663 lib = ffi.verify("#define AA 42\n"
664 "#define BB (-43) // blah\n"
665 "#define CC (22*2) /* foobar */\n"
666 "#define DD ((unsigned int)142) /* foo\nbar */\n")
667 assert lib.AA == 42
668 assert lib.BB == -43
669 assert lib.CC == 44
670 assert lib.DD == 142
671
672 def test_global_const_int_size():
673 # integer constants: ignore the declared type, always just use the value
674 for value in [-2**63, -2**31, -2**15,
675 2**15-1, 2**15, 2**31-1, 2**31, 2**32-1, 2**32,
676 2**63-1, 2**63, 2**64-1]:
677 ffi = FFI()
678 if value == int(ffi.cast("long long", value)):
679 if value < 0:
680 vstr = '(-%dLL-1)' % (~value,)
681 else:
682 vstr = '%dLL' % value
683 elif value == int(ffi.cast("unsigned long long", value)):
684 vstr = '%dULL' % value
685 else:
686 raise AssertionError(value)
687 ffi.cdef("static const unsigned short AA;")
688 lib = ffi.verify("#define AA %s\n" % vstr)
689 assert lib.AA == value
690 assert type(lib.AA) is type(int(lib.AA))
691
692 def test_global_constants_non_int():
693 ffi = FFI()
694 ffi.cdef("static char *const PP;")
695 lib = ffi.verify('static char *const PP = "testing!";\n')
696 assert ffi.typeof(lib.PP) == ffi.typeof("char *")
697 assert ffi.string(lib.PP) == b"testing!"
698
699 def test_nonfull_enum():
700 ffi = FFI()
701 ffi.cdef("enum ee { EE1, EE2, EE3, ... \n \t };")
702 py.test.raises(VerificationMissing, ffi.cast, 'enum ee', 'EE2')
703 ffi.verify("enum ee { EE1=10, EE2, EE3=-10, EE4 };")
704 assert ffi.string(ffi.cast('enum ee', 11)) == "EE2"
705 assert ffi.string(ffi.cast('enum ee', -10)) == "EE3"
706 #
707 assert ffi.typeof("enum ee").relements == {'EE1': 10, 'EE2': 11, 'EE3': -10}
708 assert ffi.typeof("enum ee").elements == {10: 'EE1', 11: 'EE2', -10: 'EE3'}
709
710 def test_full_enum():
711 ffi = FFI()
712 ffi.cdef("enum ee { EE1, EE2, EE3 };")
713 lib = ffi.verify("enum ee { EE1, EE2, EE3 };")
714 assert [lib.EE1, lib.EE2, lib.EE3] == [0, 1, 2]
715
716 def test_enum_usage():
717 ffi = FFI()
718 ffi.cdef("enum ee { EE1,EE2 }; typedef struct { enum ee x; } *sp;")
719 lib = ffi.verify("enum ee { EE1,EE2 }; typedef struct { enum ee x; } *sp;")
720 assert lib.EE2 == 1
721 s = ffi.new("sp", [lib.EE2])
722 assert s.x == 1
723 s.x = 17
724 assert s.x == 17
725
726 def test_anonymous_enum():
727 ffi = FFI()
728 ffi.cdef("enum { EE1 }; enum { EE2, EE3 };")
729 lib = ffi.verify("enum { EE1 }; enum { EE2, EE3 };")
730 assert lib.EE1 == 0
731 assert lib.EE2 == 0
732 assert lib.EE3 == 1
733
734 def test_nonfull_anonymous_enum():
735 ffi = FFI()
736 ffi.cdef("enum { EE1, ... }; enum { EE3, ... };")
737 lib = ffi.verify("enum { EE2, EE1 }; enum { EE3 };")
738 assert lib.EE1 == 1
739 assert lib.EE3 == 0
740
741 def test_nonfull_enum_syntax2():
742 ffi = FFI()
743 ffi.cdef("enum ee { EE1, EE2=\t..., EE3 };")
744 py.test.raises(VerificationMissing, ffi.cast, 'enum ee', 'EE1')
745 ffi.verify("enum ee { EE1=10, EE2, EE3=-10, EE4 };")
746 assert ffi.string(ffi.cast('enum ee', 11)) == 'EE2'
747 assert ffi.string(ffi.cast('enum ee', -10)) == 'EE3'
748 #
749 ffi = FFI()
750 ffi.cdef("enum ee { EE1, EE2=\t... };")
751 py.test.raises(VerificationMissing, ffi.cast, 'enum ee', 'EE1')
752 ffi.verify("enum ee { EE1=10, EE2, EE3=-10, EE4 };")
753 assert ffi.string(ffi.cast('enum ee', 11)) == 'EE2'
754 #
755 ffi = FFI()
756 ffi.cdef("enum ee2 { EE4=..., EE5=..., ... };")
757 ffi.verify("enum ee2 { EE4=-1234-5, EE5 }; ")
758 assert ffi.string(ffi.cast('enum ee2', -1239)) == 'EE4'
759 assert ffi.string(ffi.cast('enum ee2', -1238)) == 'EE5'
760
761 def test_get_set_errno():
762 ffi = FFI()
763 ffi.cdef("int foo(int);")
764 lib = ffi.verify("""
765 static int foo(int x)
766 {
767 errno += 1;
768 return x * 7;
769 }
770 """)
771 ffi.errno = 15
772 assert lib.foo(6) == 42
773 assert ffi.errno == 16
774
775 def test_define_int():
776 ffi = FFI()
777 ffi.cdef("#define FOO ...\n"
778 "\t#\tdefine\tBAR\t...\t\n"
779 "#define BAZ ...\n")
780 lib = ffi.verify("#define FOO 42\n"
781 "#define BAR (-44)\n"
782 "#define BAZ 0xffffffffffffffffULL\n")
783 assert lib.FOO == 42
784 assert lib.BAR == -44
785 assert lib.BAZ == 0xffffffffffffffff
786
787 def test_access_variable():
788 ffi = FFI()
789 ffi.cdef("int foo(void);\n"
790 "int somenumber;")
791 lib = ffi.verify("""
792 static int somenumber = 2;
793 static int foo(void) {
794 return somenumber * 7;
795 }
796 """)
797 assert lib.somenumber == 2
798 assert lib.foo() == 14
799 lib.somenumber = -6
800 assert lib.foo() == -42
801 assert lib.somenumber == -6
802 lib.somenumber = 2 # reset for the next run, if any
803
804 def test_access_address_of_variable():
805 # access the address of 'somenumber': need a trick
806 ffi = FFI()
807 ffi.cdef("int somenumber; static int *const somenumberptr;")
808 lib = ffi.verify("""
809 static int somenumber = 2;
810 #define somenumberptr (&somenumber)
811 """)
812 assert lib.somenumber == 2
813 lib.somenumberptr[0] = 42
814 assert lib.somenumber == 42
815 lib.somenumber = 2 # reset for the next run, if any
816
817 def test_access_array_variable(length=5):
818 ffi = FFI()
819 ffi.cdef("int foo(int);\n"
820 "int somenumber[%s];" % (length,))
821 lib = ffi.verify("""
822 static int somenumber[] = {2, 2, 3, 4, 5};
823 static int foo(int i) {
824 return somenumber[i] * 7;
825 }
826 """)
827 if length == '':
828 # a global variable of an unknown array length is implicitly
829 # transformed into a global pointer variable, because we can only
830 # work with array instances whose length we know. using a pointer
831 # instead of an array gives the correct effects.
832 assert repr(lib.somenumber).startswith("<cdata 'int *' 0x")
833 py.test.raises(TypeError, len, lib.somenumber)
834 else:
835 assert repr(lib.somenumber).startswith("<cdata 'int[%s]' 0x" % length)
836 assert len(lib.somenumber) == 5
837 assert lib.somenumber[3] == 4
838 assert lib.foo(3) == 28
839 lib.somenumber[3] = -6
840 assert lib.foo(3) == -42
841 assert lib.somenumber[3] == -6
842 assert lib.somenumber[4] == 5
843 lib.somenumber[3] = 4 # reset for the next run, if any
844
845 def test_access_array_variable_length_hidden():
846 test_access_array_variable(length='')
847
848 def test_access_struct_variable():
849 ffi = FFI()
850 ffi.cdef("struct foo { int x; ...; };\n"
851 "int foo(int);\n"
852 "struct foo stuff;")
853 lib = ffi.verify("""
854 struct foo { int x, y, z; };
855 static struct foo stuff = {2, 5, 8};
856 static int foo(int i) {
857 switch (i) {
858 case 0: return stuff.x * 7;
859 case 1: return stuff.y * 7;
860 case 2: return stuff.z * 7;
861 }
862 return -1;
863 }
864 """)
865 assert lib.stuff.x == 2
866 assert lib.foo(0) == 14
867 assert lib.foo(1) == 35
868 assert lib.foo(2) == 56
869 lib.stuff.x = -6
870 assert lib.foo(0) == -42
871 assert lib.foo(1) == 35
872 lib.stuff.x = 2 # reset for the next run, if any
873
874 def test_access_callback():
875 ffi = FFI()
876 ffi.cdef("int (*cb)(int);\n"
877 "int foo(int);\n"
878 "void reset_cb(void);")
879 lib = ffi.verify("""
880 static int g(int x) { return x * 7; }
881 static int (*cb)(int);
882 static int foo(int i) { return cb(i) - 1; }
883 static void reset_cb(void) { cb = g; }
884 """)
885 lib.reset_cb()
886 assert lib.foo(6) == 41
887 my_callback = ffi.callback("int(*)(int)", lambda n: n * 222)
888 lib.cb = my_callback
889 assert lib.foo(4) == 887
890
891 def test_access_callback_function_typedef():
892 ffi = FFI()
893 ffi.cdef("typedef int mycallback_t(int);\n"
894 "mycallback_t *cb;\n"
895 "int foo(int);\n"
896 "void reset_cb(void);")
897 lib = ffi.verify("""
898 static int g(int x) { return x * 7; }
899 static int (*cb)(int);
900 static int foo(int i) { return cb(i) - 1; }
901 static void reset_cb(void) { cb = g; }
902 """)
903 lib.reset_cb()
904 assert lib.foo(6) == 41
905 my_callback = ffi.callback("int(*)(int)", lambda n: n * 222)
906 lib.cb = my_callback
907 assert lib.foo(4) == 887
908
909 def test_call_with_struct_ptr():
910 ffi = FFI()
911 ffi.cdef("typedef struct { int x; ...; } foo_t; int foo(foo_t *);")
912 lib = ffi.verify("""
913 typedef struct { int y, x; } foo_t;
914 static int foo(foo_t *f) { return f->x * 7; }
915 """)
916 f = ffi.new("foo_t *")
917 f.x = 6
918 assert lib.foo(f) == 42
919
920 def test_unknown_type():
921 ffi = FFI()
922 ffi.cdef("""
923 typedef ... token_t;
924 int foo(token_t *);
925 #define TOKEN_SIZE ...
926 """)
927 lib = ffi.verify("""
928 typedef float token_t;
929 static int foo(token_t *tk) {
930 if (!tk)
931 return -42;
932 *tk += 1.601f;
933 return (int)*tk;
934 }
935 #define TOKEN_SIZE sizeof(token_t)
936 """)
937 # we cannot let ffi.new("token_t *") work, because we don't know ahead of
938 # time if it's ok to ask 'sizeof(token_t)' in the C code or not.
939 # See test_unknown_type_2. Workaround.
940 tkmem = ffi.new("char[]", lib.TOKEN_SIZE) # zero-initialized
941 tk = ffi.cast("token_t *", tkmem)
942 results = [lib.foo(tk) for i in range(6)]
943 assert results == [1, 3, 4, 6, 8, 9]
944 assert lib.foo(ffi.NULL) == -42
945
946 def test_unknown_type_2():
947 ffi = FFI()
948 ffi.cdef("typedef ... token_t;")
949 lib = ffi.verify("typedef struct token_s token_t;")
950 # assert did not crash, even though 'sizeof(token_t)' is not valid in C.
951
952 def test_unknown_type_3():
953 ffi = FFI()
954 ffi.cdef("""
955 typedef ... *token_p;
956 token_p foo(token_p);
957 """)
958 lib = ffi.verify("""
959 typedef struct _token_s *token_p;
960 token_p foo(token_p arg) {
961 if (arg)
962 return (token_p)0x12347;
963 else
964 return (token_p)0x12345;
965 }
966 """)
967 p = lib.foo(ffi.NULL)
968 assert int(ffi.cast("intptr_t", p)) == 0x12345
969 q = lib.foo(p)
970 assert int(ffi.cast("intptr_t", q)) == 0x12347
971
972 def test_varargs():
973 ffi = FFI()
974 ffi.cdef("int foo(int x, ...);")
975 lib = ffi.verify("""
976 int foo(int x, ...) {
977 va_list vargs;
978 va_start(vargs, x);
979 x -= va_arg(vargs, int);
980 x -= va_arg(vargs, int);
981 va_end(vargs);
982 return x;
983 }
984 """)
985 assert lib.foo(50, ffi.cast("int", 5), ffi.cast("int", 3)) == 42
986
987 def test_varargs_exact():
988 if sys.platform == 'win32':
989 py.test.skip("XXX fixme: only gives warnings")
990 ffi = FFI()
991 ffi.cdef("int foo(int x, ...);")
992 py.test.raises(VerificationError, ffi.verify, """
993 int foo(long long x, ...) {
994 return x;
995 }
996 """)
997
998 def test_varargs_struct():
999 ffi = FFI()
1000 ffi.cdef("struct foo_s { char a; int b; }; int foo(int x, ...);")
1001 lib = ffi.verify("""
1002 struct foo_s {
1003 char a; int b;
1004 };
1005 int foo(int x, ...) {
1006 va_list vargs;
1007 struct foo_s s;
1008 va_start(vargs, x);
1009 s = va_arg(vargs, struct foo_s);
1010 va_end(vargs);
1011 return s.a - s.b;
1012 }
1013 """)
1014 s = ffi.new("struct foo_s *", [b'B', 1])
1015 assert lib.foo(50, s[0]) == ord('A')
1016
1017 def test_autofilled_struct_as_argument():
1018 ffi = FFI()
1019 ffi.cdef("struct foo_s { long a; double b; ...; };\n"
1020 "int foo(struct foo_s);")
1021 lib = ffi.verify("""
1022 struct foo_s {
1023 double b;
1024 long a;
1025 };
1026 int foo(struct foo_s s) {
1027 return (int)s.a - (int)s.b;
1028 }
1029 """)
1030 s = ffi.new("struct foo_s *", [100, 1])
1031 assert lib.foo(s[0]) == 99
1032 assert lib.foo([100, 1]) == 99
1033
1034 def test_autofilled_struct_as_argument_dynamic():
1035 ffi = FFI()
1036 ffi.cdef("struct foo_s { long a; ...; };\n"
1037 "int (*foo)(struct foo_s);")
1038 lib = ffi.verify("""
1039 struct foo_s {
1040 double b;
1041 long a;
1042 };
1043 int foo1(struct foo_s s) {
1044 return (int)s.a - (int)s.b;
1045 }
1046 int (*foo)(struct foo_s s) = &foo1;
1047 """)
1048 e = py.test.raises(NotImplementedError, lib.foo, "?")
1049 msg = ("ctype 'struct foo_s' not supported as argument. It is a struct "
1050 'declared with "...;", but the C calling convention may depend on '
1051 "the missing fields; or, it contains anonymous struct/unions. "
1052 "Such structs are only supported as argument "
1053 "if the function is 'API mode' and non-variadic (i.e. declared "
1054 "inside ffibuilder.cdef()+ffibuilder.set_source() and not taking "
1055 "a final '...' argument)")
1056 assert str(e.value) == msg
1057
1058 def test_func_returns_struct():
1059 ffi = FFI()
1060 ffi.cdef("""
1061 struct foo_s { int aa, bb; };
1062 struct foo_s foo(int a, int b);
1063 """)
1064 lib = ffi.verify("""
1065 struct foo_s { int aa, bb; };
1066 struct foo_s foo(int a, int b) {
1067 struct foo_s r;
1068 r.aa = a*a;
1069 r.bb = b*b;
1070 return r;
1071 }
1072 """)
1073 s = lib.foo(6, 7)
1074 assert repr(s) == "<cdata 'struct foo_s' owning 8 bytes>"
1075 assert s.aa == 36
1076 assert s.bb == 49
1077
1078 def test_func_as_funcptr():
1079 ffi = FFI()
1080 ffi.cdef("int *(*const fooptr)(void);")
1081 lib = ffi.verify("""
1082 int *foo(void) {
1083 return (int*)"foobar";
1084 }
1085 int *(*fooptr)(void) = foo;
1086 """)
1087 foochar = ffi.cast("char *(*)(void)", lib.fooptr)
1088 s = foochar()
1089 assert ffi.string(s) == b"foobar"
1090
1091 def test_funcptr_as_argument():
1092 ffi = FFI()
1093 ffi.cdef("""
1094 void qsort(void *base, size_t nel, size_t width,
1095 int (*compar)(const void *, const void *));
1096 """)
1097 ffi.verify("#include <stdlib.h>")
1098
1099 def test_func_as_argument():
1100 ffi = FFI()
1101 ffi.cdef("""
1102 void qsort(void *base, size_t nel, size_t width,
1103 int compar(const void *, const void *));
1104 """)
1105 ffi.verify("#include <stdlib.h>")
1106
1107 def test_array_as_argument():
1108 ffi = FFI()
1109 ffi.cdef("""
1110 size_t strlen(char string[]);
1111 """)
1112 ffi.verify("#include <string.h>")
1113
1114 def test_enum_as_argument():
1115 ffi = FFI()
1116 ffi.cdef("""
1117 enum foo_e { AA, BB, ... };
1118 int foo_func(enum foo_e);
1119 """)
1120 lib = ffi.verify("""
1121 enum foo_e { AA, CC, BB };
1122 int foo_func(enum foo_e e) { return (int)e; }
1123 """)
1124 assert lib.foo_func(lib.BB) == 2
1125 py.test.raises(TypeError, lib.foo_func, "BB")
1126
1127 def test_enum_as_function_result():
1128 ffi = FFI()
1129 ffi.cdef("""
1130 enum foo_e { AA, BB, ... };
1131 enum foo_e foo_func(int x);
1132 """)
1133 lib = ffi.verify("""
1134 enum foo_e { AA, CC, BB };
1135 enum foo_e foo_func(int x) { return (enum foo_e)x; }
1136 """)
1137 assert lib.foo_func(lib.BB) == lib.BB == 2
1138
1139 def test_enum_values():
1140 ffi = FFI()
1141 ffi.cdef("enum enum1_e { AA, BB };")
1142 lib = ffi.verify("enum enum1_e { AA, BB };")
1143 assert lib.AA == 0
1144 assert lib.BB == 1
1145 assert ffi.string(ffi.cast("enum enum1_e", 1)) == 'BB'
1146
1147 def test_typedef_complete_enum():
1148 ffi = FFI()
1149 ffi.cdef("typedef enum { AA, BB } enum1_t;")
1150 lib = ffi.verify("typedef enum { AA, BB } enum1_t;")
1151 assert ffi.string(ffi.cast("enum1_t", 1)) == 'BB'
1152 assert lib.AA == 0
1153 assert lib.BB == 1
1154
1155 def test_typedef_broken_complete_enum():
1156 # xxx this is broken in old cffis, but works with recompiler.py
1157 ffi = FFI()
1158 ffi.cdef("typedef enum { AA, BB } enum1_t;")
1159 lib = ffi.verify("typedef enum { AA, CC, BB } enum1_t;")
1160 assert lib.AA == 0
1161 assert lib.BB == 2
1162
1163 def test_typedef_incomplete_enum():
1164 ffi = FFI()
1165 ffi.cdef("typedef enum { AA, BB, ... } enum1_t;")
1166 lib = ffi.verify("typedef enum { AA, CC, BB } enum1_t;")
1167 assert ffi.string(ffi.cast("enum1_t", 1)) == '1'
1168 assert ffi.string(ffi.cast("enum1_t", 2)) == 'BB'
1169 assert lib.AA == 0
1170 assert lib.BB == 2
1171
1172 def test_typedef_enum_as_argument():
1173 ffi = FFI()
1174 ffi.cdef("""
1175 typedef enum { AA, BB, ... } foo_t;
1176 int foo_func(foo_t);
1177 """)
1178 lib = ffi.verify("""
1179 typedef enum { AA, CC, BB } foo_t;
1180 int foo_func(foo_t e) { return (int)e; }
1181 """)
1182 assert lib.foo_func(lib.BB) == lib.BB == 2
1183 py.test.raises(TypeError, lib.foo_func, "BB")
1184
1185 def test_typedef_enum_as_function_result():
1186 ffi = FFI()
1187 ffi.cdef("""
1188 typedef enum { AA, BB, ... } foo_t;
1189 foo_t foo_func(int x);
1190 """)
1191 lib = ffi.verify("""
1192 typedef enum { AA, CC, BB } foo_t;
1193 foo_t foo_func(int x) { return (foo_t)x; }
1194 """)
1195 assert lib.foo_func(lib.BB) == lib.BB == 2
1196
1197 def test_function_typedef():
1198 ffi = FFI()
1199 ffi.cdef("""
1200 typedef double func_t(double);
1201 func_t sin;
1202 """)
1203 lib = ffi.verify('#include <math.h>', libraries=lib_m)
1204 assert lib.sin(1.23) == math.sin(1.23)
1205
1206 def test_opaque_integer_as_function_result():
1207 #import platform
1208 #if platform.machine().startswith('sparc'):
1209 # py.test.skip('Breaks horribly on sparc (SIGILL + corrupted stack)')
1210 #elif platform.machine() == 'mips64' and sys.maxsize > 2**32:
1211 # py.test.skip('Segfaults on mips64el')
1212 # XXX bad abuse of "struct { ...; }". It only works a bit by chance
1213 # anyway. XXX think about something better :-(
1214 ffi = FFI()
1215 ffi.cdef("""
1216 typedef struct { ...; } myhandle_t;
1217 myhandle_t foo(void);
1218 """)
1219 lib = ffi.verify("""
1220 typedef short myhandle_t;
1221 myhandle_t foo(void) { return 42; }
1222 """)
1223 h = lib.foo()
1224 assert ffi.sizeof(h) == ffi.sizeof("short")
1225
1226 def test_return_partial_struct():
1227 ffi = FFI()
1228 ffi.cdef("""
1229 typedef struct { int x; ...; } foo_t;
1230 foo_t foo(void);
1231 """)
1232 lib = ffi.verify("""
1233 typedef struct { int y, x; } foo_t;
1234 foo_t foo(void) { foo_t r = { 45, 81 }; return r; }
1235 """)
1236 h = lib.foo()
1237 assert ffi.sizeof(h) == 2 * ffi.sizeof("int")
1238 assert h.x == 81
1239
1240 def test_take_and_return_partial_structs():
1241 ffi = FFI()
1242 ffi.cdef("""
1243 typedef struct { int x; ...; } foo_t;
1244 foo_t foo(foo_t, foo_t);
1245 """)
1246 lib = ffi.verify("""
1247 typedef struct { int y, x; } foo_t;
1248 foo_t foo(foo_t a, foo_t b) {
1249 foo_t r = { 100, a.x * 5 + b.x * 7 };
1250 return r;
1251 }
1252 """)
1253 args = ffi.new("foo_t[3]")
1254 args[0].x = 1000
1255 args[2].x = -498
1256 h = lib.foo(args[0], args[2])
1257 assert ffi.sizeof(h) == 2 * ffi.sizeof("int")
1258 assert h.x == 1000 * 5 - 498 * 7
1259
1260 def test_cannot_name_struct_type():
1261 ffi = FFI()
1262 ffi.cdef("typedef struct { int x; } **sp; void foo(sp);")
1263 e = py.test.raises(VerificationError, ffi.verify,
1264 "typedef struct { int x; } **sp; void foo(sp x) { }")
1265 assert 'in argument of foo: unknown type name' in str(e.value)
1266
1267 def test_dont_check_unnamable_fields():
1268 ffi = FFI()
1269 ffi.cdef("struct foo_s { struct { int x; } someone; };")
1270 ffi.verify("struct foo_s { struct { int x; } someone; };")
1271 # assert did not crash
1272
1273 def test_nested_anonymous_struct_exact():
1274 if sys.platform == 'win32':
1275 py.test.skip("nested anonymous struct/union")
1276 ffi = FFI()
1277 ffi.cdef("""
1278 struct foo_s { struct { int a; char b; }; union { char c, d; }; };
1279 """)
1280 assert ffi.offsetof("struct foo_s", "c") == 2 * ffi.sizeof("int")
1281 assert ffi.sizeof("struct foo_s") == 3 * ffi.sizeof("int")
1282 ffi.verify("""
1283 struct foo_s { struct { int a; char b; }; union { char c, d; }; };
1284 """)
1285 p = ffi.new("struct foo_s *")
1286 assert ffi.sizeof(p[0]) == 3 * ffi.sizeof("int") # with alignment
1287 p.a = 1234567
1288 p.b = b'X'
1289 p.c = b'Y'
1290 assert p.a == 1234567
1291 assert p.b == b'X'
1292 assert p.c == b'Y'
1293 assert p.d == b'Y'
1294
1295 def test_nested_anonymous_struct_exact_error():
1296 if sys.platform == 'win32':
1297 py.test.skip("nested anonymous struct/union")
1298 ffi = FFI()
1299 ffi.cdef("""
1300 struct foo_s { struct { int a; char b; }; union { char c, d; }; };
1301 """)
1302 py.test.raises(VerificationError, ffi.verify, """
1303 struct foo_s { struct { int a; short b; }; union { char c, d; }; };
1304 """)
1305 # works fine now
1306 #py.test.raises(VerificationError, ffi.verify, """
1307 # struct foo_s { struct { int a; char e, b; }; union { char c, d; }; };
1308 #""")
1309
1310 def test_nested_anonymous_struct_inexact_1():
1311 ffi = FFI()
1312 ffi.cdef("""
1313 struct foo_s { struct { char b; ...; }; union { char c, d; }; };
1314 """)
1315 ffi.verify("""
1316 struct foo_s { int a, padding; char c, d, b; };
1317 """)
1318 assert ffi.sizeof("struct foo_s") == 3 * ffi.sizeof("int")
1319
1320 def test_nested_anonymous_struct_inexact_2():
1321 ffi = FFI()
1322 ffi.cdef("""
1323 struct foo_s { union { char c, d; }; struct { int a; char b; }; ...; };
1324 """)
1325 ffi.verify("""
1326 struct foo_s { int a, padding; char c, d, b; };
1327 """)
1328 assert ffi.sizeof("struct foo_s") == 3 * ffi.sizeof("int")
1329
1330 def test_ffi_union():
1331 ffi = FFI()
1332 ffi.cdef("union foo_u { char x; long *z; };")
1333 ffi.verify("union foo_u { char x; int y; long *z; };")
1334
1335 def test_ffi_union_partial():
1336 ffi = FFI()
1337 ffi.cdef("union foo_u { char x; ...; };")
1338 ffi.verify("union foo_u { char x; int y; };")
1339 assert ffi.sizeof("union foo_u") == 4
1340
1341 def test_ffi_union_with_partial_struct():
1342 ffi = FFI()
1343 ffi.cdef("struct foo_s { int x; ...; }; union foo_u { struct foo_s s; };")
1344 ffi.verify("struct foo_s { int a; int x; }; "
1345 "union foo_u { char b[32]; struct foo_s s; };")
1346 assert ffi.sizeof("struct foo_s") == 8
1347 assert ffi.sizeof("union foo_u") == 32
1348
1349 def test_ffi_union_partial_2():
1350 ffi = FFI()
1351 ffi.cdef("typedef union { char x; ...; } u1;")
1352 ffi.verify("typedef union { char x; int y; } u1;")
1353 assert ffi.sizeof("u1") == 4
1354
1355 def test_ffi_union_with_partial_struct_2():
1356 ffi = FFI()
1357 ffi.cdef("typedef struct { int x; ...; } s1;"
1358 "typedef union { s1 s; } u1;")
1359 ffi.verify("typedef struct { int a; int x; } s1; "
1360 "typedef union { char b[32]; s1 s; } u1;")
1361 assert ffi.sizeof("s1") == 8
1362 assert ffi.sizeof("u1") == 32
1363 assert ffi.offsetof("u1", "s") == 0
1364
1365 def test_ffi_struct_packed():
1366 if sys.platform == 'win32':
1367 py.test.skip("needs a GCC extension")
1368 ffi = FFI()
1369 ffi.cdef("struct foo_s { int b; ...; };")
1370 ffi.verify("""
1371 struct foo_s {
1372 char a;
1373 int b;
1374 } __attribute__((packed));
1375 """)
1376
1377 def test_tmpdir():
1378 import tempfile, os
1379 from pypy.module.test_lib_pypy.cffi_tests.udir import udir
1380 tmpdir = tempfile.mkdtemp(dir=str(udir))
1381 ffi = FFI()
1382 ffi.cdef("int foo(int);")
1383 lib = ffi.verify("int foo(int a) { return a + 42; }", tmpdir=tmpdir)
1384 assert os.listdir(tmpdir)
1385 assert lib.foo(100) == 142
1386
1387 def test_relative_to():
1388 py.test.skip("not available")
1389 import tempfile, os
1390 from pypy.module.test_lib_pypy.cffi_tests.udir import udir
1391 tmpdir = tempfile.mkdtemp(dir=str(udir))
1392 ffi = FFI()
1393 ffi.cdef("int foo(int);")
1394 f = open(os.path.join(tmpdir, 'foo.h'), 'w')
1395 f.write("int foo(int a) { return a + 42; }\n")
1396 f.close()
1397 lib = ffi.verify('#include "foo.h"',
1398 include_dirs=['.'],
1399 relative_to=os.path.join(tmpdir, 'x'))
1400 assert lib.foo(100) == 142
1401
1402 def test_bug1():
1403 ffi = FFI()
1404 ffi.cdef("""
1405 typedef struct tdlhandle_s { ...; } *tdl_handle_t;
1406 typedef struct my_error_code_ {
1407 tdl_handle_t *rh;
1408 } my_error_code_t;
1409 """)
1410 ffi.verify("""
1411 typedef struct tdlhandle_s { int foo; } *tdl_handle_t;
1412 typedef struct my_error_code_ {
1413 tdl_handle_t *rh;
1414 } my_error_code_t;
1415 """)
1416
1417 def test_bool():
1418 if sys.platform == 'win32':
1419 py.test.skip("_Bool not in MSVC")
1420 ffi = FFI()
1421 ffi.cdef("struct foo_s { _Bool x; };"
1422 "_Bool foo(_Bool); _Bool (*foop)(_Bool);")
1423 lib = ffi.verify("""
1424 struct foo_s { _Bool x; };
1425 int foo(int arg) {
1426 return !arg;
1427 }
1428 _Bool _foofunc(_Bool x) {
1429 return !x;
1430 }
1431 _Bool (*foop)(_Bool) = _foofunc;
1432 """)
1433 p = ffi.new("struct foo_s *")
1434 p.x = 1
1435 assert p.x is True
1436 py.test.raises(OverflowError, "p.x = -1")
1437 py.test.raises(TypeError, "p.x = 0.0")
1438 assert lib.foop(1) is False
1439 assert lib.foop(True) is False
1440 assert lib.foop(0) is True
1441 py.test.raises(OverflowError, lib.foop, 42)
1442 py.test.raises(TypeError, lib.foop, 0.0)
1443 assert lib.foo(1) is False
1444 assert lib.foo(True) is False
1445 assert lib.foo(0) is True
1446 py.test.raises(OverflowError, lib.foo, 42)
1447 py.test.raises(TypeError, lib.foo, 0.0)
1448 assert int(ffi.cast("_Bool", long(1))) == 1
1449 assert int(ffi.cast("_Bool", long(0))) == 0
1450 assert int(ffi.cast("_Bool", long(-1))) == 1
1451 assert int(ffi.cast("_Bool", 10**200)) == 1
1452 assert int(ffi.cast("_Bool", 10**40000)) == 1
1453 #
1454 class Foo(object):
1455 def __int__(self):
1456 self.seen = 1
1457 return result
1458 f = Foo()
1459 f.seen = 0
1460 result = 42
1461 assert int(ffi.cast("_Bool", f)) == 1
1462 assert f.seen
1463 f.seen = 0
1464 result = 0
1465 assert int(ffi.cast("_Bool", f)) == 0
1466 assert f.seen
1467 #
1468 py.test.raises(TypeError, ffi.cast, "_Bool", [])
1469
1470 def test_bool_on_long_double():
1471 if sys.platform == 'win32':
1472 py.test.skip("_Bool not in MSVC")
1473 f = 1E-250
1474 if f == 0.0 or f*f != 0.0:
1475 py.test.skip("unexpected precision")
1476 ffi = FFI()
1477 ffi.cdef("long double square(long double f); _Bool opposite(_Bool);")
1478 lib = ffi.verify("long double square(long double f) { return f*f; }\n"
1479 "_Bool opposite(_Bool x) { return !x; }")
1480 f0 = lib.square(0.0)
1481 f2 = lib.square(f)
1482 f3 = lib.square(f * 2.0)
1483 if repr(f2) == repr(f3):
1484 py.test.skip("long double doesn't have enough precision")
1485 assert float(f0) == float(f2) == float(f3) == 0.0 # too tiny for 'double'
1486 assert int(ffi.cast("_Bool", f2)) == 1
1487 assert int(ffi.cast("_Bool", f3)) == 1
1488 assert int(ffi.cast("_Bool", f0)) == 0
1489 py.test.raises(TypeError, lib.opposite, f2)
1490
1491 def test_cannot_pass_float():
1492 for basetype in ['char', 'short', 'int', 'long', 'long long']:
1493 for sign in ['signed', 'unsigned']:
1494 type = '%s %s' % (sign, basetype)
1495 ffi = FFI()
1496 ffi.cdef("struct foo_s { %s x; };\n"
1497 "int foo(%s);" % (type, type))
1498 lib = ffi.verify("""
1499 struct foo_s { %s x; };
1500 int foo(%s arg) {
1501 return !arg;
1502 }
1503 """ % (type, type))
1504 p = ffi.new("struct foo_s *")
1505 py.test.raises(TypeError, "p.x = 0.0")
1506 assert lib.foo(42) == 0
1507 assert lib.foo(0) == 1
1508 py.test.raises(TypeError, lib.foo, 0.0)
1509
1510 def test_addressof():
1511 ffi = FFI()
1512 ffi.cdef("""
1513 struct point_s { int x, y; };
1514 struct foo_s { int z; struct point_s point; };
1515 struct point_s sum_coord(struct point_s *);
1516 """)
1517 lib = ffi.verify("""
1518 struct point_s { int x, y; };
1519 struct foo_s { int z; struct point_s point; };
1520 struct point_s sum_coord(struct point_s *point) {
1521 struct point_s r;
1522 r.x = point->x + point->y;
1523 r.y = point->x - point->y;
1524 return r;
1525 }
1526 """)
1527 p = ffi.new("struct foo_s *")
1528 p.point.x = 16
1529 p.point.y = 9
1530 py.test.raises(TypeError, lib.sum_coord, p.point)
1531 res = lib.sum_coord(ffi.addressof(p.point))
1532 assert res.x == 25
1533 assert res.y == 7
1534 res2 = lib.sum_coord(ffi.addressof(res))
1535 assert res2.x == 32
1536 assert res2.y == 18
1537 py.test.raises(TypeError, lib.sum_coord, res2)
1538
1539 def test_callback_in_thread():
1540 py.test.xfail("adapt or remove")
1541 if sys.platform == 'win32':
1542 py.test.skip("pthread only")
1543 import os, subprocess, imp
1544 arg = os.path.join(os.path.dirname(__file__), 'callback_in_thread.py')
1545 g = subprocess.Popen([sys.executable, arg,
1546 os.path.dirname(imp.find_module('cffi')[1])])
1547 result = g.wait()
1548 assert result == 0
1549
1550 def test_keepalive_lib():
1551 py.test.xfail("adapt or remove")
1552 ffi = FFI()
1553 ffi.cdef("int foobar(void);")
1554 lib = ffi.verify("int foobar(void) { return 42; }")
1555 func = lib.foobar
1556 ffi_r = weakref.ref(ffi)
1557 lib_r = weakref.ref(lib)
1558 del ffi
1559 import gc; gc.collect() # lib stays alive
1560 assert lib_r() is not None
1561 assert ffi_r() is not None
1562 assert func() == 42
1563
1564 def test_keepalive_ffi():
1565 py.test.xfail("adapt or remove")
1566 ffi = FFI()
1567 ffi.cdef("int foobar(void);")
1568 lib = ffi.verify("int foobar(void) { return 42; }")
1569 func = lib.foobar
1570 ffi_r = weakref.ref(ffi)
1571 lib_r = weakref.ref(lib)
1572 del lib
1573 import gc; gc.collect() # ffi stays alive
1574 assert ffi_r() is not None
1575 assert lib_r() is not None
1576 assert func() == 42
1577
1578 def test_FILE_stored_in_stdout():
1579 if not sys.platform.startswith('linux'):
1580 py.test.skip("likely, we cannot assign to stdout")
1581 ffi = FFI()
1582 ffi.cdef("int printf(const char *, ...); FILE *setstdout(FILE *);")
1583 lib = ffi.verify("""
1584 #include <stdio.h>
1585 FILE *setstdout(FILE *f) {
1586 FILE *result = stdout;
1587 stdout = f;
1588 return result;
1589 }
1590 """)
1591 import os
1592 fdr, fdw = os.pipe()
1593 fw1 = os.fdopen(fdw, 'wb', 256)
1594 old_stdout = lib.setstdout(fw1)
1595 try:
1596 #
1597 fw1.write(b"X")
1598 r = lib.printf(b"hello, %d!\n", ffi.cast("int", 42))
1599 fw1.close()
1600 assert r == len("hello, 42!\n")
1601 #
1602 finally:
1603 lib.setstdout(old_stdout)
1604 #
1605 result = os.read(fdr, 256)
1606 os.close(fdr)
1607 # the 'X' might remain in the user-level buffer of 'fw1' and
1608 # end up showing up after the 'hello, 42!\n'
1609 assert result == b"Xhello, 42!\n" or result == b"hello, 42!\nX"
1610
1611 def test_FILE_stored_explicitly():
1612 ffi = FFI()
1613 ffi.cdef("int myprintf11(const char *, int); FILE *myfile;")
1614 lib = ffi.verify("""
1615 #include <stdio.h>
1616 FILE *myfile;
1617 int myprintf11(const char *out, int value) {
1618 return fprintf(myfile, out, value);
1619 }
1620 """)
1621 import os
1622 fdr, fdw = os.pipe()
1623 fw1 = os.fdopen(fdw, 'wb', 256)
1624 lib.myfile = ffi.cast("FILE *", fw1)
1625 #
1626 fw1.write(b"X")
1627 r = lib.myprintf11(b"hello, %d!\n", ffi.cast("int", 42))
1628 fw1.close()
1629 assert r == len("hello, 42!\n")
1630 #
1631 result = os.read(fdr, 256)
1632 os.close(fdr)
1633 # the 'X' might remain in the user-level buffer of 'fw1' and
1634 # end up showing up after the 'hello, 42!\n'
1635 assert result == b"Xhello, 42!\n" or result == b"hello, 42!\nX"
1636
1637 def test_global_array_with_missing_length():
1638 ffi = FFI()
1639 ffi.cdef("int fooarray[];")
1640 lib = ffi.verify("int fooarray[50];")
1641 assert repr(lib.fooarray).startswith("<cdata 'int *'")
1642
1643 def test_global_array_with_dotdotdot_length():
1644 ffi = FFI()
1645 ffi.cdef("int fooarray[...];")
1646 lib = ffi.verify("int fooarray[50];")
1647 assert repr(lib.fooarray).startswith("<cdata 'int[50]'")
1648
1649 def test_bad_global_array_with_dotdotdot_length():
1650 py.test.xfail("was detected only because 23 bytes cannot be divided by 4; "
1651 "redo more generally")
1652 ffi = FFI()
1653 ffi.cdef("int fooarray[...];")
1654 py.test.raises(VerificationError, ffi.verify, "char fooarray[23];")
1655
1656 def test_struct_containing_struct():
1657 ffi = FFI()
1658 ffi.cdef("struct foo_s { ...; }; struct bar_s { struct foo_s f; ...; };")
1659 ffi.verify("struct foo_s { int x; }; struct bar_s { struct foo_s f; };")
1660 #
1661 ffi = FFI()
1662 ffi.cdef("struct foo_s { struct bar_s f; ...; }; struct bar_s { ...; };")
1663 ffi.verify("struct bar_s { int x; }; struct foo_s { struct bar_s f; };")
1664
1665 def test_struct_returned_by_func():
1666 ffi = FFI()
1667 ffi.cdef("typedef ... foo_t; foo_t myfunc(void);")
1668 e = py.test.raises(TypeError, ffi.verify,
1669 "typedef struct { int x; } foo_t; "
1670 "foo_t myfunc(void) { foo_t x = { 42 }; return x; }")
1671 assert str(e.value) == (
1672 "function myfunc: 'foo_t' is used as result type, but is opaque")
1673
1674 def test_include():
1675 ffi1 = FFI()
1676 ffi1.cdef("typedef struct { int x; ...; } foo_t;")
1677 ffi1.verify("typedef struct { int y, x; } foo_t;")
1678 ffi2 = FFI()
1679 ffi2.include(ffi1)
1680 ffi2.cdef("int myfunc(foo_t *);")
1681 lib = ffi2.verify("typedef struct { int y, x; } foo_t;"
1682 "int myfunc(foo_t *p) { return 42 * p->x; }")
1683 res = lib.myfunc(ffi2.new("foo_t *", {'x': 10}))
1684 assert res == 420
1685 res = lib.myfunc(ffi1.new("foo_t *", {'x': -10}))
1686 assert res == -420
1687
1688 def test_include_enum():
1689 ffi1 = FFI()
1690 ffi1.cdef("enum foo_e { AA, ... };")
1691 lib1 = ffi1.verify("enum foo_e { CC, BB, AA };")
1692 ffi2 = FFI()
1693 ffi2.include(ffi1)
1694 ffi2.cdef("int myfunc(enum foo_e);")
1695 lib2 = ffi2.verify("enum foo_e { CC, BB, AA };"
1696 "int myfunc(enum foo_e x) { return (int)x; }")
1697 res = lib2.myfunc(lib2.AA)
1698 assert res == 2
1699
1700 def test_named_pointer_as_argument():
1701 ffi = FFI()
1702 ffi.cdef("typedef struct { int x; } *mystruct_p;\n"
1703 "mystruct_p ff5a(mystruct_p);")
1704 lib = ffi.verify("typedef struct { int x; } *mystruct_p;\n"
1705 "mystruct_p ff5a(mystruct_p p) { p->x += 40; return p; }")
1706 p = ffi.new("mystruct_p", [-2])
1707 q = lib.ff5a(p)
1708 assert q == p
1709 assert p.x == 38
1710
1711 def test_enum_size():
1712 cases = [('123', 4, 4294967295),
1713 ('4294967295U', 4, 4294967295),
1714 ('-123', 4, -1),
1715 ('-2147483647-1', 4, -1),
1716 ]
1717 if FFI().sizeof("long") == 8:
1718 cases += [('4294967296L', 8, 2**64-1),
1719 ('%dUL' % (2**64-1), 8, 2**64-1),
1720 ('-2147483649L', 8, -1),
1721 ('%dL-1L' % (1-2**63), 8, -1)]
1722 for hidden_value, expected_size, expected_minus1 in cases:
1723 if sys.platform == 'win32' and 'U' in hidden_value:
1724 continue # skipped on Windows
1725 ffi = FFI()
1726 ffi.cdef("enum foo_e { AA, BB, ... };")
1727 lib = ffi.verify("enum foo_e { AA, BB=%s };" % hidden_value)
1728 assert lib.AA == 0
1729 assert lib.BB == eval(hidden_value.replace('U', '').replace('L', ''))
1730 assert ffi.sizeof("enum foo_e") == expected_size
1731 if sys.platform != 'win32':
1732 assert int(ffi.cast("enum foo_e", -1)) == expected_minus1
1733 # test with the large value hidden:
1734 # disabled so far, doesn't work
1735 ## for hidden_value, expected_size, expected_minus1 in cases:
1736 ## ffi = FFI()
1737 ## ffi.cdef("enum foo_e { AA, BB, ... };")
1738 ## lib = ffi.verify("enum foo_e { AA, BB=%s };" % hidden_value)
1739 ## assert lib.AA == 0
1740 ## assert ffi.sizeof("enum foo_e") == expected_size
1741 ## assert int(ffi.cast("enum foo_e", -1)) == expected_minus1
1742
1743 def test_enum_bug118():
1744 maxulong = 256 ** FFI().sizeof("unsigned long") - 1
1745 for c2, c2c in [(-1, ''),
1746 (-1, ''),
1747 (0xffffffff, 'U'),
1748 (maxulong, 'UL'),
1749 (-int(maxulong / 3), 'L')]:
1750 if c2c and sys.platform == 'win32':
1751 continue # enums may always be signed with MSVC
1752 ffi = FFI()
1753 ffi.cdef("enum foo_e { AA };")
1754 lib = ffi.verify("enum foo_e { AA=%s%s };" % (c2, c2c))
1755 assert lib.AA == c2
1756
1757 def test_string_to_voidp_arg():
1758 ffi = FFI()
1759 ffi.cdef("int myfunc(void *);")
1760 lib = ffi.verify("int myfunc(void *p) { return ((signed char *)p)[0]; }")
1761 res = lib.myfunc(b"hi!")
1762 assert res == ord(b"h")
1763 p = ffi.new("char[]", b"gah")
1764 res = lib.myfunc(p)
1765 assert res == ord(b"g")
1766 res = lib.myfunc(ffi.cast("void *", p))
1767 assert res == ord(b"g")
1768 res = lib.myfunc(ffi.cast("int *", p))
1769 assert res == ord(b"g")
1770
1771 def test_callback_indirection():
1772 ffi = FFI()
1773 ffi.cdef("""
1774 int (*python_callback)(int how_many, int *values);
1775 int (*const c_callback)(int,...); /* pass this ptr to C routines */
1776 int some_c_function(int(*cb)(int,...));
1777 """)
1778 lib = ffi.verify("""
1779 #include <stdarg.h>
1780 #ifdef _WIN32
1781 #include <malloc.h>
1782 #define alloca _alloca
1783 #else
1784 # ifdef __FreeBSD__
1785 # include <stdlib.h>
1786 # else
1787 # include <alloca.h>
1788 # endif
1789 #endif
1790 static int (*python_callback)(int how_many, int *values);
1791 static int c_callback(int how_many, ...) {
1792 va_list ap;
1793 /* collect the "..." arguments into the values[] array */
1794 int i, *values = alloca((size_t)how_many * sizeof(int));
1795 va_start(ap, how_many);
1796 for (i=0; i<how_many; i++)
1797 values[i] = va_arg(ap, int);
1798 va_end(ap);
1799 return python_callback(how_many, values);
1800 }
1801 int some_c_function(int(*cb)(int,...)) {
1802 int result = cb(2, 10, 20);
1803 result += cb(3, 30, 40, 50);
1804 return result;
1805 }
1806 """)
1807 seen = []
1808 @ffi.callback("int(int, int*)")
1809 def python_callback(how_many, values):
1810 seen.append([values[i] for i in range(how_many)])
1811 return 42
1812 lib.python_callback = python_callback
1813
1814 res = lib.some_c_function(lib.c_callback)
1815 assert res == 84
1816 assert seen == [[10, 20], [30, 40, 50]]
1817
1818 def test_floatstar_argument():
1819 ffi = FFI()
1820 ffi.cdef("float sum3floats(float *);")
1821 lib = ffi.verify("""
1822 float sum3floats(float *f) {
1823 return f[0] + f[1] + f[2];
1824 }
1825 """)
1826 assert lib.sum3floats((1.5, 2.5, 3.5)) == 7.5
1827 p = ffi.new("float[]", (1.5, 2.5, 3.5))
1828 assert lib.sum3floats(p) == 7.5
1829
1830 def test_charstar_argument():
1831 ffi = FFI()
1832 ffi.cdef("char sum3chars(char *);")
1833 lib = ffi.verify("""
1834 char sum3chars(char *f) {
1835 return (char)(f[0] + f[1] + f[2]);
1836 }
1837 """)
1838 assert lib.sum3chars((b'\x10', b'\x20', b'\x30')) == b'\x60'
1839 p = ffi.new("char[]", b'\x10\x20\x30')
1840 assert lib.sum3chars(p) == b'\x60'
1841
1842 def test_passing_string_or_NULL():
1843 ffi = FFI()
1844 ffi.cdef("int seeme1(char *); int seeme2(int *);")
1845 lib = ffi.verify("""
1846 int seeme1(char *x) {
1847 return (x == NULL);
1848 }
1849 int seeme2(int *x) {
1850 return (x == NULL);
1851 }
1852 """)
1853 assert lib.seeme1(b"foo") == 0
1854 assert lib.seeme1(ffi.NULL) == 1
1855 assert lib.seeme2([42, 43]) == 0
1856 assert lib.seeme2(ffi.NULL) == 1
1857 py.test.raises(TypeError, lib.seeme1, None)
1858 py.test.raises(TypeError, lib.seeme2, None)
1859 py.test.raises(TypeError, lib.seeme1, 0.0)
1860 py.test.raises(TypeError, lib.seeme2, 0.0)
1861 py.test.raises(TypeError, lib.seeme1, 0)
1862 py.test.raises(TypeError, lib.seeme2, 0)
1863 zeroL = 99999999999999999999
1864 zeroL -= 99999999999999999999
1865 py.test.raises(TypeError, lib.seeme2, zeroL)
1866
1867 def test_typeof_function():
1868 ffi = FFI()
1869 ffi.cdef("int foo(int, char);")
1870 lib = ffi.verify("int foo(int x, char y) { (void)x; (void)y; return 42; }")
1871 ctype = ffi.typeof(lib.foo)
1872 assert len(ctype.args) == 2
1873 assert ctype.result == ffi.typeof("int")
1874
1875 def test_call_with_voidstar_arg():
1876 ffi = FFI()
1877 ffi.cdef("int f(void *);")
1878 lib = ffi.verify("int f(void *x) { return ((char*)x)[0]; }")
1879 assert lib.f(b"foobar") == ord(b"f")
1880
1881 def test_dir():
1882 ffi = FFI()
1883 ffi.cdef("""void somefunc(void);
1884 extern int somevar, somearray[2];
1885 static char *const sv2;
1886 enum my_e { AA, BB, ... };
1887 #define FOO ...""")
1888 lib = ffi.verify("""void somefunc(void) { }
1889 int somevar, somearray[2];
1890 #define sv2 "text"
1891 enum my_e { AA, BB };
1892 #define FOO 42""")
1893 assert dir(lib) == ['AA', 'BB', 'FOO', 'somearray',
1894 'somefunc', 'somevar', 'sv2']
1895
1896 def test_typeof_func_with_struct_argument():
1897 ffi = FFI()
1898 ffi.cdef("""struct s { int a; }; int foo(struct s);""")
1899 lib = ffi.verify("""struct s { int a; };
1900 int foo(struct s x) { return x.a; }""")
1901 s = ffi.new("struct s *", [-1234])
1902 m = lib.foo(s[0])
1903 assert m == -1234
1904 assert repr(ffi.typeof(lib.foo)) == "<ctype 'int(*)(struct s)'>"
1905
1906 def test_bug_const_char_ptr_array_1():
1907 ffi = FFI()
1908 ffi.cdef("""const char *a[...];""")
1909 lib = ffi.verify("""const char *a[5];""")
1910 assert repr(ffi.typeof(lib.a)) == "<ctype 'char *[5]'>"
1911
1912 def test_bug_const_char_ptr_array_2():
1913 ffi = FFI()
1914 ffi.cdef("""const int a[];""")
1915 lib = ffi.verify("""const int a[5];""")
1916 assert repr(ffi.typeof(lib.a)) == "<ctype 'int *'>"
1917
1918 def _test_various_calls(force_libffi):
1919 cdef_source = """
1920 int xvalue;
1921 long long ivalue, rvalue;
1922 float fvalue;
1923 double dvalue;
1924 long double Dvalue;
1925 signed char tf_bb(signed char x, signed char c);
1926 unsigned char tf_bB(signed char x, unsigned char c);
1927 short tf_bh(signed char x, short c);
1928 unsigned short tf_bH(signed char x, unsigned short c);
1929 int tf_bi(signed char x, int c);
1930 unsigned int tf_bI(signed char x, unsigned int c);
1931 long tf_bl(signed char x, long c);
1932 unsigned long tf_bL(signed char x, unsigned long c);
1933 long long tf_bq(signed char x, long long c);
1934 unsigned long long tf_bQ(signed char x, unsigned long long c);
1935 float tf_bf(signed char x, float c);
1936 double tf_bd(signed char x, double c);
1937 long double tf_bD(signed char x, long double c);
1938 """
1939 if force_libffi:
1940 cdef_source = (cdef_source
1941 .replace('tf_', '(*const tf_')
1942 .replace('(signed char x', ')(signed char x'))
1943 ffi = FFI()
1944 ffi.cdef(cdef_source)
1945 lib = ffi.verify("""
1946 int xvalue;
1947 long long ivalue, rvalue;
1948 float fvalue;
1949 double dvalue;
1950 long double Dvalue;
1951
1952 typedef signed char b_t;
1953 typedef unsigned char B_t;
1954 typedef short h_t;
1955 typedef unsigned short H_t;
1956 typedef int i_t;
1957 typedef unsigned int I_t;
1958 typedef long l_t;
1959 typedef unsigned long L_t;
1960 typedef long long q_t;
1961 typedef unsigned long long Q_t;
1962 typedef float f_t;
1963 typedef double d_t;
1964 typedef long double D_t;
1965 #define S(letter) xvalue = (int)x; letter##value = (letter##_t)c;
1966 #define R(letter) return (letter##_t)rvalue;
1967
1968 signed char tf_bb(signed char x, signed char c) { S(i) R(b) }
1969 unsigned char tf_bB(signed char x, unsigned char c) { S(i) R(B) }
1970 short tf_bh(signed char x, short c) { S(i) R(h) }
1971 unsigned short tf_bH(signed char x, unsigned short c) { S(i) R(H) }
1972 int tf_bi(signed char x, int c) { S(i) R(i) }
1973 unsigned int tf_bI(signed char x, unsigned int c) { S(i) R(I) }
1974 long tf_bl(signed char x, long c) { S(i) R(l) }
1975 unsigned long tf_bL(signed char x, unsigned long c) { S(i) R(L) }
1976 long long tf_bq(signed char x, long long c) { S(i) R(q) }
1977 unsigned long long tf_bQ(signed char x, unsigned long long c) { S(i) R(Q) }
1978 float tf_bf(signed char x, float c) { S(f) R(f) }
1979 double tf_bd(signed char x, double c) { S(d) R(d) }
1980 long double tf_bD(signed char x, long double c) { S(D) R(D) }
1981 """)
1982 lib.rvalue = 0x7182838485868788
1983 for kind, cname in [('b', 'signed char'),
1984 ('B', 'unsigned char'),
1985 ('h', 'short'),
1986 ('H', 'unsigned short'),
1987 ('i', 'int'),
1988 ('I', 'unsigned int'),
1989 ('l', 'long'),
1990 ('L', 'unsigned long'),
1991 ('q', 'long long'),
1992 ('Q', 'unsigned long long'),
1993 ('f', 'float'),
1994 ('d', 'double'),
1995 ('D', 'long double')]:
1996 sign = +1 if 'unsigned' in cname else -1
1997 lib.xvalue = 0
1998 lib.ivalue = 0
1999 lib.fvalue = 0
2000 lib.dvalue = 0
2001 lib.Dvalue = 0
2002 fun = getattr(lib, 'tf_b' + kind)
2003 res = fun(-42, sign * 99)
2004 if kind == 'D':
2005 res = float(res)
2006 assert res == int(ffi.cast(cname, 0x7182838485868788))
2007 assert lib.xvalue == -42
2008 if kind in 'fdD':
2009 assert float(getattr(lib, kind + 'value')) == -99.0
2010 else:
2011 assert lib.ivalue == sign * 99
2012
2013 def test_various_calls_direct():
2014 _test_various_calls(force_libffi=False)
2015
2016 def test_various_calls_libffi():
2017 _test_various_calls(force_libffi=True)
2018
2019 def test_ptr_to_opaque():
2020 ffi = FFI()
2021 ffi.cdef("typedef ... foo_t; int f1(foo_t*); foo_t *f2(int);")
2022 lib = ffi.verify("""
2023 #include <stdlib.h>
2024 typedef struct { int x; } foo_t;
2025 int f1(foo_t* p) {
2026 int x = p->x;
2027 free(p);
2028 return x;
2029 }
2030 foo_t *f2(int x) {
2031 foo_t *p = malloc(sizeof(foo_t));
2032 p->x = x;
2033 return p;
2034 }
2035 """)
2036 p = lib.f2(42)
2037 x = lib.f1(p)
2038 assert x == 42
2039
2040 def _run_in_multiple_threads(test1):
2041 test1()
2042 import sys
2043 try:
2044 import thread
2045 except ImportError:
2046 import _thread as thread
2047 errors = []
2048 def wrapper(lock):
2049 try:
2050 test1()
2051 except:
2052 errors.append(sys.exc_info())
2053 lock.release()
2054 locks = []
2055 for i in range(10):
2056 _lock = thread.allocate_lock()
2057 _lock.acquire()
2058 thread.start_new_thread(wrapper, (_lock,))
2059 locks.append(_lock)
2060 for _lock in locks:
2061 _lock.acquire()
2062 if errors:
2063 raise errors[0][1]
2064
2065 def test_errno_working_even_with_pypys_jit():
2066 ffi = FFI()
2067 ffi.cdef("int f(int);")
2068 lib = ffi.verify("""
2069 #include <errno.h>
2070 int f(int x) { return (errno = errno + x); }
2071 """)
2072 @_run_in_multiple_threads
2073 def test1():
2074 ffi.errno = 0
2075 for i in range(10000):
2076 e = lib.f(1)
2077 assert e == i + 1
2078 assert ffi.errno == e
2079 for i in range(10000):
2080 ffi.errno = i
2081 e = lib.f(42)
2082 assert e == i + 42
2083
2084 def test_getlasterror_working_even_with_pypys_jit():
2085 if sys.platform != 'win32':
2086 py.test.skip("win32-only test")
2087 ffi = FFI()
2088 ffi.cdef("void SetLastError(DWORD);")
2089 lib = ffi.dlopen("Kernel32.dll")
2090 @_run_in_multiple_threads
2091 def test1():
2092 for i in range(10000):
2093 n = (1 << 29) + i
2094 lib.SetLastError(n)
2095 assert ffi.getwinerror()[0] == n
2096
2097 def test_verify_dlopen_flags():
2098 if not hasattr(sys, 'setdlopenflags'):
2099 py.test.skip("requires sys.setdlopenflags()")
2100 # Careful with RTLD_GLOBAL. If by chance the FFI is not deleted
2101 # promptly, like on PyPy, then other tests may see the same
2102 # exported symbols as well. So we must not export a simple name
2103 # like 'foo'!
2104 old = sys.getdlopenflags()
2105 try:
2106 ffi1 = FFI()
2107 ffi1.cdef("int foo_verify_dlopen_flags_1;")
2108 sys.setdlopenflags(ffi1.RTLD_GLOBAL | ffi1.RTLD_NOW)
2109 lib1 = ffi1.verify("int foo_verify_dlopen_flags_1;")
2110 finally:
2111 sys.setdlopenflags(old)
2112
2113 ffi2 = FFI()
2114 ffi2.cdef("int *getptr(void);")
2115 lib2 = ffi2.verify("""
2116 extern int foo_verify_dlopen_flags_1;
2117 static int *getptr(void) { return &foo_verify_dlopen_flags_1; }
2118 """)
2119 p = lib2.getptr()
2120 assert ffi1.addressof(lib1, 'foo_verify_dlopen_flags_1') == p
2121
2122 def test_consider_not_implemented_function_type():
2123 ffi = FFI()
2124 ffi.cdef("typedef union { int a; float b; } Data;"
2125 "typedef struct { int a:2; } MyStr;"
2126 "typedef void (*foofunc_t)(Data);"
2127 "typedef Data (*bazfunc_t)(void);"
2128 "typedef MyStr (*barfunc_t)(void);")
2129 fooptr = ffi.cast("foofunc_t", 123)
2130 bazptr = ffi.cast("bazfunc_t", 123)
2131 barptr = ffi.cast("barfunc_t", 123)
2132 # assert did not crash so far
2133 e = py.test.raises(NotImplementedError, fooptr, ffi.new("Data *"))
2134 assert str(e.value) == (
2135 "ctype 'Data' not supported as argument by libffi. Unions are only "
2136 "supported as argument if the function is 'API mode' and "
2137 "non-variadic (i.e. declared inside ffibuilder.cdef()+"
2138 "ffibuilder.set_source() and not taking a final '...' argument)")
2139 e = py.test.raises(NotImplementedError, bazptr)
2140 assert str(e.value) == (
2141 "ctype 'Data' not supported as return value by libffi. Unions are "
2142 "only supported as return value if the function is 'API mode' and "
2143 "non-variadic (i.e. declared inside ffibuilder.cdef()+"
2144 "ffibuilder.set_source() and not taking a final '...' argument)")
2145 e = py.test.raises(NotImplementedError, barptr)
2146 assert str(e.value) == (
2147 "ctype 'MyStr' not supported as return value. It is a struct with "
2148 "bit fields, which libffi does not support. Such structs are only "
2149 "supported as return value if the function is 'API mode' and non-"
2150 "variadic (i.e. declared inside ffibuilder.cdef()+ffibuilder."
2151 "set_source() and not taking a final '...' argument)")
2152
2153 def test_verify_extra_arguments():
2154 ffi = FFI()
2155 ffi.cdef("#define ABA ...")
2156 lib = ffi.verify("", define_macros=[('ABA', '42')])
2157 assert lib.ABA == 42
2158
2159 def test_implicit_unicode_on_windows():
2160 from cffi import FFIError
2161 if sys.platform != 'win32':
2162 py.test.skip("win32-only test")
2163 ffi = FFI()
2164 e = py.test.raises(FFIError, ffi.cdef, "int foo(LPTSTR);")
2165 assert str(e.value) == ("The Windows type 'LPTSTR' is only available after"
2166 " you call ffi.set_unicode()")
2167 for with_unicode in [True, False]:
2168 ffi = FFI()
2169 ffi.set_unicode(with_unicode)
2170 ffi.cdef("""
2171 DWORD GetModuleFileName(HMODULE hModule, LPTSTR lpFilename,
2172 DWORD nSize);
2173 """)
2174 lib = ffi.verify("""
2175 #include <windows.h>
2176 """, libraries=['Kernel32'])
2177 outbuf = ffi.new("TCHAR[]", 200)
2178 n = lib.GetModuleFileName(ffi.NULL, outbuf, 500)
2179 assert 0 < n < 500
2180 for i in range(n):
2181 #print repr(outbuf[i])
2182 assert ord(outbuf[i]) != 0
2183 assert ord(outbuf[n]) == 0
2184 assert ord(outbuf[0]) < 128 # should be a letter, or '\'
2185
2186 def test_define_known_value():
2187 ffi = FFI()
2188 ffi.cdef("#define FOO 0x123")
2189 lib = ffi.verify("#define FOO 0x123")
2190 assert lib.FOO == 0x123
2191
2192 def test_define_wrong_value():
2193 ffi = FFI()
2194 ffi.cdef("#define FOO 123")
2195 lib = ffi.verify("#define FOO 124") # used to complain
2196 e = py.test.raises(ffi.error, "lib.FOO")
2197 assert str(e.value) == ("the C compiler says 'FOO' is equal to 124 (0x7c),"
2198 " but the cdef disagrees")
2199
2200 def test_some_integer_type_for_issue73():
2201 ffi = FFI()
2202 ffi.cdef("""
2203 typedef int... AnIntegerWith32Bits;
2204 typedef AnIntegerWith32Bits (*AFunctionReturningInteger) (void);
2205 AnIntegerWith32Bits InvokeFunction(AFunctionReturningInteger);
2206 """)
2207 lib = ffi.verify("""
2208 #ifdef __LP64__
2209 typedef int AnIntegerWith32Bits;
2210 #else
2211 typedef long AnIntegerWith32Bits;
2212 #endif
2213 typedef AnIntegerWith32Bits (*AFunctionReturningInteger) (void);
2214 AnIntegerWith32Bits InvokeFunction(AFunctionReturningInteger f) {
2215 return f();
2216 }
2217 """)
2218 @ffi.callback("AFunctionReturningInteger")
2219 def add():
2220 return 3 + 4
2221 x = lib.InvokeFunction(add)
2222 assert x == 7
2223
2224 def test_unsupported_some_primitive_types():
2225 ffi = FFI()
2226 py.test.raises((FFIError, # with pycparser <= 2.17
2227 CDefError), # with pycparser >= 2.18
2228 ffi.cdef, """typedef void... foo_t;""")
2229 #
2230 ffi.cdef("typedef int... foo_t;")
2231 py.test.raises(VerificationError, ffi.verify, "typedef float foo_t;")
2232
2233 def test_windows_dllimport_data():
2234 if sys.platform != 'win32':
2235 py.test.skip("Windows only")
2236 from pypy.module.test_lib_pypy.cffi_tests.udir import udir
2237 tmpfile = udir.join('dllimport_data.c')
2238 tmpfile.write('int my_value = 42;\n')
2239 ffi = FFI()
2240 ffi.cdef("int my_value;")
2241 lib = ffi.verify("extern __declspec(dllimport) int my_value;",
2242 sources = [str(tmpfile)])
2243 assert lib.my_value == 42
2244
2245 def test_macro_var():
2246 ffi = FFI()
2247 ffi.cdef("int myarray[50], my_value;")
2248 lib = ffi.verify("""
2249 int myarray[50];
2250 int *get_my_value(void) {
2251 static int index = 0;
2252 return &myarray[index++];
2253 }
2254 #define my_value (*get_my_value())
2255 """)
2256 assert lib.my_value == 0 # [0]
2257 lib.my_value = 42 # [1]
2258 assert lib.myarray[1] == 42
2259 assert lib.my_value == 0 # [2]
2260 lib.myarray[3] = 63
2261 assert lib.my_value == 63 # [3]
2262 p = ffi.addressof(lib, 'my_value') # [4]
2263 assert p[-1] == 63
2264 assert p[0] == 0
2265 assert p == lib.myarray + 4
2266 p[1] = 82
2267 assert lib.my_value == 82 # [5]
2268
2269 def test_const_pointer_to_pointer():
2270 ffi = FFI()
2271 ffi.cdef("struct s { char *const *a; };")
2272 ffi.verify("struct s { char *const *a; };")
2273
2274 def test_share_FILE():
2275 ffi1 = FFI()
2276 ffi1.cdef("void do_stuff(FILE *);")
2277 lib1 = ffi1.verify("void do_stuff(FILE *f) { (void)f; }")
2278 ffi2 = FFI()
2279 ffi2.cdef("FILE *barize(void);")
2280 lib2 = ffi2.verify("FILE *barize(void) { return NULL; }")
2281 lib1.do_stuff(lib2.barize())
2282
2283 def test_win_common_types():
2284 if sys.platform != 'win32':
2285 py.test.skip("Windows only")
2286 ffi = FFI()
2287 ffi.set_unicode(True)
2288 ffi.verify("")
2289 assert ffi.typeof("PBYTE") is ffi.typeof("unsigned char *")
2290 if sys.maxsize > 2**32:
2291 expected = "unsigned long long"
2292 else:
2293 expected = "unsigned int"
2294 assert ffi.typeof("UINT_PTR") is ffi.typeof(expected)
2295 assert ffi.typeof("PTSTR") is ffi.typeof("wchar_t *")
2296
2297 def _only_test_on_linux_intel():
2298 if not sys.platform.startswith('linux'):
2299 py.test.skip('only running the memory-intensive test on Linux')
2300 import platform
2301 machine = platform.machine()
2302 if 'x86' not in machine and 'x64' not in machine:
2303 py.test.skip('only running the memory-intensive test on x86/x64')
2304
2305 def test_ffi_gc_size_arg():
2306 _only_test_on_linux_intel()
2307 ffi = FFI()
2308 ffi.cdef("void *malloc(size_t); void free(void *);")
2309 lib = ffi.verify(r"""
2310 #include <stdlib.h>
2311 """)
2312 for i in range(2000):
2313 p = lib.malloc(20*1024*1024) # 20 MB
2314 p1 = ffi.cast("char *", p)
2315 for j in range(0, 20*1024*1024, 4096):
2316 p1[j] = b'!'
2317 p = ffi.gc(p, lib.free, 20*1024*1024)
2318 del p
2319 # with PyPy's GC, the above would rapidly consume 40 GB of RAM
2320 # without the third argument to ffi.gc()
2321
2322 def test_ffi_gc_size_arg_2():
2323 # a variant of the above: this "attack" works on cpython's cyclic gc too
2324 # and I found no obvious way to prevent that. So for now, this test
2325 # is skipped on CPython, where it eats all the memory.
2326 if '__pypy__' not in sys.builtin_module_names:
2327 py.test.skip("find a way to tweak the cyclic GC of CPython")
2328 _only_test_on_linux_intel()
2329 ffi = FFI()
2330 ffi.cdef("void *malloc(size_t); void free(void *);")
2331 lib = ffi.verify(r"""
2332 #include <stdlib.h>
2333 """)
2334 class X(object):
2335 pass
2336 for i in range(2000):
2337 p = lib.malloc(50*1024*1024) # 50 MB
2338 p1 = ffi.cast("char *", p)
2339 for j in range(0, 50*1024*1024, 4096):
2340 p1[j] = b'!'
2341 p = ffi.gc(p, lib.free, 50*1024*1024)
2342 x = X()
2343 x.p = p
2344 x.cyclic = x
2345 del p, x
2346
2347 def test_ffi_new_with_cycles():
2348 # still another variant, with ffi.new()
2349 if '__pypy__' not in sys.builtin_module_names:
2350 py.test.skip("find a way to tweak the cyclic GC of CPython")
2351 ffi = FFI()
2352 ffi.cdef("")
2353 lib = ffi.verify("")
2354 class X(object):
2355 pass
2356 for i in range(2000):
2357 p = ffi.new("char[]", 50*1024*1024) # 50 MB
2358 for j in range(0, 50*1024*1024, 4096):
2359 p[j] = b'!'
2360 x = X()
2361 x.p = p
2362 x.cyclic = x
2363 del p, x
+0
-418
pypy/module/test_lib_pypy/cffi_tests/cffi1/test_zdist.py less more
0 # Generated by pypy/tool/import_cffi.py
1 import sys, os, py
2 import subprocess
3 import cffi
4 from pypy.module.test_lib_pypy.cffi_tests.udir import udir
5
6
7 def chdir_to_tmp(f):
8 f.chdir_to_tmp = True
9 return f
10
11 def from_outside(f):
12 f.chdir_to_tmp = False
13 return f
14
15
16 class TestDist(object):
17
18 def setup_method(self, meth):
19 self.executable = os.path.abspath(sys.executable)
20 self.rootdir = os.path.abspath(os.path.dirname(os.path.dirname(
21 cffi.__file__)))
22 self.udir = udir.join(meth.__name__)
23 os.mkdir(str(self.udir))
24 if meth.chdir_to_tmp:
25 self.saved_cwd = os.getcwd()
26 os.chdir(str(self.udir))
27
28 def teardown_method(self, meth):
29 if hasattr(self, 'saved_cwd'):
30 os.chdir(self.saved_cwd)
31
32 def run(self, args, cwd=None):
33 env = os.environ.copy()
34 # a horrible hack to prevent distutils from finding ~/.pydistutils.cfg
35 # (there is the --no-user-cfg option, but not in Python 2.6...)
36 env['HOME'] = '/this/path/does/not/exist'
37 if cwd is None:
38 newpath = self.rootdir
39 if 'PYTHONPATH' in env:
40 newpath += os.pathsep + env['PYTHONPATH']
41 env['PYTHONPATH'] = newpath
42 subprocess.check_call([self.executable] + args, cwd=cwd, env=env)
43
44 def _prepare_setuptools(self):
45 if hasattr(TestDist, '_setuptools_ready'):
46 return
47 try:
48 import setuptools
49 except ImportError:
50 py.test.skip("setuptools not found")
51 if os.path.exists(os.path.join(self.rootdir, 'setup.py')):
52 self.run(['setup.py', 'egg_info'], cwd=self.rootdir)
53 TestDist._setuptools_ready = True
54
55 def check_produced_files(self, content, curdir=None):
56 if curdir is None:
57 curdir = str(self.udir)
58 found_so = None
59 for name in os.listdir(curdir):
60 if (name.endswith('.so') or name.endswith('.pyd') or
61 name.endswith('.dylib') or name.endswith('.dll')):
62 found_so = os.path.join(curdir, name)
63 # foo.so => foo
64 parts = name.split('.')
65 del parts[-1]
66 if len(parts) > 1 and parts[-1] != 'bar':
67 # foo.cpython-34m.so => foo, but foo.bar.so => foo.bar
68 del parts[-1]
69 name = '.'.join(parts)
70 # foo_d => foo (Python 2 debug builds)
71 if name.endswith('_d') and hasattr(sys, 'gettotalrefcount'):
72 name = name[:-2]
73 name += '.SO'
74 if name.startswith('pycparser') and name.endswith('.egg'):
75 continue # no clue why this shows up sometimes and not others
76 if name == '.eggs':
77 continue # seems new in 3.5, ignore it
78 assert name in content, "found unexpected file %r" % (
79 os.path.join(curdir, name),)
80 value = content.pop(name)
81 if value is None:
82 assert name.endswith('.SO') or (
83 os.path.isfile(os.path.join(curdir, name)))
84 else:
85 subdir = os.path.join(curdir, name)
86 assert os.path.isdir(subdir)
87 if value == '?':
88 continue
89 found_so = self.check_produced_files(value, subdir) or found_so
90 assert content == {}, "files or dirs not produced in %r: %r" % (
91 curdir, content.keys())
92 return found_so
93
94 @chdir_to_tmp
95 def test_empty(self):
96 self.check_produced_files({})
97
98 @chdir_to_tmp
99 def test_abi_emit_python_code_1(self):
100 ffi = cffi.FFI()
101 ffi.set_source("package_name_1.mymod", None)
102 ffi.emit_python_code('xyz.py')
103 self.check_produced_files({'xyz.py': None})
104
105 @chdir_to_tmp
106 def test_abi_emit_python_code_2(self):
107 ffi = cffi.FFI()
108 ffi.set_source("package_name_1.mymod", None)
109 py.test.raises(IOError, ffi.emit_python_code, 'unexisting/xyz.py')
110
111 @from_outside
112 def test_abi_emit_python_code_3(self):
113 ffi = cffi.FFI()
114 ffi.set_source("package_name_1.mymod", None)
115 ffi.emit_python_code(str(self.udir.join('xyt.py')))
116 self.check_produced_files({'xyt.py': None})
117
118 @chdir_to_tmp
119 def test_abi_compile_1(self):
120 ffi = cffi.FFI()
121 ffi.set_source("mod_name_in_package.mymod", None)
122 x = ffi.compile()
123 self.check_produced_files({'mod_name_in_package': {'mymod.py': None}})
124 assert x == os.path.join('.', 'mod_name_in_package', 'mymod.py')
125
126 @chdir_to_tmp
127 def test_abi_compile_2(self):
128 ffi = cffi.FFI()
129 ffi.set_source("mod_name_in_package.mymod", None)
130 x = ffi.compile('build2')
131 self.check_produced_files({'build2': {
132 'mod_name_in_package': {'mymod.py': None}}})
133 assert x == os.path.join('build2', 'mod_name_in_package', 'mymod.py')
134
135 @from_outside
136 def test_abi_compile_3(self):
137 ffi = cffi.FFI()
138 ffi.set_source("mod_name_in_package.mymod", None)
139 tmpdir = str(self.udir.join('build3'))
140 x = ffi.compile(tmpdir)
141 self.check_produced_files({'build3': {
142 'mod_name_in_package': {'mymod.py': None}}})
143 assert x == os.path.join(tmpdir, 'mod_name_in_package', 'mymod.py')
144
145 @chdir_to_tmp
146 def test_api_emit_c_code_1(self):
147 ffi = cffi.FFI()
148 ffi.set_source("package_name_1.mymod", "/*code would be here*/")
149 ffi.emit_c_code('xyz.c')
150 self.check_produced_files({'xyz.c': None})
151
152 @chdir_to_tmp
153 def test_api_emit_c_code_2(self):
154 ffi = cffi.FFI()
155 ffi.set_source("package_name_1.mymod", "/*code would be here*/")
156 py.test.raises(IOError, ffi.emit_c_code, 'unexisting/xyz.c')
157
158 @from_outside
159 def test_api_emit_c_code_3(self):
160 ffi = cffi.FFI()
161 ffi.set_source("package_name_1.mymod", "/*code would be here*/")
162 ffi.emit_c_code(str(self.udir.join('xyu.c')))
163 self.check_produced_files({'xyu.c': None})
164
165 @chdir_to_tmp
166 def test_api_compile_1(self):
167 ffi = cffi.FFI()
168 ffi.set_source("mod_name_in_package.mymod", "/*code would be here*/")
169 x = ffi.compile()
170 if sys.platform != 'win32':
171 sofile = self.check_produced_files({
172 'mod_name_in_package': {'mymod.SO': None,
173 'mymod.c': None,
174 'mymod.o': None}})
175 assert os.path.isabs(x) and os.path.samefile(x, sofile)
176 else:
177 self.check_produced_files({
178 'mod_name_in_package': {'mymod.SO': None,
179 'mymod.c': None},
180 'Release': '?'})
181
182 @chdir_to_tmp
183 def test_api_compile_2(self):
184 ffi = cffi.FFI()
185 ffi.set_source("mod_name_in_package.mymod", "/*code would be here*/")
186 x = ffi.compile('output')
187 if sys.platform != 'win32':
188 sofile = self.check_produced_files({
189 'output': {'mod_name_in_package': {'mymod.SO': None,
190 'mymod.c': None,
191 'mymod.o': None}}})
192 assert os.path.isabs(x) and os.path.samefile(x, sofile)
193 else:
194 self.check_produced_files({
195 'output': {'mod_name_in_package': {'mymod.SO': None,
196 'mymod.c': None},
197 'Release': '?'}})
198
199 @from_outside
200 def test_api_compile_3(self):
201 ffi = cffi.FFI()
202 ffi.set_source("mod_name_in_package.mymod", "/*code would be here*/")
203 x = ffi.compile(str(self.udir.join('foo')))
204 if sys.platform != 'win32':
205 sofile = self.check_produced_files({
206 'foo': {'mod_name_in_package': {'mymod.SO': None,
207 'mymod.c': None,
208 'mymod.o': None}}})
209 assert os.path.isabs(x) and os.path.samefile(x, sofile)
210 else:
211 self.check_produced_files({
212 'foo': {'mod_name_in_package': {'mymod.SO': None,
213 'mymod.c': None},
214 'Release': '?'}})
215
216 @chdir_to_tmp
217 def test_api_compile_explicit_target_1(self):
218 ffi = cffi.FFI()
219 ffi.set_source("mod_name_in_package.mymod", "/*code would be here*/")
220 x = ffi.compile(target="foo.bar.*")
221 if sys.platform != 'win32':
222 sofile = self.check_produced_files({
223 'mod_name_in_package': {'foo.bar.SO': None,
224 'mymod.c': None,
225 'mymod.o': None}})
226 assert os.path.isabs(x) and os.path.samefile(x, sofile)
227 else:
228 self.check_produced_files({
229 'mod_name_in_package': {'foo.bar.SO': None,
230 'mymod.c': None},
231 'Release': '?'})
232
233 @chdir_to_tmp
234 def test_api_compile_explicit_target_3(self):
235 ffi = cffi.FFI()
236 ffi.set_source("mod_name_in_package.mymod", "/*code would be here*/")
237 x = ffi.compile(target="foo.bar.baz")
238 if sys.platform != 'win32':
239 self.check_produced_files({
240 'mod_name_in_package': {'foo.bar.baz': None,
241 'mymod.c': None,
242 'mymod.o': None}})
243 sofile = os.path.join(str(self.udir),
244 'mod_name_in_package', 'foo.bar.baz')
245 assert os.path.isabs(x) and os.path.samefile(x, sofile)
246 else:
247 self.check_produced_files({
248 'mod_name_in_package': {'foo.bar.baz': None,
249 'mymod.c': None},
250 'Release': '?'})
251
252 @chdir_to_tmp
253 def test_api_distutils_extension_1(self):
254 ffi = cffi.FFI()
255 ffi.set_source("mod_name_in_package.mymod", "/*code would be here*/")
256 ext = ffi.distutils_extension()
257 self.check_produced_files({'build': {
258 'mod_name_in_package': {'mymod.c': None}}})
259 if hasattr(os.path, 'samefile'):
260 assert os.path.samefile(ext.sources[0],
261 'build/mod_name_in_package/mymod.c')
262
263 @from_outside
264 def test_api_distutils_extension_2(self):
265 ffi = cffi.FFI()
266 ffi.set_source("mod_name_in_package.mymod", "/*code would be here*/")
267 ext = ffi.distutils_extension(str(self.udir.join('foo')))
268 self.check_produced_files({'foo': {
269 'mod_name_in_package': {'mymod.c': None}}})
270 if hasattr(os.path, 'samefile'):
271 assert os.path.samefile(ext.sources[0],
272 str(self.udir.join('foo/mod_name_in_package/mymod.c')))
273
274
275 def _make_distutils_api(self):
276 os.mkdir("src")
277 os.mkdir(os.path.join("src", "pack1"))
278 with open(os.path.join("src", "pack1", "__init__.py"), "w") as f:
279 pass
280 with open("setup.py", "w") as f:
281 f.write("""if 1:
282 # https://bugs.python.org/issue23246
283 import sys
284 if sys.platform == 'win32':
285 try:
286 import setuptools
287 except ImportError:
288 pass
289
290 import cffi
291 ffi = cffi.FFI()
292 ffi.set_source("pack1.mymod", "/*code would be here*/")
293
294 from distutils.core import setup
295 setup(name='example1',
296 version='0.1',
297 packages=['pack1'],
298 package_dir={'': 'src'},
299 ext_modules=[ffi.distutils_extension()])
300 """)
301
302 @chdir_to_tmp
303 def test_distutils_api_1(self):
304 self._make_distutils_api()
305 self.run(["setup.py", "build"])
306 self.check_produced_files({'setup.py': None,
307 'build': '?',
308 'src': {'pack1': {'__init__.py': None}}})
309
310 @chdir_to_tmp
311 def test_distutils_api_2(self):
312 self._make_distutils_api()
313 self.run(["setup.py", "build_ext", "-i"])
314 self.check_produced_files({'setup.py': None,
315 'build': '?',
316 'src': {'pack1': {'__init__.py': None,
317 'mymod.SO': None}}})
318
319 def _make_setuptools_abi(self):
320 self._prepare_setuptools()
321 os.mkdir("src0")
322 os.mkdir(os.path.join("src0", "pack2"))
323 with open(os.path.join("src0", "pack2", "__init__.py"), "w") as f:
324 pass
325 with open(os.path.join("src0", "pack2", "_build.py"), "w") as f:
326 f.write("""if 1:
327 import cffi
328 ffi = cffi.FFI()
329 ffi.set_source("pack2.mymod", None)
330 """)
331 with open("setup.py", "w") as f:
332 f.write("""if 1:
333 from setuptools import setup
334 setup(name='example1',
335 version='0.1',
336 packages=['pack2'],
337 package_dir={'': 'src0'},
338 cffi_modules=["src0/pack2/_build.py:ffi"])
339 """)
340
341 @chdir_to_tmp
342 def test_setuptools_abi_1(self):
343 self._make_setuptools_abi()
344 self.run(["setup.py", "build"])
345 self.check_produced_files({'setup.py': None,
346 'build': '?',
347 'src0': {'pack2': {'__init__.py': None,
348 '_build.py': None}}})
349
350 @chdir_to_tmp
351 def test_setuptools_abi_2(self):
352 self._make_setuptools_abi()
353 self.run(["setup.py", "build_ext", "-i"])
354 self.check_produced_files({'setup.py': None,
355 'src0': {'pack2': {'__init__.py': None,
356 '_build.py': None,
357 'mymod.py': None}}})
358
359 def _make_setuptools_api(self):
360 self._prepare_setuptools()
361 os.mkdir("src1")
362 os.mkdir(os.path.join("src1", "pack3"))
363 with open(os.path.join("src1", "pack3", "__init__.py"), "w") as f:
364 pass
365 with open(os.path.join("src1", "pack3", "_build.py"), "w") as f:
366 f.write("""if 1:
367 import cffi
368 ffi = cffi.FFI()
369 ffi.set_source("pack3.mymod", "/*code would be here*/")
370 ffi._hi_there = 42
371 """)
372 with open("setup.py", "w") as f:
373 f.write("from __future__ import print_function\n"
374 """if 1:
375 from setuptools import setup
376 from distutils.command.build_ext import build_ext
377 import os
378
379 class TestBuildExt(build_ext):
380 def pre_run(self, ext, ffi):
381 print('_make_setuptools_api: in pre_run:', end=" ")
382 assert ffi._hi_there == 42
383 assert ext.name == "pack3.mymod"
384 fn = os.path.join(os.path.dirname(self.build_lib),
385 '..', 'see_me')
386 print('creating %r' % (fn,))
387 open(fn, 'w').close()
388
389 setup(name='example1',
390 version='0.1',
391 packages=['pack3'],
392 package_dir={'': 'src1'},
393 cffi_modules=["src1/pack3/_build.py:ffi"],
394 cmdclass={'build_ext': TestBuildExt},
395 )
396 """)
397
398 @chdir_to_tmp
399 def test_setuptools_api_1(self):
400 self._make_setuptools_api()
401 self.run(["setup.py", "build"])
402 self.check_produced_files({'setup.py': None,
403 'build': '?',
404 'see_me': None,
405 'src1': {'pack3': {'__init__.py': None,
406 '_build.py': None}}})
407
408 @chdir_to_tmp
409 def test_setuptools_api_2(self):
410 self._make_setuptools_api()
411 self.run(["setup.py", "build_ext", "-i"])
412 self.check_produced_files({'setup.py': None,
413 'build': '?',
414 'see_me': None,
415 'src1': {'pack3': {'__init__.py': None,
416 '_build.py': None,
417 'mymod.SO': None}}})
+0
-5
pypy/module/test_lib_pypy/cffi_tests/conftest.py less more
0 import sys
1
2 def pytest_ignore_collect(path):
3 if '__pypy__' not in sys.builtin_module_names:
4 return True
+0
-1
pypy/module/test_lib_pypy/cffi_tests/embedding/__init__.py less more
0 # Generated by pypy/tool/import_cffi.py
+0
-22
pypy/module/test_lib_pypy/cffi_tests/embedding/add1-test.c less more
0 /* Generated by pypy/tool/import_cffi.py */
1 #include <stdio.h>
2
3 #ifdef _MSC_VER
4 #include <windows.h>
5 #endif
6
7 extern int add1(int, int);
8
9
10 int main(void)
11 {
12 int x, y;
13 x = add1(40, 2);
14 y = add1(100, -5);
15 printf("got: %d %d\n", x, y);
16 #ifdef _MSC_VER
17 if (x == 0 && y == 0)
18 Sleep(2000);
19 #endif
20 return 0;
21 }
+0
-34
pypy/module/test_lib_pypy/cffi_tests/embedding/add1.py less more
0 # Generated by pypy/tool/import_cffi.py
1 import cffi
2
3 ffi = cffi.FFI()
4
5 ffi.embedding_api("""
6 int add1(int, int);
7 """)
8
9 ffi.embedding_init_code(r"""
10 import sys, time
11 sys.stdout.write("preparing")
12 for i in range(3):
13 sys.stdout.flush()
14 time.sleep(0.02)
15 sys.stdout.write(".")
16 sys.stdout.write("\n")
17
18 from _add1_cffi import ffi
19
20 int(ord("A")) # check that built-ins are there
21
22 @ffi.def_extern()
23 def add1(x, y):
24 sys.stdout.write("adding %d and %d\n" % (x, y))
25 sys.stdout.flush()
26 return x + y
27 """)
28
29 ffi.set_source("_add1_cffi", """
30 """)
31
32 fn = ffi.compile(verbose=True)
33 print('FILENAME: %s' % (fn,))
+0
-15
pypy/module/test_lib_pypy/cffi_tests/embedding/add2-test.c less more
0 /* Generated by pypy/tool/import_cffi.py */
1 #include <stdio.h>
2
3 extern int add1(int, int);
4 extern int add2(int, int, int);
5
6
7 int main(void)
8 {
9 int x, y;
10 x = add1(40, 2);
11 y = add2(100, -5, -20);
12 printf("got: %d %d\n", x, y);
13 return 0;
14 }
+0
-30
pypy/module/test_lib_pypy/cffi_tests/embedding/add2.py less more
0 # Generated by pypy/tool/import_cffi.py
1 import cffi
2
3 ffi = cffi.FFI()
4
5 ffi.embedding_api("""
6 int add2(int, int, int);
7 """)
8
9 ffi.embedding_init_code(r"""
10 import sys
11 sys.stdout.write("prepADD2\n")
12
13 assert '_add2_cffi' in sys.modules
14 m = sys.modules['_add2_cffi']
15 import _add2_cffi
16 ffi = _add2_cffi.ffi
17
18 @ffi.def_extern()
19 def add2(x, y, z):
20 sys.stdout.write("adding %d and %d and %d\n" % (x, y, z))
21 sys.stdout.flush()
22 return x + y + z
23 """)
24
25 ffi.set_source("_add2_cffi", """
26 """)
27
28 fn = ffi.compile(verbose=True)
29 print('FILENAME: %s' % (fn,))
+0
-25
pypy/module/test_lib_pypy/cffi_tests/embedding/add3.py less more
0 # Generated by pypy/tool/import_cffi.py
1 import cffi
2
3 ffi = cffi.FFI()
4
5 ffi.embedding_api("""
6 int add3(int, int, int, int);
7 """)
8
9 ffi.embedding_init_code(r"""
10 from _add3_cffi import ffi
11 import sys
12
13 @ffi.def_extern()
14 def add3(x, y, z, t):
15 sys.stdout.write("adding %d, %d, %d, %d\n" % (x, y, z, t))
16 sys.stdout.flush()
17 return x + y + z + t
18 """)
19
20 ffi.set_source("_add3_cffi", """
21 """)
22
23 fn = ffi.compile(verbose=True)
24 print('FILENAME: %s' % (fn,))
+0
-28
pypy/module/test_lib_pypy/cffi_tests/embedding/add_recursive-test.c less more
0 /* Generated by pypy/tool/import_cffi.py */
1 #include <stdio.h>
2
3 #ifdef _MSC_VER
4 # define DLLIMPORT __declspec(dllimport)
5 #else
6 # define DLLIMPORT extern
7 #endif
8
9 DLLIMPORT int add_rec(int, int);
10 DLLIMPORT int (*my_callback)(int);
11
12 static int some_callback(int x)
13 {
14 printf("some_callback(%d)\n", x);
15 fflush(stdout);
16 return add_rec(x, 9);
17 }
18
19 int main(void)
20 {
21 int x, y;
22 my_callback = some_callback;
23 x = add_rec(40, 2);
24 y = add_rec(100, -5);
25 printf("got: %d %d\n", x, y);
26 return 0;
27 }
+0
-34
pypy/module/test_lib_pypy/cffi_tests/embedding/add_recursive.py less more
0 # Generated by pypy/tool/import_cffi.py
1 import cffi
2
3 ffi = cffi.FFI()
4
5 ffi.embedding_api("""
6 int (*my_callback)(int);
7 int add_rec(int, int);
8 """)
9
10 ffi.embedding_init_code(r"""
11 from _add_recursive_cffi import ffi, lib
12 import sys
13 print("preparing REC")
14 sys.stdout.flush()
15
16 @ffi.def_extern()
17 def add_rec(x, y):
18 print("adding %d and %d" % (x, y))
19 sys.stdout.flush()
20 return x + y
21
22 x = lib.my_callback(400)
23 print('<<< %d >>>' % (x,))
24 """)
25
26 ffi.set_source("_add_recursive_cffi", """
27 /* use CFFI_DLLEXPORT: on windows, it expands to __declspec(dllexport),
28 which is needed to export a variable from a dll */
29 CFFI_DLLEXPORT int (*my_callback)(int);
30 """)
31
32 fn = ffi.compile(verbose=True)
33 print('FILENAME: %s' % (fn,))
+0
-11
pypy/module/test_lib_pypy/cffi_tests/embedding/empty.py less more
0 # Generated by pypy/tool/import_cffi.py
1 import cffi
2
3 ffi = cffi.FFI()
4
5 ffi.embedding_api("")
6
7 ffi.set_source("_empty_cffi", "")
8
9 fn = ffi.compile(verbose=True)
10 print('FILENAME: %s' % (fn,))
+0
-19
pypy/module/test_lib_pypy/cffi_tests/embedding/initerror.py less more
0 # Generated by pypy/tool/import_cffi.py
1 import cffi
2
3 ffi = cffi.FFI()
4
5 ffi.embedding_api("""
6 int add1(int, int);
7 """)
8
9 ffi.embedding_init_code(r"""
10 raise KeyError
11 """)
12
13 ffi.set_source("_initerror_cffi", """
14 """)
15
16 fn = ffi.compile(verbose=True)
17 print('FILENAME: %s' % (fn,))
18
+0
-91
pypy/module/test_lib_pypy/cffi_tests/embedding/perf-test.c less more
0 /* Generated by pypy/tool/import_cffi.py */
1 #include <stdio.h>
2 #include <assert.h>
3 #include <sys/time.h>
4 #ifdef PTEST_USE_THREAD
5 # include <pthread.h>
6 static pthread_mutex_t mutex1 = PTHREAD_MUTEX_INITIALIZER;
7 static pthread_cond_t cond1 = PTHREAD_COND_INITIALIZER;
8 static int remaining;
9 #endif
10
11
12 extern int add1(int, int);
13
14
15 static double time_delta(struct timeval *stop, struct timeval *start)
16 {
17 return (stop->tv_sec - start->tv_sec) +
18 1e-6 * (stop->tv_usec - start->tv_usec);
19 }
20
21 static double measure(void)
22 {
23 long long i, iterations;
24 int result;
25 struct timeval start, stop;
26 double elapsed;
27
28 add1(0, 0); /* prepare off-line */
29
30 i = 0;
31 iterations = 1000;
32 result = gettimeofday(&start, NULL);
33 assert(result == 0);
34
35 while (1) {
36 for (; i < iterations; i++) {
37 add1(((int)i) & 0xaaaaaa, ((int)i) & 0x555555);
38 }
39 result = gettimeofday(&stop, NULL);
40 assert(result == 0);
41
42 elapsed = time_delta(&stop, &start);
43 assert(elapsed >= 0.0);
44 if (elapsed > 2.5)
45 break;
46 iterations = iterations * 3 / 2;
47 }
48
49 return elapsed / (double)iterations;
50 }
51
52 static void *start_routine(void *arg)
53 {
54 double t = measure();
55 printf("time per call: %.3g\n", t);
56
57 #ifdef PTEST_USE_THREAD
58 pthread_mutex_lock(&mutex1);
59 remaining -= 1;
60 if (!remaining)
61 pthread_cond_signal(&cond1);
62 pthread_mutex_unlock(&mutex1);
63 #endif
64
65 return arg;
66 }
67
68
69 int main(void)
70 {
71 #ifndef PTEST_USE_THREAD
72 start_routine(0);
73 #else
74 pthread_t th;
75 int i, status;
76
77 add1(0, 0); /* this is the main thread */
78
79 remaining = PTEST_USE_THREAD;
80 for (i = 0; i < PTEST_USE_THREAD; i++) {
81 status = pthread_create(&th, NULL, start_routine, NULL);
82 assert(status == 0);
83 }
84 pthread_mutex_lock(&mutex1);
85 while (remaining)
86 pthread_cond_wait(&cond1, &mutex1);
87 pthread_mutex_unlock(&mutex1);
88 #endif
89 return 0;
90 }
+0
-22
pypy/module/test_lib_pypy/cffi_tests/embedding/perf.py less more
0 # Generated by pypy/tool/import_cffi.py
1 import cffi
2
3 ffi = cffi.FFI()
4
5 ffi.embedding_api("""
6 int add1(int, int);
7 """)
8
9 ffi.embedding_init_code(r"""
10 from _perf_cffi import ffi
11
12 @ffi.def_extern()
13 def add1(x, y):
14 return x + y
15 """)
16
17 ffi.set_source("_perf_cffi", """
18 """)
19
20 fn = ffi.compile(verbose=True)
21 print('FILENAME: %s' % (fn,))
+0
-208
pypy/module/test_lib_pypy/cffi_tests/embedding/test_basic.py less more
0 # Generated by pypy/tool/import_cffi.py
1 import py
2 import sys, os, re
3 import shutil, subprocess, time
4 from pypy.module.test_lib_pypy.cffi_tests.udir import udir
5 import cffi
6
7
8 local_dir = os.path.dirname(os.path.abspath(__file__))
9 _link_error = '?'
10
11 def check_lib_python_found(tmpdir):
12 global _link_error
13 if _link_error == '?':
14 ffi = cffi.FFI()
15 kwds = {}
16 ffi._apply_embedding_fix(kwds)
17 ffi.set_source("_test_lib_python_found", "", **kwds)
18 try:
19 ffi.compile(tmpdir=tmpdir, verbose=True)
20 except cffi.VerificationError as e:
21 _link_error = e
22 else:
23 _link_error = None
24 if _link_error:
25 py.test.skip(str(_link_error))
26
27
28 def prefix_pythonpath():
29 cffi_base = os.path.dirname(os.path.dirname(local_dir))
30 pythonpath = org_env.get('PYTHONPATH', '').split(os.pathsep)
31 if cffi_base not in pythonpath:
32 pythonpath.insert(0, cffi_base)
33 return os.pathsep.join(pythonpath)
34
35 def copy_away_env():
36 global org_env
37 try:
38 org_env
39 except NameError:
40 org_env = os.environ.copy()
41
42
43 class EmbeddingTests:
44 _compiled_modules = {}
45
46 def setup_method(self, meth):
47 check_lib_python_found(str(udir.ensure('embedding', dir=1)))
48 self._path = udir.join('embedding', meth.__name__)
49 if sys.platform == "win32" or sys.platform == "darwin":
50 self._compiled_modules.clear() # workaround
51
52 def get_path(self):
53 return str(self._path.ensure(dir=1))
54
55 def _run_base(self, args, **kwds):
56 print('RUNNING:', args, kwds)
57 return subprocess.Popen(args, **kwds)
58
59 def _run(self, args):
60 popen = self._run_base(args, cwd=self.get_path(),
61 stdout=subprocess.PIPE,
62 universal_newlines=True)
63 output = popen.stdout.read()
64 err = popen.wait()
65 if err:
66 raise OSError("popen failed with exit code %r: %r" % (
67 err, args))
68 print(output.rstrip())
69 return output
70
71 def prepare_module(self, name):
72 self.patch_environment()
73 if name not in self._compiled_modules:
74 path = self.get_path()
75 filename = '%s.py' % name
76 # NOTE: if you have an .egg globally installed with an older
77 # version of cffi, this will not work, because sys.path ends
78 # up with the .egg before the PYTHONPATH entries. I didn't
79 # find a solution to that: we could hack sys.path inside the
80 # script run here, but we can't hack it in the same way in
81 # execute().
82 pathname = os.path.join(path, filename)
83 with open(pathname, 'w') as g:
84 g.write('''
85 # https://bugs.python.org/issue23246
86 import sys
87 if sys.platform == 'win32':
88 try:
89 import setuptools
90 except ImportError:
91 pass
92 ''')
93 with open(os.path.join(local_dir, filename), 'r') as f:
94 g.write(f.read())
95
96 output = self._run([sys.executable, pathname])
97 match = re.compile(r"\bFILENAME: (.+)").search(output)
98 assert match
99 dynamic_lib_name = match.group(1)
100 if sys.platform == 'win32':
101 assert dynamic_lib_name.endswith('_cffi.dll')
102 elif sys.platform == 'darwin':
103 assert dynamic_lib_name.endswith('_cffi.dylib')
104 else:
105 assert dynamic_lib_name.endswith('_cffi.so')
106 self._compiled_modules[name] = dynamic_lib_name
107 return self._compiled_modules[name]
108
109 def compile(self, name, modules, opt=False, threads=False, defines={}):
110 path = self.get_path()
111 filename = '%s.c' % name
112 shutil.copy(os.path.join(local_dir, filename), path)
113 shutil.copy(os.path.join(local_dir, 'thread-test.h'), path)
114 import distutils.ccompiler
115 curdir = os.getcwd()
116 try:
117 os.chdir(self.get_path())
118 c = distutils.ccompiler.new_compiler()
119 print('compiling %s with %r' % (name, modules))
120 extra_preargs = []
121 debug = True
122 if sys.platform == 'win32':
123 libfiles = []
124 for m in modules:
125 m = os.path.basename(m)
126 assert m.endswith('.dll')
127 libfiles.append('Release\\%s.lib' % m[:-4])
128 modules = libfiles
129 extra_preargs.append('/MANIFEST')
130 debug = False # you need to install extra stuff
131 # for this to work
132 elif threads:
133 extra_preargs.append('-pthread')
134 objects = c.compile([filename], macros=sorted(defines.items()),
135 debug=debug)
136 c.link_executable(objects + modules, name, extra_preargs=extra_preargs)
137 finally:
138 os.chdir(curdir)
139
140 def patch_environment(self):
141 copy_away_env()
142 path = self.get_path()
143 # for libpypy-c.dll or Python27.dll
144 path = os.path.split(sys.executable)[0] + os.path.pathsep + path
145 env_extra = {'PYTHONPATH': prefix_pythonpath()}
146 if sys.platform == 'win32':
147 envname = 'PATH'
148 else:
149 envname = 'LD_LIBRARY_PATH'
150 libpath = org_env.get(envname)
151 if libpath:
152 libpath = path + os.path.pathsep + libpath
153 else:
154 libpath = path
155 env_extra[envname] = libpath
156 for key, value in sorted(env_extra.items()):
157 if os.environ.get(key) != value:
158 print('* setting env var %r to %r' % (key, value))
159 os.environ[key] = value
160
161 def execute(self, name):
162 path = self.get_path()
163 print('running %r in %r' % (name, path))
164 executable_name = name
165 if sys.platform == 'win32':
166 executable_name = os.path.join(path, executable_name + '.exe')
167 else:
168 executable_name = os.path.join('.', executable_name)
169 popen = self._run_base([executable_name], cwd=path,
170 stdout=subprocess.PIPE,
171 universal_newlines=True)
172 result = popen.stdout.read()
173 err = popen.wait()
174 if err:
175 raise OSError("%r failed with exit code %r" % (name, err))
176 return result
177
178
179 class TestBasic(EmbeddingTests):
180 def test_empty(self):
181 empty_cffi = self.prepare_module('empty')
182
183 def test_basic(self):
184 add1_cffi = self.prepare_module('add1')
185 self.compile('add1-test', [add1_cffi])
186 output = self.execute('add1-test')
187 assert output == ("preparing...\n"
188 "adding 40 and 2\n"
189 "adding 100 and -5\n"
190 "got: 42 95\n")
191
192 def test_two_modules(self):
193 add1_cffi = self.prepare_module('add1')
194 add2_cffi = self.prepare_module('add2')
195 self.compile('add2-test', [add1_cffi, add2_cffi])
196 output = self.execute('add2-test')
197 assert output == ("preparing...\n"
198 "adding 40 and 2\n"
199 "prepADD2\n"
200 "adding 100 and -5 and -20\n"
201 "got: 42 75\n")
202
203 def test_init_time_error(self):
204 initerror_cffi = self.prepare_module('initerror')
205 self.compile('add1-test', [initerror_cffi])
206 output = self.execute('add1-test')
207 assert output == "got: 0 0\n" # plus lots of info to stderr
+0
-53
pypy/module/test_lib_pypy/cffi_tests/embedding/test_performance.py less more
0 # Generated by pypy/tool/import_cffi.py
1 import sys
2 from pypy.module.test_lib_pypy.cffi_tests.embedding.test_basic import EmbeddingTests
3
4 if sys.platform == 'win32':
5 import py
6 py.test.skip("written with POSIX functions")
7
8
9 class TestPerformance(EmbeddingTests):
10 def test_perf_single_threaded(self):
11 perf_cffi = self.prepare_module('perf')
12 self.compile('perf-test', [perf_cffi], opt=True)
13 output = self.execute('perf-test')
14 print('='*79)
15 print(output.rstrip())
16 print('='*79)
17
18 def test_perf_in_1_thread(self):
19 perf_cffi = self.prepare_module('perf')
20 self.compile('perf-test', [perf_cffi], opt=True, threads=True,
21 defines={'PTEST_USE_THREAD': '1'})
22 output = self.execute('perf-test')
23 print('='*79)
24 print(output.rstrip())
25 print('='*79)
26
27 def test_perf_in_2_threads(self):
28 perf_cffi = self.prepare_module('perf')
29 self.compile('perf-test', [perf_cffi], opt=True, threads=True,
30 defines={'PTEST_USE_THREAD': '2'})
31 output = self.execute('perf-test')
32 print('='*79)
33 print(output.rstrip())
34 print('='*79)
35
36 def test_perf_in_4_threads(self):
37 perf_cffi = self.prepare_module('perf')
38 self.compile('perf-test', [perf_cffi], opt=True, threads=True,
39 defines={'PTEST_USE_THREAD': '4'})
40 output = self.execute('perf-test')
41 print('='*79)
42 print(output.rstrip())
43 print('='*79)
44
45 def test_perf_in_8_threads(self):
46 perf_cffi = self.prepare_module('perf')
47 self.compile('perf-test', [perf_cffi], opt=True, threads=True,
48 defines={'PTEST_USE_THREAD': '8'})
49 output = self.execute('perf-test')
50 print('='*79)
51 print(output.rstrip())
52 print('='*79)
+0
-16
pypy/module/test_lib_pypy/cffi_tests/embedding/test_recursive.py less more
0 # Generated by pypy/tool/import_cffi.py
1 from pypy.module.test_lib_pypy.cffi_tests.embedding.test_basic import EmbeddingTests
2
3
4 class TestRecursive(EmbeddingTests):
5 def test_recursive(self):
6 add_recursive_cffi = self.prepare_module('add_recursive')
7 self.compile('add_recursive-test', [add_recursive_cffi])
8 output = self.execute('add_recursive-test')
9 assert output == ("preparing REC\n"
10 "some_callback(400)\n"
11 "adding 400 and 9\n"
12 "<<< 409 >>>\n"
13 "adding 40 and 2\n"
14 "adding 100 and -5\n"
15 "got: 42 95\n")
+0
-62
pypy/module/test_lib_pypy/cffi_tests/embedding/test_thread.py less more
0 # Generated by pypy/tool/import_cffi.py
1 from pypy.module.test_lib_pypy.cffi_tests.embedding.test_basic import EmbeddingTests
2
3
4 class TestThread(EmbeddingTests):
5 def test_first_calls_in_parallel(self):
6 add1_cffi = self.prepare_module('add1')
7 self.compile('thread1-test', [add1_cffi], threads=True)
8 for i in range(50):
9 output = self.execute('thread1-test')
10 assert output == ("starting\n"
11 "preparing...\n" +
12 "adding 40 and 2\n" * 10 +
13 "done\n")
14
15 def _take_out(self, text, content):
16 assert content in text
17 i = text.index(content)
18 return text[:i] + text[i+len(content):]
19
20 def test_init_different_modules_in_different_threads(self):
21 add1_cffi = self.prepare_module('add1')
22 add2_cffi = self.prepare_module('add2')
23 self.compile('thread2-test', [add1_cffi, add2_cffi], threads=True)
24 output = self.execute('thread2-test')
25 output = self._take_out(output, "preparing")
26 output = self._take_out(output, ".")
27 output = self._take_out(output, ".")
28 # at least the 3rd dot should be after everything from ADD2
29 assert output == ("starting\n"
30 "prepADD2\n"
31 "adding 1000 and 200 and 30\n"
32 ".\n"
33 "adding 40 and 2\n"
34 "done\n")
35
36 def test_alt_issue(self):
37 add1_cffi = self.prepare_module('add1')
38 add2_cffi = self.prepare_module('add2')
39 self.compile('thread2-test', [add1_cffi, add2_cffi],
40 threads=True, defines={'T2TEST_AGAIN_ADD1': '1'})
41 output = self.execute('thread2-test')
42 output = self._take_out(output, "adding 40 and 2\n")
43 assert output == ("starting\n"
44 "preparing...\n"
45 "adding -1 and -1\n"
46 "prepADD2\n"
47 "adding 1000 and 200 and 30\n"
48 "done\n")
49
50 def test_load_in_parallel_more(self):
51 add2_cffi = self.prepare_module('add2')
52 add3_cffi = self.prepare_module('add3')
53 self.compile('thread3-test', [add2_cffi, add3_cffi], threads=True)
54 for i in range(150):
55 output = self.execute('thread3-test')
56 for j in range(10):
57 output = self._take_out(output, "adding 40 and 2 and 100\n")
58 output = self._take_out(output, "adding 1000, 200, 30, 4\n")
59 assert output == ("starting\n"
60 "prepADD2\n"
61 "done\n")
+0
-11
pypy/module/test_lib_pypy/cffi_tests/embedding/test_tlocal.py less more
0 # Generated by pypy/tool/import_cffi.py
1 from pypy.module.test_lib_pypy.cffi_tests.embedding.test_basic import EmbeddingTests
2
3
4 class TestThreadLocal(EmbeddingTests):
5 def test_thread_local(self):
6 tlocal_cffi = self.prepare_module('tlocal')
7 self.compile('tlocal-test', [tlocal_cffi], threads=True)
8 for i in range(10):
9 output = self.execute('tlocal-test')
10 assert output == "done\n"
+0
-97
pypy/module/test_lib_pypy/cffi_tests/embedding/thread-test.h less more
0 /* Generated by pypy/tool/import_cffi.py */
1 /************************************************************/
2 #ifndef _MSC_VER
3 /************************************************************/
4
5
6 #include <pthread.h>
7
8 /* don't include <semaphore.h>, it is not available on OS/X */
9
10 typedef struct {
11 pthread_mutex_t mutex1;
12 pthread_cond_t cond1;
13 unsigned int value;
14 } sem_t;
15
16 static int sem_init(sem_t *sem, int pshared, unsigned int value)
17 {
18 assert(pshared == 0);
19 sem->value = value;
20 return (pthread_mutex_init(&sem->mutex1, NULL) ||
21 pthread_cond_init(&sem->cond1, NULL));
22 }
23
24 static int sem_post(sem_t *sem)
25 {
26 pthread_mutex_lock(&sem->mutex1);
27 sem->value += 1;
28 pthread_cond_signal(&sem->cond1);
29 pthread_mutex_unlock(&sem->mutex1);
30 return 0;
31 }
32
33 static int sem_wait(sem_t *sem)
34 {
35 pthread_mutex_lock(&sem->mutex1);
36 while (sem->value == 0)
37 pthread_cond_wait(&sem->cond1, &sem->mutex1);
38 sem->value -= 1;
39 pthread_mutex_unlock(&sem->mutex1);
40 return 0;
41 }
42
43
44 /************************************************************/
45 #else
46 /************************************************************/
47
48
49 /* Very quick and dirty, just what I need for these tests.
50 Don't use directly in any real code!
51 */
52
53 #include <Windows.h>
54 #include <assert.h>
55
56 typedef HANDLE sem_t;
57 typedef HANDLE pthread_t;
58
59 static int sem_init(sem_t *sem, int pshared, unsigned int value)
60 {
61 assert(pshared == 0);
62 assert(value == 0);
63 *sem = CreateSemaphore(NULL, 0, 999, NULL);
64 return *sem ? 0 : -1;
65 }
66
67 static int sem_post(sem_t *sem)
68 {
69 return ReleaseSemaphore(*sem, 1, NULL) ? 0 : -1;
70 }
71
72 static int sem_wait(sem_t *sem)
73 {
74 WaitForSingleObject(*sem, INFINITE);
75 return 0;
76 }
77
78 static DWORD WINAPI myThreadProc(LPVOID lpParameter)
79 {
80 void *(* start_routine)(void *) = (void *(*)(void *))lpParameter;
81 start_routine(NULL);
82 return 0;
83 }
84
85 static int pthread_create(pthread_t *thread, void *attr,
86 void *start_routine(void *), void *arg)
87 {
88 assert(arg == NULL);
89 *thread = CreateThread(NULL, 0, myThreadProc, start_routine, 0, NULL);
90 return *thread ? 0 : -1;
91 }
92
93
94 /************************************************************/
95 #endif
96 /************************************************************/
+0
-44
pypy/module/test_lib_pypy/cffi_tests/embedding/thread1-test.c less more
0 /* Generated by pypy/tool/import_cffi.py */
1 #include <stdio.h>
2 #include <assert.h>
3 #include "thread-test.h"
4
5 #define NTHREADS 10
6
7
8 extern int add1(int, int);
9
10 static sem_t done;
11
12
13 static void *start_routine(void *arg)
14 {
15 int x, status;
16 x = add1(40, 2);
17 assert(x == 42);
18
19 status = sem_post(&done);
20 assert(status == 0);
21
22 return arg;
23 }
24
25 int main(void)
26 {
27 pthread_t th;
28 int i, status = sem_init(&done, 0, 0);
29 assert(status == 0);
30
31 printf("starting\n");
32 fflush(stdout);
33 for (i = 0; i < NTHREADS; i++) {
34 status = pthread_create(&th, NULL, start_routine, NULL);
35 assert(status == 0);
36 }
37 for (i = 0; i < NTHREADS; i++) {
38 status = sem_wait(&done);
39 assert(status == 0);
40 }
41 printf("done\n");
42 return 0;
43 }
+0
-58
pypy/module/test_lib_pypy/cffi_tests/embedding/thread2-test.c less more
0 /* Generated by pypy/tool/import_cffi.py */
1 #include <stdio.h>
2 #include <assert.h>
3 #include "thread-test.h"
4
5 extern int add1(int, int);
6 extern int add2(int, int, int);
7
8 static sem_t done;
9
10
11 static void *start_routine_1(void *arg)
12 {
13 int x, status;
14 x = add1(40, 2);
15 assert(x == 42);
16
17 status = sem_post(&done);
18 assert(status == 0);
19
20 return arg;
21 }
22
23 static void *start_routine_2(void *arg)
24 {
25 int x, status;
26 #ifdef T2TEST_AGAIN_ADD1
27 add1(-1, -1);
28 #endif
29 x = add2(1000, 200, 30);
30 assert(x == 1230);
31
32 status = sem_post(&done);
33 assert(status == 0);
34
35 return arg;
36 }
37
38 int main(void)
39 {
40 pthread_t th;
41 int i, status = sem_init(&done, 0, 0);
42 assert(status == 0);
43
44 printf("starting\n");
45 fflush(stdout);
46 status = pthread_create(&th, NULL, start_routine_1, NULL);
47 assert(status == 0);
48 status = pthread_create(&th, NULL, start_routine_2, NULL);
49 assert(status == 0);
50
51 for (i = 0; i < 2; i++) {
52 status = sem_wait(&done);
53 assert(status == 0);
54 }
55 printf("done\n");
56 return 0;
57 }
+0
-56
pypy/module/test_lib_pypy/cffi_tests/embedding/thread3-test.c less more
0 /* Generated by pypy/tool/import_cffi.py */
1 #include <stdio.h>
2 #include <assert.h>
3 #include "thread-test.h"
4
5 extern int add2(int, int, int);
6 extern int add3(int, int, int, int);
7
8 static sem_t done;
9
10
11 static void *start_routine_2(void *arg)
12 {
13 int x, status;
14 x = add2(40, 2, 100);
15 assert(x == 142);
16
17 status = sem_post(&done);
18 assert(status == 0);
19
20 return arg;
21 }
22
23 static void *start_routine_3(void *arg)
24 {
25 int x, status;
26 x = add3(1000, 200, 30, 4);
27 assert(x == 1234);
28
29 status = sem_post(&done);
30 assert(status == 0);
31
32 return arg;
33 }
34
35 int main(void)
36 {
37 pthread_t th;
38 int i, status = sem_init(&done, 0, 0);
39 assert(status == 0);
40
41 printf("starting\n");
42 fflush(stdout);
43 for (i = 0; i < 10; i++) {
44 status = pthread_create(&th, NULL, start_routine_2, NULL);
45 assert(status == 0);
46 status = pthread_create(&th, NULL, start_routine_3, NULL);
47 assert(status == 0);
48 }
49 for (i = 0; i < 20; i++) {
50 status = sem_wait(&done);
51 assert(status == 0);
52 }
53 printf("done\n");
54 return 0;
55 }
+0
-48
pypy/module/test_lib_pypy/cffi_tests/embedding/tlocal-test.c less more
0 /* Generated by pypy/tool/import_cffi.py */
1 #include <stdio.h>
2 #include <assert.h>
3 #include "thread-test.h"
4
5 #define NTHREADS 10
6
7
8 extern int add1(int, int);
9
10 static sem_t done;
11
12
13 static void *start_routine(void *arg)
14 {
15 int i, x, expected, status;
16
17 expected = add1(40, 2);
18 assert((expected % 1000) == 42);
19
20 for (i=0; i<10; i++) {
21 x = add1(50, i);
22 assert(x == expected + 8 + i);
23 }
24
25 status = sem_post(&done);
26 assert(status == 0);
27
28 return arg;
29 }
30
31 int main(void)
32 {
33 pthread_t th;
34 int i, status = sem_init(&done, 0, 0);
35 assert(status == 0);
36
37 for (i = 0; i < NTHREADS; i++) {
38 status = pthread_create(&th, NULL, start_routine, NULL);
39 assert(status == 0);
40 }
41 for (i = 0; i < NTHREADS; i++) {
42 status = sem_wait(&done);
43 assert(status == 0);
44 }
45 printf("done\n");
46 return 0;
47 }
+0
-34
pypy/module/test_lib_pypy/cffi_tests/embedding/tlocal.py less more
0 # Generated by pypy/tool/import_cffi.py
1 import cffi
2
3 ffi = cffi.FFI()
4
5 ffi.embedding_api("""
6 int add1(int, int);
7 """)
8
9 ffi.embedding_init_code(r"""
10 from _tlocal_cffi import ffi
11 import itertools
12 try:
13 import thread
14 g_seen = itertools.count().next
15 except ImportError:
16 import _thread as thread # py3
17 g_seen = itertools.count().__next__
18 tloc = thread._local()
19
20 @ffi.def_extern()
21 def add1(x, y):
22 try:
23 num = tloc.num
24 except AttributeError:
25 num = tloc.num = g_seen() * 1000
26 return x + y + num
27 """)
28
29 ffi.set_source("_tlocal_cffi", """
30 """)
31
32 fn = ffi.compile(verbose=True)
33 print('FILENAME: %s' % (fn,))
+0
-64
pypy/module/test_lib_pypy/cffi_tests/support.py less more
0 # Generated by pypy/tool/import_cffi.py
1 import sys
2
3 if sys.version_info < (3,):
4 __all__ = ['u']
5
6 class U(object):
7 def __add__(self, other):
8 return eval('u'+repr(other).replace(r'\\u', r'\u')
9 .replace(r'\\U', r'\U'))
10 u = U()
11 long = long # for further "from pypy.module.test_lib_pypy.cffi_tests.support import long"
12 assert u+'a\x00b' == eval(r"u'a\x00b'")
13 assert u+'a\u1234b' == eval(r"u'a\u1234b'")
14 assert u+'a\U00012345b' == eval(r"u'a\U00012345b'")
15
16 else:
17 __all__ = ['u', 'unicode', 'long']
18 u = ""
19 unicode = str
20 long = int
21
22
23 class StdErrCapture(object):
24 """Capture writes to sys.stderr (not to the underlying file descriptor)."""
25 def __enter__(self):
26 try:
27 from StringIO import StringIO
28 except ImportError:
29 from io import StringIO
30 self.old_stderr = sys.stderr
31 sys.stderr = f = StringIO()
32 return f
33 def __exit__(self, *args):
34 sys.stderr = self.old_stderr
35
36
37 class FdWriteCapture(object):
38 """xxx limited to capture at most 512 bytes of output, according
39 to the Posix manual."""
40
41 def __init__(self, capture_fd=2): # stderr by default
42 if sys.platform == 'win32':
43 import py
44 py.test.skip("seems not to work, too bad")
45 self.capture_fd = capture_fd
46
47 def __enter__(self):
48 import os
49 self.read_fd, self.write_fd = os.pipe()
50 self.copy_fd = os.dup(self.capture_fd)
51 os.dup2(self.write_fd, self.capture_fd)
52 return self
53
54 def __exit__(self, *args):
55 import os
56 os.dup2(self.copy_fd, self.capture_fd)
57 os.close(self.copy_fd)
58 os.close(self.write_fd)
59 self._value = os.read(self.read_fd, 512)
60 os.close(self.read_fd)
61
62 def getvalue(self):
63 return self._value
+0
-12
pypy/module/test_lib_pypy/cffi_tests/test_egg_version.py less more
0 from email.parser import Parser
1
2 import py
3
4 import cffi
5 import pypy
6
7 egg_info = py.path.local(pypy.__file__)/'../../lib_pypy/cffi.egg-info/PKG-INFO'
8
9 def test_egg_version():
10 info = Parser().parsestr(egg_info.read())
11 assert info['version'] == cffi.__version__
+0
-14
pypy/module/test_lib_pypy/cffi_tests/udir.py less more
0 # Generated by pypy/tool/import_cffi.py
1 import py
2 import sys
3
4 udir = py.path.local.make_numbered_dir(prefix = 'ffi-')
5
6
7 # Windows-only workaround for some configurations: see
8 # https://bugs.python.org/issue23246 (Python 2.7.9)
9 if sys.platform == 'win32':
10 try:
11 import setuptools
12 except ImportError:
13 pass
+0
-8
pypy/module/test_lib_pypy/ctypes_tests/README less more
0 -------Ctypes tests------
1
2 Unlike the other tests in the PyPy sources, these tests are assumed to run after the translation is complete.
3 Therefore, using the resulting binary, you can then call, for example:
4
5 /path/to/your_modified_pypy_binary pytest.py pypy/module/test_lib_pypy/ctypes_tests/test_libc.py
6
7 This also applies to any other test in ctypes_tests.
+0
-0
pypy/module/test_lib_pypy/ctypes_tests/__init__.py less more
(Empty file)
+0
-583
pypy/module/test_lib_pypy/ctypes_tests/_ctypes_test.c less more
0 #if defined(_MSC_VER) || defined(__CYGWIN__)
1 #include <windows.h>
2 #define MS_WIN32
3 #endif
4
5 #ifdef _WIN32
6 #define EXPORT(x) __declspec(dllexport) x
7 #else
8 #define EXPORT(x) extern x
9 #endif
10
11 #include <stdlib.h>
12 #include <math.h>
13 #include <string.h>
14 #include <wchar.h>
15 #include <stdio.h>
16 #include <errno.h>
17
18 #define HAVE_LONG_LONG
19 #define LONG_LONG long long
20 #define HAVE_WCHAR_H
21
22
23 /* some functions handy for testing */
24
25 EXPORT(char *)my_strtok(char *token, const char *delim)
26 {
27 return strtok(token, delim);
28 }
29
30 EXPORT(char *)my_strchr(const char *s, int c)
31 {
32 return strchr(s, c);
33 }
34
35
36 EXPORT(double) my_sqrt(double a)
37 {
38 return sqrt(a);
39 }
40
41 EXPORT(void) my_qsort(void *base, size_t num, size_t width, int(*compare)(const void*, const void*))
42 {
43 qsort(base, num, width, compare);
44 }
45
46 EXPORT(char) deref_LP_c_char_p(char** argv)
47 {
48 char* s = *argv;
49 return s[0];
50 }
51
52 EXPORT(int *) _testfunc_ai8(int a[8])
53 {
54 return a;
55 }
56
57 EXPORT(void) _testfunc_v(int a, int b, int *presult)
58 {
59 *presult = a + b;
60 }
61
62 EXPORT(int) _testfunc_i_bhilfd(signed char b, short h, int i, long l, float f, double d)
63 {
64 /* printf("_testfunc_i_bhilfd got %d %d %d %ld %f %f\n",
65 b, h, i, l, f, d);
66 */
67 return (int)(b + h + i + l + f + d);
68 }
69
70 EXPORT(float) _testfunc_f_bhilfd(signed char b, short h, int i, long l, float f, double d)
71 {
72 /* printf("_testfunc_f_bhilfd got %d %d %d %ld %f %f\n",
73 b, h, i, l, f, d);
74 */
75 return (float)(b + h + i + l + f + d);
76 }
77
78 EXPORT(double) _testfunc_d_bhilfd(signed char b, short h, int i, long l, float f, double d)
79 {
80 /* printf("_testfunc_d_bhilfd got %d %d %d %ld %f %f\n",
81 b, h, i, l, f, d);
82 */
83 return (double)(b + h + i + l + f + d);
84 }
85
86 EXPORT(char *) _testfunc_p_p(void *s)
87 {
88 return (char *)s;
89 }
90
91 EXPORT(void *) _testfunc_c_p_p(int *argcp, char **argv)
92 {
93 return argv[(*argcp)-1];
94 }
95
96 EXPORT(void *) get_strchr(void)
97 {
98 return (void *)strchr;
99 }
100
101 EXPORT(char *) my_strdup(char *src)
102 {
103 char *dst = (char *)malloc(strlen(src)+1);
104 if (!dst)
105 return NULL;
106 strcpy(dst, src);
107 return dst;
108 }
109
110 EXPORT(void)my_free(void *ptr)
111 {
112 free(ptr);
113 }
114
115 #ifdef HAVE_WCHAR_H
116 EXPORT(wchar_t *) my_wcsdup(wchar_t *src)
117 {
118 size_t len = wcslen(src);
119 wchar_t *ptr = (wchar_t *)malloc((len + 1) * sizeof(wchar_t));
120 if (ptr == NULL)
121 return NULL;
122 memcpy(ptr, src, (len+1) * sizeof(wchar_t));
123 return ptr;
124 }
125
126 EXPORT(size_t) my_wcslen(wchar_t *src)
127 {
128 return wcslen(src);
129 }
130 #endif
131
132 #ifndef MS_WIN32
133 # ifndef __stdcall
134 # define __stdcall /* */
135 # endif
136 #endif
137
138 typedef struct {
139 int (*c)(int, int);
140 int (__stdcall *s)(int, int);
141 } FUNCS;
142
143 EXPORT(int) _testfunc_callfuncp(FUNCS *fp)
144 {
145 fp->c(1, 2);
146 fp->s(3, 4);
147 return 0;
148 }
149
150 EXPORT(int) _testfunc_deref_pointer(int *pi)
151 {
152 return *pi;
153 }
154
155 #ifdef MS_WIN32
156 EXPORT(int) _testfunc_piunk(IUnknown FAR *piunk)
157 {
158 piunk->lpVtbl->AddRef(piunk);
159 return piunk->lpVtbl->Release(piunk);
160 }
161 #endif
162
163 EXPORT(int) _testfunc_callback_with_pointer(int (*func)(int *))
164 {
165 int table[] = {1, 2, 3, 4, 5, 6, 7, 8, 9, 10};
166
167 return (*func)(table);
168 }
169
170 EXPORT(int) _testfunc_callback_opaque(int (*func)(void*), void* arg)
171 {
172 return (*func)(arg);
173 }
174
175 EXPORT(int) _testfunc_callback_void(void (*func)(void))
176 {
177 func();
178 return 0;
179 }
180
181 #ifdef HAVE_LONG_LONG
182 EXPORT(LONG_LONG) _testfunc_q_bhilfdq(signed char b, short h, int i, long l, float f,
183 double d, LONG_LONG q)
184 {
185 return (LONG_LONG)(b + h + i + l + f + d + q);
186 }
187
188 EXPORT(LONG_LONG) _testfunc_q_bhilfd(signed char b, short h, int i, long l, float f, double d)
189 {
190 return (LONG_LONG)(b + h + i + l + f + d);
191 }
192
193 EXPORT(int) _testfunc_callback_i_if(int value, int (*func)(int))
194 {
195 int sum = 0;
196 while (value != 0) {
197 sum += func(value);
198 value /= 2;
199 }
200 return sum;
201 }
202
203 EXPORT(LONG_LONG) _testfunc_callback_q_qf(LONG_LONG value,
204 LONG_LONG (*func)(LONG_LONG))
205 {
206 LONG_LONG sum = 0;
207
208 while (value != 0) {
209 sum += func(value);
210 value /= 2;
211 }
212 return sum;
213 }
214
215 #endif
216
217 typedef struct {
218 char *name;
219 char *value;
220 } SPAM;
221
222 typedef struct {
223 char *name;
224 int num_spams;
225 SPAM *spams;
226 } EGG;
227
228 SPAM my_spams[2] = {
229 { "name1", "value1" },
230 { "name2", "value2" },
231 };
232
233 EGG my_eggs[1] = {
234 { "first egg", 1, my_spams }
235 };
236
237 EXPORT(int) getSPAMANDEGGS(EGG **eggs)
238 {
239 *eggs = my_eggs;
240 return 1;
241 }
242
243 typedef struct tagpoint {
244 int x;
245 int y;
246 } point;
247
248 EXPORT(int) _testfunc_byval(point in, point *pout)
249 {
250 if (pout) {
251 pout->x = in.x;
252 pout->y = in.y;
253 }
254 return in.x + in.y;
255 }
256
257 EXPORT (int) an_integer = 42;
258
259 EXPORT(int) get_an_integer(void)
260 {
261 return an_integer;
262 }
263
264 EXPORT(char) a_string[16] = "0123456789abcdef";
265
266 EXPORT(int) get_a_string_char(int index)
267 {
268 return a_string[index];
269 }
270
271 EXPORT(double)
272 integrate(double a, double b, double (*f)(double), long nstep)
273 {
274 double x, sum=0.0, dx=(b-a)/(double)nstep;
275 for(x=a+0.5*dx; (b-x)*(x-a)>0.0; x+=dx)
276 {
277 double y = f(x);
278 printf("f(x)=%.1f\n", y);
279 sum += f(x);
280 }
281 return sum/(double)nstep;
282 }
283
284 typedef struct {
285 void (*initialize)(void *(*)(int), void(*)(void *));
286 } xxx_library;
287
288 static void _xxx_init(void *(*Xalloc)(int), void (*Xfree)(void *))
289 {
290 void *ptr;
291
292 printf("_xxx_init got %p %p\n", Xalloc, Xfree);
293 printf("calling\n");
294 ptr = Xalloc(32);
295 Xfree(ptr);
296 printf("calls done, ptr was %p\n", ptr);
297 }
298
299 xxx_library _xxx_lib = {
300 _xxx_init
301 };
302
303 EXPORT(xxx_library) *library_get(void)
304 {
305 return &_xxx_lib;
306 }
307
308 #ifdef MS_WIN32
309 /* See Don Box (german), pp 79ff. */
310 EXPORT(void) GetString(BSTR *pbstr)
311 {
312 *pbstr = SysAllocString(L"Goodbye!");
313 }
314 #endif
315
316 EXPORT(void) _py_func_si(char *s, int i)
317 {
318 }
319
320 EXPORT(void) _py_func(void)
321 {
322 }
323
324 EXPORT(LONG_LONG) last_tf_arg_s = 0;
325 EXPORT(unsigned LONG_LONG) last_tf_arg_u = 0;
326
327 struct BITS {
328 int A: 1, B:2, C:3, D:4, E: 5, F: 6, G: 7, H: 8, I: 9;
329 short M: 1, N: 2, O: 3, P: 4, Q: 5, R: 6, S: 7;
330 };
331
332 EXPORT(void) set_bitfields(struct BITS *bits, char name, int value)
333 {
334 switch (name) {
335 case 'A': bits->A = value; break;
336 case 'B': bits->B = value; break;
337 case 'C': bits->C = value; break;
338 case 'D': bits->D = value; break;
339 case 'E': bits->E = value; break;
340 case 'F': bits->F = value; break;
341 case 'G': bits->G = value; break;
342 case 'H': bits->H = value; break;
343 case 'I': bits->I = value; break;
344
345 case 'M': bits->M = value; break;
346 case 'N': bits->N = value; break;
347 case 'O': bits->O = value; break;
348 case 'P': bits->P = value; break;
349 case 'Q': bits->Q = value; break;
350 case 'R': bits->R = value; break;
351 case 'S': bits->S = value; break;
352 }
353 }
354
355 EXPORT(int) unpack_bitfields(struct BITS *bits, char name)
356 {
357 switch (name) {
358 case 'A': return bits->A;
359 case 'B': return bits->B;
360 case 'C': return bits->C;
361 case 'D': return bits->D;
362 case 'E': return bits->E;
363 case 'F': return bits->F;
364 case 'G': return bits->G;
365 case 'H': return bits->H;
366 case 'I': return bits->I;
367
368 case 'M': return bits->M;
369 case 'N': return bits->N;
370 case 'O': return bits->O;
371 case 'P': return bits->P;
372 case 'Q': return bits->Q;
373 case 'R': return bits->R;
374 case 'S': return bits->S;
375 }
376 return 0;
377 }
378
379 #define S last_tf_arg_s = (LONG_LONG)c
380 #define U last_tf_arg_u = (unsigned LONG_LONG)c
381
382 EXPORT(signed char) tf_b(signed char c) { S; return c/3; }
383 EXPORT(unsigned char) tf_B(unsigned char c) { U; return c/3; }
384 EXPORT(short) tf_h(short c) { S; return c/3; }
385 EXPORT(unsigned short) tf_H(unsigned short c) { U; return c/3; }
386 EXPORT(int) tf_i(int c) { S; return c/3; }
387 EXPORT(unsigned int) tf_I(unsigned int c) { U; return c/3; }
388 EXPORT(long) tf_l(long c) { S; return c/3; }
389 EXPORT(unsigned long) tf_L(unsigned long c) { U; return c/3; }
390 EXPORT(LONG_LONG) tf_q(LONG_LONG c) { S; return c/3; }
391 EXPORT(unsigned LONG_LONG) tf_Q(unsigned LONG_LONG c) { U; return c/3; }
392 EXPORT(float) tf_f(float c) { S; return c/3; }
393 EXPORT(double) tf_d(double c) { S; return c/3; }
394
395 #ifdef MS_WIN32
396 EXPORT(signed char) __stdcall s_tf_b(signed char c) { S; return c/3; }
397 EXPORT(unsigned char) __stdcall s_tf_B(unsigned char c) { U; return c/3; }
398 EXPORT(short) __stdcall s_tf_h(short c) { S; return c/3; }
399 EXPORT(unsigned short) __stdcall s_tf_H(unsigned short c) { U; return c/3; }
400 EXPORT(int) __stdcall s_tf_i(int c) { S; return c/3; }
401 EXPORT(unsigned int) __stdcall s_tf_I(unsigned int c) { U; return c/3; }
402 EXPORT(long) __stdcall s_tf_l(long c) { S; return c/3; }
403 EXPORT(unsigned long) __stdcall s_tf_L(unsigned long c) { U; return c/3; }
404 EXPORT(LONG_LONG) __stdcall s_tf_q(LONG_LONG c) { S; return c/3; }
405 EXPORT(unsigned LONG_LONG) __stdcall s_tf_Q(unsigned LONG_LONG c) { U; return c/3; }
406 EXPORT(float) __stdcall s_tf_f(float c) { S; return c/3; }
407 EXPORT(double) __stdcall s_tf_d(double c) { S; return c/3; }
408 #endif
409 /*******/
410
411 EXPORT(signed char) tf_bb(signed char x, signed char c) { S; return c/3; }
412 EXPORT(unsigned char) tf_bB(signed char x, unsigned char c) { U; return c/3; }
413 EXPORT(short) tf_bh(signed char x, short c) { S; return c/3; }
414 EXPORT(unsigned short) tf_bH(signed char x, unsigned short c) { U; return c/3; }
415 EXPORT(int) tf_bi(signed char x, int c) { S; return c/3; }
416 EXPORT(unsigned int) tf_bI(signed char x, unsigned int c) { U; return c/3; }
417 EXPORT(long) tf_bl(signed char x, long c) { S; return c/3; }
418 EXPORT(unsigned long) tf_bL(signed char x, unsigned long c) { U; return c/3; }
419 EXPORT(LONG_LONG) tf_bq(signed char x, LONG_LONG c) { S; return c/3; }
420 EXPORT(unsigned LONG_LONG) tf_bQ(signed char x, unsigned LONG_LONG c) { U; return c/3; }
421 EXPORT(float) tf_bf(signed char x, float c) { S; return c/3; }
422 EXPORT(double) tf_bd(signed char x, double c) { S; return c/3; }
423 EXPORT(void) tv_i(int c) { S; return; }
424
425 #ifdef MS_WIN32
426 EXPORT(signed char) __stdcall s_tf_bb(signed char x, signed char c) { S; return c/3; }
427 EXPORT(unsigned char) __stdcall s_tf_bB(signed char x, unsigned char c) { U; return c/3; }
428 EXPORT(short) __stdcall s_tf_bh(signed char x, short c) { S; return c/3; }
429 EXPORT(unsigned short) __stdcall s_tf_bH(signed char x, unsigned short c) { U; return c/3; }
430 EXPORT(int) __stdcall s_tf_bi(signed char x, int c) { S; return c/3; }
431 EXPORT(unsigned int) __stdcall s_tf_bI(signed char x, unsigned int c) { U; return c/3; }
432 EXPORT(long) __stdcall s_tf_bl(signed char x, long c) { S; return c/3; }
433 EXPORT(unsigned long) __stdcall s_tf_bL(signed char x, unsigned long c) { U; return c/3; }
434 EXPORT(LONG_LONG) __stdcall s_tf_bq(signed char x, LONG_LONG c) { S; return c/3; }
435 EXPORT(unsigned LONG_LONG) __stdcall s_tf_bQ(signed char x, unsigned LONG_LONG c) { U; return c/3; }
436 EXPORT(float) __stdcall s_tf_bf(signed char x, float c) { S; return c/3; }
437 EXPORT(double) __stdcall s_tf_bd(signed char x, double c) { S; return c/3; }
438 EXPORT(void) __stdcall s_tv_i(int c) { S; return; }
439 #endif
440
441 /********/
442
443 #ifndef MS_WIN32
444
445 typedef struct {
446 long x;
447 long y;
448 } POINT;
449
450 typedef struct {
451 long left;
452 long top;
453 long right;
454 long bottom;
455 } RECT;
456
457 #endif
458
459 EXPORT(int) PointInRect(RECT *prc, POINT pt)
460 {
461 if (pt.x < prc->left)
462 return 0;
463 if (pt.x > prc->right)
464 return 0;
465 if (pt.y < prc->top)
466 return 0;
467 if (pt.y > prc->bottom)
468 return 0;
469 return 1;
470 }
471
472 typedef struct {
473 short x;
474 short y;
475 } S2H;
476
477 EXPORT(S2H) ret_2h_func(S2H inp)
478 {
479 inp.x *= 2;
480 inp.y *= 3;
481 return inp;
482 }
483
484 typedef struct {
485 int a, b, c, d, e, f, g, h;
486 } S8I;
487
488
489
490 typedef int (*CALLBACK_RECT)(RECT rect);
491
492 EXPORT(int) call_callback_with_rect(CALLBACK_RECT cb, RECT rect)
493 {
494 return cb(rect);
495 }
496
497
498 EXPORT(S8I) ret_8i_func(S8I inp)
499 {
500 inp.a *= 2;
501 inp.b *= 3;
502 inp.c *= 4;
503 inp.d *= 5;
504 inp.e *= 6;
505 inp.f *= 7;
506 inp.g *= 8;
507 inp.h *= 9;
508 return inp;
509 }
510
511 EXPORT(int) GetRectangle(int flag, RECT *prect)
512 {
513 if (flag == 0)
514 return 0;
515 prect->left = (int)flag;
516 prect->top = (int)flag + 1;
517 prect->right = (int)flag + 2;
518 prect->bottom = (int)flag + 3;
519 return 1;
520 }
521
522 EXPORT(void) TwoOutArgs(int a, int *pi, int b, int *pj)
523 {
524 *pi += a;
525 *pj += b;
526 }
527
528 #ifdef MS_WIN32
529 EXPORT(S2H) __stdcall s_ret_2h_func(S2H inp) { return ret_2h_func(inp); }
530 EXPORT(S8I) __stdcall s_ret_8i_func(S8I inp) { return ret_8i_func(inp); }
531 #endif
532
533 #ifdef MS_WIN32
534 /* Should port this */
535 #include <stdlib.h>
536 #include <search.h>
537
538 EXPORT (HRESULT) KeepObject(IUnknown *punk)
539 {
540 static IUnknown *pobj;
541 if (punk)
542 punk->lpVtbl->AddRef(punk);
543 if (pobj)
544 pobj->lpVtbl->Release(pobj);
545 pobj = punk;
546 return S_OK;
547 }
548
549 #endif
550
551 typedef union {
552 short x;
553 long y;
554 } UN;
555
556 EXPORT(UN) ret_un_func(UN inp)
557 {
558 inp.y = inp.x * 10000;
559 return inp;
560 }
561
562 EXPORT(int) my_unused_function(void)
563 {
564 return 42;
565 }
566
567 EXPORT(int) test_errno(void)
568 {
569 int result = errno;
570 errno = result + 1;
571 return result;
572 }
573
574 EXPORT(int *) test_issue1655(char const *tag, int *len)
575 {
576 static int data[] = { -1, -2, -3, -4 };
577 *len = -42;
578 if (strcmp(tag, "testing!") != 0)
579 return NULL;
580 *len = sizeof(data) / sizeof(data[0]);
581 return data;
582 }
+0
-103
pypy/module/test_lib_pypy/ctypes_tests/conftest.py less more
0 import py
1 import pytest
2 import sys
3 import os
4
5 def pytest_ignore_collect(path):
6 if '__pypy__' not in sys.builtin_module_names:
7 return True
8
9 # XXX: copied from pypy/tool/cpyext/extbuild.py
10 if os.name != 'nt':
11 so_ext = 'so'
12 else:
13 so_ext = 'dll'
14
15 def _build(cfilenames, outputfilename, compile_extra, link_extra,
16 include_dirs, libraries, library_dirs):
17 try:
18 # monkeypatch distutils for some versions of msvc compiler
19 import setuptools
20 except ImportError:
21 # XXX if this fails and is required,
22 # we must call pypy -mensurepip after translation
23 pass
24 from distutils.ccompiler import new_compiler
25 from distutils import sysconfig
26
27 # XXX for Darwin running old versions of CPython 2.7.x
28 sysconfig.get_config_vars()
29
30 compiler = new_compiler(force=1)
31 sysconfig.customize_compiler(compiler) # XXX
32 objects = []
33 for cfile in cfilenames:
34 cfile = py.path.local(cfile)
35 old = cfile.dirpath().chdir()
36 try:
37 res = compiler.compile([cfile.basename],
38 include_dirs=include_dirs, extra_preargs=compile_extra)
39 assert len(res) == 1
40 cobjfile = py.path.local(res[0])
41 assert cobjfile.check()
42 objects.append(str(cobjfile))
43 finally:
44 old.chdir()
45
46 compiler.link_shared_object(
47 objects, str(outputfilename),
48 libraries=libraries,
49 extra_preargs=link_extra,
50 library_dirs=library_dirs)
51
52 def c_compile(cfilenames, outputfilename,
53 compile_extra=None, link_extra=None,
54 include_dirs=None, libraries=None, library_dirs=None):
55 compile_extra = compile_extra or []
56 link_extra = link_extra or []
57 include_dirs = include_dirs or []
58 libraries = libraries or []
59 library_dirs = library_dirs or []
60 if sys.platform == 'win32':
61 link_extra = link_extra + ['/DEBUG'] # generate .pdb file
62 if sys.platform == 'darwin':
63 # support Fink & Darwinports
64 for s in ('/sw/', '/opt/local/'):
65 if (s + 'include' not in include_dirs
66 and os.path.exists(s + 'include')):
67 include_dirs.append(s + 'include')
68 if s + 'lib' not in library_dirs and os.path.exists(s + 'lib'):
69 library_dirs.append(s + 'lib')
70
71 outputfilename = py.path.local(outputfilename).new(ext=so_ext)
72 saved_environ = os.environ.copy()
73 try:
74 _build(
75 cfilenames, outputfilename,
76 compile_extra, link_extra,
77 include_dirs, libraries, library_dirs)
78 finally:
79 # workaround for a distutils bugs where some env vars can
80 # become longer and longer every time it is used
81 for key, value in saved_environ.items():
82 if os.environ.get(key) != value:
83 os.environ[key] = value
84 return outputfilename
85 # end copy
86
87 def compile_so_file():
88 udir = pytest.ensuretemp('_ctypes_test')
89 cfile = py.path.local(__file__).dirpath().join("_ctypes_test.c")
90
91 if sys.platform == 'win32':
92 libraries = ['oleaut32']
93 else:
94 libraries = []
95
96 return c_compile([cfile], str(udir / '_ctypes_test'), libraries=libraries)
97
98 # we need to run after the "tmpdir" plugin which installs pytest.ensuretemp
99 @pytest.mark.trylast
100 def pytest_configure(config):
101 global sofile
102 sofile = compile_so_file()
+0
-15
pypy/module/test_lib_pypy/ctypes_tests/description.txt less more
0 test_bitfields.py # bitfields not supported
1 test_byteswap.py # __ctype_be__ and __ctypes_le__ not implemented
2 test_errcheck.py # empty
3 test_init.py # obscure
4 test_internals.py # uses gc.getrefcounts
5 test_keeprefs.py # implementation details: ._objects
6 test_macholib.py # OS X specific
7 test_objects.py # implementation details: ._objects
8 test_python_api.py # CPython specific
9 test_refcounts.py # CPython specific
10 test_repr.py # not implemented
11 test_unaligned_structures.py # _pack_ not implemented
12 test_values.py # some strange stuff
13 test_varsize_struct.py # resize not implemented
14 test_win32.py # Windows specific
+0
-57
pypy/module/test_lib_pypy/ctypes_tests/support.py less more
0 import py
1 import sys
2 import ctypes
3
4 try:
5 import _rawffi
6 except ImportError:
7 _rawffi = None
8
9 class WhiteBoxTests:
10
11 def setup_class(cls):
12 if _rawffi:
13 py.test.skip("white-box tests for pypy _rawffi based ctypes impl")
14
15 def del_funcptr_refs_maybe(obj, attrname):
16 dll = getattr(obj, attrname, None)
17 if not dll:
18 return
19 _FuncPtr = dll._FuncPtr
20 for name in dir(dll):
21 obj = getattr(dll, name, None)
22 if isinstance(obj, _FuncPtr):
23 delattr(dll, name)
24
25 class BaseCTypesTestChecker:
26 def setup_class(cls):
27 if _rawffi:
28 import gc
29 for _ in range(4):
30 gc.collect()
31 try:
32 cls.old_num = _rawffi._num_of_allocated_objects()
33 except RuntimeError:
34 pass
35
36 def teardown_class(cls):
37 if not hasattr(sys, 'pypy_translation_info'):
38 return
39 if sys.pypy_translation_info['translation.gc'] == 'boehm':
40 return # it seems that boehm has problems with __del__, so not
41 # everything is freed
42 #
43 mod = sys.modules[cls.__module__]
44 del_funcptr_refs_maybe(mod, 'dll')
45 del_funcptr_refs_maybe(mod, 'dll2')
46 del_funcptr_refs_maybe(mod, 'lib')
47 del_funcptr_refs_maybe(mod, 'testdll')
48 del_funcptr_refs_maybe(mod, 'ctdll')
49 del_funcptr_refs_maybe(cls, '_dll')
50 #
51 if hasattr(cls, 'old_num'):
52 import gc
53 for _ in range(4):
54 gc.collect()
55 # there is one reference coming from the byref() above
56 assert _rawffi._num_of_allocated_objects() == cls.old_num
+0
-86
pypy/module/test_lib_pypy/ctypes_tests/test_anon.py less more
0 import pytest
1 from ctypes import *
2 from .support import BaseCTypesTestChecker
3
4 class TestAnon(BaseCTypesTestChecker):
5
6 def test_anon(self):
7 class ANON(Union):
8 _fields_ = [("a", c_int),
9 ("b", c_int)]
10
11 class Y(Structure):
12 _fields_ = [("x", c_int),
13 ("_", ANON),
14 ("y", c_int)]
15 _anonymous_ = ["_"]
16
17 assert Y.a.offset == sizeof(c_int)
18 assert Y.b.offset == sizeof(c_int)
19
20 assert ANON.a.offset == 0
21 assert ANON.b.offset == 0
22
23 def test_anon_nonseq(self):
24 # TypeError: _anonymous_ must be a sequence
25 with pytest.raises(TypeError):
26 type(Structure)(
27 "Name", (Structure,), {"_fields_": [], "_anonymous_": 42})
28
29 def test_anon_nonmember(self):
30 # AttributeError: type object 'Name' has no attribute 'x'
31 with pytest.raises(AttributeError):
32 type(Structure)(
33 "Name", (Structure,), {"_fields_": [], "_anonymous_": ["x"]})
34
35 def test_nested(self):
36 class ANON_S(Structure):
37 _fields_ = [("a", c_int)]
38
39 class ANON_U(Union):
40 _fields_ = [("_", ANON_S),
41 ("b", c_int)]
42 _anonymous_ = ["_"]
43
44 class Y(Structure):
45 _fields_ = [("x", c_int),
46 ("_", ANON_U),
47 ("y", c_int)]
48 _anonymous_ = ["_"]
49
50 assert Y.x.offset == 0
51 assert Y.a.offset == sizeof(c_int)
52 assert Y.b.offset == sizeof(c_int)
53 assert Y._.offset == sizeof(c_int)
54 assert Y.y.offset == sizeof(c_int) * 2
55
56 assert Y._names_ == ['x', 'a', 'b', 'y']
57
58 def test_anonymous_fields_on_instance(self):
59 # this is about the *instance-level* access of anonymous fields,
60 # which you'd guess is the most common, but used not to work
61 # (issue #2230)
62
63 class B(Structure):
64 _fields_ = [("x", c_int), ("y", c_int), ("z", c_int)]
65 class A(Structure):
66 _anonymous_ = ["b"]
67 _fields_ = [("b", B)]
68
69 a = A()
70 a.x = 5
71 assert a.x == 5
72 assert a.b.x == 5
73 a.b.x += 1
74 assert a.x == 6
75
76 class C(Structure):
77 _anonymous_ = ["a"]
78 _fields_ = [("v", c_int), ("a", A)]
79
80 c = C()
81 c.v = 3
82 c.y = -8
83 assert c.v == 3
84 assert c.y == c.a.y == c.a.b.y == -8
85 assert not hasattr(c, 'b')
+0
-177
pypy/module/test_lib_pypy/ctypes_tests/test_array.py less more
0 import pytest
1 from ctypes import *
2 from .support import BaseCTypesTestChecker
3
4 formats = "bBhHiIlLqQfd"
5
6 formats = c_byte, c_ubyte, c_short, c_ushort, c_int, c_uint, \
7 c_long, c_ulonglong, c_float, c_double
8
9 class TestArray(BaseCTypesTestChecker):
10 def test_simple(self):
11 # create classes holding simple numeric types, and check
12 # various properties.
13
14 init = range(15, 25)
15
16 for fmt in formats:
17 alen = len(init)
18 int_array = ARRAY(fmt, alen)
19
20 ia = int_array(*init)
21 # length of instance ok?
22 assert len(ia) == alen
23
24 # slot values ok?
25 values = [ia[i] for i in range(len(init))]
26 assert values == init
27
28 # change the items
29 from operator import setitem
30 new_values = range(42, 42+alen)
31 [setitem(ia, n, new_values[n]) for n in range(alen)]
32 values = [ia[i] for i in range(len(init))]
33 assert values == new_values
34
35 # are the items initialized to 0?
36 ia = int_array()
37 values = [ia[i] for i in range(len(init))]
38 assert values == [0] * len(init)
39
40 # Too many in itializers should be caught
41 with pytest.raises(IndexError):
42 int_array(*range(alen*2))
43
44 CharArray = ARRAY(c_char, 3)
45
46 ca = CharArray("a", "b", "c")
47
48 # Should this work? It doesn't:
49 # CharArray("abc")
50 with pytest.raises(TypeError):
51 CharArray("abc")
52
53 assert ca[0] == "a"
54 assert ca[1] == "b"
55 assert ca[2] == "c"
56 assert ca[-3] == "a"
57 assert ca[-2] == "b"
58 assert ca[-1] == "c"
59
60 assert len(ca) == 3
61
62 # slicing is now supported, but not extended slicing (3-argument)!
63 from operator import getslice, delitem
64 with pytest.raises(TypeError):
65 getslice(ca, 0, 1, -1)
66
67 # cannot delete items
68 with pytest.raises(TypeError):
69 delitem(ca, 0)
70
71 def test_numeric_arrays(self):
72
73 alen = 5
74
75 numarray = ARRAY(c_int, alen)
76
77 na = numarray()
78 values = [na[i] for i in range(alen)]
79 assert values == [0] * alen
80
81 na = numarray(*[c_int()] * alen)
82 values = [na[i] for i in range(alen)]
83 assert values == [0]*alen
84
85 na = numarray(1, 2, 3, 4, 5)
86 values = [i for i in na]
87 assert values == [1, 2, 3, 4, 5]
88
89 na = numarray(*map(c_int, (1, 2, 3, 4, 5)))
90 values = [i for i in na]
91 assert values == [1, 2, 3, 4, 5]
92
93 def test_slice(self):
94 values = range(5)
95 numarray = c_int * 5
96
97 na = numarray(*(c_int(x) for x in values))
98
99 assert list(na[0:0]) == []
100 assert list(na[:]) == values
101 assert list(na[:10]) == values
102
103 def test_classcache(self):
104 assert not ARRAY(c_int, 3) is ARRAY(c_int, 4)
105 assert ARRAY(c_int, 3) is ARRAY(c_int, 3)
106
107 def test_from_address(self):
108 # Failed with 0.9.8, reported by JUrner
109 p = create_string_buffer("foo")
110 sz = (c_char * 3).from_address(addressof(p))
111 assert sz[:] == "foo"
112 assert sz.value == "foo"
113
114 def test_init_again(self):
115 sz = (c_char * 3)()
116 addr1 = addressof(sz)
117 sz.__init__(*"foo")
118 addr2 = addressof(sz)
119 assert addr1 == addr2
120
121 try:
122 create_unicode_buffer
123 except NameError:
124 pass
125 else:
126 def test_from_addressW(self):
127 p = create_unicode_buffer("foo")
128 sz = (c_wchar * 3).from_address(addressof(p))
129 assert sz[:] == "foo"
130 assert sz.value == "foo"
131
132 class TestSophisticatedThings(BaseCTypesTestChecker):
133 def test_array_of_structures(self):
134 class X(Structure):
135 _fields_ = [('x', c_int), ('y', c_int)]
136
137 Y = X * 2
138 y = Y()
139 x = X()
140 x.y = 3
141 y[1] = x
142 assert y[1].y == 3
143
144 def test_output_simple(self):
145 A = c_char * 10
146 TP = POINTER(A)
147 x = TP(A())
148 assert x[0] != ''
149
150 A = c_wchar * 10
151 TP = POINTER(A)
152 x = TP(A())
153 assert x[0] != ''
154
155 def test_output_simple_array(self):
156 A = c_char * 10
157 AA = A * 10
158 aa = AA()
159 assert aa[0] != ''
160
161 def test_output_complex_test(self):
162 class Car(Structure):
163 _fields_ = [("brand", c_char * 10),
164 ("speed", c_float),
165 ("owner", c_char * 10)]
166
167 assert isinstance(Car("abcdefghi", 42.0, "12345").brand, bytes)
168 assert Car("abcdefghi", 42.0, "12345").brand == "abcdefghi"
169 assert Car("abcdefghio", 42.0, "12345").brand == "abcdefghio"
170 with pytest.raises(ValueError):
171 Car("abcdefghiop", 42.0, "12345")
172
173 A = Car._fields_[2][1]
174 TP = POINTER(A)
175 x = TP(A())
176 assert x[0] != ''
+0
-62
pypy/module/test_lib_pypy/ctypes_tests/test_array_in_pointer.py less more
0 from ctypes import *
1 from binascii import hexlify
2 import re
3 import py
4 from .support import BaseCTypesTestChecker
5
6 def dump(obj):
7 # helper function to dump memory contents in hex, with a hyphen
8 # between the bytes.
9 # cast it to the raw buffer
10 h = hexlify(buffer(obj))
11 return re.sub(r"(..)", r"\1-", h)[:-1]
12
13 class Value(Structure):
14 _fields_ = [("val", c_byte)]
15
16 class Container(Structure):
17 _fields_ = [("pvalues", POINTER(Value))]
18
19 class TestOne(BaseCTypesTestChecker):
20 def test(self):
21 # create an array of 4 values
22 val_array = (Value * 4)()
23
24 # create a container, which holds a pointer to the pvalues array.
25 c = Container()
26 c.pvalues = val_array
27
28 # memory contains 4 NUL bytes now, that's correct
29 assert "00-00-00-00" == dump(val_array)
30
31 # set the values of the array through the pointer:
32 for i in range(4):
33 c.pvalues[i].val = i + 1
34
35 values = [c.pvalues[i].val for i in range(4)]
36
37 # These are the expected results: here s the bug!
38 assert (
39 (values, dump(val_array))) == (
40 ([1, 2, 3, 4], "01-02-03-04")
41 )
42
43 def test_2(self):
44
45 val_array = (Value * 4)()
46
47 # memory contains 4 NUL bytes now, that's correct
48 assert "00-00-00-00" == dump(val_array)
49
50 ptr = cast(val_array, POINTER(Value))
51 # set the values of the array through the pointer:
52 for i in range(4):
53 ptr[i].val = i + 1
54
55 values = [ptr[i].val for i in range(4)]
56
57 # These are the expected results: here s the bug!
58 assert (
59 (values, dump(val_array))) == (
60 ([1, 2, 3, 4], "01-02-03-04")
61 )
+0
-217
pypy/module/test_lib_pypy/ctypes_tests/test_as_parameter.py less more
0 from ctypes import *
1 import pytest
2 from .support import BaseCTypesTestChecker
3
4 def setup_module(mod):
5 import conftest
6 _ctypes_test = str(conftest.sofile)
7 mod.dll = CDLL(_ctypes_test)
8
9 try:
10 CALLBACK_FUNCTYPE = WINFUNCTYPE
11 except NameError:
12 # fake to enable this test on Linux
13 CALLBACK_FUNCTYPE = CFUNCTYPE
14
15 class POINT(Structure):
16 _fields_ = [("x", c_int), ("y", c_int)]
17
18 class BasicTestWrap(BaseCTypesTestChecker):
19 def wrap(self, param):
20 return param
21
22 def test_wchar_parm(self):
23 try:
24 c_wchar
25 except NameError:
26 return
27 f = dll._testfunc_i_bhilfd
28 f.argtypes = [c_byte, c_wchar, c_int, c_long, c_float, c_double]
29 result = f(self.wrap(1), self.wrap("x"), self.wrap(3), self.wrap(4), self.wrap(5.0), self.wrap(6.0))
30 assert result == 139
31 assert type(result), int
32
33 def test_pointers(self):
34 f = dll._testfunc_p_p
35 f.restype = POINTER(c_int)
36 f.argtypes = [POINTER(c_int)]
37
38 # This only works if the value c_int(42) passed to the
39 # function is still alive while the pointer (the result) is
40 # used.
41
42 v = c_int(42)
43
44 assert pointer(v).contents.value == 42
45 result = f(self.wrap(pointer(v)))
46 assert type(result) == POINTER(c_int)
47 assert result.contents.value == 42
48
49 # This on works...
50 result = f(self.wrap(pointer(v)))
51 assert result.contents.value == v.value
52
53 p = pointer(c_int(99))
54 result = f(self.wrap(p))
55 assert result.contents.value == 99
56
57 def test_shorts(self):
58 f = dll._testfunc_callback_i_if
59
60 args = []
61 expected = [262144, 131072, 65536, 32768, 16384, 8192, 4096, 2048,
62 1024, 512, 256, 128, 64, 32, 16, 8, 4, 2, 1]
63
64 def callback(v):
65 args.append(v)
66 return v
67
68 CallBack = CFUNCTYPE(c_int, c_int)
69
70 cb = CallBack(callback)
71 f(self.wrap(2**18), self.wrap(cb))
72 assert args == expected
73
74 ################################################################
75
76 def test_callbacks(self):
77 f = dll._testfunc_callback_i_if
78 f.restype = c_int
79
80 MyCallback = CFUNCTYPE(c_int, c_int)
81
82 def callback(value):
83 #print "called back with", value
84 return value
85
86 cb = MyCallback(callback)
87
88 result = f(self.wrap(-10), self.wrap(cb))
89 assert result == -18
90
91 # test with prototype
92 f.argtypes = [c_int, MyCallback]
93 cb = MyCallback(callback)
94
95 result = f(self.wrap(-10), self.wrap(cb))
96 assert result == -18
97
98 result = f(self.wrap(-10), self.wrap(cb))
99 assert result == -18
100
101 AnotherCallback = CALLBACK_FUNCTYPE(c_int, c_int, c_int, c_int, c_int)
102
103 # check that the prototype works: we call f with wrong
104 # argument types
105 cb = AnotherCallback(callback)
106 with pytest.raises(ArgumentError):
107 f(self.wrap(-10), self.wrap(cb))
108
109 def test_callbacks_2(self):
110 # Can also use simple datatypes as argument type specifiers
111 # for the callback function.
112 # In this case the call receives an instance of that type
113 f = dll._testfunc_callback_i_if
114 f.restype = c_int
115
116 MyCallback = CFUNCTYPE(c_int, c_int)
117
118 f.argtypes = [c_int, MyCallback]
119
120 def callback(value):
121 #print "called back with", value
122 assert type(value) == int
123 return value
124
125 cb = MyCallback(callback)
126 result = f(self.wrap(-10), self.wrap(cb))
127 assert result == -18
128
129 def test_longlong_callbacks(self):
130
131 f = dll._testfunc_callback_q_qf
132 f.restype = c_longlong
133
134 MyCallback = CFUNCTYPE(c_longlong, c_longlong)
135
136 f.argtypes = [c_longlong, MyCallback]
137
138 def callback(value):
139 assert isinstance(value, (int, long))
140 return value & 0x7FFFFFFF
141
142 cb = MyCallback(callback)
143
144 assert 13577625587 == int(f(self.wrap(1000000000000), self.wrap(cb)))
145
146 def test_byval(self):
147 # without prototype
148 ptin = POINT(1, 2)
149 ptout = POINT()
150 # EXPORT int _testfunc_byval(point in, point *pout)
151 result = dll._testfunc_byval(ptin, byref(ptout))
152 got = result, ptout.x, ptout.y
153 expected = 3, 1, 2
154 assert got == expected
155
156 # with prototype
157 ptin = POINT(101, 102)
158 ptout = POINT()
159 dll._testfunc_byval.argtypes = (POINT, POINTER(POINT))
160 dll._testfunc_byval.restype = c_int
161 result = dll._testfunc_byval(self.wrap(ptin), byref(ptout))
162 got = result, ptout.x, ptout.y
163 expected = 203, 101, 102
164 assert got == expected
165
166 def test_struct_return_2H(self):
167 class S2H(Structure):
168 _fields_ = [("x", c_short),
169 ("y", c_short)]
170 dll.ret_2h_func.restype = S2H
171 dll.ret_2h_func.argtypes = [S2H]
172 inp = S2H(99, 88)
173 s2h = dll.ret_2h_func(self.wrap(inp))
174 assert (s2h.x, s2h.y) == (99*2, 88*3)
175
176 def test_struct_return_8H(self):
177 class S8I(Structure):
178 _fields_ = [("a", c_int),
179 ("b", c_int),
180 ("c", c_int),
181 ("d", c_int),
182 ("e", c_int),
183 ("f", c_int),
184 ("g", c_int),
185 ("h", c_int)]
186 dll.ret_8i_func.restype = S8I
187 dll.ret_8i_func.argtypes = [S8I]
188 inp = S8I(9, 8, 7, 6, 5, 4, 3, 2)
189 s8i = dll.ret_8i_func(self.wrap(inp))
190 assert (s8i.a, s8i.b, s8i.c, s8i.d, s8i.e, s8i.f, s8i.g, s8i.h) == (
191 (9*2, 8*3, 7*4, 6*5, 5*6, 4*7, 3*8, 2*9))
192
193 #~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
194
195 class AsParamWrapper(object):
196 def __init__(self, param):
197 self._as_parameter_ = param
198
199 class TestWrap(BasicTestWrap):
200 wrap = AsParamWrapper
201
202 #~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
203
204 class AsParamPropertyWrapper(object):
205 def __init__(self, param):
206 self._param = param
207
208 def getParameter(self):
209 return self._param
210 _as_parameter_ = property(getParameter)
211
212 class TestAsParam(BasicTestWrap):
213 wrap = AsParamPropertyWrapper
214
215 #~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
216
+0
-26
pypy/module/test_lib_pypy/ctypes_tests/test_base.py less more
0 from .support import WhiteBoxTests
1
2 from ctypes import *
3
4 # WhiteBoxTests
5
6 class TestCTypesBase(WhiteBoxTests):
7 def test_pointer(self):
8 p = pointer(pointer(c_int(2)))
9 x = p[0]
10 assert x._base is p
11
12 def test_structure(self):
13 class X(Structure):
14 _fields_ = [('x', POINTER(c_int)),
15 ('y', POINTER(c_int))]
16
17 x = X()
18 assert x.y._base is x
19 assert x.y._index == 1
20
21 def test_array(self):
22 X = POINTER(c_int) * 24
23 x = X()
24 assert x[16]._base is x
25 assert x[16]._index == 16
+0
-249
pypy/module/test_lib_pypy/ctypes_tests/test_bitfields.py less more
0 import pytest
1 from ctypes import *
2 from .support import BaseCTypesTestChecker
3 import os
4
5 import ctypes
6
7 signed_int_types = (c_byte, c_short, c_int, c_long, c_longlong)
8 unsigned_int_types = (c_ubyte, c_ushort, c_uint, c_ulong, c_ulonglong)
9 int_types = unsigned_int_types + signed_int_types
10
11
12 def setup_module(mod):
13 import conftest
14 _ctypes_test = str(conftest.sofile)
15 func = CDLL(_ctypes_test).unpack_bitfields
16 func.argtypes = POINTER(BITS), c_char
17 mod.func = func
18
19
20 class BITS(Structure):
21 _fields_ = [("A", c_int, 1),
22 ("B", c_int, 2),
23 ("C", c_int, 3),
24 ("D", c_int, 4),
25 ("E", c_int, 5),
26 ("F", c_int, 6),
27 ("G", c_int, 7),
28 ("H", c_int, 8),
29 ("I", c_int, 9),
30
31 ("M", c_short, 1),
32 ("N", c_short, 2),
33 ("O", c_short, 3),
34 ("P", c_short, 4),
35 ("Q", c_short, 5),
36 ("R", c_short, 6),
37 ("S", c_short, 7)]
38
39
40 class TestC:
41 def test_ints(self):
42 for i in range(512):
43 for name in "ABCDEFGHI":
44 b = BITS()
45 setattr(b, name, i)
46 assert (name, i, getattr(b, name)) == (name, i, func(byref(b), name))
47
48 def test_shorts(self):
49 for i in range(256):
50 for name in "MNOPQRS":
51 b = BITS()
52 setattr(b, name, i)
53 assert (name, i, getattr(b, name)) == (name, i, func(byref(b), name))
54
55
56 class TestBitField:
57 def test_longlong(self):
58 class X(Structure):
59 _fields_ = [("a", c_longlong, 1),
60 ("b", c_longlong, 62),
61 ("c", c_longlong, 1)]
62
63 assert sizeof(X) == sizeof(c_longlong)
64 x = X()
65 x.a, x.b, x.c = -1, 7, -1
66 assert (x.a, x.b, x.c) == (-1, 7, -1)
67
68 x = X()
69 x.a, x.b, x.c = -1, -7, -1
70 assert (x.a, x.b, x.c) == (-1, -7, -1)
71
72 def test_ulonglong(self):
73 class X(Structure):
74 _fields_ = [("a", c_ulonglong, 1),
75 ("b", c_ulonglong, 62),
76 ("c", c_ulonglong, 1)]
77
78 assert sizeof(X) == sizeof(c_longlong)
79 x = X()
80 assert (x.a, x.b, x.c) == (0, 0, 0)
81 x.a, x.b, x.c = 7, 2305843009213693953, 7
82 assert (x.a, x.b, x.c) == (1, 2305843009213693953, 1)
83
84 def test_signed(self):
85 for c_typ in signed_int_types:
86 class X(Structure):
87 _fields_ = [("dummy", c_typ),
88 ("a", c_typ, 3),
89 ("b", c_typ, 3),
90 ("c", c_typ, 1)]
91 assert sizeof(X) == sizeof(c_typ)*2
92
93 x = X()
94 assert (c_typ, x.a, x.b, x.c) == (c_typ, 0, 0, 0)
95 x.a = -1
96 assert (c_typ, x.a, x.b, x.c) == (c_typ, -1, 0, 0)
97 x.a, x.b = 0, -1
98 assert (c_typ, x.a, x.b, x.c) == (c_typ, 0, -1, 0)
99
100 def test_unsigned(self):
101 for c_typ in unsigned_int_types:
102 class X(Structure):
103 _fields_ = [("a", c_typ, 3),
104 ("b", c_typ, 3),
105 ("c", c_typ, 1)]
106 assert sizeof(X) == sizeof(c_typ)
107
108 x = X()
109 assert (c_typ, x.a, x.b, x.c) == (c_typ, 0, 0, 0)
110 x.a = -1
111 assert (c_typ, x.a, x.b, x.c) == (c_typ, 7, 0, 0)
112 x.a, x.b = 0, -1
113 assert (c_typ, x.a, x.b, x.c) == (c_typ, 0, 7, 0)
114
115 def fail_fields(self, *fields):
116 return self.get_except(type(Structure), "X", (),
117 {"_fields_": fields})
118
119 def test_nonint_types(self):
120 # bit fields are not allowed on non-integer types.
121 result = self.fail_fields(("a", c_char_p, 1))
122 assert result == (TypeError, 'bit fields not allowed for type c_char_p')
123
124 result = self.fail_fields(("a", c_void_p, 1))
125 assert result == (TypeError, 'bit fields not allowed for type c_void_p')
126
127 if c_int != c_long:
128 result = self.fail_fields(("a", POINTER(c_int), 1))
129 assert result == (TypeError, 'bit fields not allowed for type LP_c_int')
130
131 result = self.fail_fields(("a", c_char, 1))
132 assert result == (TypeError, 'bit fields not allowed for type c_char')
133
134 try:
135 c_wchar
136 except NameError:
137 pass
138 else:
139 result = self.fail_fields(("a", c_wchar, 1))
140 assert result == (TypeError, 'bit fields not allowed for type c_wchar')
141
142 class Dummy(Structure):
143 _fields_ = []
144
145 result = self.fail_fields(("a", Dummy, 1))
146 assert result == (TypeError, 'bit fields not allowed for type Dummy')
147
148 def test_single_bitfield_size(self):
149 for c_typ in int_types:
150 result = self.fail_fields(("a", c_typ, -1))
151 assert result == (ValueError, 'number of bits invalid for bit field')
152
153 result = self.fail_fields(("a", c_typ, 0))
154 assert result == (ValueError, 'number of bits invalid for bit field')
155
156 class X(Structure):
157 _fields_ = [("a", c_typ, 1)]
158 assert sizeof(X) == sizeof(c_typ)
159
160 class X(Structure):
161 _fields_ = [("a", c_typ, sizeof(c_typ)*8)]
162 assert sizeof(X) == sizeof(c_typ)
163
164 result = self.fail_fields(("a", c_typ, sizeof(c_typ)*8 + 1))
165 assert result == (ValueError, 'number of bits invalid for bit field')
166
167 def test_multi_bitfields_size(self):
168 class X(Structure):
169 _fields_ = [("a", c_short, 1),
170 ("b", c_short, 14),
171 ("c", c_short, 1)]
172 assert sizeof(X) == sizeof(c_short)
173
174 class X(Structure):
175 _fields_ = [("a", c_short, 1),
176 ("a1", c_short),
177 ("b", c_short, 14),
178 ("c", c_short, 1)]
179 assert sizeof(X) == sizeof(c_short)*3
180 assert X.a.offset == 0
181 assert X.a1.offset == sizeof(c_short)
182 assert X.b.offset == sizeof(c_short)*2
183 assert X.c.offset == sizeof(c_short)*2
184
185 class X(Structure):
186 _fields_ = [("a", c_short, 3),
187 ("b", c_short, 14),
188 ("c", c_short, 14)]
189 assert sizeof(X) == sizeof(c_short)*3
190 assert X.a.offset == sizeof(c_short)*0
191 assert X.b.offset == sizeof(c_short)*1
192 assert X.c.offset == sizeof(c_short)*2
193
194 def get_except(self, func, *args, **kw):
195 try:
196 func(*args, **kw)
197 except Exception as detail:
198 import traceback
199 traceback.print_exc()
200 return detail.__class__, str(detail)
201
202 def test_mixed_1(self):
203 class X(Structure):
204 _fields_ = [("a", c_byte, 4),
205 ("b", c_int, 4)]
206 if os.name in ("nt", "ce"):
207 assert sizeof(X) == sizeof(c_int)*2
208 else:
209 assert sizeof(X) == sizeof(c_int)
210
211 def test_mixed_2(self):
212 class X(Structure):
213 _fields_ = [("a", c_byte, 4),
214 ("b", c_int, 32)]
215 assert sizeof(X) == sizeof(c_int)*2
216
217 def test_mixed_3(self):
218 class X(Structure):
219 _fields_ = [("a", c_byte, 4),
220 ("b", c_ubyte, 4)]
221 assert sizeof(X) == sizeof(c_byte)
222
223 def test_anon_bitfields(self):
224 # anonymous bit-fields gave a strange error message
225 class X(Structure):
226 _fields_ = [("a", c_byte, 4),
227 ("b", c_ubyte, 4)]
228 class Y(Structure):
229 _anonymous_ = ["_"]
230 _fields_ = [("_", X)]
231
232 def test_set_fields_attr(self):
233 class A(Structure):
234 pass
235 A._fields_ = [("a", c_byte),
236 ("b", c_ubyte)]
237
238 def test_set_fields_attr_bitfields(self):
239 class A(Structure):
240 pass
241 A._fields_ = [("a", POINTER(A)),
242 ("b", c_ubyte, 4)]
243
244 def test_set_fields_cycle_fails(self):
245 class A(Structure):
246 pass
247 with pytest.raises(AttributeError):
248 A._fields_ = [("a", A)]
+0
-62
pypy/module/test_lib_pypy/ctypes_tests/test_buffers.py less more
0 from ctypes import *
1 from .support import BaseCTypesTestChecker
2
3 class TestStringBuffer(BaseCTypesTestChecker):
4
5 def test_buffer(self):
6 b = create_string_buffer(32)
7 assert len(b) == 32
8 assert sizeof(b) == 32 * sizeof(c_char)
9 assert type(b[0]) is str
10
11 b = create_string_buffer(b"abc")
12 assert len(b) == 4 # trailing nul char
13 assert sizeof(b) == 4 * sizeof(c_char)
14 assert type(b[0]) is bytes
15 assert b[0] == b"a"
16 assert b[:] == b"abc\0"
17
18 def test_string_conversion(self):
19 b = create_string_buffer(u"abc")
20 assert len(b) == 4 # trailing nul char
21 assert sizeof(b) == 4 * sizeof(c_char)
22 assert type(b[0]) is str
23 assert b[0] == "a"
24 assert b[:] == "abc\0"
25
26 def test_from_buffer(self):
27 b1 = bytearray("abcde")
28 b = (c_char * 5).from_buffer(b1)
29 assert b[2] == "c"
30 #
31 b1 = bytearray("abcd")
32 b = c_int.from_buffer(b1)
33 assert b.value in (1684234849, # little endian
34 1633837924) # big endian
35
36 try:
37 c_wchar
38 except NameError:
39 pass
40 else:
41 def test_unicode_buffer(self):
42 b = create_unicode_buffer(32)
43 assert len(b) == 32
44 assert sizeof(b) == 32 * sizeof(c_wchar)
45 assert type(b[0]) is unicode
46
47 b = create_unicode_buffer(u"abc")
48 assert len(b) == 4 # trailing nul char
49 assert sizeof(b) == 4 * sizeof(c_wchar)
50 assert type(b[0]) is unicode
51 assert b[0] == u"a"
52 assert b[:] == "abc\0"
53
54 def test_unicode_conversion(self):
55 b = create_unicode_buffer(b"abc")
56 assert len(b) == 4 # trailing nul char
57 assert sizeof(b) == 4 * sizeof(c_wchar)
58 assert type(b[0]) is unicode
59 assert b[0] == u"a"
60 assert b[:] == "abc\0"
61
+0
-80
pypy/module/test_lib_pypy/ctypes_tests/test_callback_traceback.py less more
0 # derived from test_random_things.py
1 import py
2 from ctypes import *
3 import sys
4
5 def callback_func(arg):
6 42 / arg
7 raise ValueError(arg)
8
9 class TestCallbackTraceback:
10 # When an exception is raised in a ctypes callback function, the C
11 # code prints a traceback.
12 #
13 # This test makes sure the exception types *and* the exception
14 # value is printed correctly.
15 #
16 # Changed in 0.9.3: No longer is '(in callback)' prepended to the
17 # error message - instead a additional frame for the C code is
18 # created, then a full traceback printed. When SystemExit is
19 # raised in a callback function, the interpreter exits.
20
21 def capture_stderr(self, func, *args, **kw):
22 # helper - call function 'func', and return the captured stderr
23 import StringIO
24 old_stderr = sys.stderr
25 logger = sys.stderr = StringIO.StringIO()
26 try:
27 func(*args, **kw)
28 finally:
29 sys.stderr = old_stderr
30 return logger.getvalue()
31
32 def test_ValueError(self):
33 cb = CFUNCTYPE(c_int, c_int)(callback_func)
34 out = self.capture_stderr(cb, 42)
35 assert out.splitlines()[-1] == (
36 "ValueError: 42")
37
38 def test_IntegerDivisionError(self):
39 cb = CFUNCTYPE(c_int, c_int)(callback_func)
40 out = self.capture_stderr(cb, 0)
41 assert out.splitlines()[-1][:19] == (
42 "ZeroDivisionError: ")
43
44 def test_FloatDivisionError(self):
45 cb = CFUNCTYPE(c_int, c_double)(callback_func)
46 out = self.capture_stderr(cb, 0.0)
47 assert out.splitlines()[-1][:19] == (
48 "ZeroDivisionError: ")
49
50 def test_TypeErrorDivisionError(self):
51 cb = CFUNCTYPE(c_int, c_char_p)(callback_func)
52 out = self.capture_stderr(cb, "spam")
53 assert out.splitlines()[-1].startswith(
54 "TypeError: "
55 "unsupported operand type(s) for")
56
57 def test_SystemExit(self):
58 import _rawffi
59 if sys.flags.inspect:
60 skip("requires sys.flags.inspect == 0")
61 def callback_func(arg):
62 raise SystemExit(42)
63 def custom_exit(value):
64 raise Exception("<<<exit(%r)>>>" % (value,))
65 original_exit = _rawffi.exit
66 try:
67 _rawffi.exit = custom_exit
68 #
69 cb = CFUNCTYPE(c_int, c_int)(callback_func)
70 cb2 = cast(cast(cb, c_void_p), CFUNCTYPE(c_int, c_int))
71 out = self.capture_stderr(cb2, 0)
72 assert out.splitlines()[-1] == "Exception: <<<exit(42)>>>"
73 #
74 cb = CFUNCTYPE(c_int, c_int)(callback_func)
75 out = self.capture_stderr(cb, 0)
76 assert out.splitlines()[-1] == "Exception: <<<exit(42)>>>"
77 #
78 finally:
79 _rawffi.exit = original_exit
+0
-281
pypy/module/test_lib_pypy/ctypes_tests/test_callbacks.py less more
0 from ctypes import *
1 import pytest
2 from .support import BaseCTypesTestChecker
3
4 class TestCallbacks(BaseCTypesTestChecker):
5 functype = CFUNCTYPE
6
7 ## def tearDown(self):
8 ## import gc
9 ## gc.collect()
10
11 def callback(self, *args):
12 self.got_args = args
13 return args[-1]
14
15 def check_type(self, typ, arg):
16 unwrapped_types = {
17 c_float: (float,),
18 c_double: (float,),
19 c_char: (str,),
20 c_char_p: (str,),
21 c_uint: (int, long),
22 c_ulong: (int, long),
23 }
24
25 PROTO = self.functype.im_func(typ, typ)
26 cfunc = PROTO(self.callback)
27 result = cfunc(arg)
28 if typ == c_float:
29 assert abs(result - arg) < 0.000001
30 else:
31 assert self.got_args == (arg,)
32 assert result == arg
33
34 result2 = cfunc(typ(arg))
35 assert type(result2) in unwrapped_types.get(typ, (int, long))
36
37 PROTO = self.functype.im_func(typ, c_byte, typ)
38 result = PROTO(self.callback)(-3, arg)
39 if typ == c_float:
40 assert abs(result - arg) < 0.000001
41 else:
42 assert self.got_args == (-3, arg)
43 assert result == arg
44
45 ################
46
47 def test_byte(self):
48 self.check_type(c_byte, 42)
49 self.check_type(c_byte, -42)
50
51 def test_ubyte(self):
52 self.check_type(c_ubyte, 42)
53
54 def test_short(self):
55 self.check_type(c_short, 42)
56 self.check_type(c_short, -42)
57
58 def test_ushort(self):
59 self.check_type(c_ushort, 42)
60
61 def test_int(self):
62 self.check_type(c_int, 42)
63 self.check_type(c_int, -42)
64
65 def test_uint(self):
66 self.check_type(c_uint, 42)
67
68 def test_long(self):
69 self.check_type(c_long, 42)
70 self.check_type(c_long, -42)
71
72 def test_ulong(self):
73 self.check_type(c_ulong, 42)
74
75 def test_longlong(self):
76 self.check_type(c_longlong, 42)
77 self.check_type(c_longlong, -42)
78
79 def test_ulonglong(self):
80 self.check_type(c_ulonglong, 42)
81
82 def test_float(self):
83 # only almost equal: double -> float -> double
84 import math
85 self.check_type(c_float, math.e)
86 self.check_type(c_float, -math.e)
87
88 def test_double(self):
89 self.check_type(c_double, 3.14)
90 self.check_type(c_double, -3.14)
91
92 def test_char(self):
93 self.check_type(c_char, "x")
94 self.check_type(c_char, "a")
95
96 # disabled: would now (correctly) raise a RuntimeWarning about
97 # a memory leak. A callback function cannot return a non-integral
98 # C type without causing a memory leak.
99 ## def test_char_p(self):
100 ## self.check_type(c_char_p, "abc")
101 ## self.check_type(c_char_p, "def")
102
103
104 @pytest.mark.xfail(
105 reason="we are less strict about callback return type sanity")
106 def test_unsupported_restype_1(self):
107 # Only "fundamental" result types are supported for callback
108 # functions, the type must have a non-NULL stgdict->setfunc.
109 # POINTER(c_double), for example, is not supported.
110
111 prototype = self.functype.im_func(POINTER(c_double))
112 # The type is checked when the prototype is called
113 with pytest.raises(TypeError):
114 prototype(lambda: None)
115
116 try:
117 WINFUNCTYPE
118 except NameError:
119 pass
120 else:
121 class TestStdcallCallbacks(TestCallbacks):
122 functype = WINFUNCTYPE
123
124 ################################################################
125
126 class TestSampleCallbacks(BaseCTypesTestChecker):
127
128 def test_integrate(self):
129 # Derived from some then non-working code, posted by David Foster
130 import conftest
131 _ctypes_test = str(conftest.sofile)
132 dll = CDLL(_ctypes_test)
133
134 # The function prototype called by 'integrate': double func(double);
135 CALLBACK = CFUNCTYPE(c_double, c_double)
136
137 # The integrate function itself, exposed from the _ctypes_test dll
138 integrate = dll.integrate
139 integrate.argtypes = (c_double, c_double, CALLBACK, c_long)
140 integrate.restype = c_double
141
142 def func(x):
143 print 'calculating x**2 of',x
144 return x**2
145
146 result = integrate(0.0, 1.0, CALLBACK(func), 10)
147 diff = abs(result - 1./3.)
148
149 assert diff < 0.01, "%s not less than 0.01" % diff
150
151 ################################################################
152
153 class TestMoreCallbacks(BaseCTypesTestChecker):
154
155 def test_callback_with_struct_argument(self):
156 class RECT(Structure):
157 _fields_ = [("left", c_int), ("top", c_int),
158 ("right", c_int), ("bottom", c_int)]
159
160 proto = CFUNCTYPE(c_int, RECT)
161 def callback(point):
162 return point.left+point.top+point.right+point.bottom
163
164 cbp = proto(callback)
165
166 rect = RECT(1000,100,10,1)
167
168 res = cbp(rect)
169
170 assert res == 1111
171
172 def test_callback_from_c_with_struct_argument(self):
173 import conftest
174 _ctypes_test = str(conftest.sofile)
175 dll = CDLL(_ctypes_test)
176
177 class RECT(Structure):
178 _fields_ = [("left", c_long), ("top", c_long),
179 ("right", c_long), ("bottom", c_long)]
180
181 proto = CFUNCTYPE(c_int, RECT)
182 def callback(point):
183 return point.left+point.top+point.right+point.bottom
184
185 cbp = proto(callback)
186 rect = RECT(1000,100,10,1)
187
188 call_callback_with_rect = dll.call_callback_with_rect
189 call_callback_with_rect.restype = c_int
190 call_callback_with_rect.argtypes = [proto, RECT]
191 res = call_callback_with_rect(cbp, rect)
192 assert res == 1111
193
194 def test_callback_unsupported_return_struct(self):
195 class RECT(Structure):
196 _fields_ = [("left", c_int), ("top", c_int),
197 ("right", c_int), ("bottom", c_int)]
198
199 proto = CFUNCTYPE(RECT, c_int)
200 with pytest.raises(TypeError):
201 proto(lambda r: 0)
202
203
204 def test_qsort(self):
205 import conftest
206 _ctypes_test = str(conftest.sofile)
207 dll = CDLL(_ctypes_test)
208
209 PI = POINTER(c_int)
210 A = c_int*5
211 a = A()
212 for i in range(5):
213 a[i] = 5-i
214
215 assert a[0] == 5 # sanity
216
217 def comp(a, b):
218 a = a.contents.value
219 b = b.contents.value
220 return cmp(a,b)
221 qs = dll.my_qsort
222 qs.restype = None
223 CMP = CFUNCTYPE(c_int, PI, PI)
224 qs.argtypes = (PI, c_size_t, c_size_t, CMP)
225
226 qs(cast(a, PI), 5, sizeof(c_int), CMP(comp))
227
228 res = list(a)
229
230 assert res == [1,2,3,4,5]
231
232 def test_pyobject_as_opaque(self):
233 import conftest
234 _ctypes_test = str(conftest.sofile)
235 dll = CDLL(_ctypes_test)
236
237 def callback(arg):
238 return arg()
239
240 CTP = CFUNCTYPE(c_int, py_object)
241 cfunc = dll._testfunc_callback_opaque
242 cfunc.argtypes = [CTP, py_object]
243 cfunc.restype = c_int
244 res = cfunc(CTP(callback), lambda : 3)
245 assert res == 3
246
247 def test_callback_void(self, capsys):
248 import conftest
249 _ctypes_test = str(conftest.sofile)
250 dll = CDLL(_ctypes_test)
251
252 def callback():
253 pass
254
255 CTP = CFUNCTYPE(None)
256 cfunc = dll._testfunc_callback_void
257 cfunc.argtypes = [CTP]
258 cfunc.restype = int
259 cfunc(CTP(callback))
260 out, err = capsys.readouterr()
261 assert (out, err) == ("", "")
262
263
264 def test_callback_pyobject(self):
265 def callback(obj):
266 return obj
267
268 FUNC = CFUNCTYPE(py_object, py_object)
269 cfunc = FUNC(callback)
270 param = c_int(42)
271 assert cfunc(param) is param
272
273 def test_raise_argumenterror(self):
274 def callback(x):
275 pass
276 FUNC = CFUNCTYPE(None, c_void_p)
277 cfunc = FUNC(callback)
278 param = c_uint(42)
279 with pytest.raises(ArgumentError):
280 cfunc(param)
+0
-106
pypy/module/test_lib_pypy/ctypes_tests/test_cast.py less more
0 from ctypes import *
1 import sys, py
2 from .support import BaseCTypesTestChecker
3
4 def setup_module(mod):
5 import conftest
6 mod.lib = CDLL(str(conftest.sofile))
7
8 class TestCast(BaseCTypesTestChecker):
9
10 def test_array2pointer(self):
11 array = (c_int * 3)(42, 17, 2)
12
13 # casting an array to a pointer works.
14 ptr = cast(array, POINTER(c_int))
15 assert [ptr[i] for i in range(3)] == [42, 17, 2]
16
17 if 2*sizeof(c_short) == sizeof(c_int):
18 ptr = cast(array, POINTER(c_short))
19 if sys.byteorder == "little":
20 assert [ptr[i] for i in range(6)] == (
21 [42, 0, 17, 0, 2, 0])
22 else:
23 assert [ptr[i] for i in range(6)] == (
24 [0, 42, 0, 17, 0, 2])
25
26 def test_address2pointer(self):
27 array = (c_int * 3)(42, 17, 2)
28
29 address = addressof(array)
30 ptr = cast(c_void_p(address), POINTER(c_int))
31 assert [ptr[i] for i in range(3)] == [42, 17, 2]
32
33 ptr = cast(address, POINTER(c_int))
34 assert [ptr[i] for i in range(3)] == [42, 17, 2]
35
36 def test_p2a_objects(self):
37 py.test.skip("we make copies of strings")
38 array = (c_char_p * 5)()
39 assert array._objects is None
40 array[0] = "foo bar"
41 assert array._objects == {'0': "foo bar"}
42
43 p = cast(array, POINTER(c_char_p))
44 # array and p share a common _objects attribute
45 assert p._objects is array._objects
46 assert array._objects == {'0': "foo bar", id(array): array}
47 p[0] = "spam spam"
48 assert p._objects == {'0': "spam spam", id(array): array}
49 assert array._objects is p._objects
50 p[1] = "foo bar"
51 assert p._objects == {'1': 'foo bar', '0': "spam spam", id(array): array}
52 assert array._objects is p._objects
53
54 def test_other(self):
55 p = cast((c_int * 4)(1, 2, 3, 4), POINTER(c_int))
56 assert p[:4] == [1,2, 3, 4]
57 c_int()
58 assert p[:4] == [1, 2, 3, 4]
59 p[2] = 96
60 assert p[:4] == [1, 2, 96, 4]
61 c_int()
62 assert p[:4] == [1, 2, 96, 4]
63
64 def test_char_p(self):
65 # This didn't work: bad argument to internal function
66 s = c_char_p("hiho")
67
68 assert cast(cast(s, c_void_p), c_char_p).value == (
69 "hiho")
70
71 try:
72 c_wchar_p
73 except NameError:
74 pass
75 else:
76 def test_wchar_p(self):
77 s = c_wchar_p("hiho")
78 assert cast(cast(s, c_void_p), c_wchar_p).value == (
79 "hiho")
80
81 def test_cast_functype(self):
82 # make sure we can cast function type
83 my_sqrt = lib.my_sqrt
84 saved_objects = my_sqrt._objects.copy()
85 sqrt = cast(cast(my_sqrt, c_void_p), CFUNCTYPE(c_double, c_double))
86 assert sqrt(4.0) == 2.0
87 assert not cast(0, CFUNCTYPE(c_int))
88 #
89 assert sqrt._objects is my_sqrt._objects # on CPython too
90 my_sqrt._objects.clear()
91 my_sqrt._objects.update(saved_objects)
92
93 def test_cast_argumenterror(self):
94 param = c_uint(42)
95 py.test.raises(ArgumentError, "cast(param, c_void_p)")
96
97 def test_c_bool(self):
98 x = c_bool(42)
99 assert x.value is True
100 x = c_bool(0.0)
101 assert x.value is False
102 x = c_bool("")
103 assert x.value is False
104 x = c_bool(['yadda'])
105 assert x.value is True
+0
-201
pypy/module/test_lib_pypy/ctypes_tests/test_cfuncs.py less more
0 # A lot of failures in these tests on Mac OS X.
1 # Byte order related?
2
3 from ctypes import *
4 import py
5 from .support import BaseCTypesTestChecker
6
7 def setup_module(mod):
8 import conftest
9 mod._ctypes_test = str(conftest.sofile)
10 # this means you cannot run tests directly without invoking this
11 mod.TestCFunctions._dll = CDLL(_ctypes_test)
12
13 class TestCFunctions(BaseCTypesTestChecker):
14
15 def S(self):
16 return c_longlong.in_dll(self._dll, "last_tf_arg_s").value
17 def U(self):
18 return c_ulonglong.in_dll(self._dll, "last_tf_arg_u").value
19
20 def test_byte(self):
21 self._dll.tf_b.restype = c_byte
22 self._dll.tf_b.argtypes = (c_byte,)
23 assert self._dll.tf_b(-126) == -42
24 assert self.S() == -126
25
26 def test_byte_plus(self):
27 self._dll.tf_bb.restype = c_byte
28 self._dll.tf_bb.argtypes = (c_byte, c_byte)
29 assert self._dll.tf_bb(0, -126) == -42
30 assert self.S() == -126
31
32 def test_ubyte(self):
33 self._dll.tf_B.restype = c_ubyte
34 self._dll.tf_B.argtypes = (c_ubyte,)
35 assert self._dll.tf_B(255) == 85
36 assert self.U() == 255
37
38 def test_ubyte_plus(self):
39 self._dll.tf_bB.restype = c_ubyte
40 self._dll.tf_bB.argtypes = (c_byte, c_ubyte)
41 assert self._dll.tf_bB(0, 255) == 85
42 assert self.U() == 255
43
44 def test_short(self):
45 self._dll.tf_h.restype = c_short
46 self._dll.tf_h.argtypes = (c_short,)
47 assert self._dll.tf_h(-32766) == -10922
48 assert self.S() == -32766
49
50 def test_short_plus(self):
51 self._dll.tf_bh.restype = c_short
52 self._dll.tf_bh.argtypes = (c_byte, c_short)
53 assert self._dll.tf_bh(0, -32766) == -10922
54 assert self.S() == -32766
55
56 def test_ushort(self):
57 self._dll.tf_H.restype = c_ushort
58 self._dll.tf_H.argtypes = (c_ushort,)
59 assert self._dll.tf_H(65535) == 21845
60 assert self.U() == 65535
61
62 def test_ushort_plus(self):
63 self._dll.tf_bH.restype = c_ushort
64 self._dll.tf_bH.argtypes = (c_byte, c_ushort)
65 assert self._dll.tf_bH(0, 65535) == 21845
66 assert self.U() == 65535
67
68 def test_int(self):
69 self._dll.tf_i.restype = c_int
70 self._dll.tf_i.argtypes = (c_int,)
71 assert self._dll.tf_i(-2147483646) == -715827882
72 assert self.S() == -2147483646
73
74 def test_int_plus(self):
75 self._dll.tf_bi.restype = c_int
76 self._dll.tf_bi.argtypes = (c_byte, c_int)
77 assert self._dll.tf_bi(0, -2147483646) == -715827882
78 assert self.S() == -2147483646
79
80 def test_uint(self):
81 self._dll.tf_I.restype = c_uint
82 self._dll.tf_I.argtypes = (c_uint,)
83 assert self._dll.tf_I(4294967295) == 1431655765
84 assert self.U() == 4294967295
85
86 def test_uint_plus(self):
87 self._dll.tf_bI.restype = c_uint
88 self._dll.tf_bI.argtypes = (c_byte, c_uint)
89 assert self._dll.tf_bI(0, 4294967295) == 1431655765
90 assert self.U() == 4294967295
91
92 def test_long(self):
93 self._dll.tf_l.restype = c_long
94 self._dll.tf_l.argtypes = (c_long,)
95 assert self._dll.tf_l(-2147483646) == -715827882
96 assert self.S() == -2147483646
97
98 def test_long_plus(self):
99 self._dll.tf_bl.restype = c_long
100 self._dll.tf_bl.argtypes = (c_byte, c_long)
101 assert self._dll.tf_bl(0, -2147483646) == -715827882
102 assert self.S() == -2147483646
103
104 def test_ulong(self):
105 self._dll.tf_L.restype = c_ulong
106 self._dll.tf_L.argtypes = (c_ulong,)
107 assert self._dll.tf_L(4294967295) == 1431655765
108 assert self.U() == 4294967295
109
110 def test_ulong_plus(self):
111 self._dll.tf_bL.restype = c_ulong
112 self._dll.tf_bL.argtypes = (c_char, c_ulong)
113 assert self._dll.tf_bL(' ', 4294967295) == 1431655765
114 assert self.U() == 4294967295
115
116 def test_longlong(self):
117 self._dll.tf_q.restype = c_longlong
118 self._dll.tf_q.argtypes = (c_longlong, )
119 assert self._dll.tf_q(-9223372036854775806) == -3074457345618258602
120 assert self.S() == -9223372036854775806
121
122 def test_longlong_plus(self):
123 self._dll.tf_bq.restype = c_longlong
124 self._dll.tf_bq.argtypes = (c_byte, c_longlong)
125 assert self._dll.tf_bq(0, -9223372036854775806) == -3074457345618258602
126 assert self.S() == -9223372036854775806
127
128 def test_ulonglong(self):
129 self._dll.tf_Q.restype = c_ulonglong
130 self._dll.tf_Q.argtypes = (c_ulonglong, )
131 assert self._dll.tf_Q(18446744073709551615) == 6148914691236517205
132 assert self.U() == 18446744073709551615
133
134 def test_ulonglong_plus(self):
135 self._dll.tf_bQ.restype = c_ulonglong
136 self._dll.tf_bQ.argtypes = (c_byte, c_ulonglong)
137 assert self._dll.tf_bQ(0, 18446744073709551615) == 6148914691236517205
138 assert self.U() == 18446744073709551615
139
140 def test_float(self):
141 self._dll.tf_f.restype = c_float
142 self._dll.tf_f.argtypes = (c_float,)
143 assert self._dll.tf_f(-42.) == -14.
144 assert self.S() == -42
145
146 def test_float_plus(self):
147 self._dll.tf_bf.restype = c_float
148 self._dll.tf_bf.argtypes = (c_byte, c_float)
149 assert self._dll.tf_bf(0, -42.) == -14.
150 assert self.S() == -42
151
152 def test_double(self):
153 self._dll.tf_d.restype = c_double
154 self._dll.tf_d.argtypes = (c_double,)
155 assert self._dll.tf_d(42.) == 14.
156 assert self.S() == 42
157
158 def test_double_plus(self):
159 self._dll.tf_bd.restype = c_double
160 self._dll.tf_bd.argtypes = (c_byte, c_double)
161 assert self._dll.tf_bd(0, 42.) == 14.
162 assert self.S() == 42
163
164 def test_callwithresult(self):
165 def process_result(result):
166 return result * 2
167 self._dll.tf_i.restype = process_result
168 self._dll.tf_i.argtypes = (c_int,)
169 assert self._dll.tf_i(42) == 28
170 assert self.S() == 42
171 assert self._dll.tf_i(-42) == -28
172 assert self.S() == -42
173
174 def test_void(self):
175 self._dll.tv_i.restype = None
176 self._dll.tv_i.argtypes = (c_int,)
177 assert self._dll.tv_i(42) == None
178 assert self.S() == 42
179 assert self._dll.tv_i(-42) == None
180 assert self.S() == -42
181
182 # The following repeates the above tests with stdcall functions (where
183 # they are available)
184 try:
185 WinDLL
186 except NameError:
187 pass
188 else:
189 class stdcall_dll(WinDLL):
190 def __getattr__(self, name):
191 if name[:2] == '__' and name[-2:] == '__':
192 raise AttributeError(name)
193 func = self._FuncPtr(("s_" + name, self))
194 setattr(self, name, func)
195 return func
196
197 class TestStdcallCFunctions(TestCFunctions):
198 def setup_class(cls):
199 TestCFunctions.setup_class.im_func(cls)
200 cls._dll = stdcall_dll(_ctypes_test)
+0
-37
pypy/module/test_lib_pypy/ctypes_tests/test_checkretval.py less more
0 import pytest
1 import sys
2
3 from ctypes import *
4
5 def setup_module(mod):
6 import conftest
7 mod.dll = CDLL(str(conftest.sofile))
8
9 class CHECKED(c_int):
10 def _check_retval_(value):
11 # Receives a CHECKED instance.
12 return str(value.value)
13 _check_retval_ = staticmethod(_check_retval_)
14
15 class TestRetval:
16
17 def test_checkretval(self):
18 assert 42 == dll._testfunc_p_p(42)
19
20 dll._testfunc_p_p.restype = CHECKED
21 assert "42" == dll._testfunc_p_p(42)
22
23 dll._testfunc_p_p.restype = None
24 assert None == dll._testfunc_p_p(42)
25
26 del dll._testfunc_p_p.restype
27 assert 42 == dll._testfunc_p_p(42)
28
29 try:
30 oledll
31 except NameError:
32 pass
33 else:
34 def test_oledll(self):
35 with pytest.raises(WindowsError):
36 oledll.oleaut32.CreateTypeLib2(0, 0, 0)
+0
-83
pypy/module/test_lib_pypy/ctypes_tests/test_commethods.py less more
0 # unittest for SOME ctypes com function calls.
1 # Can't resist from implementing some kind of mini-comtypes
2 # theller ;-)
3
4 import pytest
5 import sys
6 if sys.platform != "win32":
7 pytest.importorskip('skip_the_whole_module') # hack!
8
9 import ctypes, new, unittest
10 from ctypes.wintypes import HRESULT
11 from _ctypes import COMError
12
13 oleaut32 = ctypes.OleDLL("oleaut32")
14
15 class UnboundMethod(object):
16 def __init__(self, func, index, name):
17 self.func = func
18 self.index = index
19 self.name = name
20 self.__doc__ = func.__doc__
21
22 def __repr__(self):
23 return "<Unbound COM method index %d: %s at %x>" % (self.index, self.name, id(self))
24
25 def __get__(self, instance, owner):
26 if instance is None:
27 return self
28 return new.instancemethod(self.func, instance, owner)
29
30 def commethod(index, restype, *argtypes):
31 """A decorator that generates COM methods. The decorated function
32 itself is not used except for it's name."""
33 def make_commethod(func):
34 comfunc = ctypes.WINFUNCTYPE(restype, *argtypes)(index, func.__name__)
35 comfunc.__name__ = func.__name__
36 comfunc.__doc__ = func.__doc__
37 return UnboundMethod(comfunc, index, func.__name__)
38 return make_commethod
39
40 class ICreateTypeLib2(ctypes.c_void_p):
41
42 @commethod(1, ctypes.c_long)
43 def AddRef(self):
44 pass
45
46 @commethod(2, ctypes.c_long)
47 def Release(self):
48 pass
49
50 @commethod(4, HRESULT, ctypes.c_wchar_p)
51 def SetName(self):
52 """Set the name of the library."""
53
54 @commethod(12, HRESULT)
55 def SaveAllChanges(self):
56 pass
57
58
59 CreateTypeLib2 = oleaut32.CreateTypeLib2
60 CreateTypeLib2.argtypes = (ctypes.c_int, ctypes.c_wchar_p, ctypes.POINTER(ICreateTypeLib2))
61
62 ################################################################
63
64 def test_basic_comtypes():
65 punk = ICreateTypeLib2()
66 hr = CreateTypeLib2(0, "foobar.tlb", punk)
67 assert hr == 0
68
69 assert 2 == punk.AddRef()
70 assert 3 == punk.AddRef()
71 assert 4 == punk.AddRef()
72
73 punk.SetName("TypeLib_ByPYPY")
74 with pytest.raises(COMError):
75 punk.SetName(None)
76
77 # This would save the typelib to disk.
78 ## punk.SaveAllChanges()
79
80 assert 3 == punk.Release()
81 assert 2 == punk.Release()
82 assert 1 == punk.Release()
+0
-26
pypy/module/test_lib_pypy/ctypes_tests/test_errno.py less more
0 import py
1
2 import ctypes
3 from _ctypes import function
4
5 try:
6 import _rawffi
7 except ImportError:
8 py.test.skip("app-level test only for PyPy")
9
10 class TestErrno:
11
12 def test_errno_saved_and_restored(self):
13 def check():
14 assert _rawffi.get_errno() == 42
15 assert ctypes.get_errno() == old
16 check.free_temp_buffers = lambda *args: None
17 f = function.CFuncPtr()
18 old = _rawffi.get_errno()
19 f._flags_ = _rawffi.FUNCFLAG_USE_ERRNO
20 ctypes.set_errno(42)
21 f._call_funcptr(check)
22 assert _rawffi.get_errno() == old
23 ctypes.set_errno(0)
24
25 # see also test_functions.test_errno
+0
-248
pypy/module/test_lib_pypy/ctypes_tests/test_extra.py less more
0 """
1 The purpose of this test file is to check how ctypes really work,
2 down to what aliases what and what exact types operations return.
3 """
4
5 import py
6 from ctypes import *
7 from .support import BaseCTypesTestChecker
8
9 class TestExtra(BaseCTypesTestChecker):
10 def test_primitive_pointer(self):
11 x = c_int(5)
12 assert x.value == 5
13 x.value = 6
14 assert x.value == 6
15
16 p = pointer(x) # p ---> x = 6
17 assert isinstance(p.contents, c_int)
18 p.contents.value += 1
19 assert x.value == 7 # p ---> x = 7
20
21 y = c_int(12)
22 p.contents = y # p ---> y = 12
23 p.contents.value += 2 # p ---> y = 14
24 assert y.value == 14
25 assert x.value == 7
26
27 pp = pointer(p) # pp ---> p ---> y = 14
28 pp.contents.contents = x # pp ---> p ---> x = 7
29 p.contents.value += 2 # pp ---> p ---> x = 9
30 assert x.value == 9
31
32 assert isinstance(p[0], int)
33 p[0] += 1 # pp ---> p ---> x = 10
34 assert x.value == 10
35 z = c_int(86)
36 p[0] = z # pp ---> p ---> x = 86 (not z!)
37 assert x.value == 86
38 z.value = 84
39 assert x.value == 86
40
41 assert isinstance(pp[0], POINTER(c_int))
42 assert pp[0].contents.value == x.value == 86
43 pp[0].contents = z # pp ---> p ---> z = 84
44 assert p.contents.value == z.value == 84
45
46 ## *** the rest is commented out because it should work but occasionally
47 ## *** trigger a ctypes bug (SourceForge bug #1467852). ***
48 ## q = pointer(y)
49 ## pp[0] = q # pp ---> p ---> y = 14
50 ## assert y.value == 14 # (^^^ not q! )
51 ## assert p.contents.value == 14
52 ## assert pp.contents.contents.value == 14
53 ## q.contents = x
54 ## assert pp.contents.contents.value == 14
55
56
57 def test_char_p(self):
58 x = c_char_p("hello\x00world")
59 assert x.value == "hello"
60 x.value = "world"
61 assert x.value == "world"
62
63 p = pointer(x)
64 assert p[0] == x.value == "world"
65 p[0] = "other"
66 assert x.value == p.contents.value == p[0] == "other"
67
68 myarray = (c_char_p * 10)()
69 myarray[7] = "hello"
70 assert isinstance(myarray[7], str)
71 assert myarray[7] == "hello"
72
73 def test_struct(self):
74 class tagpoint(Structure):
75 _fields_ = [('x', c_int),
76 ('p', POINTER(c_short))]
77
78 y = c_short(123)
79 z = c_short(-33)
80 s = tagpoint()
81 s.p.contents = z
82 assert s.p.contents.value == -33
83 s.p = pointer(y)
84 assert s.p.contents.value == 123
85 s.p.contents.value = 124
86 assert y.value == 124
87
88 s = tagpoint(x=12)
89 assert s.x == 12
90 s = tagpoint(17, p=pointer(z))
91 assert s.x == 17
92 assert s.p.contents.value == -33
93
94 def test_ptr_array(self):
95 a = (POINTER(c_ushort) * 5)()
96 x = c_ushort(52)
97 y = c_ushort(1000)
98
99 a[2] = pointer(x)
100 assert a[2].contents.value == 52
101 a[2].contents.value += 1
102 assert x.value == 53
103
104 a[3].contents = y
105 assert a[3].contents.value == 1000
106 a[3].contents.value += 1
107 assert y.value == 1001
108
109 def test_void_p(self):
110 x = c_int(12)
111 p1 = cast(pointer(x), c_void_p)
112 p2 = cast(p1, POINTER(c_int))
113 assert p2.contents.value == 12
114
115 def test_char_array(self):
116 a = (c_char * 3)()
117 a[0] = 'x'
118 a[1] = 'y'
119 assert a.value == 'xy'
120 a[2] = 'z'
121 assert a.value == 'xyz'
122
123 b = create_string_buffer(3)
124 assert type(b) is type(a)
125 assert len(b) == 3
126
127 b.value = "nxw"
128 assert b[0] == 'n'
129 assert b[1] == 'x'
130 assert b[2] == 'w'
131
132 b.value = "?"
133 assert b[0] == '?'
134 assert b[1] == '\x00'
135 assert b[2] == 'w'
136
137 class S(Structure):
138 _fields_ = [('p', POINTER(c_char))]
139
140 s = S()
141 s.p = b
142 s.p.contents.value = '!'
143 assert b.value == '!'
144
145 assert len(create_string_buffer(0)) == 0
146
147 def test_array(self):
148 a = (c_int * 10)()
149
150 class S(Structure):
151 _fields_ = [('p', POINTER(c_int))]
152
153 s = S()
154 s.p = a
155 s.p.contents.value = 42
156 assert a[0] == 42
157
158 a = (c_int * 5)(5, 6, 7)
159 assert list(a) == [5, 6, 7, 0, 0]
160
161 def test_truth_value(self):
162 p = POINTER(c_int)()
163 assert not p
164 p.contents = c_int(12)
165 assert p
166 # I can't figure out how to reset p to NULL...
167
168 assert c_int(12)
169 assert not c_int(0) # a bit strange, if you ask me
170 assert c_int(-1)
171 assert not c_byte(0)
172 assert not c_char('\x00') # hum
173 assert not c_float(0.0)
174 assert not c_double(0.0)
175 assert not c_ulonglong(0)
176 assert c_ulonglong(2**42)
177
178 assert c_char_p("hello")
179 assert c_char_p("")
180 assert not c_char_p(None)
181
182 assert not c_void_p()
183
184 def test_sizeof(self):
185 x = create_string_buffer(117)
186 assert sizeof(x) == 117 # assumes that chars are one byte each
187 x = (c_int * 42)()
188 assert sizeof(x) == 42 * sizeof(c_int)
189
190 def test_convert_pointers(self):
191 import conftest
192 _ctypes_test = str(conftest.sofile)
193 dll = CDLL(_ctypes_test)
194 func = dll._testfunc_p_p
195 func.restype = c_char_p
196
197 # automatic conversions to c_char_p
198 func.argtypes = [c_char_p]
199 assert func("hello") == "hello"
200 assert func(c_char_p("hello")) == "hello"
201 assert func((c_char * 6)(*"hello")) == "hello"
202 assert func(create_string_buffer("hello")) == "hello"
203
204 # automatic conversions to c_void_p
205 func.argtypes = [c_void_p]
206 assert func("hello") == "hello"
207 assert func(c_char_p("hello")) == "hello"
208 assert func((c_char * 6)(*"hello")) == "hello"
209 assert func((c_byte * 6)(104,101,108,108,111)) =="hello"
210 assert func(create_string_buffer("hello")) == "hello"
211
212 def test_varsize_cast(self):
213 import struct
214 N = struct.calcsize("l")
215 x = c_long()
216 p = cast(pointer(x), POINTER(c_ubyte*N))
217 for i, c in enumerate(struct.pack("l", 12345678)):
218 p.contents[i] = ord(c)
219 assert x.value == 12345678
220
221 def test_cfunctype_inspection(self):
222 T = CFUNCTYPE(c_int, c_ubyte)
223 # T.argtypes and T.restype don't work, must use a dummy instance
224 assert list(T().argtypes) == [c_ubyte]
225 assert T().restype == c_int
226
227 def test_from_param(self):
228 # other working cases of from_param
229 assert isinstance(c_void_p.from_param((c_int * 4)()), c_int*4)
230
231 def test_array_mul(self):
232 assert c_int * 10 == 10 * c_int
233 py.test.raises(TypeError, 'c_int * c_int')
234 py.test.raises(TypeError, 'c_int * (-1.5)')
235 py.test.raises(TypeError, 'c_int * "foo"')
236 py.test.raises(TypeError, '(-1.5) * c_int')
237 py.test.raises(TypeError, '"foo" * c_int')
238
239 def test_cast_none(self):
240 def check(P):
241 x = cast(None, P)
242 assert isinstance(x, P)
243 assert not x
244 check(c_void_p)
245 check(c_char_p)
246 check(POINTER(c_int))
247 check(POINTER(c_int * 10))
+0
-156
pypy/module/test_lib_pypy/ctypes_tests/test_funcptr.py less more
0 import pytest
1 import sys, os, unittest
2 from ctypes import *
3
4 try:
5 WINFUNCTYPE
6 except NameError:
7 # fake to enable this test on Linux
8 WINFUNCTYPE = CFUNCTYPE
9
10 def setup_module(mod):
11 import conftest
12 _ctypes_test = str(conftest.sofile)
13 mod.lib = CDLL(_ctypes_test)
14
15
16 class TestCFuncPtr:
17 def test_basic(self):
18 X = WINFUNCTYPE(c_int, c_int, c_int)
19
20 def func(*args):
21 return len(args)
22
23 x = X(func)
24 assert x.restype == c_int
25 assert x.argtypes == (c_int, c_int)
26 assert sizeof(x) == sizeof(c_voidp)
27 assert sizeof(X) == sizeof(c_voidp)
28
29 @pytest.mark.xfail(
30 reason="cdecl funcptrs ignoring extra args is not implemented")
31 def test_first(self):
32 StdCallback = WINFUNCTYPE(c_int, c_int, c_int)
33 CdeclCallback = CFUNCTYPE(c_int, c_int, c_int)
34
35 def func(a, b):
36 return a + b
37
38 s = StdCallback(func)
39 c = CdeclCallback(func)
40
41 assert s(1, 2) == 3
42 assert c(1, 2) == 3
43 # The following no longer raises a TypeError - it is now
44 # possible, as in C, to call cdecl functions with more parameters.
45 #self.assertRaises(TypeError, c, 1, 2, 3)
46 assert c(1, 2, 3, 4, 5, 6) == 3
47 if not WINFUNCTYPE is CFUNCTYPE and os.name != "ce":
48 with pytest.raises(TypeError):
49 s(1, 2, 3)
50
51 @pytest.mark.skipif("sys.platform != 'win32'")
52 def test_structures(self):
53 WNDPROC = WINFUNCTYPE(c_long, c_int, c_int, c_int, c_int)
54
55 def wndproc(hwnd, msg, wParam, lParam):
56 return hwnd + msg + wParam + lParam
57
58 HINSTANCE = c_int
59 HICON = c_int
60 HCURSOR = c_int
61 LPCTSTR = c_char_p
62
63 class WNDCLASS(Structure):
64 _fields_ = [("style", c_uint),
65 ("lpfnWndProc", WNDPROC),
66 ("cbClsExtra", c_int),
67 ("cbWndExtra", c_int),
68 ("hInstance", HINSTANCE),
69 ("hIcon", HICON),
70 ("hCursor", HCURSOR),
71 ("lpszMenuName", LPCTSTR),
72 ("lpszClassName", LPCTSTR)]
73
74 wndclass = WNDCLASS()
75 wndclass.lpfnWndProc = WNDPROC(wndproc)
76
77 WNDPROC_2 = WINFUNCTYPE(c_long, c_int, c_int, c_int, c_int)
78
79 # This is no longer true, now that WINFUNCTYPE caches created types internally.
80 ## # CFuncPtr subclasses are compared by identity, so this raises a TypeError:
81 ## raises(TypeError, setattr, wndclass,
82 ## "lpfnWndProc", WNDPROC_2(wndproc))
83 # instead:
84
85 assert WNDPROC is WNDPROC_2
86 # 'wndclass.lpfnWndProc' leaks 94 references. Why?
87 assert wndclass.lpfnWndProc(1, 2, 3, 4) == 10
88
89
90 f = wndclass.lpfnWndProc
91
92 del wndclass
93 del wndproc
94
95 assert f(10, 11, 12, 13) == 46
96
97 def test_dllfunctions(self):
98
99 def NoNullHandle(value):
100 if not value:
101 raise WinError()
102 return value
103
104 strchr = lib.my_strchr
105 strchr.restype = c_char_p
106 strchr.argtypes = (c_char_p, c_char)
107 assert strchr("abcdefghi", "b") == "bcdefghi"
108 assert strchr("abcdefghi", "x") == None
109
110
111 strtok = lib.my_strtok
112 strtok.restype = c_char_p
113 # Neither of this does work: strtok changes the buffer it is passed
114 ## strtok.argtypes = (c_char_p, c_char_p)
115 ## strtok.argtypes = (c_string, c_char_p)
116
117 def c_string(init):
118 size = len(init) + 1
119 return (c_char*size)(*init)
120
121 s = "a\nb\nc"
122 b = c_string(s)
123
124 ## b = (c_char * (len(s)+1))()
125 ## b.value = s
126
127 ## b = c_string(s)
128 assert strtok(b, "\n") == "a"
129 assert strtok(None, "\n") == "b"
130 assert strtok(None, "\n") == "c"
131 assert strtok(None, "\n") == None
132
133 @pytest.mark.xfail(
134 reason="This test needs mmap to make sure the code is executable, "
135 "please rewrite me")
136 def test_from_address(self):
137 def make_function():
138 proto = CFUNCTYPE(c_int)
139 a=create_string_buffer(
140 "\xB8\x78\x56\x34\x12" # mov eax, 0x12345678
141 "\xc3" # ret 0
142 )
143 ptr = pointer(a)
144 func = proto.from_address(addressof(ptr))
145 func.__keep = ptr # keep ptr alive
146 return func
147 f = make_function()
148 # This assembler should also work on Linux 32bit,
149 # but it segfaults for some reason.
150 if sys.platform == 'win32':
151 assert f() == 0x12345678
152
153 def test_restype(self):
154 foo = lib.my_unused_function
155 assert foo.restype is c_int # by default
+0
-639
pypy/module/test_lib_pypy/ctypes_tests/test_functions.py less more
0 """
1 Here is probably the place to write the docs, since the test-cases
2 show how the type behave.
3
4 Later...
5 """
6
7 from __future__ import with_statement
8 from ctypes import *
9 import sys
10 import pytest
11 from .support import BaseCTypesTestChecker
12
13 try:
14 WINFUNCTYPE
15 except NameError:
16 # fake to enable this test on Linux
17 WINFUNCTYPE = CFUNCTYPE
18
19
20 def setup_module(mod):
21 import conftest
22 _ctypes_test = str(conftest.sofile)
23 mod.dll = CDLL(_ctypes_test, use_errno=True)
24 if sys.platform == "win32":
25 mod.windll = WinDLL(_ctypes_test)
26
27 class POINT(Structure):
28 _fields_ = [("x", c_int), ("y", c_int)]
29 class RECT(Structure):
30 _fields_ = [("left", c_int), ("top", c_int),
31 ("right", c_int), ("bottom", c_int)]
32
33 class TestFunctions(BaseCTypesTestChecker):
34
35 def test_mro(self):
36 # in Python 2.3, this raises TypeError: MRO conflict among bases classes,
37 # in Python 2.2 it works.
38 #
39 # But in early versions of _ctypes.c, the result of tp_new
40 # wasn't checked, and it even crashed Python.
41 # Found by Greg Chapman.
42
43 try:
44 class X(object, Array):
45 _length_ = 5
46 _type_ = "i"
47 except TypeError:
48 pass
49
50
51 from _ctypes import _Pointer
52 try:
53 class X(object, _Pointer):
54 pass
55 except TypeError:
56 pass
57
58 from _ctypes import _SimpleCData
59 try:
60 class X(object, _SimpleCData):
61 _type_ = "i"
62 except TypeError:
63 pass
64
65 try:
66 class X(object, Structure):
67 _fields_ = []
68 except TypeError:
69 pass
70
71
72 def test_wchar_parm(self):
73 try:
74 c_wchar
75 except NameError:
76 return
77 f = dll._testfunc_i_bhilfd
78 f.argtypes = [c_byte, c_wchar, c_int, c_long, c_float, c_double]
79 result = f(1, "x", 3, 4, 5.0, 6.0)
80 assert result == 139
81 assert type(result) == int
82
83 def test_wchar_result(self):
84 try:
85 c_wchar
86 except NameError:
87 return
88 f = dll._testfunc_i_bhilfd
89 f.argtypes = [c_byte, c_short, c_int, c_long, c_float, c_double]
90 f.restype = c_wchar
91 result = f(0, 0, 0, 0, 0, 0)
92 assert result == u'\x00'
93
94 def test_char_result(self):
95 f = dll._testfunc_i_bhilfd
96 f.argtypes = [c_byte, c_short, c_int, c_long, c_float, c_double]
97 f.restype = c_char
98 result = f(0, 0, 0, 0, 0, 0)
99 assert result == b'\x00'
100
101 def test_boolresult(self):
102 f = dll._testfunc_i_bhilfd
103 f.argtypes = [c_byte, c_short, c_int, c_long, c_float, c_double]
104 f.restype = c_bool
105 false_result = f(0, 0, 0, 0, 0, 0)
106 assert false_result is False
107 true_result = f(1, 0, 0, 0, 0, 0)
108 assert true_result is True
109
110 def test_voidresult(self):
111 f = dll._testfunc_v
112 f.restype = None
113 f.argtypes = [c_int, c_int, POINTER(c_int)]
114 result = c_int()
115 assert None == f(1, 2, byref(result))
116 assert result.value == 3
117
118 def test_intresult(self):
119 f = dll._testfunc_i_bhilfd
120 f.argtypes = [c_byte, c_short, c_int, c_long, c_float, c_double]
121 f.restype = c_int
122 result = f(1, 2, 3, 4, 5.0, 6.0)
123 assert result == 21
124 assert type(result) == int
125
126 result = f(-1, -2, -3, -4, -5.0, -6.0)
127 assert result == -21
128 assert type(result) == int
129
130 # If we declare the function to return a short,
131 # is the high part split off?
132 f.restype = c_short
133 result = f(1, 2, 3, 4, 5.0, 6.0)
134 assert result == 21
135 assert type(result) == int
136
137 result = f(1, 2, 3, 0x10004, 5.0, 6.0)
138 assert result == 21
139 assert type(result) == int
140
141 # You cannot assing character format codes as restype any longer
142 with pytest.raises(TypeError):
143 setattr(f, "restype", "i")
144
145 def test_unicode_function_name(self):
146 f = dll[u'_testfunc_i_bhilfd']
147 f.argtypes = [c_byte, c_short, c_int, c_long, c_float, c_double]
148 f.restype = c_int
149 result = f(1, 2, 3, 4, 5.0, 6.0)
150 assert result == 21
151
152 def test_truncate_python_longs(self):
153 f = dll._testfunc_i_bhilfd
154 f.argtypes = [c_byte, c_short, c_int, c_long, c_float, c_double]
155 f.restype = c_int
156 x = sys.maxint * 2
157 result = f(x, x, x, x, 0, 0)
158 assert result == -8
159
160
161 def test_floatresult(self):
162 f = dll._testfunc_f_bhilfd
163 f.argtypes = [c_byte, c_short, c_int, c_long, c_float, c_double]
164 f.restype = c_float
165 result = f(1, 2, 3, 4, 5.0, 6.0)
166 assert result == 21
167 assert type(result) == float
168
169 result = f(-1, -2, -3, -4, -5.0, -6.0)
170 assert result == -21
171 assert type(result) == float
172
173 def test_doubleresult(self):
174 f = dll._testfunc_d_bhilfd
175 f.argtypes = [c_byte, c_short, c_int, c_long, c_float, c_double]
176 f.restype = c_double
177 result = f(1, 2, 3, 4, 5.0, 6.0)
178 assert result == 21
179 assert type(result) == float
180
181 result = f(-1, -2, -3, -4, -5.0, -6.0)
182 assert result == -21
183 assert type(result) == float
184
185 def test_longlongresult(self):
186 try:
187 c_longlong
188 except NameError:
189 return
190 f = dll._testfunc_q_bhilfd
191 f.restype = c_longlong
192 f.argtypes = [c_byte, c_short, c_int, c_long, c_float, c_double]
193 result = f(1, 2, 3, 4, 5.0, 6.0)
194 assert result == 21
195
196 f = dll._testfunc_q_bhilfdq
197 f.restype = c_longlong
198 f.argtypes = [c_byte, c_short, c_int, c_long, c_float, c_double, c_longlong]
199 result = f(1, 2, 3, 4, 5.0, 6.0, 21)
200 assert result == 42
201
202 def test_stringresult(self):
203 f = dll._testfunc_p_p
204 f.argtypes = None
205 f.restype = c_char_p
206 result = f("123")
207 assert result == "123"
208
209 result = f(None)
210 assert result == None
211
212 def test_pointers(self):
213 f = dll._testfunc_p_p
214 f.restype = POINTER(c_int)
215 f.argtypes = [POINTER(c_int)]
216
217 # This only works if the value c_int(42) passed to the
218 # function is still alive while the pointer (the result) is
219 # used.
220
221 v = c_int(42)
222
223 assert pointer(v).contents.value == 42
224 result = f(pointer(v))
225 assert type(result) == POINTER(c_int)
226 assert result.contents.value == 42
227
228 # This on works...
229 result = f(pointer(v))
230 assert result.contents.value == v.value
231
232 p = pointer(c_int(99))
233 result = f(p)
234 assert result.contents.value == 99
235
236 arg = byref(v)
237 result = f(arg)
238 assert not result.contents == v.value
239
240 with pytest.raises(ArgumentError):
241 f(byref(c_short(22)))
242
243 # It is dangerous, however, because you don't control the lifetime
244 # of the pointer:
245 result = f(byref(c_int(99)))
246 assert not result.contents == 99
247
248 def test_convert_pointers(self):
249 f = dll.deref_LP_c_char_p
250 f.restype = c_char
251 f.argtypes = [POINTER(c_char_p)]
252 #
253 s = c_char_p('hello world')
254 ps = pointer(s)
255 assert f(ps) == 'h'
256 assert f(s) == 'h' # automatic conversion from char** to char*
257
258 def test_errors_1(self):
259 f = dll._testfunc_p_p
260 f.argtypes = [POINTER(c_int)]
261 f.restype = c_int
262
263 class X(Structure):
264 _fields_ = [("y", c_int)]
265
266 with pytest.raises(ArgumentError):
267 f(X()) #cannot convert parameter
268
269 ################################################################
270 def test_shorts(self):
271 f = dll._testfunc_callback_i_if
272
273 args = []
274 expected = [262144, 131072, 65536, 32768, 16384, 8192, 4096, 2048,
275 1024, 512, 256, 128, 64, 32, 16, 8, 4, 2, 1]
276
277 def callback(v):
278 args.append(v)
279 return v
280
281 CallBack = CFUNCTYPE(c_int, c_int)
282
283 cb = CallBack(callback)
284 f(2**18, cb)
285 assert args == expected
286
287 ################################################################
288
289
290 def test_callbacks(self):
291 f = dll._testfunc_callback_i_if
292 f.restype = c_int
293
294 MyCallback = CFUNCTYPE(c_int, c_int)
295
296 def callback(value):
297 #print "called back with", value
298 return value
299
300 cb = MyCallback(callback)
301 result = f(-10, cb)
302 assert result == -18
303
304 # test with prototype
305 f.argtypes = [c_int, MyCallback]
306 cb = MyCallback(callback)
307 result = f(-10, cb)
308 assert result == -18
309
310 AnotherCallback = WINFUNCTYPE(c_int, c_int, c_int, c_int, c_int)
311
312 # check that the prototype works: we call f with wrong
313 # argument types
314 cb = AnotherCallback(callback)
315 with pytest.raises(ArgumentError):
316 f(-10, cb)
317
318
319 def test_callbacks_2(self):
320 # Can also use simple datatypes as argument type specifiers
321 # for the callback function.
322 # In this case the call receives an instance of that type
323 f = dll._testfunc_callback_i_if
324 f.restype = c_int
325
326 MyCallback = CFUNCTYPE(c_int, c_int)
327
328 f.argtypes = [c_int, MyCallback]
329
330 def callback(value):
331 #print "called back with", value
332 assert type(value) == int
333 return value
334
335 cb = MyCallback(callback)
336 result = f(-10, cb)
337 assert result == -18
338
339 def test_longlong_callbacks(self):
340
341 f = dll._testfunc_callback_q_qf
342 f.restype = c_longlong
343
344 MyCallback = CFUNCTYPE(c_longlong, c_longlong)
345
346 f.argtypes = [c_longlong, MyCallback]
347
348 def callback(value):
349 assert isinstance(value, (int, long))
350 return value & 0x7FFFFFFF
351
352 cb = MyCallback(callback)
353
354 assert 13577625587 == f(1000000000000, cb)
355
356 def test_errors_2(self):
357 with pytest.raises(AttributeError):
358 getattr(dll, "_xxx_yyy")
359 with pytest.raises(ValueError):
360 c_int.in_dll(dll, "_xxx_yyy")
361
362 def test_byval(self):
363 # without prototype
364 ptin = POINT(1, 2)
365 ptout = POINT()
366 # EXPORT int _testfunc_byval(point in, point *pout)
367 result = dll._testfunc_byval(ptin, byref(ptout))
368 got = result, ptout.x, ptout.y
369 expected = 3, 1, 2
370 assert got == expected
371
372 # with prototype
373 ptin = POINT(101, 102)
374 ptout = POINT()
375 dll._testfunc_byval.argtypes = (POINT, POINTER(POINT))
376 dll._testfunc_byval.restype = c_int
377 result = dll._testfunc_byval(ptin, byref(ptout))
378 got = result, ptout.x, ptout.y
379 expected = 203, 101, 102
380 assert got == expected
381
382 def test_struct_return_2H(self):
383 class S2H(Structure):
384 _fields_ = [("x", c_short),
385 ("y", c_short)]
386 dll.ret_2h_func.restype = S2H
387 dll.ret_2h_func.argtypes = [S2H]
388 inp = S2H(99, 88)
389 s2h = dll.ret_2h_func(inp)
390 assert (s2h.x, s2h.y) == (99*2, 88*3)
391
392 if sys.platform == "win32":
393 def test_struct_return_2H_stdcall(self):
394 class S2H(Structure):
395 _fields_ = [("x", c_short),
396 ("y", c_short)]
397
398 windll.s_ret_2h_func.restype = S2H
399 windll.s_ret_2h_func.argtypes = [S2H]
400 s2h = windll.s_ret_2h_func(S2H(99, 88))
401 assert (s2h.x, s2h.y) == (99*2, 88*3)
402
403 def test_struct_return_8H(self):
404 class S8I(Structure):
405 _fields_ = [("a", c_int),
406 ("b", c_int),
407 ("c", c_int),
408 ("d", c_int),
409 ("e", c_int),
410 ("f", c_int),
411 ("g", c_int),
412 ("h", c_int)]
413 dll.ret_8i_func.restype = S8I
414 dll.ret_8i_func.argtypes = [S8I]
415 inp = S8I(9, 8, 7, 6, 5, 4, 3, 2)
416 s8i = dll.ret_8i_func(inp)
417 assert (s8i.a, s8i.b, s8i.c, s8i.d, s8i.e, s8i.f, s8i.g, s8i.h) == (
418 (9*2, 8*3, 7*4, 6*5, 5*6, 4*7, 3*8, 2*9))
419
420 if sys.platform == "win32":
421 def test_struct_return_8H_stdcall(self):
422 class S8I(Structure):
423 _fields_ = [("a", c_int),
424 ("b", c_int),
425 ("c", c_int),
426 ("d", c_int),
427 ("e", c_int),
428 ("f", c_int),
429 ("g", c_int),
430 ("h", c_int)]
431 windll.s_ret_8i_func.restype = S8I
432 windll.s_ret_8i_func.argtypes = [S8I]
433 inp = S8I(9, 8, 7, 6, 5, 4, 3, 2)
434 s8i = windll.s_ret_8i_func(inp)
435 assert (s8i.a, s8i.b, s8i.c, s8i.d, s8i.e, s8i.f, s8i.g, s8i.h) == (
436 (9*2, 8*3, 7*4, 6*5, 5*6, 4*7, 3*8, 2*9))
437
438 def test_call_some_args(self):
439 f = dll.my_strchr
440 f.argtypes = [c_char_p]
441 f.restype = c_char_p
442 result = f("abcd", ord("b"))
443 assert result == "bcd"
444
445 def test_keepalive_buffers(self, monkeypatch):
446 import gc
447 f = dll.my_strchr
448 f.argtypes = [c_char_p]
449 f.restype = c_char_p
450 #
451 orig__call_funcptr = f._call_funcptr
452 def _call_funcptr(funcptr, *newargs):
453 gc.collect()
454 gc.collect()
455 gc.collect()
456 return orig__call_funcptr(funcptr, *newargs)
457 monkeypatch.setattr(f, '_call_funcptr', _call_funcptr)
458 #
459 result = f("abcd", ord("b"))
460 assert result == "bcd"
461
462 def test_caching_bug_1(self):
463 # the same test as test_call_some_args, with two extra lines
464 # in the middle that trigger caching in f._ptr, which then
465 # makes the last two lines fail
466 f = dll.my_strchr
467 f.argtypes = [c_char_p, c_int]
468 f.restype = c_char_p
469 result = f("abcd", ord("b"))
470 assert result == "bcd"
471 result = f("abcd", ord("b"), 42)
472 assert result == "bcd"
473
474 @pytest.mark.xfail(reason="we are less strict in checking callback parameters")
475 def test_sf1651235(self):
476 # see http://www.python.org/sf/1651235
477 proto = CFUNCTYPE(c_int, RECT, POINT)
478 def callback(*args):
479 return 0
480
481 callback = proto(callback)
482 with pytest.raises(ArgumentError):
483 callback((1, 2, 3, 4), POINT())
484
485 def test_argument_conversion_and_checks(self):
486 #This test is designed to check for segfaults if the wrong type of argument is passed as parameter
487 strlen = dll.my_strchr
488 strlen.argtypes = [c_char_p, c_int]
489 strlen.restype = c_char_p
490 assert strlen("eggs", ord("g")) == "ggs"
491
492 # Should raise ArgumentError, not segfault
493 with pytest.raises(ArgumentError):
494 strlen(0, 0)
495 with pytest.raises(ArgumentError):
496 strlen(False, 0)
497
498 def test_union_as_passed_value(self):
499 class UN(Union):
500 _fields_ = [("x", c_short),
501 ("y", c_long)]
502 dll.ret_un_func.restype = UN
503 dll.ret_un_func.argtypes = [UN]
504 A = UN * 2
505 a = A()
506 a[1].x = 33
507 u = dll.ret_un_func(a[1])
508 assert u.y == 33*10000
509
510 def test_cache_funcptr(self):
511 tf_b = dll.tf_b
512 tf_b.restype = c_byte
513 tf_b.argtypes = (c_byte,)
514 assert tf_b(-126) == -42
515 ptr = tf_b._ptr
516 assert ptr is not None
517 assert tf_b(-126) == -42
518 assert tf_b._ptr is ptr
519
520 def test_custom_from_param(self):
521 class A(c_byte):
522 @classmethod
523 def from_param(cls, obj):
524 seen.append(obj)
525 return -126
526 tf_b = dll.tf_b
527 tf_b.restype = c_byte
528 tf_b.argtypes = (c_byte,)
529 tf_b.argtypes = [A]
530 seen = []
531 assert tf_b("yadda") == -42
532 assert seen == ["yadda"]
533
534 @pytest.mark.xfail(reason="warnings are disabled")
535 def test_warnings(self):
536 import warnings
537 warnings.simplefilter("always")
538 with warnings.catch_warnings(record=True) as w:
539 dll.get_an_integer()
540 assert len(w) == 1
541 assert issubclass(w[0].category, RuntimeWarning)
542 assert "C function without declared arguments called" in str(w[0])
543
544 @pytest.mark.xfail
545 def test_errcheck(self):
546 def errcheck(result, func, args):
547 assert result == -42
548 assert type(result) is int
549 arg, = args
550 assert arg == -126
551 assert type(arg) is int
552 return result
553 #
554 tf_b = dll.tf_b
555 tf_b.restype = c_byte
556 tf_b.argtypes = (c_byte,)
557 tf_b.errcheck = errcheck
558 assert tf_b(-126) == -42
559 del tf_b.errcheck
560 with warnings.catch_warnings(record=True) as w:
561 dll.get_an_integer.argtypes = []
562 dll.get_an_integer()
563 assert len(w) == 1
564 assert issubclass(w[0].category, RuntimeWarning)
565 assert "C function without declared return type called" in str(w[0])
566
567 with warnings.catch_warnings(record=True) as w:
568 dll.get_an_integer.restype = None
569 dll.get_an_integer()
570 assert len(w) == 0
571
572 warnings.resetwarnings()
573
574
575 def test_errno(self):
576 test_errno = dll.test_errno
577 test_errno.restype = c_int
578 set_errno(42)
579 res = test_errno()
580 n = get_errno()
581 assert (res, n) == (42, 43)
582 set_errno(0)
583 assert get_errno() == 0
584
585 def test_issue1655(self):
586 def ret_list_p(icount):
587 def sz_array_p(obj, func, args):
588 assert ('.LP_c_int object' in repr(obj) or
589 '.LP_c_long object' in repr(obj))
590 assert repr(args) in ("('testing!', c_int(4))",
591 "('testing!', c_long(4))")
592 assert args[icount].value == 4
593 return [ obj[i] for i in range(args[icount].value) ]
594 return sz_array_p
595
596 get_data_prototype = CFUNCTYPE(POINTER(c_int),
597 c_char_p, POINTER(c_int))
598 get_data_paramflag = ((1,), (2,))
599 get_data_signature = ('test_issue1655', dll)
600
601 get_data = get_data_prototype( get_data_signature, get_data_paramflag )
602 assert get_data('testing!') == 4
603
604 get_data.errcheck = ret_list_p(1)
605 assert get_data('testing!') == [-1, -2, -3, -4]
606
607 def test_issue2533(self, tmpdir):
608 import cffi
609 ffi = cffi.FFI()
610 ffi.cdef("int **fetchme(void);")
611 ffi.set_source("_x_cffi", """
612 int **fetchme(void)
613 {
614 static int a = 42;
615 static int *pa = &a;
616 return &pa;
617 }
618 """)
619 ffi.compile(verbose=True, tmpdir=str(tmpdir))
620
621 import sys
622 sys.path.insert(0, str(tmpdir))
623 try:
624 from _x_cffi import ffi, lib
625 finally:
626 sys.path.pop(0)
627 fetchme = ffi.addressof(lib, 'fetchme')
628 fetchme = int(ffi.cast("intptr_t", fetchme))
629
630 FN = CFUNCTYPE(POINTER(POINTER(c_int)))
631 ff = cast(fetchme, FN)
632
633 g = ff()
634 assert g.contents.contents.value == 42
635
636 h = c_int(43)
637 g[0] = pointer(h) # used to crash here
638 assert g.contents.contents.value == 43
+0
-41
pypy/module/test_lib_pypy/ctypes_tests/test_guess_argtypes.py less more
0
1 """ This test checks whether args wrapping behavior is correct
2 """
3 import py
4 import sys
5
6 from ctypes import *
7
8 def test_wrap_args():
9 if not hasattr(sys, 'pypy_translation_info'):
10 py.test.skip("pypy white-box test")
11 from _ctypes.function import CFuncPtr
12
13 def guess(value):
14 _, cobj, ctype = CFuncPtr._conv_param(None, value)
15 return ctype
16 ## cobj = CFuncPtr._conv_param(None, value)
17 ## return type(cobj)
18
19 assert guess(13) == c_int
20 assert guess(0) == c_int
21 assert guess(b'xca') == c_char_p
22 assert guess(None) == c_void_p
23 assert guess(c_int(3)) == c_int
24 assert guess('xca') == c_wchar_p
25
26 class Stuff:
27 pass
28 s = Stuff()
29 s._as_parameter_ = None
30
31 assert guess(s) == c_void_p
32
33 def test_guess_unicode():
34 if not hasattr(sys, 'pypy_translation_info') and sys.platform != 'win32':
35 py.test.skip("CPython segfaults: see http://bugs.python.org/issue5203")
36 import conftest
37 dll = CDLL(str(conftest.sofile))
38 wcslen = dll.my_wcslen
39 text = "Some long unicode string"
40 assert wcslen(text) == len(text)
+0
-37
pypy/module/test_lib_pypy/ctypes_tests/test_incomplete.py less more
0 import unittest
1 from ctypes import *
2
3 ################################################################
4 #
5 # The incomplete pointer example from the tutorial
6 #
7
8 class TestCase:
9
10 def test_incomplete_example(self):
11 lpcell = POINTER("cell")
12 class cell(Structure):
13 _fields_ = [("name", c_char_p),
14 ("next", lpcell)]
15
16 SetPointerType(lpcell, cell)
17
18 c1 = cell()
19 c1.name = "foo"
20 c2 = cell()
21 c2.name = "bar"
22
23 c1.next = pointer(c2)
24 c2.next = pointer(c1)
25
26 p = c1
27
28 result = []
29 for i in range(8):
30 result.append(p.name)
31 p = p.next[0]
32 assert result == ["foo", "bar"] * 4
33
34 # to not leak references, we must clean _pointer_type_cache
35 from ctypes import _pointer_type_cache
36 del _pointer_type_cache[cell]
+0
-39
pypy/module/test_lib_pypy/ctypes_tests/test_init.py less more
0 import pytest
1 from ctypes import *
2
3
4 class X(Structure):
5 _fields_ = [("a", c_int),
6 ("b", c_int)]
7 new_was_called = False
8
9 def __new__(cls):
10 result = super(X, cls).__new__(cls)
11 result.new_was_called = True
12 return result
13
14 def __init__(self):
15 self.a = 9
16 self.b = 12
17
18 class Y(Structure):
19 _fields_ = [("x", X)]
20
21
22 @pytest.mark.xfail(
23 reason="subclassing semantics and implementation details not implemented")
24 def test_get():
25 # make sure the only accessing a nested structure
26 # doesn't call the structure's __new__ and __init__
27 y = Y()
28 assert (y.x.a, y.x.b) == (0, 0)
29 assert y.x.new_was_called == False
30
31 # But explicitely creating an X structure calls __new__ and __init__, of course.
32 x = X()
33 assert (x.a, x.b) == (9, 12)
34 assert x.new_was_called == True
35
36 y.x = x
37 assert (y.x.a, y.x.b) == (9, 12)
38 assert y.x.new_was_called == False
+0
-270
pypy/module/test_lib_pypy/ctypes_tests/test_keepalive.py less more
0 import py
1
2 from ctypes import *
3 import sys
4
5 class TestKeepalive:
6 """ Tests whether various objects land in _objects
7 or not
8 """
9 def test_array_of_pointers(self):
10 # tests array item assignements & pointer.contents = ...
11 A = POINTER(c_long) * 24
12 a = A()
13 l = c_long(2)
14 p = pointer(l)
15 a[3] = p
16 assert l._objects is None
17 assert p._objects == {'1':l}
18 assert a._objects == {'3':{'1':l}}
19
20 def test_simple_structure_and_pointer(self):
21 class X(Structure):
22 _fields_ = [('x', POINTER(c_int))]
23
24 x = X()
25 p = POINTER(c_int)()
26 assert x._objects is None
27 assert p._objects is None
28 x.x = p
29 assert p._objects == {}
30 assert len(x._objects) == 1
31 assert x._objects['0'] is p._objects
32
33 def test_simple_structure_and_pointer_with_array(self):
34 class X(Structure):
35 _fields_ = [('array', POINTER(c_int))]
36
37 x = X()
38 a = (c_int * 3)(1, 2, 3)
39 assert x._objects is None
40 x.array = a
41 assert x._objects['0'] is a
42
43 def test_structure_with_pointers(self):
44 class X(Structure):
45 _fields_ = [('x', POINTER(c_int)),
46 ('y', POINTER(c_int))]
47
48 x = X()
49 u = c_int(3)
50 p = pointer(u)
51 x.x = p
52 assert x.x._objects is None
53 assert p._objects == {'1': u}
54 assert x._objects == {'0': p._objects}
55
56 w = c_int(4)
57 q = pointer(w)
58 x.y = q
59 assert p._objects == {'1': u}
60 assert q._objects == {'1': w}
61 assert x._objects == {'0': p._objects, '1': q._objects}
62
63 n = POINTER(c_int)()
64 x.x = n
65 x.y = n
66 assert x._objects == {'0': n._objects, '1': n._objects}
67 assert x._objects['0'] is n._objects
68 assert n._objects is not None
69
70 def test_union_with_pointers(self):
71 class X(Union):
72 _fields_ = [('x', POINTER(c_int)),
73 ('y', POINTER(c_int))]
74
75 x = X()
76 u = c_int(3)
77 p = pointer(u)
78 x.x = p
79 assert x.x._objects is None
80 assert p._objects == {'1': u}
81 assert x._objects == {'0': p._objects}
82
83 # unions works just like structures it seems
84 w = c_int(4)
85 q = pointer(w)
86 x.y = q
87 assert p._objects == {'1': u}
88 assert q._objects == {'1': w}
89 assert x._objects == {'0': p._objects, '1': q._objects}
90
91 n = POINTER(c_int)()
92 x.x = n
93 x.y = n
94 assert x._objects == {'0': n._objects, '1': n._objects}
95 assert x._objects['0'] is n._objects
96 assert n._objects is not None
97
98 def test_pointer_setitem(self):
99 x = c_int(2)
100 y = c_int(3)
101 p = pointer(x)
102 assert p._objects == {'1':x}
103 p[0] = y
104 assert p._objects.keys() == ['1']
105 assert p._objects['1'].value == 3
106
107 def test_primitive(self):
108 if not hasattr(sys, 'pypy_translation_info'):
109 py.test.skip("pypy white-box test")
110 assert c_char_p("abc")._objects._buffer[0] == "a"
111 assert c_int(3)._objects is None
112
113 def test_pointer_to_pointer(self):
114 l = c_long(2)
115 assert l._objects is None
116
117 p1 = pointer(l)
118 assert p1._objects == {'1':l}
119
120 p2 = pointer(p1)
121 assert p2._objects == {'1':p1, '0':{'1':l}}
122
123 def test_cfunc(self):
124 def f():
125 pass
126 cf = CFUNCTYPE(c_int, c_int)(f)
127 assert cf._objects == {'0':cf}
128
129 def test_cfunc_cast(self):
130 def f():
131 pass
132 cf = CFUNCTYPE(c_int, c_int)(f)
133 p1 = cast(cf, c_void_p)
134 assert p1._objects == {id(cf): cf, '0': cf}
135
136 def test_array_of_struct_with_pointer(self):
137 class S(Structure):
138 _fields_ = [('x', c_int)]
139 PS = POINTER(S)
140
141 class Q(Structure):
142 _fields_ = [('p', PS)]
143
144 A = Q*10
145 a=A()
146 s=S()
147 s.x=3
148 a[3].p = pointer(s)
149
150 assert a._objects['0:3']['1'] is s
151
152 def test_array_of_union_with_pointer(self):
153 class S(Structure):
154 _fields_ = [('x', c_int)]
155 PS = POINTER(S)
156
157 class Q(Union):
158 _fields_ = [('p', PS), ('x', c_int)]
159
160 A = Q*10
161 a=A()
162 s=S()
163 s.x=3
164 a[3].p = pointer(s)
165
166 assert a._objects['0:3']['1'] is s
167
168 def test_struct_with_inlined_array(self):
169 class S(Structure):
170 _fields_ = [('b', c_int),
171 ('a', POINTER(c_int) * 2)]
172
173 s = S()
174 stuff = c_int(2)
175 s.a[1] = pointer(stuff)
176 assert s._objects == {'1:1': {'1': stuff}}
177
178 def test_union_with_inlined_array(self):
179 class S(Union):
180 _fields_ = [('b', c_int),
181 ('a', POINTER(c_int) * 2)]
182
183 s = S()
184 stuff = c_int(2)
185 s.a[1] = pointer(stuff)
186 assert s._objects == {'1:1': {'1': stuff}}
187
188 def test_struct_within_struct(self):
189 class R(Structure):
190 _fields_ = [('p', POINTER(c_int))]
191
192 class S(Structure):
193 _fields_ = [('b', c_int),
194 ('r', R)]
195
196 s = S()
197 stuff = c_int(2)
198 s.r.p = pointer(stuff)
199 assert s._objects == {'0:1': {'1': stuff}}
200
201 r = R()
202 s.r = r
203 # obscure
204 assert s._objects == {'1': {}, '0:1': {'1': stuff}}
205
206 def test_union_within_union(self):
207 class R(Union):
208 _fields_ = [('p', POINTER(c_int))]
209
210 class S(Union):
211 _fields_ = [('b', c_int),
212 ('r', R)]
213
214 s = S()
215 stuff = c_int(2)
216 s.r.p = pointer(stuff)
217 assert s._objects == {'0:1': {'1': stuff}}
218
219 r = R()
220 s.r = r
221 # obscure
222 assert s._objects == {'1': {}, '0:1': {'1': stuff}}
223
224 def test_c_char_p(self):
225 n = 2
226 xs = "hello" * n
227 x = c_char_p(xs)
228 del xs
229 import gc; gc.collect()
230 print('x = %r' % x)
231 assert x.value == 'hellohello'
232 assert x._objects == 'hellohello'
233 #
234 class datum(Structure):
235 _fields_ = [
236 ('dptr', c_char_p),
237 ('dsize', c_int),
238 ]
239 class union(Union):
240 _fields_ = [
241 ('dptr', c_char_p),
242 ('dsize', c_int),
243 ]
244 for wrap in [False, True]:
245 n = 2
246 xs = "hello" * n
247 if wrap:
248 xs = c_char_p(xs)
249 dat = datum()
250 dat.dptr = xs
251 dat.dsize = 15
252 del xs
253 import gc; gc.collect()
254 print('dat.dptr = %r' % dat.dptr)
255 print('dat._objects = %r' % dat._objects)
256 assert dat.dptr == "hellohello"
257 assert dat._objects.keys() == ['0']
258
259 xs = "hello" * n
260 if wrap:
261 xs = c_char_p(xs)
262 dat = union()
263 dat.dptr = xs
264 del xs
265 import gc; gc.collect()
266 print('dat.dptr = %r' % dat.dptr)
267 print('dat._objects = %r' % dat._objects)
268 assert dat.dptr == "hellohello"
269 assert dat._objects.keys() == ['0']
+0
-151
pypy/module/test_lib_pypy/ctypes_tests/test_keeprefs.py less more
0 import py
1 from ctypes import *
2
3 class TestSimple:
4 def test_cint(self):
5 x = c_int()
6 assert x._objects == None
7 x.value = 42
8 assert x._objects == None
9 x = c_int(99)
10 assert x._objects == None
11
12 def test_ccharp(self):
13 py.test.skip("we make copies of strings")
14 x = c_char_p()
15 assert x._objects == None
16 x.value = "abc"
17 assert x._objects == "abc"
18 x = c_char_p("spam")
19 assert x._objects == "spam"
20
21 class TestStructure:
22 def test_cint_struct(self):
23 class X(Structure):
24 _fields_ = [("a", c_int),
25 ("b", c_int)]
26
27 x = X()
28 assert x._objects == None
29 x.a = 42
30 x.b = 99
31 assert x._objects == None
32
33 def test_ccharp_struct(self):
34 py.test.skip("we make copies of strings")
35 class X(Structure):
36 _fields_ = [("a", c_char_p),
37 ("b", c_char_p)]
38 x = X()
39 assert x._objects == None
40
41 x.a = "spam"
42 x.b = "foo"
43 assert x._objects == {"0": "spam", "1": "foo"}
44
45 def test_struct_struct(self):
46 class POINT(Structure):
47 _fields_ = [("x", c_int), ("y", c_int)]
48 class RECT(Structure):
49 _fields_ = [("ul", POINT), ("lr", POINT)]
50
51 r = RECT()
52 r.ul.x = 0
53 r.ul.y = 1
54 r.lr.x = 2
55 r.lr.y = 3
56 assert r._objects == None
57
58 r = RECT()
59 pt = POINT(1, 2)
60 r.ul = pt
61 assert r._objects == {'0': {}}
62 r.ul.x = 22
63 r.ul.y = 44
64 assert r._objects == {'0': {}}
65 r.lr = POINT()
66 assert r._objects == {'0': {}, '1': {}}
67
68 class TestArray:
69 def test_cint_array(self):
70 INTARR = c_int * 3
71
72 ia = INTARR()
73 assert ia._objects == None
74 ia[0] = 1
75 ia[1] = 2
76 ia[2] = 3
77 assert ia._objects == None
78
79 class X(Structure):
80 _fields_ = [("x", c_int),
81 ("a", INTARR)]
82
83 x = X()
84 x.x = 1000
85 x.a[0] = 42
86 x.a[1] = 96
87 assert x._objects == None
88 x.a = ia
89 assert x._objects == {'1': {}}
90
91 class TestPointer:
92 def test_p_cint(self):
93 i = c_int(42)
94 x = pointer(i)
95 assert x._objects == {'1': i}
96
97 class TestDeletePointer:
98 def X_test(self):
99 class X(Structure):
100 _fields_ = [("p", POINTER(c_char_p))]
101 x = X()
102 i = c_char_p("abc def")
103 from sys import getrefcount as grc
104 print("2?", grc(i))
105 x.p = pointer(i)
106 print("3?", grc(i))
107 for i in range(320):
108 c_int(99)
109 x.p[0]
110 print(x.p[0])
111 ## del x
112 ## print("2?", grc(i))
113 ## del i
114 import gc
115 gc.collect()
116 for i in range(320):
117 c_int(99)
118 x.p[0]
119 print(x.p[0])
120 print(x.p.contents)
121 ## print(x._objects)
122
123 x.p[0] = "spam spam"
124 ## print x.p[0]
125 print("+" * 42)
126 print(x._objects)
127
128 class TestPointerToStructure:
129 def test(self):
130 class POINT(Structure):
131 _fields_ = [("x", c_int), ("y", c_int)]
132 class RECT(Structure):
133 _fields_ = [("a", POINTER(POINT)),
134 ("b", POINTER(POINT))]
135 r = RECT()
136 p1 = POINT(1, 2)
137
138 r.a = pointer(p1)
139 r.b = pointer(p1)
140 ## from pprint import pprint as pp
141 ## pp(p1._objects)
142 ## pp(r._objects)
143
144 r.a[0].x = 42
145 r.a[0].y = 99
146
147 # to avoid leaking when tests are run several times
148 # clean up the types left in the cache.
149 from ctypes import _pointer_type_cache
150 del _pointer_type_cache[POINT]
+0
-28
pypy/module/test_lib_pypy/ctypes_tests/test_libc.py less more
0 import py
1 import sys, os
2
3 from ctypes import *
4
5 def setup_module(mod):
6 import conftest
7 mod.lib = CDLL(str(conftest.sofile))
8
9 class TestLibC:
10 def test_sqrt(self):
11 lib.my_sqrt.argtypes = c_double,
12 lib.my_sqrt.restype = c_double
13 assert lib.my_sqrt(4.0) == 2.0
14 import math
15 assert lib.my_sqrt(2.0) == math.sqrt(2.0)
16
17 def test_qsort(self):
18 comparefunc = CFUNCTYPE(c_int, POINTER(c_char), POINTER(c_char))
19 lib.my_qsort.argtypes = c_void_p, c_size_t, c_size_t, comparefunc
20 lib.my_qsort.restype = None
21
22 def sort(a, b):
23 return cmp(a[0], b[0])
24
25 chars = create_string_buffer("spam, spam, and spam")
26 lib.my_qsort(chars, len(chars)-1, sizeof(c_char), comparefunc(sort))
27 assert chars.raw == " ,,aaaadmmmnpppsss\x00"
+0
-87
pypy/module/test_lib_pypy/ctypes_tests/test_loading.py less more
0 import pytest
1 from ctypes import *
2 import sys
3 import os
4 from ctypes.util import find_library
5 from ctypes.test import is_resource_enabled
6
7 libc_name = None
8 if os.name == "nt":
9 libc_name = "msvcrt"
10 elif os.name == "ce":
11 libc_name = "coredll"
12 elif sys.platform == "cygwin":
13 libc_name = "cygwin1.dll"
14 else:
15 libc_name = find_library("c")
16
17 if True or is_resource_enabled("printing"):
18 print("\tfind_library('c') -> ", find_library('c'), file=sys.stderr)
19 print("\tfind_library('m') -> ", find_library('m'), file=sys.stderr)
20
21 class TestLoader:
22
23 unknowndll = "xxrandomnamexx"
24
25 if libc_name is not None:
26 def test_load(self):
27 CDLL(libc_name)
28 CDLL(os.path.basename(libc_name))
29 with pytest.raises(OSError):
30 CDLL(self.unknowndll)
31
32 if libc_name is not None and os.path.basename(libc_name) == "libc.so.6":
33 def test_load_version(self):
34 cdll.LoadLibrary("libc.so.6")
35 # linux uses version, libc 9 should not exist
36 with pytest.raises(OSError):
37 cdll.LoadLibrary("libc.so.9")
38 with pytest.raises(OSError):
39 cdll.LoadLibrary(self.unknowndll)
40
41 def test_find(self):
42 for name in ("c", "m"):
43 lib = find_library(name)
44 if lib:
45 cdll.LoadLibrary(lib)
46 CDLL(lib)
47
48 def test__handle(self):
49 lib = find_library("c")
50 if lib:
51 cdll = CDLL(lib)
52 assert type(cdll._handle) in (int, long)
53
54 if os.name in ("nt", "ce"):
55 def test_load_library(self):
56 if is_resource_enabled("printing"):
57 print(find_library("kernel32"))
58 print(find_library("user32"))
59
60 if os.name == "nt":
61 windll.kernel32.GetModuleHandleW
62 windll["kernel32"].GetModuleHandleW
63 windll.LoadLibrary("kernel32").GetModuleHandleW
64 WinDLL("kernel32").GetModuleHandleW
65 elif os.name == "ce":
66 windll.coredll.GetModuleHandleW
67 windll["coredll"].GetModuleHandleW
68 windll.LoadLibrary("coredll").GetModuleHandleW
69 WinDLL("coredll").GetModuleHandleW
70
71 def test_load_ordinal_functions(self):
72 import conftest
73 _ctypes_test = str(conftest.sofile)
74 dll = CDLL(_ctypes_test)
75 # We load the same function both via ordinal and name
76 func_ord = dll[2]
77 func_name = dll.GetString
78 # addressof gets the address where the function pointer is stored
79 a_ord = addressof(func_ord)
80 a_name = addressof(func_name)
81 f_ord_addr = c_void_p.from_address(a_ord).value
82 f_name_addr = c_void_p.from_address(a_name).value
83 assert hex(f_ord_addr) == hex(f_name_addr)
84
85 with pytest.raises(AttributeError):
86 dll[1234]
+0
-61
pypy/module/test_lib_pypy/ctypes_tests/test_memfunctions.py less more
0
1 import py
2 import sys
3 from ctypes import *
4 from .support import BaseCTypesTestChecker
5
6 class TestMemFunctions(BaseCTypesTestChecker):
7 def test_memmove(self):
8 # large buffers apparently increase the chance that the memory
9 # is allocated in high address space.
10 a = create_string_buffer(1000000)
11 p = "Hello, World"
12 result = memmove(a, p, len(p))
13 assert a.value == "Hello, World"
14
15 assert string_at(result) == "Hello, World"
16 assert string_at(result, 5) == "Hello"
17 assert string_at(result, 16) == "Hello, World\0\0\0\0"
18 assert string_at(result, 0) == ""
19
20 def test_memset(self):
21 a = create_string_buffer(1000000)
22 result = memset(a, ord('x'), 16)
23 assert a.value == "xxxxxxxxxxxxxxxx"
24
25 assert string_at(result) == "xxxxxxxxxxxxxxxx"
26 assert string_at(a) == "xxxxxxxxxxxxxxxx"
27 assert string_at(a, 20) == "xxxxxxxxxxxxxxxx\0\0\0\0"
28
29 def test_cast(self):
30 a = (c_ubyte * 32)(*map(ord, "abcdef"))
31 assert cast(a, c_char_p).value == "abcdef"
32 assert cast(a, POINTER(c_byte))[:7] == (
33 [97, 98, 99, 100, 101, 102, 0])
34
35 def test_string_at(self):
36 s = string_at("foo bar")
37 # XXX The following may be wrong, depending on how Python
38 # manages string instances
39 #assert 2 == sys.getrefcount(s)
40 assert s, "foo bar"
41
42 assert string_at("foo bar", 8) == "foo bar\0"
43 assert string_at("foo bar", 3) == "foo"
44
45 try:
46 create_unicode_buffer
47 except NameError:
48 pass
49 else:
50 def test_wstring_at(self):
51 p = create_unicode_buffer("Hello, World")
52 a = create_unicode_buffer(1000000)
53 result = memmove(a, p, len(p) * sizeof(c_wchar))
54 assert a.value == "Hello, World"
55
56 assert wstring_at(a) == "Hello, World"
57 assert wstring_at(a, 5) == "Hello"
58 assert wstring_at(a, 16) == "Hello, World\0\0\0\0"
59 assert wstring_at(a, 0) == ""
60
+0
-229
pypy/module/test_lib_pypy/ctypes_tests/test_numbers.py less more
0 import pytest
1 from ctypes import *
2 from .support import BaseCTypesTestChecker
3 import sys, struct
4
5 def valid_ranges(*types):
6 # given a sequence of numeric types, collect their _type_
7 # attribute, which is a single format character compatible with
8 # the struct module, use the struct module to calculate the
9 # minimum and maximum value allowed for this format.
10 # Returns a list of (min, max) values.
11 result = []
12 for t in types:
13 fmt = t._type_
14 size = struct.calcsize(fmt)
15 a = struct.unpack(fmt, (b"\x00"*32)[:size])[0]
16 b = struct.unpack(fmt, (b"\xFF"*32)[:size])[0]
17 c = struct.unpack(fmt, (b"\x7F"+b"\x00"*32)[:size])[0]
18 d = struct.unpack(fmt, (b"\x80"+b"\xFF"*32)[:size])[0]
19 result.append((min(a, b, c, d), max(a, b, c, d)))
20 return result
21
22 ArgType = type(byref(c_int(0)))
23
24 unsigned_types = [c_ubyte, c_ushort, c_uint, c_ulong]
25 signed_types = [c_byte, c_short, c_int, c_long, c_longlong]
26
27 float_types = [c_double, c_float, c_longdouble]
28
29 try:
30 c_ulonglong
31 c_longlong
32 except NameError:
33 pass
34 else:
35 unsigned_types.append(c_ulonglong)
36 signed_types.append(c_longlong)
37
38 unsigned_ranges = valid_ranges(*unsigned_types)
39 signed_ranges = valid_ranges(*signed_types)
40
41 ################################################################
42
43 class TestNumber(BaseCTypesTestChecker):
44
45 def test_default_init(self):
46 # default values are set to zero
47 for t in signed_types + unsigned_types + float_types:
48 assert t().value == 0
49
50 def test_unsigned_values(self):
51 # the value given to the constructor is available
52 # as the 'value' attribute
53 for t, (l, h) in zip(unsigned_types, unsigned_ranges):
54 assert t(l).value == l
55 assert t(h).value == h
56
57 def test_signed_values(self):
58 # see above
59 for t, (l, h) in zip(signed_types, signed_ranges):
60 assert t(l).value == l
61 assert t(h).value == h
62
63 def test_typeerror(self):
64 # Only numbers are allowed in the contructor,
65 # otherwise TypeError is raised
66 for t in signed_types + unsigned_types + float_types:
67 with pytest.raises(TypeError):
68 t("")
69 with pytest.raises(TypeError):
70 t(None)
71
72 ## def test_valid_ranges(self):
73 ## # invalid values of the correct type
74 ## # raise ValueError (not OverflowError)
75 ## for t, (l, h) in zip(unsigned_types, unsigned_ranges):
76 ## self.assertRaises(ValueError, t, l-1)
77 ## self.assertRaises(ValueError, t, h+1)
78
79 @pytest.mark.xfail(reason="testing implementation internals")
80 def test_from_param(self):
81 # the from_param class method attribute always
82 # returns PyCArgObject instances
83 for t in signed_types + unsigned_types + float_types:
84 assert ArgType == type(t.from_param(0))
85
86 @pytest.mark.xfail(reason="testing implementation internals")
87 def test_byref(self):
88 # calling byref returns also a PyCArgObject instance
89 for t in signed_types + unsigned_types + float_types:
90 parm = byref(t())
91 assert ArgType == type(parm)
92
93 def test_init_again(self):
94 for t in signed_types + unsigned_types + float_types:
95 parm = t()
96 addr1 = addressof(parm)
97 parm.__init__(0)
98 addr2 = addressof(parm)
99 assert addr1 == addr2
100
101 def test_floats(self):
102 # c_float and c_double can be created from
103 # Python int and float
104 for t in float_types:
105 assert t(2.0).value == 2.0
106 assert t(2).value == 2.0
107
108 def test_integers(self):
109 # integers cannot be constructed from floats
110 for t in signed_types + unsigned_types:
111 with pytest.raises(TypeError):
112 t(3.14)
113
114 def test_sizes(self):
115 for t in signed_types + unsigned_types + float_types:
116 if t is c_longdouble: # no support for 'g' in the struct module
117 continue
118 size = struct.calcsize(t._type_)
119 # sizeof of the type...
120 assert sizeof(t) == size
121 # and sizeof of an instance
122 assert sizeof(t()) == size
123
124 def test_alignments(self):
125 for t in signed_types + unsigned_types + float_types:
126 if t is c_longdouble: # no support for 'g' in the struct module
127 continue
128 code = t._type_ # the typecode
129 if code == 'g':
130 # typecode not supported by "struct"
131 continue
132 align = struct.calcsize("c%c" % code) - struct.calcsize(code)
133
134 # alignment of the type...
135 assert (code, alignment(t)) == (code, align)
136 # and alignment of an instance
137 assert (code, alignment(t())) == (code, align)
138
139 def test_int_from_address(self):
140 from array import array
141 for t in signed_types + unsigned_types:
142 # the array module doesn't suppport all format codes
143 # (no 'q' or 'Q')
144 try:
145 array(t._type_)
146 except ValueError:
147 continue
148 a = array(t._type_, [100])
149
150 # v now is an integer at an 'external' memory location
151 v = t.from_address(a.buffer_info()[0])
152 assert v.value == a[0]
153 assert type(v) == t
154
155 # changing the value at the memory location changes v's value also
156 a[0] = 42
157 assert v.value == a[0]
158
159
160 def test_float_from_address(self):
161 from array import array
162 for t in float_types:
163 if t is c_longdouble: # no support for 'g' in the array module
164 continue
165 a = array(t._type_, [3.14])
166 v = t.from_address(a.buffer_info()[0])
167 assert v.value == a[0]
168 assert type(v) is t
169 a[0] = 2.3456e17
170 assert v.value == a[0]
171 assert type(v) is t
172
173 def test_char_from_address(self):
174 from ctypes import c_char
175 from array import array
176
177 a = array('c', 'x')
178 v = c_char.from_address(a.buffer_info()[0])
179 assert v.value == a[0]
180 assert type(v) is c_char
181
182 a[0] = '?'
183 assert v.value == a[0]
184
185 def test_init(self):
186 # c_int() can be initialized from Python's int, and c_int.
187 # Not from c_long or so, which seems strange, abd should
188 # probably be changed:
189 with pytest.raises(TypeError):
190 c_int(c_long(42))
191
192 def test_subclass(self):
193 class enum(c_int):
194 def __new__(cls, value):
195 dont_call_me
196 class S(Structure):
197 _fields_ = [('t', enum)]
198 assert isinstance(S().t, enum)
199
200 #@pytest.mark.xfail("'__pypy__' not in sys.builtin_module_names")
201 @pytest.mark.xfail
202 def test_no_missing_shape_to_ffi_type(self):
203 # whitebox test
204 "re-enable after adding 'g' to _shape_to_ffi_type.typemap, "
205 "which I think needs fighting all the way up from "
206 "rpython.rlib.libffi"
207 from _ctypes.basics import _shape_to_ffi_type
208 from _rawffi import Array
209 for i in range(1, 256):
210 try:
211 Array(chr(i))
212 except ValueError:
213 pass
214 else:
215 assert chr(i) in _shape_to_ffi_type.typemap
216
217 @pytest.mark.xfail
218 def test_pointer_to_long_double(self):
219 import ctypes
220 ctypes.POINTER(ctypes.c_longdouble)
221
222 ## def test_perf(self):
223 ## check_perf()
224
225 #from ctypes import _SimpleCData
226 #class c_int_S(_SimpleCData):
227 # _type_ = "i"
228 # __slots__ = []
+0
-234
pypy/module/test_lib_pypy/ctypes_tests/test_parameters.py less more
0 import pytest
1 import sys
2
3 class TestSimpleTypes:
4
5 def setup_class(cls):
6 import ctypes
7 try:
8 from _ctypes import set_conversion_mode
9 except ImportError:
10 pass
11 else:
12 cls.prev_conv_mode = set_conversion_mode("ascii", "strict")
13
14 def teardown_class(cls):
15 try:
16 from _ctypes import set_conversion_mode
17 except ImportError:
18 pass
19 else:
20 set_conversion_mode(*cls.prev_conv_mode)
21
22
23 def test_subclasses(self):
24 from ctypes import c_void_p, c_char_p
25 # ctypes 0.9.5 and before did overwrite from_param in SimpleType_new
26 class CVOIDP(c_void_p):
27 def from_param(cls, value):
28 return value * 2
29 from_param = classmethod(from_param)
30
31 class CCHARP(c_char_p):
32 def from_param(cls, value):
33 return value * 4
34 from_param = classmethod(from_param)
35
36 assert CVOIDP.from_param("abc") == "abcabc"
37 assert CCHARP.from_param("abc") == "abcabcabcabc"
38
39 try:
40 from ctypes import c_wchar_p
41 except ImportError:
42 return
43
44 class CWCHARP(c_wchar_p):
45 def from_param(cls, value):
46 return value * 3
47 from_param = classmethod(from_param)
48
49 assert CWCHARP.from_param("abc") == "abcabcabc"
50
51 def test_pointer_subclasses(self):
52 from ctypes import POINTER, c_void_p
53
54 Void_pp = POINTER(c_void_p)
55 class My_void_p(c_void_p):
56 pass
57
58 My_void_pp = POINTER(My_void_p)
59 o = My_void_pp()
60
61 assert Void_pp.from_param(o) is o
62
63 # XXX Replace by c_char_p tests
64 @pytest.mark.xfail(reason="testing implementation internals")
65 def test_cstrings(self):
66 from ctypes import c_char_p, byref
67
68 # c_char_p.from_param on a Python String packs the string
69 # into a cparam object
70 s = "123"
71 assert c_char_p.from_param(s)._obj is s
72
73 # new in 0.9.1: convert (encode) unicode to ascii
74 assert c_char_p.from_param(u"123")._obj == b"123"
75 with pytest.raises(UnicodeEncodeError):
76 c_char_p.from_param(u"123\377")
77
78 with pytest.raises(TypeError):
79 c_char_p.from_param(42)
80
81 # calling c_char_p.from_param with a c_char_p instance
82 # returns the argument itself:
83 a = c_char_p("123")
84 assert c_char_p.from_param(a) is a
85
86 @pytest.mark.xfail(reason="testing implementation internals")
87 def test_cw_strings(self):
88 from ctypes import byref
89 try:
90 from ctypes import c_wchar_p
91 except ImportError:
92 ## print "(No c_wchar_p)"
93 return
94 s = "123"
95 if sys.platform == "win32":
96 assert c_wchar_p.from_param(s)._obj is s
97 with pytest.raises(TypeError):
98 c_wchar_p.from_param(42)
99
100 # new in 0.9.1: convert (decode) ascii to unicode
101 assert c_wchar_p.from_param(b"123")._obj == u"123"
102 with pytest.raises(UnicodeDecodeError):
103 c_wchar_p.from_param(b"123\377")
104
105 pa = c_wchar_p.from_param(c_wchar_p("123"))
106 assert type(pa) == c_wchar_p
107
108 def test_int_pointers(self):
109 from ctypes import c_short, c_uint, c_int, c_long, POINTER, pointer
110 LPINT = POINTER(c_int)
111
112 ## p = pointer(c_int(42))
113 ## x = LPINT.from_param(p)
114 x = LPINT.from_param(pointer(c_int(42)))
115 assert x.contents.value == 42
116 assert LPINT(c_int(42)).contents.value == 42
117
118 assert not LPINT.from_param(None)
119
120 if c_int != c_long:
121 with pytest.raises(TypeError):
122 LPINT.from_param(pointer(c_long(42)))
123 with pytest.raises(TypeError):
124 LPINT.from_param(pointer(c_uint(42)))
125 with pytest.raises(TypeError):
126 LPINT.from_param(pointer(c_short(42)))
127
128 def test_byref_pointer(self):
129 # The from_param class method of POINTER(typ) classes accepts what is
130 # returned by byref(obj), it type(obj) == typ
131 from ctypes import c_short, c_uint, c_int, c_long, pointer, POINTER, byref
132 LPINT = POINTER(c_int)
133
134 LPINT.from_param(byref(c_int(42)))
135
136 with pytest.raises(TypeError):
137 LPINT.from_param(byref(c_short(22)))
138 if c_int != c_long:
139 with pytest.raises(TypeError):
140 LPINT.from_param(byref(c_long(22)))
141 with pytest.raises(TypeError):
142 LPINT.from_param(byref(c_uint(22)))
143
144 def test_byref_pointerpointer(self):
145 # See above
146 from ctypes import c_short, c_uint, c_int, c_long, pointer, POINTER, byref
147
148 LPLPINT = POINTER(POINTER(c_int))
149 LPLPINT.from_param(byref(pointer(c_int(42))))
150
151 with pytest.raises(TypeError):
152 LPLPINT.from_param(byref(pointer(c_short(22))))
153 if c_int != c_long:
154 with pytest.raises(TypeError):
155 LPLPINT.from_param(byref(pointer(c_long(22))))
156 with pytest.raises(TypeError):
157 LPLPINT.from_param(byref(pointer(c_uint(22))))
158
159 def test_array_pointers(self):
160 from ctypes import c_short, c_uint, c_int, c_long, POINTER
161 INTARRAY = c_int * 3
162 ia = INTARRAY()
163 assert len(ia) == 3
164 assert [ia[i] for i in range(3)] == [0, 0, 0]
165
166 # Pointers are only compatible with arrays containing items of
167 # the same type!
168 LPINT = POINTER(c_int)
169 LPINT.from_param((c_int*3)())
170 with pytest.raises(TypeError):
171 LPINT.from_param(c_short*3)
172 with pytest.raises(TypeError):
173 LPINT.from_param(c_long*3)
174 with pytest.raises(TypeError):
175 LPINT.from_param(c_uint*3)
176
177 ## def test_performance(self):
178 ## check_perf()
179
180 @pytest.mark.xfail(reason="testing implementation internals")
181 def test_noctypes_argtype(self):
182 from ctypes import CDLL, c_void_p, ArgumentError
183 import conftest
184 dll = CDLL(str(conftest.sofile))
185
186 func = dll._testfunc_p_p
187 func.restype = c_void_p
188 # TypeError: has no from_param method
189 with pytest.raises(TypeError):
190 setattr(func, "argtypes", (object,))
191
192 class Adapter(object):
193 def from_param(cls, obj):
194 return None
195
196 func.argtypes = (Adapter(),)
197 assert func(None) == None
198 assert func(object()) == None
199
200 class Adapter(object):
201 def from_param(cls, obj):
202 return obj
203
204 func.argtypes = (Adapter(),)
205 # don't know how to convert parameter 1
206 with pytest.raises(ArgumentError):
207 func(object())
208 assert func(c_void_p(42)) == 42
209
210 class Adapter(object):
211 def from_param(cls, obj):
212 raise ValueError(obj)
213
214 func.argtypes = (Adapter(),)
215 # ArgumentError: argument 1: ValueError: 99
216 with pytest.raises(ArgumentError):
217 func(99)
218
219 def test_multiple_signature(self):
220 # when .argtypes is not set, calling a function with a certain
221 # set of parameters should not prevent another call with
222 # another set.
223 from ctypes import CDLL, byref
224 import conftest
225 dll = CDLL(str(conftest.sofile))
226 func = dll._testfunc_p_p
227
228 # This is call has too many arguments
229 assert func(None, 1) == 0
230
231 # This one is normal
232 assert func(None) == 0
233
+0
-274
pypy/module/test_lib_pypy/ctypes_tests/test_pointers.py less more
0 import py
1 from ctypes import *
2 from .support import BaseCTypesTestChecker
3
4 ctype_types = [c_byte, c_ubyte, c_short, c_ushort, c_int, c_uint,
5 c_long, c_ulong, c_longlong, c_ulonglong, c_double, c_float]
6 python_types = [int, int, int, int, int, int,
7 int, int, int, int, float, float]
8
9 def setup_module(mod):
10 import conftest
11 mod._ctypes_test = str(conftest.sofile)
12
13 class TestPointers(BaseCTypesTestChecker):
14
15 def test_get_ffi_argtype(self):
16 P = POINTER(c_int)
17 ffitype = P.get_ffi_argtype()
18 assert P.get_ffi_argtype() is ffitype
19 assert ffitype.deref_pointer() is c_int.get_ffi_argtype()
20
21 def test_pointer_crash(self):
22
23 class A(POINTER(c_ulong)):
24 pass
25
26 POINTER(c_ulong)(c_ulong(22))
27 # Pointer can't set contents: has no _type_
28 py.test.raises(TypeError, A, c_ulong(33))
29
30 def test_pass_pointers(self):
31 dll = CDLL(_ctypes_test)
32 func = dll._testfunc_p_p
33 func.restype = c_long
34
35 i = c_int(12345678)
36 ## func.argtypes = (POINTER(c_int),)
37 address = func(byref(i))
38 assert c_int.from_address(address).value == 12345678
39
40 func.restype = POINTER(c_int)
41 res = func(pointer(i))
42 assert res.contents.value == 12345678
43 assert res[0] == 12345678
44
45 def test_change_pointers(self):
46 dll = CDLL(_ctypes_test)
47 func = dll._testfunc_p_p
48
49 i = c_int(87654)
50 func.restype = POINTER(c_int)
51 func.argtypes = (POINTER(c_int),)
52
53 res = func(pointer(i))
54 assert res[0] == 87654
55 assert res.contents.value == 87654
56
57 # C code: *res = 54345
58 res[0] = 54345
59 assert i.value == 54345
60
61 # C code:
62 # int x = 12321;
63 # res = &x
64 res.contents = c_int(12321)
65 assert i.value == 54345
66
67 def test_callbacks_with_pointers(self):
68 # a function type receiving a pointer
69 PROTOTYPE = CFUNCTYPE(c_int, POINTER(c_int))
70
71 self.result = []
72
73 def func(arg):
74 for i in range(10):
75 ## print arg[i],
76 self.result.append(arg[i])
77 ## print
78 return 0
79 callback = PROTOTYPE(func)
80
81 dll = CDLL(_ctypes_test)
82 # This function expects a function pointer,
83 # and calls this with an integer pointer as parameter.
84 # The int pointer points to a table containing the numbers 1..10
85 doit = dll._testfunc_callback_with_pointer
86
87 ## i = c_int(42)
88 ## callback(byref(i))
89 ## self.failUnless(i.value == 84)
90
91 doit(callback)
92 ## print self.result
93 doit(callback)
94 ## print self.result
95
96 def test_basics(self):
97 from operator import delitem
98 for ct, pt in zip(ctype_types, python_types):
99 i = ct(42)
100 p = pointer(i)
101 ## print type(p.contents), ct
102 assert type(p.contents) is ct
103 # p.contents is the same as p[0]
104 ## print p.contents
105 ## self.failUnless(p.contents == 42)
106 ## self.failUnless(p[0] == 42)
107
108 py.test.raises(TypeError, delitem, p, 0)
109
110 def test_byref(self):
111 for ct, pt in zip(ctype_types, python_types):
112 i = ct(42)
113 p = byref(i)
114 assert type(p._obj) is ct
115 assert p._obj.value == 42
116
117 def test_pointer_to_pointer(self):
118 x = c_int(32)
119 y = c_int(42)
120 p1 = pointer(x)
121 p2 = pointer(p1)
122 assert p2.contents.contents.value == 32
123 p2.contents.contents = y
124 assert p2.contents.contents.value == 42
125 assert p1.contents.value == 42
126
127 def test_from_address(self):
128 from array import array
129 a = array('i', [100, 200, 300, 400, 500])
130 addr = a.buffer_info()[0]
131
132 p = POINTER(POINTER(c_int))
133 ## print dir(p)
134 ## print p.from_address
135 ## print p.from_address(addr)[0][0]
136
137 def test_other(self):
138 class Table(Structure):
139 _fields_ = [("a", c_int),
140 ("b", c_int),
141 ("c", c_int)]
142
143 pt = pointer(Table(1, 2, 3))
144
145 assert pt.contents.a == 1
146 assert pt.contents.b == 2
147 assert pt.contents.c == 3
148
149 pt.contents.c = 33
150
151 from ctypes import _pointer_type_cache
152 del _pointer_type_cache[Table]
153
154 def test_basic(self):
155 p = pointer(c_int(42))
156 # Although a pointer can be indexed, it ha no length
157 py.test.raises(TypeError, len, p)
158 assert p[0] == 42
159 assert p.contents.value == 42
160
161 def test_charpp(self):
162 """Test that a character pointer-to-pointer is correctly passed"""
163 dll = CDLL(_ctypes_test)
164 func = dll._testfunc_c_p_p
165 func.restype = c_char_p
166 argv = (c_char_p * 2)()
167 argc = c_int( 2 )
168 argv[0] = 'hello'
169 assert argv[0] == 'hello'
170 argv[1] = 'world'
171 result = func( byref(argc), argv )
172 assert result == 'world', result
173
174 def test_charpp2(self):
175 """Test that a character pointer-to-pointer is correctly passed"""
176 dll = CDLL(_ctypes_test)
177 func = dll._testfunc_c_p_p
178 func.restype = c_char_p
179 argv = (c_char_p * 2)()
180 argc = c_int( 2 )
181 argv[0] = 'hello'
182 argv[1] = 'world'
183 result = func( byref(argc), byref(argv) )
184 assert result == 'world', result
185
186 def test_charpp3(self):
187 """Test that a character pointer-to-pointer is correctly passed"""
188 dll = CDLL(_ctypes_test)
189 func = dll._testfunc_c_p_p
190 func.argtypes = (POINTER(c_int), c_char_p * 2)
191 func.restype = c_char_p
192 argv = (c_char_p * 2)()
193 argc = c_int( 2 )
194 argv[0] = 'hello'
195 argv[1] = 'world'
196 result = func( byref(argc), argv )
197 assert result == 'world', result
198
199 def test_charpp4(self):
200 """Test that a character pointer-to-pointer is correctly passed"""
201 dll = CDLL(_ctypes_test)
202 func = dll._testfunc_c_p_p
203 func.argtypes = (POINTER(c_int), POINTER(c_char_p * 2))
204 func.restype = c_char_p
205 argv = (c_char_p * 2)()
206 argc = c_int( 2 )
207 argv[0] = 'hello'
208 argv[1] = 'world'
209 result = func( byref(argc), argv )
210 assert result == 'world', result
211
212 def test_charpp5(self):
213 """Test that a character pointer-to-pointer is correctly passed"""
214 dll = CDLL(_ctypes_test)
215 func = dll._testfunc_c_p_p
216 func.argtypes = (POINTER(c_int), POINTER(c_char_p * 2))
217 func.restype = c_char_p
218 argv = (c_char_p * 2)()
219 argc = c_int( 2 )
220 argv[0] = 'hello'
221 argv[1] = 'world'
222 result = func( byref(argc), byref(argv) )
223 assert result == 'world', result
224
225 def test_bug_1467852(self):
226 # http://sourceforge.net/tracker/?func=detail&atid=532154&aid=1467852&group_id=71702
227 x = c_int(5)
228 dummy = []
229 for i in range(32000):
230 dummy.append(c_int(i))
231 y = c_int(6)
232 p = pointer(x)
233 pp = pointer(p)
234 q = pointer(y)
235 pp[0] = q # <==
236 assert p[0] == 6
237 def test_c_void_p(self):
238 # http://sourceforge.net/tracker/?func=detail&aid=1518190&group_id=5470&atid=105470
239 if sizeof(c_void_p) == 4:
240 assert c_void_p(0xFFFFFFFF).value == c_void_p(-1).value
241 assert c_void_p(0xFFFFFFFFFFFFFFFF).value == c_void_p(-1).value
242 elif sizeof(c_void_p) == 8:
243 assert c_void_p(0xFFFFFFFF).value == 0xFFFFFFFF
244 assert c_void_p(0xFFFFFFFFFFFFFFFF).value == c_void_p(-1).value
245 assert c_void_p(0xFFFFFFFFFFFFFFFFFFFFFFFF).value == c_void_p(-1).value
246
247 py.test.raises(TypeError, c_void_p, 3.14) # make sure floats are NOT accepted
248 py.test.raises(TypeError, c_void_p, object()) # nor other objects
249
250 def test_c_char_p_byref(self):
251 dll = CDLL(_ctypes_test)
252 TwoOutArgs = dll.TwoOutArgs
253 TwoOutArgs.restype = None
254 TwoOutArgs.argtypes = [c_int, c_void_p, c_int, c_void_p]
255 a = c_int(3)
256 b = c_int(4)
257 c = c_int(5)
258 d = c_int(6)
259 TwoOutArgs(a, byref(b), c, byref(d))
260 assert b.value == 7
261 assert d.value == 11
262
263 def test_byref_cannot_be_bound(self):
264 class A(object):
265 _byref = byref
266 A._byref(c_int(5))
267
268 def test_byref_with_offset(self):
269 c = c_int()
270 d = byref(c)
271 base = cast(d, c_void_p).value
272 for i in [0, 1, 4, 1444, -10293]:
273 assert cast(byref(c, i), c_void_p).value == base + i
+0
-270
pypy/module/test_lib_pypy/ctypes_tests/test_prototypes.py less more
0 import pytest
1 from ctypes import *
2 from .support import BaseCTypesTestChecker
3
4 # IMPORTANT INFO:
5 #
6 # Consider this call:
7 # func.restype = c_char_p
8 # func(c_char_p("123"))
9 # It returns
10 # "123"
11 #
12 # WHY IS THIS SO?
13 #
14 # argument tuple (c_char_p("123"), ) is destroyed after the function
15 # func is called, but NOT before the result is actually built.
16 #
17 # If the arglist would be destroyed BEFORE the result has been built,
18 # the c_char_p("123") object would already have a zero refcount,
19 # and the pointer passed to (and returned by) the function would
20 # probably point to deallocated space.
21 #
22 # In this case, there would have to be an additional reference to the argument...
23
24 def setup_module(mod):
25 import conftest
26 _ctypes_test = str(conftest.sofile)
27 mod.testdll = CDLL(_ctypes_test)
28
29 class TestFuncPrototypes(BaseCTypesTestChecker):
30
31 def test_restype_setattr(self):
32 func = testdll._testfunc_p_p
33 with pytest.raises(TypeError):
34 setattr(func, 'restype', 20)
35
36 def test_argtypes_setattr(self):
37 func = testdll._testfunc_p_p
38 with pytest.raises(TypeError):
39 setattr(func, 'argtypes', 20)
40 with pytest.raises(TypeError):
41 setattr(func, 'argtypes', [20])
42
43 func = CFUNCTYPE(c_long, c_void_p, c_long)(lambda: None)
44 assert func.argtypes == (c_void_p, c_long)
45
46 def test_paramflags_setattr(self):
47 func = CFUNCTYPE(c_long, c_void_p, c_long)(lambda: None)
48 with pytest.raises(TypeError):
49 setattr(func, 'paramflags', 'spam')
50 with pytest.raises(ValueError):
51 setattr(func, 'paramflags', (1, 2, 3, 4))
52 with pytest.raises(TypeError):
53 setattr(func, 'paramflags', ((1,), ('a',)))
54 func.paramflags = (1,), (1|4,)
55
56 def test_kwargs(self):
57 proto = CFUNCTYPE(c_char_p, c_char_p, c_int)
58 paramflags = (1, 'text', "tavino"), (1, 'letter', ord('v'))
59 func = proto(('my_strchr', testdll), paramflags)
60 assert func.argtypes == (c_char_p, c_int)
61 assert func.restype == c_char_p
62
63 result = func("abcd", ord('b'))
64 assert result == "bcd"
65
66 result = func()
67 assert result == "vino"
68
69 result = func("grapevine")
70 assert result == "vine"
71
72 result = func(text="grapevine")
73 assert result == "vine"
74
75 result = func(letter=ord('i'))
76 assert result == "ino"
77
78 result = func(letter=ord('p'), text="impossible")
79 assert result == "possible"
80
81 result = func(text="impossible", letter=ord('p'))
82 assert result == "possible"
83
84 # Return machine address `a` as a (possibly long) non-negative integer.
85 # Starting with Python 2.5, id(anything) is always non-negative, and
86 # the ctypes addressof() inherits that via PyLong_FromVoidPtr().
87 def positive_address(a):
88 if a >= 0:
89 return a
90 # View the bits in `a` as unsigned instead.
91 import struct
92 num_bits = struct.calcsize("P") * 8 # num bits in native machine address
93 a += 1 << num_bits
94 assert a >= 0
95 return a
96
97 def c_wbuffer(init):
98 n = len(init) + 1
99 return (c_wchar * n)(*init)
100
101 class TestCharPointers(BaseCTypesTestChecker):
102
103 def test_int_pointer_arg(self):
104 func = testdll._testfunc_p_p
105 func.restype = c_long
106 assert 0 == func(0)
107
108 ci = c_int(0)
109
110 func.argtypes = POINTER(c_int),
111 assert positive_address(addressof(ci)) == (
112 positive_address(func(byref(ci))))
113
114 func.argtypes = c_char_p,
115 with pytest.raises(ArgumentError):
116 func(byref(ci))
117
118 func.argtypes = POINTER(c_short),
119 with pytest.raises(ArgumentError):
120 func(byref(ci))
121
122 func.argtypes = POINTER(c_double),
123 with pytest.raises(ArgumentError):
124 func(byref(ci))
125
126 def test_POINTER_c_char_arg(self):
127 func = testdll._testfunc_p_p
128 func.restype = c_char_p
129 func.argtypes = POINTER(c_char),
130
131 assert None == func(None)
132 assert "123" == func("123")
133 assert None == func(c_char_p(None))
134 assert "123" == func(c_char_p("123"))
135
136 assert "123" == func(c_buffer("123"))
137 ca = c_char("a")
138 assert "a" == func(pointer(ca))[0]
139 assert "a" == func(byref(ca))[0]
140
141 def test_c_char_p_arg(self):
142 func = testdll._testfunc_p_p
143 func.restype = c_char_p
144 func.argtypes = c_char_p,
145
146 assert None == func(None)
147 assert "123" == func("123")
148 assert None == func(c_char_p(None))
149 assert "123" == func(c_char_p("123"))
150
151 assert "123" == func(c_buffer("123"))
152 ca = c_char("a")
153 assert "a" == func(pointer(ca))[0]
154 assert "a" == func(byref(ca))[0]
155
156 def test_c_void_p_arg(self):
157 func = testdll._testfunc_p_p
158 func.restype = c_char_p
159 func.argtypes = c_void_p,
160
161 assert None == func(None)
162 assert "123" == func("123")
163 assert "123" == func(c_char_p("123"))
164 assert None == func(c_char_p(None))
165
166 assert "123" == func(c_buffer("123"))
167 ca = c_char("a")
168 assert "a" == func(pointer(ca))[0]
169 assert "a" == func(byref(ca))[0]
170
171 func(byref(c_int()))
172 func(pointer(c_int()))
173 func((c_int * 3)())
174
175 try:
176 func.restype = c_wchar_p
177 except NameError:
178 pass
179 else:
180 assert None == func(c_wchar_p(None))
181 assert "123" == func(c_wchar_p("123"))
182
183 def test_instance(self):
184 func = testdll._testfunc_p_p
185 func.restype = c_void_p
186
187 class X:
188 _as_parameter_ = None
189
190 func.argtypes = c_void_p,
191 assert None == func(X())
192
193 func.argtypes = None
194 assert None == func(X())
195
196 try:
197 c_wchar
198 except NameError:
199 pass
200 else:
201 class TestWCharPointers(BaseCTypesTestChecker):
202
203 def setup_class(cls):
204 func = testdll._testfunc_p_p
205 func.restype = c_int
206 func.argtypes = None
207 cls.func = func
208 BaseCTypesTestChecker.setup_class.im_func(cls)
209
210
211 def test_POINTER_c_wchar_arg(self):
212 func = self.func
213 func.restype = c_wchar_p
214 func.argtypes = POINTER(c_wchar),
215
216 assert None == func(None)
217 assert "123" == func("123")
218 assert None == func(c_wchar_p(None))
219 assert "123" == func(c_wchar_p("123"))
220
221 assert "123" == func(c_wbuffer("123"))
222 ca = c_wchar("a")
223 assert "a" == func(pointer(ca))[0]
224 assert "a" == func(byref(ca))[0]
225
226 def test_c_wchar_p_arg(self):
227 func = self.func
228 func.restype = c_wchar_p
229 func.argtypes = c_wchar_p,
230
231 c_wchar_p.from_param("123")
232
233 assert None == func(None)
234 assert "123" == func("123")
235 assert None == func(c_wchar_p(None))
236 assert "123" == func(c_wchar_p("123"))
237
238 # XXX Currently, these raise TypeErrors, although they shouldn't:
239 assert "123" == func(c_wbuffer("123"))
240 ca = c_wchar("a")
241 assert "a" == func(pointer(ca))[0]
242 assert "a" == func(byref(ca))[0]
243
244 class TestArray(BaseCTypesTestChecker):
245 def test(self):
246 func = testdll._testfunc_ai8
247 func.restype = POINTER(c_int)
248 func.argtypes = c_int * 8,
249
250 func((c_int * 8)(1, 2, 3, 4, 5, 6, 7, 8))
251
252 # This did crash before:
253
254 def func(): pass
255 CFUNCTYPE(None, c_int * 3)(func)
256
257 def test_array_to_ptr_wrongtype(self):
258 ARRAY = c_byte * 8
259 func = testdll._testfunc_ai8
260 func.restype = POINTER(c_int)
261 func.argtypes = [c_int * 8]
262 array = ARRAY(1, 2, 3, 4, 5, 6, 7, 8)
263 with pytest.raises(ArgumentError):
264 func(array)
265
266 ################################################################
267
268 if __name__ == '__main__':
269 unittest.main()
+0
-30
pypy/module/test_lib_pypy/ctypes_tests/test_repr.py less more
0 import py
1 from .support import BaseCTypesTestChecker
2 from ctypes import *
3
4
5 subclasses = []
6 for base in [c_byte, c_short, c_int, c_long, c_longlong,
7 c_ubyte, c_ushort, c_uint, c_ulong, c_ulonglong,
8 c_float, c_double]:
9 class X(base):
10 pass
11 subclasses.append(X)
12
13 class X(c_char):
14 pass
15
16 # This test checks if the __repr__ is correct for subclasses of simple types
17
18 class TestRepr(BaseCTypesTestChecker):
19 def test_numbers(self):
20 py.test.skip("reprs not implemented")
21 for typ in subclasses:
22 base = typ.__bases__[0]
23 assert repr(base(42)).startswith(base.__name__)
24 assert "<X object at" == repr(typ(42))[:12]
25
26 def test_char(self):
27 py.test.skip("reprs not implemented")
28 assert "c_char('x')" == repr(c_char('x'))
29 assert "<X object at" == repr(X('x'))[:12]
+0
-37
pypy/module/test_lib_pypy/ctypes_tests/test_returnfuncptrs.py less more
0 import pytest
1
2 from ctypes import *
3
4 def setup_module(mod):
5 import conftest
6 mod.dll = CDLL(str(conftest.sofile))
7
8 class TestReturnFuncPtr:
9
10 def test_with_prototype(self):
11 # The _ctypes_test shared lib/dll exports quite some functions for testing.
12 # The get_strchr function returns a *pointer* to the C strchr function.
13 get_strchr = dll.get_strchr
14 get_strchr.restype = CFUNCTYPE(c_char_p, c_char_p, c_char)
15 strchr = get_strchr()
16 assert strchr("abcdef", "b") == "bcdef"
17 assert strchr("abcdef", "x") == None
18 with pytest.raises(ArgumentError):
19 strchr("abcdef", 3)
20 with pytest.raises(TypeError):
21 strchr("abcdef")
22
23 def test_without_prototype(self):
24 get_strchr = dll.get_strchr
25 # the default 'c_int' would not work on systems where sizeof(int) != sizeof(void *)
26 get_strchr.restype = c_void_p
27 addr = get_strchr()
28 # _CFuncPtr instances are now callable with an integer argument
29 # which denotes a function address:
30 strchr = CFUNCTYPE(c_char_p, c_char_p, c_char)(addr)
31 assert strchr("abcdef", "b"), "bcdef"
32 assert strchr("abcdef", "x") == None
33 with pytest.raises(ArgumentError):
34 strchr("abcdef", 3)
35 with pytest.raises(TypeError):
36 strchr("abcdef")
+0
-55
pypy/module/test_lib_pypy/ctypes_tests/test_simplesubclasses.py less more
0 import py
1 from .support import BaseCTypesTestChecker
2 from ctypes import *
3
4 class MyInt(c_int):
5 def __cmp__(self, other):
6 if type(other) != MyInt:
7 return -1
8 return cmp(self.value, other.value)
9
10 class Test(BaseCTypesTestChecker):
11
12 def test_compare(self):
13 assert MyInt(3) == MyInt(3)
14 assert not MyInt(42) == MyInt(43)
15
16 def test_ignore_retval(self):
17 # Test if the return value of a callback is ignored
18 # if restype is None
19 proto = CFUNCTYPE(None)
20 def func():
21 return (1, "abc", None)
22
23 cb = proto(func)
24 assert None == cb()
25
26
27 def test_int_callback(self):
28 py.test.skip("subclassing semantics and implementation details not implemented")
29 args = []
30 def func(arg):
31 args.append(arg)
32 return arg
33
34 cb = CFUNCTYPE(None, MyInt)(func)
35
36 assert None == cb(42)
37 assert type(args[-1]) == MyInt
38
39 cb = CFUNCTYPE(c_int, c_int)(func)
40
41 assert 42 == cb(42)
42 assert type(args[-1]) == int
43
44 def test_int_struct(self):
45 py.test.skip("subclassing semantics and implementation details not implemented")
46 class X(Structure):
47 _fields_ = [("x", MyInt)]
48
49 assert X().x == MyInt()
50
51 s = X()
52 s.x = MyInt(42)
53
54 assert s.x == MyInt(42)
+0
-24
pypy/module/test_lib_pypy/ctypes_tests/test_sizes.py less more
0 # Test specifically-sized containers.
1
2 from ctypes import *
3 from .support import BaseCTypesTestChecker
4
5 class TestSizes(BaseCTypesTestChecker):
6 def test_8(self):
7 assert 1 == sizeof(c_int8)
8 assert 1 == sizeof(c_uint8)
9
10 def test_16(self):
11 assert 2 == sizeof(c_int16)
12 assert 2 == sizeof(c_uint16)
13
14 def test_32(self):
15 assert 4 == sizeof(c_int32)
16 assert 4 == sizeof(c_uint32)
17
18 def test_64(self):
19 assert 8 == sizeof(c_int64)
20 assert 8 == sizeof(c_uint64)
21
22 def test_size_t(self):
23 assert sizeof(c_void_p) == sizeof(c_size_t)
+0
-120
pypy/module/test_lib_pypy/ctypes_tests/test_slicing.py less more
0 import pytest
1 from .support import BaseCTypesTestChecker
2 from ctypes import *
3
4 def setup_module(mod):
5 import conftest
6 _ctypes_test = str(conftest.sofile)
7 mod.dll = CDLL(_ctypes_test)
8
9 class TestSlices(BaseCTypesTestChecker):
10 def test_getslice_cint(self):
11 a = (c_int * 100)(*xrange(1100, 1200))
12 b = range(1100, 1200)
13 assert a[0:2] == b[0:2]
14 assert len(a) == len(b)
15 assert a[5:7] == b[5:7]
16 assert a[-1] == b[-1]
17 assert a[:] == b[:]
18
19 a[0:5] = range(5, 10)
20 assert a[0:5] == range(5, 10)
21
22 def test_setslice_cint(self):
23 a = (c_int * 100)(*xrange(1100, 1200))
24 b = range(1100, 1200)
25
26 a[32:47] = range(32, 47)
27 assert a[32:47] == range(32, 47)
28
29 from operator import setslice
30
31 # TypeError: int expected instead of str instance
32 with pytest.raises(TypeError):
33 setslice(a, 0, 5, b"abcde")
34 # TypeError: int expected instead of str instance
35 with pytest.raises(TypeError):
36 setslice(a, 0, 5, [b"a", b"b", b"c", b"d", b"e"])
37 # TypeError: int expected instead of float instance
38 with pytest.raises(TypeError):
39 setslice(a, 0, 5, [1, 2, 3, 4, 3.14])
40 # ValueError: Can only assign sequence of same size
41 with pytest.raises(ValueError):
42 setslice(a, 0, 5, range(32))
43
44 def test_char_ptr(self):
45 s = "abcdefghijklmnopqrstuvwxyz"
46
47 dll.my_strdup.restype = POINTER(c_char)
48 dll.my_free.restype = None
49 res = dll.my_strdup(s)
50 assert res[:len(s)] == s
51
52 import operator
53 with pytest.raises(TypeError):
54 operator.setslice(res, 0, 5, u"abcde")
55 dll.my_free(res)
56
57 dll.my_strdup.restype = POINTER(c_byte)
58 res = dll.my_strdup(s)
59 assert res[:len(s)] == range(ord("a"), ord("z")+1)
60 dll.my_free(res)
61
62 def test_char_ptr_with_free(self):
63 s = "abcdefghijklmnopqrstuvwxyz"
64
65 class allocated_c_char_p(c_char_p):
66 pass
67
68 dll.my_free.restype = None
69 def errcheck(result, func, args):
70 retval = result.value
71 dll.my_free(result)
72 return retval
73
74 dll.my_strdup.restype = allocated_c_char_p
75 dll.my_strdup.errcheck = errcheck
76 try:
77 res = dll.my_strdup(s)
78 assert res == s
79 finally:
80 del dll.my_strdup.errcheck
81
82
83 def test_char_array(self):
84 s = "abcdefghijklmnopqrstuvwxyz\0"
85
86 p = (c_char * 27)(*s)
87 assert p[:] == s
88
89
90 try:
91 c_wchar
92 except NameError:
93 pass
94 else:
95 def test_wchar_ptr(self):
96 s = "abcdefghijklmnopqrstuvwxyz\0"
97
98 dll.my_wcsdup.restype = POINTER(c_wchar)
99 dll.my_wcsdup.argtypes = POINTER(c_wchar),
100 dll.my_free.restype = None
101 res = dll.my_wcsdup(s)
102 assert res[:len(s)] == s
103
104 import operator
105 with pytest.raises(TypeError):
106 operator.setslice(res, 0, 5, u"abcde")
107 dll.my_free(res)
108
109 if sizeof(c_wchar) == sizeof(c_short):
110 dll.my_wcsdup.restype = POINTER(c_short)
111 elif sizeof(c_wchar) == sizeof(c_int):
112 dll.my_wcsdup.restype = POINTER(c_int)
113 elif sizeof(c_wchar) == sizeof(c_long):
114 dll.my_wcsdup.restype = POINTER(c_long)
115 else:
116 return
117 res = dll.my_wcsdup(s)
118 assert res[:len(s)-1] == range(ord("a"), ord("z")+1)
119 dll.my_free(res)
+0
-80
pypy/module/test_lib_pypy/ctypes_tests/test_stringptr.py less more
0 import pytest
1 from .support import BaseCTypesTestChecker
2 from ctypes import *
3
4 def setup_module(mod):
5 import conftest
6 _ctypes_test = str(conftest.sofile)
7 mod.lib = CDLL(_ctypes_test)
8
9
10 class TestStringPtr(BaseCTypesTestChecker):
11
12 def test__POINTER_c_char(self):
13 class X(Structure):
14 _fields_ = [("str", POINTER(c_char))]
15 x = X()
16
17 # NULL pointer access
18 with pytest.raises(ValueError):
19 x.str.contents
20 b = c_buffer("Hello, World")
21 #from sys import getrefcount as grc
22 #assert grc(b) == 2
23 x.str = b
24 #assert grc(b) == 3
25
26 # POINTER(c_char) and Python string is NOT compatible
27 # POINTER(c_char) and c_buffer() is compatible
28 for i in range(len(b)):
29 assert b[i] == x.str[i]
30
31 # XXX pypy modified:
32 #raises(TypeError, setattr, x, "str", "Hello, World")
33 x = b = None
34
35 def test__c_char_p(self):
36 class X(Structure):
37 _fields_ = [("str", c_char_p)]
38 x = X()
39
40 # c_char_p and Python string is compatible
41 # c_char_p and c_buffer is NOT compatible
42 assert x.str == None
43 x.str = "Hello, World"
44 assert x.str == "Hello, World"
45 # XXX pypy modified:
46 #b = c_buffer("Hello, World")
47 #raises(TypeError, setattr, x, "str", b)
48 x = None
49
50
51 def test_functions(self):
52 strchr = lib.my_strchr
53 strchr.restype = c_char_p
54
55 # c_char_p and Python string is compatible
56 # c_char_p and c_buffer are now compatible
57 strchr.argtypes = c_char_p, c_char
58 assert strchr("abcdef", "c") == "cdef"
59 assert strchr(c_buffer("abcdef"), "c") == "cdef"
60
61 # POINTER(c_char) and Python string is NOT compatible
62 # POINTER(c_char) and c_buffer() is compatible
63 strchr.argtypes = POINTER(c_char), c_char
64 buf = c_buffer("abcdef")
65 assert strchr(buf, "c") == "cdef"
66 assert strchr("abcdef", "c") == "cdef"
67
68 # XXX These calls are dangerous, because the first argument
69 # to strchr is no longer valid after the function returns!
70 # So we must keep a reference to buf separately
71
72 strchr.restype = POINTER(c_char)
73 buf = c_buffer("abcdef")
74 r = strchr(buf, "c")
75 x = r[0], r[1], r[2], r[3], r[4]
76 assert x == ("c", "d", "e", "f", "\000")
77 del buf
78 # x1 will NOT be the same as x, usually:
79 x1 = r[0], r[1], r[2], r[3], r[4]
+0
-114
pypy/module/test_lib_pypy/ctypes_tests/test_strings.py less more
0
1 import py
2 from ctypes import *
3 from .support import BaseCTypesTestChecker
4
5 class TestStringArray(BaseCTypesTestChecker):
6 def test_one(self):
7 BUF = c_char * 4
8
9 buf = BUF("a", "b", "c")
10 assert buf.value == "abc"
11 assert buf.raw == "abc\000"
12
13 buf.value = "ABCD"
14 assert buf.value == "ABCD"
15 assert buf.raw == "ABCD"
16
17 buf.value = "x"
18 assert buf.value == "x"
19 assert buf.raw == "x\000CD"
20
21 buf[1] = "Z"
22 assert buf.value == "xZCD"
23 assert buf.raw == "xZCD"
24
25 py.test.raises(ValueError, setattr, buf, "value", "aaaaaaaa")
26 py.test.raises(TypeError, setattr, buf, "value", 42)
27
28 def test_c_buffer_value(self):
29 buf = c_buffer(32)
30
31 buf.value = "Hello, World"
32 assert buf.value == "Hello, World"
33
34 def test_c_buffer_raw(self):
35 buf = c_buffer(32)
36
37 buf.raw = "Hello, World"
38 assert buf.value == "Hello, World"
39
40 def test_c_buffer_raw_from_buffer(self):
41 buf = c_buffer(32)
42 buf.raw = buffer("Hello, World")
43 assert buf.value == "Hello, World"
44
45 def test_c_buffer_raw_from_memoryview(self):
46 buf = c_buffer(32)
47 buf.raw = memoryview("Hello, World")
48 assert buf.value == "Hello, World"
49
50 def test_param_1(self):
51 BUF = c_char * 4
52 buf = BUF()
53 ## print c_char_p.from_param(buf)
54
55 def test_param_2(self):
56 BUF = c_char * 4
57 buf = BUF()
58 ## print BUF.from_param(c_char_p("python"))
59 ## print BUF.from_param(BUF(*"pyth"))
60
61 try:
62 c_wchar
63 except NameError:
64 pass
65 else:
66 class TestWString(BaseCTypesTestChecker):
67 def test(self):
68 BUF = c_wchar * 4
69
70 buf = BUF("a", "b", "c")
71 assert buf.value == "abc"
72
73 buf.value = "ABCD"
74 assert buf.value == "ABCD"
75
76 buf.value = "x"
77 assert buf.value == "x"
78
79 buf[1] = "Z"
80 assert buf.value == "xZCD"
81
82 # XXX write real tests for w_char
83
84
85 def run_test(rep, msg, func, arg):
86 items = range(rep)
87 from time import clock
88 start = clock()
89 for i in items:
90 func(arg); func(arg); func(arg); func(arg); func(arg)
91 stop = clock()
92 print("%20s: %.2f us" % (msg, ((stop-start)*1e6/5/rep)))
93
94 def check_perf():
95 # Construct 5 objects
96
97 REP = 200000
98
99 run_test(REP, "c_string(None)", c_string, None)
100 run_test(REP, "c_string('abc')", c_string, 'abc')
101
102 # Python 2.3 -OO, win2k, P4 700 MHz:
103 #
104 # c_string(None): 1.75 us
105 # c_string('abc'): 2.74 us
106
107 # Python 2.2 -OO, win2k, P4 700 MHz:
108 #
109 # c_string(None): 2.95 us
110 # c_string('abc'): 3.67 us
111
112
113 ## check_perf()
+0
-54
pypy/module/test_lib_pypy/ctypes_tests/test_struct_fields.py less more
0 import pytest
1 from .support import BaseCTypesTestChecker
2 from ctypes import *
3
4 class TestStructFields(BaseCTypesTestChecker):
5 # Structure/Union classes must get 'finalized' sooner or
6 # later, when one of these things happen:
7 #
8 # 1. _fields_ is set.
9 # 2. An instance is created.
10 # 3. The type is used as field of another Structure/Union.
11 # 4. The type is subclassed
12 #
13 # When they are finalized, assigning _fields_ is no longer allowed.
14
15 def test_1_A(self):
16 class X(Structure):
17 pass
18 assert sizeof(X) == 0 # not finalized
19 X._fields_ = [] # finalized
20 with pytest.raises(AttributeError):
21 X._fields_ = []
22
23 def test_1_B(self):
24 class X(Structure):
25 _fields_ = [] # finalized
26 with pytest.raises(AttributeError):
27 X._fields_ = []
28
29 def test_2(self):
30 class X(Structure):
31 pass
32 X()
33 with pytest.raises(AttributeError):
34 X._fields_ = []
35
36 def test_3(self):
37 class X(Structure):
38 pass
39 class Y(Structure):
40 _fields_ = [("x", X)] # finalizes X
41 with pytest.raises(AttributeError):
42 X._fields_ = []
43
44 def test_4(self):
45 class X(Structure):
46 pass
47 class Y(X):
48 pass
49 with pytest.raises(AttributeError):
50 X._fields_ = []
51 Y._fields_ = []
52 with pytest.raises(AttributeError):
53 X._fields_ = []
+0
-615
pypy/module/test_lib_pypy/ctypes_tests/test_structures.py less more
0 from ctypes import *
1 from struct import calcsize
2 from .support import BaseCTypesTestChecker
3
4 import pytest
5
6
7 class TestSubclasses(BaseCTypesTestChecker):
8 def test_subclass(self):
9 class X(Structure):
10 _fields_ = [("a", c_int)]
11
12 class Y(X):
13 _fields_ = [("b", c_int)]
14
15 class Z(X):
16 pass
17
18 assert sizeof(X) == sizeof(c_int)
19 assert sizeof(Y) == sizeof(c_int)*2
20 assert sizeof(Z) == sizeof(c_int)
21 assert X._fields_ == [("a", c_int)]
22 assert Y._fields_ == [("b", c_int)]
23 assert Z._fields_ == [("a", c_int)]
24 assert Y._names_ == ['a', 'b']
25
26 def test_subclass_delayed(self):
27 class X(Structure):
28 pass
29 assert sizeof(X) == 0
30 X._fields_ = [("a", c_int)]
31
32 class Y(X):
33 pass
34 assert sizeof(Y) == sizeof(X)
35 Y._fields_ = [("b", c_int)]
36
37 class Z(X):
38 pass
39
40 assert sizeof(X) == sizeof(c_int)
41 assert sizeof(Y) == sizeof(c_int)*2
42 assert sizeof(Z) == sizeof(c_int)
43 assert X._fields_ == [("a", c_int)]
44 assert Y._fields_ == [("b", c_int)]
45 assert Z._fields_ == [("a", c_int)]
46
47
48 class TestStructure(BaseCTypesTestChecker):
49 formats = {"c": c_char,
50 "b": c_byte,
51 "B": c_ubyte,
52 "h": c_short,
53 "H": c_ushort,
54 "i": c_int,
55 "I": c_uint,
56 "l": c_long,
57 "L": c_ulong,
58 "q": c_longlong,
59 "Q": c_ulonglong,
60 "f": c_float,
61 "d": c_double,
62 }
63
64 def test_simple_structs(self):
65 for code, tp in self.formats.items():
66 class X(Structure):
67 _fields_ = [("x", c_char),
68 ("y", tp)]
69 assert (sizeof(X), code) == (
70 (calcsize("c%c" % (code,)), code))
71
72 def test_unions(self):
73 for code, tp in self.formats.items():
74 class X(Union):
75 _fields_ = [("x", c_char),
76 ("y", tp)]
77 assert (sizeof(X), code) == (
78 (calcsize("%c" % (code)), code))
79
80 def test_struct_alignment(self):
81 class X(Structure):
82 _fields_ = [("x", c_char * 3)]
83 assert alignment(X) == calcsize("s")
84 assert sizeof(X) == calcsize("3s")
85
86 class Y(Structure):
87 _fields_ = [("x", c_char * 3),
88 ("y", c_int)]
89 assert alignment(Y) == calcsize("i")
90 assert sizeof(Y) == calcsize("3si")
91
92 class SI(Structure):
93 _fields_ = [("a", X),
94 ("b", Y)]
95 assert alignment(SI) == max(alignment(Y), alignment(X))
96 assert sizeof(SI) == calcsize("3s0i 3si 0i")
97
98 class IS(Structure):
99 _fields_ = [("b", Y),
100 ("a", X)]
101
102 assert alignment(SI) == max(alignment(X), alignment(Y))
103 assert sizeof(IS) == calcsize("3si 3s 0i")
104
105 class XX(Structure):
106 _fields_ = [("a", X),
107 ("b", X)]
108 assert alignment(XX) == alignment(X)
109 assert sizeof(XX) == calcsize("3s 3s 0s")
110
111 def test_emtpy(self):
112 # I had problems with these
113 #
114 # Although these are patological cases: Empty Structures!
115 class X(Structure):
116 _fields_ = []
117
118 class Y(Union):
119 _fields_ = []
120
121 # Is this really the correct alignment, or should it be 0?
122 assert alignment(X) == alignment(Y) == 1
123 assert sizeof(X) == sizeof(Y) == 0
124
125 class XX(Structure):
126 _fields_ = [("a", X),
127 ("b", X)]
128
129 assert alignment(XX) == 1
130 assert sizeof(XX) == 0
131
132 def test_fields(self):
133 # test the offset and size attributes of Structure/Unoin fields.
134 class X(Structure):
135 _fields_ = [("x", c_int),
136 ("y", c_char)]
137
138 assert X.x.offset == 0
139 assert X.x.size == sizeof(c_int)
140
141 assert X.y.offset == sizeof(c_int)
142 assert X.y.size == sizeof(c_char)
143
144 # readonly
145 with pytest.raises((TypeError, AttributeError)):
146 X.x.offset = 92
147 with pytest.raises((TypeError, AttributeError)):
148 X.x.size = 92
149
150 class X(Union):
151 _fields_ = [("x", c_int),
152 ("y", c_char)]
153
154 assert X.x.offset == 0
155 assert X.x.size == sizeof(c_int)
156
157 assert X.y.offset == 0
158 assert X.y.size == sizeof(c_char)
159
160 # readonly
161 with pytest.raises((TypeError, AttributeError)):
162 X.x.offset = 92
163 with pytest.raises((TypeError, AttributeError)):
164 X.x.size = 92
165
166 # XXX Should we check nested data types also?
167 # offset is always relative to the class...
168
169 def test_packed(self):
170 class X(Structure):
171 _fields_ = [("a", c_byte),
172 ("b", c_longlong)]
173 _pack_ = 1
174
175 assert sizeof(X) == 9
176 assert X.b.offset == 1
177
178 class X(Structure):
179 _fields_ = [("a", c_byte),
180 ("b", c_longlong)]
181 _pack_ = 2
182 assert sizeof(X) == 10
183 assert X.b.offset == 2
184
185 class X(Structure):
186 _fields_ = [("a", c_byte),
187 ("b", c_longlong)]
188 _pack_ = 4
189 assert sizeof(X) == 12
190 assert X.b.offset == 4
191
192 import struct
193 longlong_size = struct.calcsize("q")
194 longlong_align = struct.calcsize("bq") - longlong_size
195
196 class X(Structure):
197 _fields_ = [("a", c_byte),
198 ("b", c_longlong)]
199 _pack_ = 8
200
201 assert sizeof(X) == longlong_align + longlong_size
202 assert X.b.offset == min(8, longlong_align)
203
204
205 d = {"_fields_": [("a", "b"),
206 ("b", "q")],
207 "_pack_": -1}
208 with pytest.raises(ValueError):
209 type(Structure)("X", (Structure,), d)
210
211 def test_initializers(self):
212 class Person(Structure):
213 _fields_ = [("name", c_char*6),
214 ("age", c_int)]
215
216 with pytest.raises(TypeError):
217 Person(42)
218 with pytest.raises(ValueError):
219 Person("asldkjaslkdjaslkdj")
220 with pytest.raises(TypeError):
221 Person("Name", "HI")
222
223 # short enough
224 assert Person("12345", 5).name == "12345"
225 # exact fit
226 assert Person("123456", 5).name == "123456"
227 # too long
228 with pytest.raises(ValueError):
229 Person("1234567", 5)
230
231
232 def test_keyword_initializers(self):
233 class POINT(Structure):
234 _fields_ = [("x", c_int), ("y", c_int)]
235 pt = POINT(1, 2)
236 assert (pt.x, pt.y) == (1, 2)
237
238 pt = POINT(y=2, x=1)
239 assert (pt.x, pt.y) == (1, 2)
240
241 def test_subclass_initializer(self):
242 class POINT(Structure):
243 _fields_ = [("x", c_int), ("y", c_int)]
244
245 class POSITION(POINT):
246 # A subclass without _fields_
247 pass
248 pos = POSITION(1, 2)
249 assert (pos.x, pos.y) == (1, 2)
250 # Try a second time, result may be different (cf. issue1498)
251 pos = POSITION(1, 2)
252 assert (pos.x, pos.y) == (1, 2)
253
254 def test_invalid_field_types(self):
255 class POINT(Structure):
256 pass
257 with pytest.raises(TypeError):
258 POINT._fields_ = [("x", 1), ("y", 2)]
259
260 def test_intarray_fields(self):
261 class SomeInts(Structure):
262 _fields_ = [("a", c_int * 4)]
263
264 # can use tuple to initialize array (but not list!)
265 assert SomeInts((1, 2)).a[:] == [1, 2, 0, 0]
266 assert SomeInts((1, 2, 3, 4)).a[:] == [1, 2, 3, 4]
267 # too long
268 # XXX Should raise ValueError?, not RuntimeError
269 with pytest.raises(RuntimeError):
270 SomeInts((1, 2, 3, 4, 5))
271
272 def test_nested_initializers(self):
273 # test initializing nested structures
274 class Phone(Structure):
275 _fields_ = [("areacode", c_char*6),
276 ("number", c_char*12)]
277
278 class Person(Structure):
279 _fields_ = [("name", c_char * 12),
280 ("phone", Phone),
281 ("age", c_int)]
282
283 p = Person("Someone", ("1234", "5678"), 5)
284
285 assert p.name == "Someone"
286 assert p.phone.areacode == "1234"
287 assert p.phone.number == "5678"
288 assert p.age == 5
289
290 def test_structures_with_wchar(self):
291 pytest.skip("need unicode support on _rawffi level")
292 try:
293 c_wchar
294 except NameError:
295 return # no unicode
296
297 class PersonW(Structure):
298 _fields_ = [("name", c_wchar * 12),
299 ("age", c_int)]
300
301 p = PersonW(u"Someone")
302 assert p.name == "Someone"
303
304 assert PersonW(u"1234567890").name == u"1234567890"
305 assert PersonW(u"12345678901").name == u"12345678901"
306 # exact fit
307 assert PersonW(u"123456789012").name == u"123456789012"
308 #too long
309 with pytest.raises(ValueError):
310 PersonW(u"1234567890123")
311
312 def test_init_errors(self):
313 pytest.skip("not implemented error details")
314 class Phone(Structure):
315 _fields_ = [("areacode", c_char*6),
316 ("number", c_char*12)]
317
318 class Person(Structure):
319 _fields_ = [("name", c_char * 12),
320 ("phone", Phone),
321 ("age", c_int)]
322
323 cls, msg = self.get_except(Person, "Someone", (1, 2))
324 assert cls == RuntimeError
325 # In Python 2.5, Exception is a new-style class, and the repr changed
326 if issubclass(Exception, object):
327 assert msg == (
328 "(Phone) <type 'exceptions.TypeError'>: "
329 "expected string or Unicode object, int found")
330 else:
331 assert msg == (
332 "(Phone) exceptions.TypeError: "
333 "expected string or Unicode object, int found")
334
335 cls, msg = self.get_except(Person, "Someone", ("a", "b", "c"))
336 assert cls == RuntimeError
337 if issubclass(Exception, object):
338 assert msg == (
339 "(Phone) <type 'exceptions.ValueError'>: too many initializers")
340 else:
341 assert msg == "(Phone) exceptions.ValueError: too many initializers"
342
343
344 def get_except(self, func, *args):
345 # XXX remove this, py.test.raises returns a nice inspectable object
346 try:
347 func(*args)
348 except Exception as detail:
349 return detail.__class__, str(detail)
350
351
352 ## def test_subclass_creation(self):
353 ## meta = type(Structure)
354 ## # same as 'class X(Structure): pass'
355 ## # fails, since we need either a _fields_ or a _abstract_ attribute
356 ## cls, msg = self.get_except(meta, "X", (Structure,), {})
357 ## self.failUnlessEqual((cls, msg),
358 ## (AttributeError, "class must define a '_fields_' attribute"))
359
360 def test_abstract_class(self):
361 pytest.skip("_abstract_ semantics not implemented")
362 class X(Structure):
363 _abstract_ = "something"
364 # try 'X()'
365 cls, msg = self.get_except(eval, "X()", locals())
366 assert (cls, msg) == (TypeError, "abstract class")
367
368 def test_methods(self):
369 ## class X(Structure):
370 ## _fields_ = []
371
372 assert "in_dll" in dir(type(Structure))
373 assert "from_address" in dir(type(Structure))
374 assert "in_dll" in dir(type(Structure))
375
376 def test_fields_is_a_tuple(self):
377 class Person(Structure):
378 _fields_ = (("name", c_char*6),
379 ("age", c_int))
380
381 # short enough
382 p = Person("123456", 6)
383 assert p.name == "123456"
384 assert p.age == 6
385
386 def test_subclassing_field_is_a_tuple(self):
387 pytest.skip("subclassing semantics not implemented")
388 class Person(Structure):
389 _fields_ = (("name", c_char*6),
390 ("age", c_int))
391 class PersonWithIncome(Person):
392 _fields_ = [("income", c_int)]
393
394 # short enough
395 p = PersonWithIncome("123456", 6, 5)
396 assert p.name == "123456"
397 assert p.age == 6
398 assert p.income == 5
399
400 def test___init__(self):
401 class Person(Structure):
402 _fields_ = (("name", c_char*10),
403 ("age", c_int))
404
405 def __init__(self, name, surname, age):
406 self.name = name + ' ' + surname
407 self.age = age
408
409 p = Person("John", "Doe", 25)
410 assert p.name == "John Doe"
411 assert p.age == 25
412
413 def test_setattr(self):
414 class X(Structure):
415 _fields_ = [("a", c_int)]
416
417 x = X()
418 x.other = 42
419 assert x.other == 42
420
421 def test_withslots(self):
422 class X(Structure):
423 _fields_ = [("a", c_int * 2)]
424 __slots__ = ['a']
425
426 x = X()
427 x.a = (42, 43)
428 assert tuple(x.a) == (42, 43)
429
430 def test_getattr_recursion(self):
431 # Structure.__getattr__ used to call itself recursively
432 # and hit the recursion limit.
433 import sys
434 events = []
435
436 def tracefunc(frame, event, arg):
437 funcname = frame.f_code.co_name
438 if 'getattr' in funcname:
439 events.append(funcname)
440
441 oldtrace = sys.settrace(tracefunc)
442 try:
443 class X(Structure):
444 _fields_ = [("a", c_int)]
445
446 assert len(events) < 20
447 finally:
448 sys.settrace(oldtrace)
449 events = None
450
451 def test_large_fields(self):
452 # make sure that large fields are not "confused" with bitfields
453 # (because the bitfields use the higher bits of the "size" attribute)
454 Array = c_long * 8192
455 class X(Structure):
456 _fields_ = [('items', Array)]
457 obj = X()
458 assert isinstance(obj.items, Array)
459
460 def test_b_base(self):
461 # _b_base_ used to be None here in PyPy
462 class X(Structure):
463 _fields_ = [('x', c_int)]
464 obj = X()
465 p = pointer(obj)
466 assert p.contents._b_base_ is p
467
468 def test_swapped_bytes(self):
469 import sys
470
471 for i in [c_short, c_int, c_long, c_longlong,
472 c_float, c_double, c_ushort, c_uint,
473 c_ulong, c_ulonglong]:
474 FIELDS = [
475 ('n', i)
476 ]
477
478 class Native(Structure):
479 _fields_ = FIELDS
480
481 class Big(BigEndianStructure):
482 _fields_ = FIELDS
483
484 class Little(LittleEndianStructure):
485 _fields_ = FIELDS
486
487 def dostruct(c):
488 ba = create_string_buffer(sizeof(c))
489 ms = c.from_buffer(ba)
490 ms.n = 0xff00
491 return repr(ba[:])
492
493 if sys.byteorder == 'little':
494 assert dostruct(Native) == dostruct(Little)
495 assert dostruct(Native) != dostruct(Big)
496 else:
497 assert dostruct(Native) == dostruct(Big)
498 assert dostruct(Native) != dostruct(Little)
499
500
501 class TestPointerMember(BaseCTypesTestChecker):
502 def test_1(self):
503 # a Structure with a POINTER field
504 class S(Structure):
505 _fields_ = [("array", POINTER(c_int))]
506
507 s = S()
508 # We can assign arrays of the correct type
509 s.array = (c_int * 3)(1, 2, 3)
510 items = [s.array[i] for i in range(3)]
511 assert items == [1, 2, 3]
512
513 # The following are bugs, but are included here because the unittests
514 # also describe the current behaviour.
515 #
516 # This fails with SystemError: bad arg to internal function
517 # or with IndexError (with a patch I have)
518
519 s.array[0] = 42
520
521 items = [s.array[i] for i in range(3)]
522 assert items == [42, 2, 3]
523
524 s.array[0] = 1
525
526 ## s.array[1] = 42
527
528 items = [s.array[i] for i in range(3)]
529 assert items == [1, 2, 3]
530
531 def test_none_to_pointer_fields(self):
532 class S(Structure):
533 _fields_ = [("x", c_int),
534 ("p", POINTER(c_int))]
535
536 s = S()
537 s.x = 12345678
538 s.p = None
539 assert s.x == 12345678
540
541
542 class TestRecursiveStructure(BaseCTypesTestChecker):
543 def test_contains_itself(self):
544 class Recursive(Structure):
545 pass
546
547 try:
548 Recursive._fields_ = [("next", Recursive)]
549 except AttributeError as details:
550 assert ("Structure or union cannot contain itself" in
551 str(details))
552 else:
553 raise AssertionError("Structure or union cannot contain itself")
554
555 def test_vice_versa(self):
556 pytest.skip("mutually dependent lazily defined structures error semantics")
557 class First(Structure):
558 pass
559 class Second(Structure):
560 pass
561
562 First._fields_ = [("second", Second)]
563
564 try:
565 Second._fields_ = [("first", First)]
566 except AttributeError as details:
567 assert ("_fields_ is final" in
568 str(details))
569 else:
570 raise AssertionError("AttributeError not raised")
571
572 def test_nonfinal_struct(self):
573 class X(Structure):
574 pass
575 assert sizeof(X) == 0
576 X._fields_ = [("a", c_int),]
577 with pytest.raises(AttributeError):
578 X._fields_ = []
579
580 class X(Structure):
581 pass
582 X()
583 with pytest.raises(AttributeError):
584 X._fields_ = []
585
586 class X(Structure):
587 pass
588 class Y(X):
589 pass
590 with pytest.raises(AttributeError):
591 X._fields_ = []
592 Y.__fields__ = []
593
594
595 class TestPatologicalCases(BaseCTypesTestChecker):
596 def test_structure_overloading_getattr(self):
597 class X(Structure):
598 _fields_ = [('x', c_int)]
599
600 def __getattr__(self, name):
601 raise AttributeError(name)
602
603 x = X()
604 assert x.x == 0
605
606 def test_duplicate_names(self):
607 class S(Structure):
608 _fields_ = [('a', c_int),
609 ('b', c_int),
610 ('a', c_byte)]
611 s = S(260, -123)
612 assert sizeof(s) == 3 * sizeof(c_int)
613 assert s.a == 4 # 256 + 4
614 assert s.b == -123
+0
-117
pypy/module/test_lib_pypy/ctypes_tests/test_unicode.py less more
0 # coding: latin-1
1 import ctypes
2 import pytest
3 from .support import BaseCTypesTestChecker
4
5 try:
6 ctypes.c_wchar
7 except AttributeError:
8 pass
9 else:
10 def setup_module(mod):
11 import conftest
12 dll = ctypes.CDLL(str(conftest.sofile))
13 mod.wcslen = dll.my_wcslen
14 mod.wcslen.argtypes = [ctypes.c_wchar_p]
15 mod.func = dll._testfunc_p_p
16
17 def teardown_module(mod):
18 del mod.func
19 del mod.wcslen
20
21 class TestUnicode(BaseCTypesTestChecker):
22 def setup_method(self, method):
23 self.prev_conv_mode = ctypes.set_conversion_mode("ascii", "strict")
24
25 def teardown_method(self, method):
26 ctypes.set_conversion_mode(*self.prev_conv_mode)
27
28 def test_ascii_strict(self):
29 ctypes.set_conversion_mode("ascii", "strict")
30 # no conversions take place with unicode arguments
31 assert wcslen(u"abc") == 3
32 assert wcslen(u"ab\u2070") == 3
33 # bytes args are converted
34 assert wcslen(b"abc") == 3
35 pytest.raises(ctypes.ArgumentError, wcslen, "abä")
36
37 def test_ascii_replace(self):
38 ctypes.set_conversion_mode("ascii", "replace")
39 assert wcslen("abc") == 3
40 assert wcslen("ab\u2070") == 3
41 assert wcslen(b"abc") == 3
42 assert wcslen(b"abä") == 3
43
44 def test_ascii_ignore(self):
45 ctypes.set_conversion_mode("ascii", "ignore")
46 assert wcslen("abc") == 3
47 assert wcslen("ab\u2070") == 3
48 # ignore error mode skips non-ascii characters
49 assert wcslen(b"abc") == 3
50 assert wcslen(b"дцья") == 0
51
52 def test_latin1_strict(self):
53 ctypes.set_conversion_mode("latin-1", "strict")
54 assert wcslen("abc") == 3
55 assert wcslen("ab\u2070") == 3
56 assert wcslen(b"abc") == 3
57 assert wcslen(b"дцья") == 4
58
59 def test_buffers(self):
60 ctypes.set_conversion_mode("ascii", "strict")
61 buf = ctypes.create_unicode_buffer(b"abc")
62 assert len(buf) == 3+1
63
64 ctypes.set_conversion_mode("ascii", "replace")
65 buf = ctypes.create_unicode_buffer(b"abהצ�")
66 assert buf[:] == "ab\uFFFD\uFFFD\uFFFD\0"
67
68 ctypes.set_conversion_mode("ascii", "ignore")
69 buf = ctypes.create_unicode_buffer(b"abהצ�")
70 # is that correct? not sure. But with 'ignore', you get what you pay for..
71 assert buf[:] == u"ab\0\0\0\0"
72
73 class TestString(TestUnicode):
74 def setup_method(self, method):
75 self.prev_conv_mode = ctypes.set_conversion_mode("ascii", "strict")
76 func.argtypes = [ctypes.c_char_p]
77 func.restype = ctypes.c_char_p
78
79 def teardown_method(self, method):
80 ctypes.set_conversion_mode(*self.prev_conv_mode)
81 func.argtypes = None
82 func.restype = ctypes.c_int
83
84 def test_ascii_replace(self):
85 ctypes.set_conversion_mode("ascii", "strict")
86 assert func(b"abc") == "abc"
87 assert func(u"abc") == "abc"
88 with pytest.raises(ctypes.ArgumentError):
89 func(u"abä")
90
91 def test_ascii_ignore(self):
92 ctypes.set_conversion_mode("ascii", "ignore")
93 assert func("abc") == "abc"
94 assert func(u"abc") == "abc"
95 assert func(u"дцья") == ""
96
97 def test_ascii_replace_2(self):
98 ctypes.set_conversion_mode("ascii", "replace")
99 assert func("abc") == "abc"
100 assert func(u"abc") == "abc"
101 assert func(u"дцья") == "????"
102
103 def test_buffers(self):
104 ctypes.set_conversion_mode("ascii", "strict")
105 buf = ctypes.create_string_buffer(u"abc")
106 assert len(buf) == 3+1
107
108 ctypes.set_conversion_mode("ascii", "replace")
109 buf = ctypes.create_string_buffer(u"abהצ�")
110 assert buf[:] == "ab???\0"
111
112 ctypes.set_conversion_mode("ascii", "ignore")
113 buf = ctypes.create_string_buffer(u"abהצ�")
114 # is that correct? not sure. But with 'ignore', you get what you pay for..
115 assert buf[:] == "ab\0\0\0\0"
116
+0
-31
pypy/module/test_lib_pypy/ctypes_tests/test_unions.py less more
0 import sys
1 from ctypes import *
2 from .support import BaseCTypesTestChecker
3
4 class TestUnion(BaseCTypesTestChecker):
5 def test_getattr(self):
6 class Stuff(Union):
7 _fields_ = [('x', c_char), ('y', c_int)]
8
9 stuff = Stuff()
10 stuff.y = ord('x') | (ord('z') << 24)
11 if sys.byteorder == 'little':
12 assert stuff.x == 'x'
13 else:
14 assert stuff.x == 'z'
15
16 def test_union_of_structures(self):
17 class Stuff(Structure):
18 _fields_ = [('x', c_int)]
19
20 class Stuff2(Structure):
21 _fields_ = [('x', c_int)]
22
23 class UnionofStuff(Union):
24 _fields_ = [('one', Stuff),
25 ('two', Stuff2)]
26
27 u = UnionofStuff()
28 u.one.x = 3
29 assert u.two.x == 3
30
+0
-94
pypy/module/test_lib_pypy/ctypes_tests/test_values.py less more
0 """
1 A testcase which accesses *values* in a dll.
2 """
3
4 import pytest
5 from ctypes import *
6 from .support import BaseCTypesTestChecker
7
8 def setup_module(mod):
9 import conftest
10 _ctypes_test = str(conftest.sofile)
11 mod.ctdll = CDLL(_ctypes_test)
12
13 class TestValues(BaseCTypesTestChecker):
14
15 def test_an_integer(self):
16 an_integer = c_int.in_dll(ctdll, "an_integer")
17 x = an_integer.value
18 assert x == ctdll.get_an_integer()
19 an_integer.value *= 2
20 assert x*2 == ctdll.get_an_integer()
21
22 def test_a_string(self):
23 a_string = (c_char * 16).in_dll(ctdll, "a_string")
24 assert a_string.raw == "0123456789abcdef"
25 a_string[15] = '$'
26 assert ctdll.get_a_string_char(15) == ord('$')
27
28 def test_undefined(self):
29 with pytest.raises(ValueError):
30 c_int.in_dll(ctdll, "Undefined_Symbol")
31
32 class TestWin_Values(BaseCTypesTestChecker):
33 """This test only works when python itself is a dll/shared library"""
34 def setup_class(cls):
35 pytest.skip("tests expect and access cpython dll")
36
37 def test_optimizeflag(self):
38 # This test accesses the Py_OptimizeFlag intger, which is
39 # exported by the Python dll.
40
41 # It's value is set depending on the -O and -OO flags:
42 # if not given, it is 0 and __debug__ is 1.
43 # If -O is given, the flag is 1, for -OO it is 2.
44 # docstrings are also removed in the latter case.
45 opt = c_int.in_dll(pydll, "Py_OptimizeFlag").value
46 if __debug__:
47 assert opt == 0
48 elif ValuesTestCase.__doc__ is not None:
49 assert opt == 1
50 else:
51 assert opt == 2
52
53 def test_frozentable(self):
54 # Python exports a PyImport_FrozenModules symbol. This is a
55 # pointer to an array of struct _frozen entries. The end of the
56 # array is marked by an entry containing a NULL name and zero
57 # size.
58
59 # In standard Python, this table contains a __hello__
60 # module, and a __phello__ package containing a spam
61 # module.
62 class struct_frozen(Structure):
63 _fields_ = [("name", c_char_p),
64 ("code", POINTER(c_ubyte)),
65 ("size", c_int)]
66 FrozenTable = POINTER(struct_frozen)
67
68 ft = FrozenTable.in_dll(pydll, "PyImport_FrozenModules")
69 # ft is a pointer to the struct_frozen entries:
70 items = []
71 for entry in ft:
72 # This is dangerous. We *can* iterate over a pointer, but
73 # the loop will not terminate (maybe with an access
74 # violation;-) because the pointer instance has no size.
75 if entry.name is None:
76 break
77 items.append((entry.name, entry.size))
78 import sys
79 if sys.version_info[:2] >= (2, 3):
80 expected = [("__hello__", 104), ("__phello__", -104), ("__phello__.spam", 104)]
81 else:
82 expected = [("__hello__", 100), ("__phello__", -100), ("__phello__.spam", 100)]
83 assert items == expected
84
85 from ctypes import _pointer_type_cache
86 del _pointer_type_cache[struct_frozen]
87
88 def test_undefined(self):
89 with pytest.raises(ValueError):
90 c_int.in_dll(pydll, "Undefined_Symbol")
91
92 if __name__ == '__main__':
93 unittest.main()
+0
-57
pypy/module/test_lib_pypy/ctypes_tests/test_varsize_struct.py less more
0 import pytest
1 from .support import BaseCTypesTestChecker
2 from ctypes import *
3
4 class TestVarSize(BaseCTypesTestChecker):
5 def test_resize(self):
6 pytest.skip("resizing not implemented")
7 class X(Structure):
8 _fields_ = [("item", c_int),
9 ("array", c_int * 1)]
10
11 assert sizeof(X) == sizeof(c_int) * 2
12 x = X()
13 x.item = 42
14 x.array[0] = 100
15 assert sizeof(x) == sizeof(c_int) * 2
16
17 # make room for one additional item
18 new_size = sizeof(X) + sizeof(c_int) * 1
19 resize(x, new_size)
20 assert sizeof(x) == new_size
21 assert (x.item, x.array[0]) == (42, 100)
22
23 # make room for 10 additional items
24 new_size = sizeof(X) + sizeof(c_int) * 9
25 resize(x, new_size)
26 assert sizeof(x) == new_size
27 assert (x.item, x.array[0]) == (42, 100)
28
29 # make room for one additional item
30 new_size = sizeof(X) + sizeof(c_int) * 1
31 resize(x, new_size)
32 assert sizeof(x) == new_size
33 assert (x.item, x.array[0]) == (42, 100)
34
35 def test_array_invalid_length(self):
36 # cannot create arrays with non-positive size
37 with pytest.raises(ValueError):
38 c_int * -1
39 with pytest.raises(ValueError):
40 c_int * -3
41
42 def test_zerosized_array(self):
43 array = (c_int * 0)()
44 # accessing elements of zero-sized arrays raise IndexError
45 with pytest.raises(IndexError):
46 array.__setitem__(0, None)
47 with pytest.raises(IndexError):
48 array.__getitem__(0)
49 with pytest.raises(IndexError):
50 array.__setitem__(1, None)
51 with pytest.raises(IndexError):
52 array.__getitem__(1)
53 with pytest.raises(IndexError):
54 array.__setitem__(-1, None)
55 with pytest.raises(IndexError):
56 array.__getitem__(-1)
+0
-84
pypy/module/test_lib_pypy/ctypes_tests/test_win32.py less more
0 # Windows specific tests
1
2 from ctypes import *
3 from ctypes.test import is_resource_enabled
4 from .support import BaseCTypesTestChecker
5
6 import pytest
7 import sys
8
9 if sys.platform != "win32":
10 pytest.importorskip('skip_the_whole_module') # hack!
11
12 class TestWindows(BaseCTypesTestChecker):
13 def test_callconv_1(self):
14 # Testing stdcall function
15
16 IsWindow = windll.user32.IsWindow
17 # ValueError: Procedure probably called with not enough arguments (4 bytes missing)
18 with pytest.raises(ValueError):
19 IsWindow()
20
21 # This one should succeeed...
22 assert IsWindow(0) == 0
23
24 # ValueError: Procedure probably called with too many arguments (8 bytes in excess)
25 with pytest.raises(ValueError):
26 IsWindow(0, 0, 0)
27
28 def test_callconv_2(self):
29 # Calling stdcall function as cdecl
30
31 IsWindow = cdll.user32.IsWindow
32
33 # ValueError: Procedure called with not enough arguments (4 bytes missing)
34 # or wrong calling convention
35 with pytest.raises(ValueError):
36 IsWindow(None)
37
38 if is_resource_enabled("SEH"):
39 def test_SEH(self):
40 # Call functions with invalid arguments, and make sure that access violations
41 # are trapped and raise an exception.
42 with pytest.raises(WindowsError):
43 windll.kernel32.GetModuleHandleA(32)
44
45 class TestWintypes(BaseCTypesTestChecker):
46
47 def test_COMError(self):
48 import _ctypes
49 from _ctypes import COMError
50 assert COMError.__doc__ == "Raised when a COM method call failed."
51
52 ex = COMError(-1, "text", ("details",))
53 assert ex.hresult == -1
54 assert ex.text == "text"
55 assert ex.details == ("details",)
56 assert (ex.hresult, ex.text, ex.details) == ex[:]
57
58 def test_VARIANT(self):
59 from ctypes import wintypes
60 a = wintypes.VARIANT_BOOL()
61 assert a.value is False
62 b = wintypes.VARIANT_BOOL(3)
63 assert b.value is True
64
65 class TestStructures(BaseCTypesTestChecker):
66
67 def test_struct_by_value(self):
68 class POINT(Structure):
69 _fields_ = [("x", c_long),
70 ("y", c_long)]
71
72 class RECT(Structure):
73 _fields_ = [("left", c_long),
74 ("top", c_long),
75 ("right", c_long),
76 ("bottom", c_long)]
77
78 import conftest
79 dll = CDLL(str(conftest.sofile))
80
81 pt = POINT(10, 10)
82 rect = RECT(0, 0, 20, 20)
83 assert dll.PointInRect(byref(rect), pt) == 1
+0
-80
pypy/module/test_lib_pypy/test_dbm_extra.py less more
0 import py, os
1 from rpython.tool.udir import udir
2 try:
3 from lib_pypy import dbm
4 except ImportError as e:
5 py.test.skip(e)
6
7 import sys
8 if '__pypy__' not in sys.builtin_module_names:
9 skip("lib_pypy.dbm requires PyPy's ctypes")
10
11 def test_get():
12 path = str(udir.join('test_dbm_extra.test_get'))
13 d = dbm.open(path, 'c')
14 x = d.get("42")
15 assert x is None
16 d.close()
17
18 def test_delitem():
19 path = str(udir.join('test_dbm_extra.test_delitem'))
20 d = dbm.open(path, 'c')
21 py.test.raises(KeyError, "del d['xyz']")
22
23 def test_nonstring():
24 path = str(udir.join('test_dbm_extra.test_nonstring'))
25 d = dbm.open(path, 'c')
26 py.test.raises(TypeError, "d[123] = 'xyz'")
27 py.test.raises(TypeError, "d['xyz'] = 123")
28 py.test.raises(TypeError, "d['xyz'] = None")
29 py.test.raises(TypeError, "del d[123]")
30 py.test.raises(TypeError, "d[123]")
31 py.test.raises(TypeError, "123 in d")
32 py.test.raises(TypeError, "d.has_key(123)")
33 py.test.raises(TypeError, "d.setdefault(123, 'xyz')")
34 py.test.raises(TypeError, "d.setdefault('xyz', 123)")
35 py.test.raises(TypeError, "d.get(123)")
36 assert dict(d) == {}
37 d.setdefault('xyz', '123')
38 assert dict(d) == {'xyz': '123'}
39 d.close()
40
41 def test_multiple_sets():
42 path = str(udir.join('test_dbm_extra.test_multiple_sets'))
43 d = dbm.open(path, 'c')
44 d['xyz'] = '12'
45 d['xyz'] = '3'
46 d['xyz'] = '546'
47 assert dict(d) == {'xyz': '546'}
48 assert d['xyz'] == '546'
49
50 def test_extra():
51 py.test.raises(TypeError, dbm.datum, 123)
52 py.test.raises(TypeError, dbm.datum, False)
53
54 def test_null():
55 db = dbm.open('test', 'c')
56 db['1'] = 'a\x00b'
57 db.close()
58
59 db = dbm.open('test', 'r')
60 assert db['1'] == 'a\x00b'
61 db.close()
62
63 def test_key_with_empty_value():
64 # this test fails on CPython too (at least on tannit), and the
65 # case shows up when gdbm is not installed and test_anydbm.py
66 # falls back dbm.
67 py.test.skip("test may fail on CPython too")
68 path = str(udir.join('test_dbm_extra.test_key_with_empty_value'))
69 d = dbm.open(path, 'c')
70 assert 'key_with_empty_value' not in d
71 d['key_with_empty_value'] = ''
72 assert 'key_with_empty_value' in d
73 assert d['key_with_empty_value'] == ''
74 d.close()
75
76 def test_unicode_filename():
77 path = str(udir) + os.sep + u'test_dbm_extra.test_unicode_filename'
78 d = dbm.open(path, 'c')
79 d.close()
+0
-16
pypy/module/test_lib_pypy/test_exception_extra.py less more
0 def app_test_environmenterror_repr():
1 e = EnvironmentError("hello")
2 assert str(e) == "hello"
3 e = EnvironmentError(1, "hello")
4 assert str(e) == "[Errno 1] hello"
5 e = EnvironmentError(1, "hello", "world")
6 assert str(e) == "[Errno 1] hello: 'world'"
7
8 def app_test_baseexception():
9 assert issubclass(Exception, BaseException)
10
11 def app_test_systemexit():
12 assert issubclass(SystemExit, BaseException)
13
14 def app_test_keyboardinterrupt():
15 assert issubclass(KeyboardInterrupt, BaseException)
+0
-48
pypy/module/test_lib_pypy/test_functools.py less more
0 import pytest
1
2 from lib_pypy import _functools
3
4
5 def test_partial_reduce():
6 partial = _functools.partial(test_partial_reduce)
7 state = partial.__reduce__()
8 d = state[2][2]
9 assert state == (type(partial), (test_partial_reduce,),
10 (test_partial_reduce, (), d, None))
11 assert d is None or d == {} # both are acceptable
12
13 def test_partial_setstate():
14 partial = _functools.partial(object)
15 partial.__setstate__((test_partial_setstate, (), None, None))
16 assert partial.func == test_partial_setstate
17
18 def test_partial_pickle():
19 pytest.skip("can't run this test: _functools.partial now has "
20 "__module__=='functools', in this case confusing pickle")
21 import pickle
22 partial1 = _functools.partial(test_partial_pickle)
23 string = pickle.dumps(partial1)
24 partial2 = pickle.loads(string)
25 assert partial1.func == partial2.func
26
27 def test_immutable_attributes():
28 partial = _functools.partial(object)
29 with pytest.raises((TypeError, AttributeError)):
30 partial.func = sum
31 with pytest.raises(TypeError) as exc:
32 del partial.__dict__
33 assert str(exc.value) == "a partial object's dictionary may not be deleted"
34 with pytest.raises(AttributeError):
35 del partial.zzz
36
37 def test_self_keyword():
38 partial = _functools.partial(dict, self=42)
39 assert partial(other=43) == {'self': 42, 'other': 43}
40
41 def test_no_keywords():
42 kw1 = _functools.partial(dict).keywords
43 kw2 = _functools.partial(dict, **{}).keywords
44 # CPython gives different results for these two cases, which is not
45 # possible to emulate in pure Python; see issue #2043
46 assert kw1 == {} or kw1 is None
47 assert kw2 == {}
+0
-21
pypy/module/test_lib_pypy/test_gdbm_extra.py less more
0 from __future__ import absolute_import
1 import py
2 from rpython.tool.udir import udir
3 try:
4 from lib_pypy import gdbm
5 except ImportError as e:
6 py.test.skip(e)
7
8 def test_len():
9 path = str(udir.join('test_gdbm_extra'))
10 g = gdbm.open(path, 'c')
11 g['abc'] = 'def'
12 assert len(g) == 1
13 g['bcd'] = 'efg'
14 assert len(g) == 2
15 del g['abc']
16 assert len(g) == 1
17
18 def test_unicode():
19 path = unicode(udir.join('test_gdm_unicode'))
20 g = gdbm.open(path, 'c') # does not crash
+0
-41
pypy/module/test_lib_pypy/test_grp_extra.py less more
0 from pypy.module.test_lib_pypy.support import import_lib_pypy
1
2
3 class AppTestGrp:
4 spaceconfig = dict(usemodules=('_rawffi', 'binascii', 'fcntl', 'itertools',
5 'select', 'signal'))
6
7 def setup_class(cls):
8 cls.w_grp = import_lib_pypy(cls.space, 'grp',
9 "No grp module on this platform")
10
11 def test_basic(self):
12 e = raises(KeyError, self.grp.getgrnam, "dEkLofcG")
13 assert e.value.args[0] == "'getgrnam(): name not found: dEkLofcG'"
14 for name in ["root", "wheel"]:
15 try:
16 g = self.grp.getgrnam(name)
17 except KeyError:
18 continue
19 assert g.gr_gid == 0
20 assert 'root' in g.gr_mem or g.gr_mem == []
21 assert g.gr_name == name
22 assert isinstance(g.gr_passwd, str) # usually just 'x', don't hope :-)
23 break
24 else:
25 raise
26
27 def test_extra(self):
28 grp = self.grp
29 print(grp.__file__)
30 raises(TypeError, grp.getgrnam, False)
31 raises(TypeError, grp.getgrnam, None)
32
33 def test_struct_group(self):
34 g = self.grp.struct_group((10, 20, 30, 40))
35 assert len(g) == 4
36 assert list(g) == [10, 20, 30, 40]
37 assert g.gr_name == 10
38 assert g.gr_passwd == 20
39 assert g.gr_gid == 30
40 assert g.gr_mem == 40
+0
-22
pypy/module/test_lib_pypy/test_itertools.py less more
0 class AppTestItertools:
1 spaceconfig = dict(usemodules=['itertools'])
2
3 def setup_class(cls):
4 cls.w_itertools = cls.space.appexec([], "(): import itertools; return itertools")
5
6 def test_chain(self):
7 it = self.itertools.chain([], [1, 2, 3])
8 lst = list(it)
9 assert lst == [1, 2, 3]
10
11 def test_islice(self):
12 import sys
13 itertools = self.itertools
14
15 slic = itertools.islice(itertools.count(), 1, 10, sys.maxsize)
16 assert len(list(slic)) == 1
17
18 if '__pypy__' not in sys.builtin_module_names:
19 skip("this takes ages on top of CPython's itertools module")
20 slic = itertools.islice(itertools.count(), 1, 10, sys.maxsize-20)
21 assert len(list(slic)) == 1
0 import py
0 import pytest
11 import sys
22 import marshal as cpy_marshal
33 from lib_pypy import _marshal as marshal
4
5 from rpython.tool.udir import udir
64
75 hello = "he"
86 hello += "llo"
108 return lambda y: x+y
119 scopefunc = func(42)
1210
13 TESTCASES = [
14 None,
15 False,
16 True,
17 StopIteration,
18 Ellipsis,
11 SUBCLASSABLE = [
1912 42,
2013 sys.maxsize,
2114 -1.25,
3023 [3, 4],
3124 {},
3225 {5: 6, 7: 8},
26 u'hello',
27 set(),
28 set([1, 2]),
29 frozenset(),
30 frozenset([3, 4]),
31 ]
32
33 TESTCASES = SUBCLASSABLE + [
34 None,
35 False,
36 True,
37 StopIteration,
38 Ellipsis,
3339 func.__code__,
3440 scopefunc.__code__,
35 'hello',
36 ]
37
38 try:
39 TESTCASES += [
40 set(),
41 set([1, 2]),
42 frozenset(),
43 frozenset([3, 4]),
44 ]
45 except NameError:
46 pass # Python < 2.4
47
48 if getattr(cpy_marshal, 'version', 0) > 1:
49 cpy_dump_version = (1,)
50 else:
51 cpy_dump_version = ()
41 ]
5242
5343
54 def test_cases():
55 for case in TESTCASES:
56 yield dumps_and_reload, case
57 yield loads_from_cpython, case
58 yield dumps_to_cpython, case
59 if case is not StopIteration:
60 yield dumps_subclass, case
61 yield load_from_cpython, case
62 yield dump_to_cpython, case
63
64 def dumps_and_reload(case):
65 print('dump_and_reload', repr(case))
44 @pytest.mark.parametrize('case', TESTCASES)
45 def test_dumps_and_reload(case):
6646 s = marshal.dumps(case)
6747 obj = marshal.loads(s)
6848 assert obj == case
6949
70 def loads_from_cpython(case):
71 print('load_from_cpython', repr(case))
72 try:
73 s = cpy_marshal.dumps(case, *cpy_dump_version)
74 except ValueError:
75 py.test.skip("this version of CPython doesn't support this object")
50 @pytest.mark.parametrize('case', TESTCASES)
51 def test_loads_from_cpython(case):
52 s = cpy_marshal.dumps(case, 1) # XXX: fails with version 2
7653 obj = marshal.loads(s)
7754 assert obj == case
7855
79 def dumps_to_cpython(case):
80 print('dump_to_cpython', repr(case))
81 try:
82 cpy_marshal.dumps(case, *cpy_dump_version)
83 except ValueError:
84 py.test.skip("this version of CPython doesn't support this object")
56 @pytest.mark.parametrize('case', TESTCASES)
57 def test_dumps_to_cpython(case):
8558 s = marshal.dumps(case)
8659 obj = cpy_marshal.loads(s)
8760 assert obj == case
8861
89 def dumps_subclass(case):
90 try:
91 class Subclass(type(case)):
92 pass
93 case = Subclass(case)
94 except TypeError:
95 py.test.skip("this version of CPython doesn't support this object")
62 @pytest.mark.parametrize('case', SUBCLASSABLE)
63 def test_dumps_subclass(case):
64 class Subclass(type(case)):
65 pass
66 case = Subclass(case)
9667 s = marshal.dumps(case)
9768 obj = marshal.loads(s)
9869 assert obj == case
9970
100 def load_from_cpython(case):
101 p = str(udir.join('test.dat'))
71 @pytest.mark.parametrize('case', TESTCASES)
72 def test_load_from_cpython(tmpdir, case):
73 p = str(tmpdir.join('test.dat'))
10274
103 f1 = open(p, "w")
104 try:
105 try:
106 s = cpy_marshal.dump(case, f1, *cpy_dump_version)
107 finally:
108 f1.close()
109 except ValueError:
110 py.test.skip("this version of CPython doesn't support this object")
111
112 f2 = open(p, "r")
113 try:
75 with open(p, "w") as f1:
76 s = cpy_marshal.dump(case, f1, 1) # XXX: fails with version 2
77 with open(p, "r") as f2:
11478 obj = marshal.load(f2)
115 finally:
116 f2.close()
11779 assert obj == case
11880
119 def dump_to_cpython(case):
120
121 try:
122 cpy_marshal.dumps(case, *cpy_dump_version)
123 except ValueError:
124 py.test.skip("this version of CPython doesn't support this object")
125
126 p = str(udir.join('test.dat'))
127 f1 = open(p, "w")
128 try:
129 try:
130 s = marshal.dump(case, f1)
131 finally:
132 f1.close()
133 except ValueError:
134 py.test.skip("this version of CPython doesn't support this object")
135
136 f2 = open(p, "r")
137 try:
81 @pytest.mark.parametrize('case', TESTCASES)
82 def test_dump_to_cpython(tmpdir, case):
83 p = str(tmpdir.join('test.dat'))
84 with open(p, "w") as f1:
85 s = marshal.dump(case, f1)
86 with open(p, "r") as f2:
13887 obj = cpy_marshal.load(f2)
139 finally:
140 f2.close()
14188 assert obj == case
14289
14390 def test_load_truncated_string():
14491 s = '(\x02\x00\x00\x00i\x03\x00\x00\x00sB\xf9\x00\x00\nabcd'
145 py.test.raises(EOFError, marshal.loads, s)
92 with pytest.raises(EOFError):
93 marshal.loads(s)
14694
14795 def test_dump_unicode_length():
14896 s = b'123\xe9'.decode('latin-1')
+0
-331
pypy/module/test_lib_pypy/test_sqlite3.py less more
0 # -*- coding: utf-8 -*-
1 """Tests for _sqlite3.py"""
2
3 from __future__ import absolute_import
4 import pytest
5 import sys
6
7
8 def pytest_funcarg__con(request):
9 con = _sqlite3.connect(':memory:')
10 request.addfinalizer(lambda: con.close())
11 return con
12
13
14 class BaseTestSQLite:
15 def test_list_ddl(self, con):
16 """From issue996. Mostly just looking for lack of exceptions."""
17 cursor = con.cursor()
18 cursor.execute('CREATE TABLE foo (bar INTEGER)')
19 result = list(cursor)
20 assert result == []
21 cursor.execute('INSERT INTO foo (bar) VALUES (42)')
22 result = list(cursor)
23 assert result == []
24 cursor.execute('SELECT * FROM foo')
25 result = list(cursor)
26 assert result == [(42,)]
27
28 def test_connect_takes_same_positional_args_as_Connection(self, con):
29 if not hasattr(_sqlite3, '_ffi'):
30 pytest.skip("only works for lib_pypy _sqlite3")
31 from inspect import getargspec
32 clsargs = getargspec(_sqlite3.Connection.__init__).args[1:] # ignore self
33 conargs = getargspec(_sqlite3.connect).args
34 assert clsargs == conargs
35
36 def test_total_changes_after_close(self, con):
37 con.close()
38 pytest.raises(_sqlite3.ProgrammingError, "con.total_changes")
39
40 def test_connection_check_init(self):
41 class Connection(_sqlite3.Connection):
42 def __init__(self, name):
43 pass
44
45 con = Connection(":memory:")
46 e = pytest.raises(_sqlite3.ProgrammingError, "con.cursor()")
47 assert '__init__' in str(e.value)
48
49 def test_cursor_check_init(self, con):
50 class Cursor(_sqlite3.Cursor):
51 def __init__(self, name):
52 pass
53
54 cur = Cursor(con)
55 e = pytest.raises(_sqlite3.ProgrammingError, "cur.execute('select 1')")
56 assert '__init__' in str(e.value)
57
58 def test_connection_after_close(self, con):
59 pytest.raises(TypeError, "con()")
60 con.close()
61 # raises ProgrammingError because should check closed before check args
62 pytest.raises(_sqlite3.ProgrammingError, "con()")
63
64 def test_cursor_iter(self, con):
65 cur = con.cursor()
66 with pytest.raises(StopIteration):
67 next(cur)
68
69 cur.execute('select 1')
70 next(cur)
71 with pytest.raises(StopIteration):
72 next(cur)
73
74 cur.execute('select 1')
75 con.commit()
76 next(cur)
77 with pytest.raises(StopIteration):
78 next(cur)
79
80 with pytest.raises(_sqlite3.ProgrammingError):
81 cur.executemany('select 1', [])
82 with pytest.raises(StopIteration):
83 next(cur)
84
85 cur.execute('select 1')
86 cur.execute('create table test(ing)')
87 with pytest.raises(StopIteration):
88 next(cur)
89
90 cur.execute('select 1')
91 cur.execute('insert into test values(1)')
92 con.commit()
93 with pytest.raises(StopIteration):
94 next(cur)
95
96 def test_cursor_after_close(self, con):
97 cur = con.execute('select 1')
98 cur.close()
99 con.close()
100 pytest.raises(_sqlite3.ProgrammingError, "cur.close()")
101 # raises ProgrammingError because should check closed before check args
102 pytest.raises(_sqlite3.ProgrammingError, "cur.execute(1,2,3,4,5)")
103 pytest.raises(_sqlite3.ProgrammingError, "cur.executemany(1,2,3,4,5)")
104
105 @pytest.mark.skipif("not hasattr(sys, 'pypy_translation_info')")
106 def test_connection_del(self, tmpdir):
107 """For issue1325."""
108 import os
109 import gc
110 try:
111 import resource
112 except ImportError:
113 pytest.skip("needs resource module")
114
115 limit = resource.getrlimit(resource.RLIMIT_NOFILE)
116 try:
117 fds = 0
118 while True:
119 fds += 1
120 resource.setrlimit(resource.RLIMIT_NOFILE, (fds, limit[1]))
121 try:
122 for p in os.pipe(): os.close(p)
123 except OSError:
124 assert fds < 100
125 else:
126 break
127
128 def open_many(cleanup):
129 con = []
130 for i in range(3):
131 con.append(_sqlite3.connect(str(tmpdir.join('test.db'))))
132 if cleanup:
133 con[i] = None
134 gc.collect(); gc.collect()
135
136 pytest.raises(_sqlite3.OperationalError, open_many, False)
137 gc.collect(); gc.collect()
138 open_many(True)
139 finally:
140 resource.setrlimit(resource.RLIMIT_NOFILE, limit)
141
142 def test_on_conflict_rollback_executemany(self, con):
143 major, minor, micro = _sqlite3.sqlite_version.split('.')[:3]
144 if (int(major), int(minor), int(micro)) < (3, 2, 2):
145 pytest.skip("requires sqlite3 version >= 3.2.2")
146 con.execute("create table foo(x, unique(x) on conflict rollback)")
147 con.execute("insert into foo(x) values (1)")
148 try:
149 con.executemany("insert into foo(x) values (?)", [[1]])
150 except _sqlite3.DatabaseError:
151 pass
152 con.execute("insert into foo(x) values (2)")
153 try:
154 con.commit()
155 except _sqlite3.OperationalError:
156 pytest.fail("_sqlite3 knew nothing about the implicit ROLLBACK")
157
158 def test_statement_arg_checking(self, con):
159 with pytest.raises(_sqlite3.Warning) as e:
160 con(123)
161 assert str(e.value) == 'SQL is of wrong type. Must be string or unicode.'
162 with pytest.raises(ValueError) as e:
163 con.execute(123)
164 assert str(e.value) == 'operation parameter must be str or unicode'
165 with pytest.raises(ValueError) as e:
166 con.executemany(123, 123)
167 assert str(e.value) == 'operation parameter must be str or unicode'
168 with pytest.raises(ValueError) as e:
169 con.executescript(123)
170 assert str(e.value) == 'script argument must be unicode or string.'
171
172 def test_statement_param_checking(self, con):
173 con.execute('create table foo(x)')
174 con.execute('insert into foo(x) values (?)', [2])
175 con.execute('insert into foo(x) values (?)', (2,))
176 class seq(object):
177 def __len__(self):
178 return 1
179 def __getitem__(self, key):
180 return 2
181 con.execute('insert into foo(x) values (?)', seq())
182 del seq.__len__
183 with pytest.raises(_sqlite3.ProgrammingError):
184 con.execute('insert into foo(x) values (?)', seq())
185 with pytest.raises(_sqlite3.ProgrammingError):
186 con.execute('insert into foo(x) values (?)', {2:2})
187 with pytest.raises(ValueError) as e:
188 con.execute('insert into foo(x) values (?)', 2)
189 assert str(e.value) == 'parameters are of unsupported type'
190
191 def test_explicit_begin(self, con):
192 con.execute('BEGIN')
193 con.execute('BEGIN ')
194 con.execute('BEGIN')
195 con.commit()
196 con.execute('BEGIN')
197 con.commit()
198
199 def test_row_factory_use(self, con):
200 con.row_factory = 42
201 con.execute('select 1')
202
203 def test_returning_blob_must_own_memory(self, con):
204 import gc
205 con.create_function("returnblob", 0, lambda: buffer("blob"))
206 cur = con.execute("select returnblob()")
207 val = cur.fetchone()[0]
208 for i in range(5):
209 gc.collect()
210 got = (val[0], val[1], val[2], val[3])
211 assert got == ('b', 'l', 'o', 'b')
212 # in theory 'val' should be a read-write buffer
213 # but it's not right now
214 if not hasattr(_sqlite3, '_ffi'):
215 val[1] = 'X'
216 got = (val[0], val[1], val[2], val[3])
217 assert got == ('b', 'X', 'o', 'b')
218
219 def test_description_after_fetchall(self, con):
220 cur = con.cursor()
221 assert cur.description is None
222 cur.execute("select 42").fetchall()
223 assert cur.description is not None
224
225 def test_executemany_lastrowid(self, con):
226 cur = con.cursor()
227 cur.execute("create table test(a)")
228 cur.executemany("insert into test values (?)", [[1], [2], [3]])
229 assert cur.lastrowid is None
230 # issue 2682
231 cur.execute('''insert
232 into test
233 values (?)
234 ''', (1, ))
235 assert cur.lastrowid is not None
236 cur.execute('''insert\t into test values (?) ''', (1, ))
237 assert cur.lastrowid is not None
238
239 def test_authorizer_bad_value(self, con):
240 def authorizer_cb(action, arg1, arg2, dbname, source):
241 return 42
242 con.set_authorizer(authorizer_cb)
243 with pytest.raises(_sqlite3.OperationalError) as e:
244 con.execute('select 123')
245 major, minor, micro = _sqlite3.sqlite_version.split('.')[:3]
246 if (int(major), int(minor), int(micro)) >= (3, 6, 14):
247 assert str(e.value) == 'authorizer malfunction'
248 else:
249 assert str(e.value) == \
250 ("illegal return value (1) from the authorization function - "
251 "should be SQLITE_OK, SQLITE_IGNORE, or SQLITE_DENY")
252
253 def test_issue1573(self, con):
254 cur = con.cursor()
255 cur.execute(u'SELECT 1 as méil')
256 assert cur.description[0][0] == u"méil".encode('utf-8')
257
258 def test_adapter_exception(self, con):
259 def cast(obj):
260 raise ZeroDivisionError
261
262 _sqlite3.register_adapter(int, cast)
263 try:
264 cur = con.cursor()
265 cur.execute("select ?", (4,))
266 val = cur.fetchone()[0]
267 # Adapter error is ignored, and parameter is passed as is.
268 assert val == 4
269 assert type(val) is int
270 finally:
271 del _sqlite3.adapters[(int, _sqlite3.PrepareProtocol)]
272
273 def test_null_character(self, con):
274 if not hasattr(_sqlite3, '_ffi') and sys.version_info < (2, 7, 9):
275 pytest.skip("_sqlite3 too old")
276 exc = raises(ValueError, con, "\0select 1")
277 assert str(exc.value) == "the query contains a null character"
278 exc = raises(ValueError, con, "select 1\0")
279 assert str(exc.value) == "the query contains a null character"
280 cur = con.cursor()
281 exc = raises(ValueError, cur.execute, "\0select 2")
282 assert str(exc.value) == "the query contains a null character"
283 exc = raises(ValueError, cur.execute, "select 2\0")
284 assert str(exc.value) == "the query contains a null character"
285
286 def test_close_in_del_ordering(self):
287 import gc
288 class SQLiteBackend(object):
289 success = False
290 def __init__(self):
291 self.connection = _sqlite3.connect(":memory:")
292 def close(self):
293 self.connection.close()
294 def __del__(self):
295 self.close()
296 SQLiteBackend.success = True
297 def create_db_if_needed(self):
298 conn = self.connection
299 cursor = conn.cursor()
300 cursor.execute("""
301 create table if not exists nameoftable(value text)
302 """)
303 cursor.close()
304 conn.commit()
305 SQLiteBackend().create_db_if_needed()
306 gc.collect()
307 gc.collect()
308 assert SQLiteBackend.success
309
310
311 class TestSQLiteHost(BaseTestSQLite):
312 def setup_class(cls):
313 global _sqlite3
314 import _sqlite3
315
316
317 class TestSQLitePyPy(BaseTestSQLite):
318 def setup_class(cls):
319 if sys.version_info < (2, 7):
320 pytest.skip("_sqlite3 requires Python 2.7")
321
322 try:
323 from lib_pypy import _sqlite3_cffi
324 except ImportError:
325 # On CPython, "pip install cffi". On old PyPy's, no chance
326 pytest.skip("install cffi and run lib_pypy/_sqlite3_build.py "
327 "manually first")
328
329 global _sqlite3
330 from lib_pypy import _sqlite3
+0
-14
pypy/module/test_lib_pypy/test_syslog.py less more
0 import sys, py
1 try:
2 from lib_pypy import syslog
3 except ImportError:
4 py.test.skip('no syslog on this platform')
5 except AssertionError:
6 if '__pypy__' in sys.builtin_module_names:
7 raise
8 py.test.skip('AssertionError during import (wrong cffi version?)')
9
10 # XXX very minimal test
11
12 def test_syslog():
13 assert hasattr(syslog, 'LOG_ALERT')
4848 # Run signal handlers if we were interrupted
4949 space.getexecutioncontext().checksignals()
5050 if microseconds >= 0:
51 microseconds = r_longlong(endtime - (time.time() * 1e6))
51 microseconds = r_longlong((endtime - (time.time() * 1e6))
52 + 0.999)
5253 # Check for negative values, since those mean block
5354 # forever
5455 if microseconds <= 0:
246247 "cannot release un-acquired lock")
247248 self.rlock_count -= 1
248249 if self.rlock_count == 0:
249 self.rlock_owner == 0
250 self.rlock_owner = 0
250251 self.lock.release()
251252
252253 def is_owned_w(self, space):
305305 finally:
306306 signal.signal(signal.SIGALRM, oldalrm)
307307
308
309 class AppTestLockRepr(GenericTestThread):
310
308311 def test_lock_repr(self):
309312 import _thread
310313 lock = _thread.allocate_lock()
4343 return OperationError(w_error, space.newtext(msg))
4444
4545
46 @unwrap_spec(string='bufferstr', level=int)
47 def compress(space, string, level=rzlib.Z_DEFAULT_COMPRESSION):
48 """
49 compress(string[, level]) -- Returned compressed string.
46 @unwrap_spec(data='bufferstr', level=int)
47 def compress(space, data, level=rzlib.Z_DEFAULT_COMPRESSION):
48 """
49 compress(data[, level]) -- Returned compressed string.
5050
5151 Optional arg level is the compression level, in 1-9.
5252 """
5656 except ValueError:
5757 raise zlib_error(space, "Bad compression level")
5858 try:
59 result = rzlib.compress(stream, string, rzlib.Z_FINISH)
59 result = rzlib.compress(stream, data, rzlib.Z_FINISH)
6060 finally:
6161 rzlib.deflateEnd(stream)
6262 except rzlib.RZlibError as e:
306306 w_descr = space.lookup(w_obj, '__getitem__')
307307 if w_descr is None:
308308 raise oefmt(space.w_TypeError,
309 "'%T' object is not subscriptable", w_obj)
309 "'%T' object is not subscriptable (key %R)",
310 w_obj, w_key)
310311 return space.get_and_call_function(w_descr, w_obj, w_key)
311312
312313 def setitem(space, w_obj, w_key, w_val):
366366
367367 def warn(self, w_msg, w_warningcls, stacklevel=2):
368368 pass
369
370 def _try_buffer_w(self, w_obj, flags):
371 return w_obj.buffer_w(self, flags)
369372
370373 # ----------
371374
131131 return format_float(x, 'g', DTSF_STR_PRECISION)
132132
133133
134 def unpackcomplex(space, w_complex):
134 def unpackcomplex(space, w_complex, strict_typing=True, firstarg=True):
135135 """
136 Convert w_complex into a complex and return the unwrapped (real, imag)
137 tuple. Also, typecheck the value returned by __complex__ to actually be a
138 complex (and not e.g. a float).
136 convert w_complex into a complex and return the unwrapped (real, imag)
137 tuple. If strict_typing==True, we also typecheck the value returned by
138 __complex__ to actually be a complex (and not e.g. a float).
139 See test___complex___returning_non_complex.
139140 """
140141 if type(w_complex) is W_ComplexObject:
141142 return (w_complex.realval, w_complex.imagval)
168169 raise oefmt(space.w_TypeError,
169170 "complex number expected, got '%T'", w_complex)
170171 #
171 return (space.float_w(space.float(w_complex)), 0.0)
172 try:
173 return (space.float_w(space.float(w_complex)), 0.0)
174 except OperationError as e:
175 if not e.match(space, space.w_TypeError):
176 raise
177 if firstarg:
178 raise oefmt(space.w_TypeError,
179 "complex() first argument must be a string or a number, not '%T'",
180 w_complex)
181 else:
182 raise oefmt(space.w_TypeError,
183 "complex() second argument must be a number, not '%T'",
184 w_complex)
185
172186
173187
174188 class W_ComplexObject(W_Root):
302316 # now take w_imag into account
303317 if not noarg2:
304318 # complex(x, y) == x+y*j, even if 'y' is already a complex.
305 realval2, imagval2 = unpackcomplex(space, w_imag)
319 realval2, imagval2 = unpackcomplex(space, w_imag,
320 firstarg=False)
306321
307322 # try to preserve the signs of zeroes of realval and realval2
308323 if imagval2 != 0.0:
444459 try:
445460 return self.div(w_rhs)
446461 except ZeroDivisionError as e:
447 raise OperationError(space.w_ZeroDivisionError, space.newtext(str(e)))
462 raise oefmt(space.w_ZeroDivisionError, "complex division by zero")
448463
449464 def descr_rtruediv(self, space, w_lhs):
450465 w_lhs = self._to_complex(space, w_lhs)
453468 try:
454469 return w_lhs.div(self)
455470 except ZeroDivisionError as e:
456 raise OperationError(space.w_ZeroDivisionError, space.newtext(str(e)))
471 raise oefmt(space.w_ZeroDivisionError, "complex division by zero")
457472
458473 def descr_floordiv(self, space, w_rhs):
459474 raise oefmt(space.w_TypeError, "can't take floor of complex number.")
1010 WrappedDefault, applevel, interp2app, unwrap_spec)
1111 from pypy.interpreter.mixedmodule import MixedModule
1212 from pypy.interpreter.signature import Signature
13 from pypy.interpreter.typedef import TypeDef
13 from pypy.interpreter.typedef import TypeDef, interp_attrproperty_w
1414 from pypy.interpreter.unicodehelper import decode_utf8
1515 from pypy.objspace.std.util import negate
1616
225225 """Not exposed directly to app-level, but via __pypy__.reversed_dict().
226226 """
227227 strategy = self.get_strategy()
228 if strategy.has_iterreversed:
229 it = strategy.iterreversed(self)
230 return W_DictMultiIterKeysObject(space, it)
231 else:
232 # fall-back
233 w_keys = self.w_keys()
234 return space.call_method(w_keys, '__reversed__')
228 return strategy.iterreversed(self)
235229
236230 def nondescr_delitem_if_value_is(self, space, w_key, w_value):
237231 """Not exposed directly to app-level, but used by
245239 """Not exposed directly to app-level, but via __pypy__.move_to_end().
246240 """
247241 strategy = self.get_strategy()
248 if strategy.has_move_to_end:
249 strategy.move_to_end(self, w_key, last_flag)
250 else:
251 # fall-back
252 w_value = self.getitem(w_key)
253 if w_value is None:
254 space.raise_key_error(w_key)
255 else:
256 self.internal_delitem(w_key)
257 if last_flag:
258 self.setitem(w_key, w_value)
259 else:
260 # *very slow* fall-back
261 keys_w = []
262 values_w = []
263 iteratorimplementation = self.iteritems()
264 while True:
265 w_k, w_v = iteratorimplementation.next_item()
266 if w_k is None:
267 break
268 keys_w.append(w_k)
269 values_w.append(w_v)
270 self.clear()
271 self.setitem(w_key, w_value)
272 for i in range(len(keys_w)):
273 self.setitem(keys_w[i], values_w[i])
242 strategy.move_to_end(self, w_key, last_flag)
274243
275244 def nondescr_popitem_first(self, space):
276245 """Not exposed directly to app-level, but via __pypy__.popitem_first().
297266 otherwise KeyError is raised
298267 """
299268 strategy = self.get_strategy()
300 if strategy.has_pop:
301 try:
302 return strategy.pop(self, w_key, w_default)
303 except KeyError:
304 raise space.raise_key_error(w_key)
305 # fall-back
306 w_item = self.getitem(w_key)
307 if w_item is None:
308 if w_default is not None:
309 return w_default
310 else:
311 space.raise_key_error(w_key)
312 else:
313 self.internal_delitem(w_key)
314 return w_item
269 try:
270 return strategy.pop(self, w_key, w_default)
271 except KeyError:
272 raise space.raise_key_error(w_key)
315273
316274 def descr_popitem(self, space):
317275 """D.popitem() -> (k, v), remove and return some (key, value) pair as
546504 raise NotImplementedError
547505
548506 has_iterreversed = False
549 has_move_to_end = False
550507 has_pop = False
551508 # ^^^ no default implementation available for these methods
552509
561518 def prepare_update(self, w_dict, num_extra):
562519 pass
563520
521 def move_to_end(self, w_dict, w_key, last_flag):
522 # fall-back
523 w_value = w_dict.getitem(w_key)
524 if w_value is None:
525 self.space.raise_key_error(w_key)
526 else:
527 w_dict.internal_delitem(w_key)
528 if last_flag:
529 w_dict.setitem(w_key, w_value)
530 else:
531 # *very slow* fall-back
532 keys_w = []
533 values_w = []
534 iteratorimplementation = w_dict.iteritems()
535 while True:
536 w_k, w_v = iteratorimplementation.next_item()
537 if w_k is None:
538 break
539 keys_w.append(w_k)
540 values_w.append(w_v)
541 w_dict.clear()
542 w_dict.setitem(w_key, w_value)
543 for i in range(len(keys_w)):
544 w_dict.setitem(keys_w[i], values_w[i])
545
546
547 def pop(self, w_dict, w_key, w_default):
548 # fall-back
549 w_item = w_dict.getitem(w_key)
550 if w_item is None:
551 if w_default is not None:
552 return w_default
553 else:
554 raise KeyError
555 else:
556 w_dict.internal_delitem(w_key)
557 return w_item
558
559 def iterreversed(self, w_dict):
560 # fall-back if getiterreversed is not present
561 w_keys = self.w_keys(w_dict)
562 return self.space.call_method(w_keys, '__reversed__')
564563
565564 class EmptyDictStrategy(DictStrategy):
566565 erase, unerase = rerased.new_erasing_pair("empty")
658657
659658 def view_as_kwargs(self, w_dict):
660659 return ([], [])
660
661 def move_to_end(self, w_dict, w_key, last_flag):
662 self.space.raise_key_error(w_key)
663
664 def pop(self, w_dict, w_key, w_default):
665 if w_default is not None:
666 return w_default
667 else:
668 raise KeyError
661669
662670 # ---------- iterator interface ----------------
663671
828836
829837 if hasattr(dictimpl, 'getiterreversed'):
830838 def iterreversed(self, w_dict):
831 return IterClassReversed(self.space, self, w_dict)
839 return W_DictMultiIterKeysObject(
840 self.space,
841 IterClassReversed(self.space, self, w_dict))
832842 dictimpl.iterreversed = iterreversed
833 dictimpl.has_iterreversed = True
834
835 if hasattr(dictimpl, 'move_to_end'):
836 dictimpl.has_move_to_end = True
837
838 if hasattr(dictimpl, 'pop'):
839 dictimpl.has_pop = True
840843
841844 @jit.look_inside_iff(lambda self, w_dict, w_updatedict:
842845 w_dict_unrolling_heuristic(w_dict))
15341537 descr_or, descr_ror = _as_set_op('or', 'update')
15351538 descr_xor, descr_rxor = _as_set_op('xor', 'symmetric_difference_update')
15361539
1540 def new_dict_items(space, w_type, w_dict):
1541 w_dict = space.interp_w(W_DictMultiObject, w_dict)
1542 w_obj = space.allocate_instance(W_DictViewItemsObject, w_type)
1543 W_DictViewObject.__init__(w_obj, space, w_dict)
1544 return w_obj
1545
15371546 class W_DictViewItemsObject(W_DictViewObject, SetLikeDictView):
15381547 def descr_iter(self, space):
15391548 return W_DictMultiIterItemsObject(space, self.w_dict.iteritems())
15531562 return space.w_False
15541563 return space.newbool(space.eq_w(w_value, w_found))
15551564
1565 def new_dict_keys(space, w_type, w_dict):
1566 w_dict = space.interp_w(W_DictMultiObject, w_dict)
1567 w_obj = space.allocate_instance(W_DictViewKeysObject, w_type)
1568 W_DictViewObject.__init__(w_obj, space, w_dict)
1569 return w_obj
1570
15561571 class W_DictViewKeysObject(W_DictViewObject, SetLikeDictView):
15571572 def descr_iter(self, space):
15581573 return W_DictMultiIterKeysObject(space, self.w_dict.iterkeys())
1574
15591575 def descr_contains(self, space, w_key):
15601576 return self.w_dict.descr_contains(space, w_key)
1577
1578 def new_dict_values(space, w_type, w_dict):
1579 w_dict = space.interp_w(W_DictMultiObject, w_dict)
1580 w_obj = space.allocate_instance(W_DictViewValuesObject, w_type)
1581 W_DictViewObject.__init__(w_obj, space, w_dict)
1582 return w_obj
15611583
15621584 class W_DictViewValuesObject(W_DictViewObject):
15631585 def descr_iter(self, space):
15651587
15661588 W_DictViewItemsObject.typedef = TypeDef(
15671589 "dict_items",
1590 __new__ = interp2app(new_dict_items),
15681591 __repr__ = interp2app(W_DictViewItemsObject.descr_repr),
15691592 __len__ = interp2app(W_DictViewItemsObject.descr_len),
15701593 __iter__ = interp2app(W_DictViewItemsObject.descr_iter),
15861609 __xor__ = interp2app(W_DictViewItemsObject.descr_xor),
15871610 __rxor__ = interp2app(W_DictViewItemsObject.descr_rxor),
15881611 isdisjoint = interp2app(W_DictViewItemsObject.descr_isdisjoint),
1612 _dict = interp_attrproperty_w('w_dict', cls=W_DictViewItemsObject),
15891613 )
15901614
15911615 W_DictViewKeysObject.typedef = TypeDef(
15921616 "dict_keys",
1617 __new__ = interp2app(new_dict_keys),
15931618 __repr__ = interp2app(W_DictViewKeysObject.descr_repr),
15941619 __len__ = interp2app(W_DictViewKeysObject.descr_len),
15951620 __iter__ = interp2app(W_DictViewKeysObject.descr_iter),
16111636 __xor__ = interp2app(W_DictViewKeysObject.descr_xor),
16121637 __rxor__ = interp2app(W_DictViewKeysObject.descr_rxor),
16131638 isdisjoint = interp2app(W_DictViewKeysObject.descr_isdisjoint),
1639 _dict = interp_attrproperty_w('w_dict', cls=W_DictViewKeysObject),
16141640 )
16151641
16161642 W_DictViewValuesObject.typedef = TypeDef(
16171643 "dict_values",
1644 __new__ = interp2app(new_dict_values),
16181645 __repr__ = interp2app(W_DictViewValuesObject.descr_repr),
16191646 __len__ = interp2app(W_DictViewValuesObject.descr_len),
16201647 __iter__ = interp2app(W_DictViewValuesObject.descr_iter),
1648 _dict = interp_attrproperty_w('w_dict', cls=W_DictViewValuesObject),
16211649 )
409409
410410 def descr_hash(self, space):
411411 h = _hash_float(space, self.floatval)
412 h -= (h == -1)
413412 return space.newint(h)
414413
415414 def descr_format(self, space, w_spec):
760759 x = ((x << e) & HASH_MODULUS) | x >> (HASH_BITS - e)
761760
762761 x = intmask(intmask(x) * sign)
763 return -2 if x == -1 else x
762 x -= (x == -1)
763 return x
764764
765765
766766 def _divmod_w(space, w_float1, w_float2):
9696 w_obj = space.call_function(w_inttype, w_obj)
9797 return w_obj
9898
99 @unwrap_spec(nbytes=int, byteorder='text', signed=bool)
100 def descr_to_bytes(self, space, nbytes, byteorder, signed=False):
99 @unwrap_spec(length=int, byteorder='text', signed=bool)
100 def descr_to_bytes(self, space, length, byteorder, signed=False):
101101 """to_bytes(...)
102102 int.to_bytes(length, byteorder, *, signed=False) -> bytes
103103
120120 """
121121 bigint = space.bigint_w(self)
122122 try:
123 byte_string = bigint.tobytes(nbytes, byteorder=byteorder,
123 byte_string = bigint.tobytes(length, byteorder=byteorder,
124124 signed=signed)
125125 except InvalidEndiannessError:
126126 raise oefmt(space.w_ValueError,
370370 return wrapint(space, a)
371371
372372
373 @jit.look_inside_iff(lambda space, iv, iw, iz:
374 jit.isconstant(iw) and jit.isconstant(iz))
375373 def _pow(space, iv, iw, iz):
376374 """Helper for pow"""
377 if iw < 0:
378 if iz != 0:
379 raise oefmt(space.w_ValueError,
380 "pow() 2nd argument cannot be negative when 3rd "
381 "argument specified")
375 if iz == 0:
376 return _pow_nomod(iv, iw)
377 else:
378 return _pow_mod(space, iv, iw, iz)
379
380 @jit.look_inside_iff(lambda iv, iw: jit.isconstant(iw))
381 def _pow_nomod(iv, iw):
382 if iw <= 0:
383 if iw == 0:
384 return 1
382385 # bounce it, since it always returns float
383386 raise ValueError
384387 temp = iv
385388 ix = 1
386 while iw > 0:
389 while True:
387390 if iw & 1:
388391 try:
389392 ix = ovfcheck(ix * temp)
396399 temp = ovfcheck(temp * temp) # Square the value of temp
397400 except OverflowError:
398401 raise
399 if iz:
400 # If we did a multiplication, perform a modulo
401 ix %= iz
402 temp %= iz
403 if iz:
404 ix %= iz
402 return ix
403
404 @jit.look_inside_iff(lambda space, iv, iw, iz:
405 jit.isconstant(iw) and jit.isconstant(iz))
406 def _pow_mod(space, iv, iw, iz):
407 from rpython.rlib.rarithmetic import mulmod
408
409 if iw <= 0:
410 if iw == 0:
411 return 1 % iz # != 1, for iz == 1 or iz < 0
412 raise oefmt(space.w_ValueError,
413 "pow() 2nd argument cannot be negative when 3rd "
414 "argument specified")
415 if iz < 0:
416 try:
417 iz = ovfcheck(-iz)
418 except OverflowError:
419 raise
420 iz_negative = True
421 else:
422 iz_negative = False
423
424 temp = iv
425 ix = 1
426 while True:
427 if iw & 1:
428 ix = mulmod(ix, temp, iz)
429 iw >>= 1 # Shift exponent down by 1 bit
430 if iw == 0:
431 break
432 temp = mulmod(temp, temp, iz)
433
434 if iz_negative and ix > 0:
435 ix -= iz
405436 return ix
406437
407438
809840
810841 def _string_to_int_or_long(space, w_inttype, w_source, string, base=10):
811842 try:
812 value = string_to_int(string, base)
843 value = string_to_int(string, base, no_implicit_octal=True)
813844 except ParseStringError as e:
814845 raise wrap_parsestringerror(space, e, w_source)
815846 except ParseStringOverflowError as e:
9999 cache.hits[name] = cache.hits.get(name, 0) + 1
100100 return attr
101101 attr = self._find_map_attr(name, index)
102 cache.attrs[attr_hash] = self
103 cache.names[attr_hash] = name
104 cache.indexes[attr_hash] = index
105 cache.cached_attrs[attr_hash] = attr
106 if space.config.objspace.std.withmethodcachecounter:
107 cache.misses[name] = cache.misses.get(name, 0) + 1
102 if space._side_effects_ok():
103 cache.attrs[attr_hash] = self
104 cache.names[attr_hash] = name
105 cache.indexes[attr_hash] = index
106 cache.cached_attrs[attr_hash] = attr
107 if space.config.objspace.std.withmethodcachecounter:
108 cache.misses[name] = cache.misses.get(name, 0) + 1
108109 return attr
109110
110111 def _find_map_attr(self, name, index):
994995
995996 @jit.dont_look_inside
996997 def _fill_cache(pycode, nameindex, map, version_tag, storageindex, w_method=None):
998 if not pycode.space._side_effects_ok():
999 return
9971000 entry = pycode._mapdict_caches[nameindex]
9981001 if entry is INVALID_CACHE_ENTRY:
9991002 entry = CacheEntry()
455455 return space.newunicode(uc)
456456
457457 @unmarshaller(TYPE_INTERNED)
458 def unmarshal_bytes(space, u, tc):
459 w_u = unmarshal_unicode(space, u, tc)
460 return u.space.new_interned_w_str(w_u)
458 def unmarshal_interned(space, u, tc):
459 w_ret = unmarshal_unicode(space, u, tc)
460 return u.space.new_interned_w_str(w_ret)
461461
462462 def _unmarshal_ascii(u, short_length, interned):
463463 if short_length:
378378 def _pow(space, iv, iw, iz):
379379 if iw < 0:
380380 if iz != 0:
381 raise oefmt(space.w_TypeError,
381 raise oefmt(space.w_ValueError,
382382 "pow() 2nd argument cannot be negative when 3rd "
383383 "argument specified")
384384 raise ValueError
7070 value = getattr(self, 'value%s' % i)
7171 if typetuple[i] == object:
7272 y = space.int_w(space.hash(value))
73 elif typetuple[i] == int:
74 # mimic cpythons behavior of a hash value of -2 for -1
75 y = value
76 y -= (y == -1) # No explicit condition, to avoid JIT bridges
7773 elif typetuple[i] == float:
7874 # get the correct hash for float which is an
7975 # integer & other less frequent cases
377377 assert complex(s) == 1+2j
378378 assert complex('\N{EM SPACE}(\N{EN SPACE}1+1j ) ') == 1+1j
379379
380 def test_constructor_bad_error_message(self):
381 err = raises(TypeError, complex, {}).value
382 assert "float" not in str(err)
383 assert str(err) == "complex() first argument must be a string or a number, not 'dict'"
384 err = raises(TypeError, complex, 1, {}).value
385 assert "float" not in str(err)
386 assert str(err) == "complex() second argument must be a number, not 'dict'"
387
388 def test_error_messages(self):
389 err = raises(ZeroDivisionError, "1+1j / 0").value
390 assert str(err) == "complex division by zero"
391 err = raises(TypeError, "1+1j // 0").value
392 assert str(err) == "can't take floor of complex number."
393
394
380395 def test_hash(self):
381396 for x in range(-30, 30):
382397 assert hash(x) == hash(complex(x, 0))
230230 raises(KeyError, d.pop, "abc")
231231 assert len(d) == 2
232232
233 def test_pop_empty_bug(self):
234 d = {}
235 assert d.pop(1, 2) == 2
236 def f(**d): return d
237 d = f()
238 assert d.pop(1, 2) == 2
239
240 def test_pop_kwargs(self):
241 def kw(**d): return d
242 d = kw(o=2, t=4)
243 dd = d.copy()
244 result = dd.pop("o")
245 assert result == 2
246 assert len(dd) == 1
247 dd = d.copy()
248 result = dd.pop("o", 44)
249 assert result == 2
250 assert len(dd) == 1
251 result = dd.pop("o", 44)
252 assert result == 44
253 assert len(dd) == 1
254 raises(KeyError, dd.pop, "33")
255
256 assert d.pop("abc", None) is None
257 raises(KeyError, d.pop, "abc")
258 assert len(d) == 2
259
233260 def test_items(self):
234261 d = {1: 2, 3: 4}
235262 its = list(d.items())
260287
261288 def test_reversed_dict(self):
262289 import __pypy__
263 for d in [{}, {1: 2, 3: 4, 5: 6}, {"a": 5, "b": 2, "c": 6}]:
290 def kw(**d): return d
291 for d in [{}, {1: 2, 3: 4, 5: 6}, {"a": 5, "b": 2, "c": 6}, kw(a=1, b=2)]:
264292 assert list(__pypy__.reversed_dict(d)) == list(d.keys())[::-1]
265293 raises(TypeError, __pypy__.reversed_dict, 42)
266294
757785 assert len(d.keys()) == 2
758786 assert len(d.items()) == 2
759787 assert len(d.values()) == 2
760
761 def test_constructors_not_callable(self):
762 kt = type({}.keys())
763 raises(TypeError, kt, {})
764 raises(TypeError, kt)
765 it = type({}.items())
766 raises(TypeError, it, {})
767 raises(TypeError, it)
768 vt = type({}.values())
769 raises(TypeError, vt, {})
770 raises(TypeError, vt)
771788
772789 def test_dict_keys(self):
773790 d = {1: 10, "a": "ABC"}
11481165 assert type(list(d.keys())[0]) is str
11491166
11501167 def test_empty_to_int(self):
1151 skip('IntDictStrategy is disabled for now, re-enable it!')
11521168 import sys
11531169 d = {}
11541170 d[1] = "hi"
13181334 def fromcache(self, cls):
13191335 return cls(self)
13201336
1337 def _side_effects_ok(self):
1338 return True
1339
13211340 w_StopIteration = StopIteration
13221341 w_None = None
13231342 w_NoneType = type(None, None)
00 # encoding: utf-8
11 import sys
2 from pypy.interpreter.error import OperationError
23 from pypy.objspace.std import intobject as iobj
3 from rpython.rlib.rarithmetic import r_uint, is_valid_int
4 from rpython.rlib.rarithmetic import r_uint, is_valid_int, intmask
45 from rpython.rlib.rbigint import rbigint
56
67 class TestW_IntObject:
167168 v = f1.descr_pow(space, f2, space.w_None)
168169 assert space.isinstance_w(v, space.w_int)
169170 assert space.bigint_w(v).eq(rbigint.fromlong(pow(10, 20)))
171
172 try:
173 from hypothesis import given, strategies, example
174 except ImportError:
175 pass
176 else:
177 @given(
178 a=strategies.integers(min_value=-sys.maxint-1, max_value=sys.maxint),
179 b=strategies.integers(min_value=-sys.maxint-1, max_value=sys.maxint),
180 c=strategies.integers(min_value=-sys.maxint-1, max_value=sys.maxint))
181 @example(0, 0, -sys.maxint-1)
182 @example(0, 1, -sys.maxint-1)
183 @example(1, 0, -sys.maxint-1)
184 def test_hypot_pow(self, a, b, c):
185 if c == 0:
186 return
187 #
188 # "pow(a, b, c)": if b < 0, should get an app-level ValueError.
189 # Otherwise, should always work except if c == -maxint-1
190 if b < 0:
191 expected = "app-level ValueError"
192 elif b > 0 and c == -sys.maxint-1:
193 expected = OverflowError
194 else:
195 expected = pow(a, b, c)
196
197 try:
198 result = iobj._pow(self.space, a, b, c)
199 except OperationError as e:
200 assert ('ValueError: pow() 2nd argument cannot be negative '
201 'when 3rd argument specified' == e.errorstr(self.space))
202 result = "app-level ValueError"
203 except OverflowError:
204 result = OverflowError
205 assert result == expected
206
207 @given(
208 a=strategies.integers(min_value=-sys.maxint-1, max_value=sys.maxint),
209 b=strategies.integers(min_value=-sys.maxint-1, max_value=sys.maxint))
210 def test_hypot_pow_nomod(self, a, b):
211 # "a ** b": detect overflows and ValueErrors
212 if b < 0:
213 expected = ValueError
214 elif b > 128 and not (-1 <= a <= 1):
215 expected = OverflowError
216 else:
217 expected = a ** b
218 if expected != intmask(expected):
219 expected = OverflowError
220
221 try:
222 result = iobj._pow(self.space, a, b, 0)
223 except ValueError:
224 result = ValueError
225 except OverflowError:
226 result = OverflowError
227 assert result == expected
170228
171229 def test_neg(self):
172230 space = self.space
620678 assert type(x) is int
621679 assert str(x) == "0"
622680
681 def test_binop_overflow(self):
682 x = int(2)
683 assert x.__lshift__(128) == 680564733841876926926749214863536422912
684
685 def test_rbinop_overflow(self):
686 x = int(321)
687 assert x.__rlshift__(333) == 1422567365923326114875084456308921708325401211889530744784729710809598337369906606315292749899759616
688
623689 def test_ceil(self):
624690 assert 8 .__ceil__() == 8
625691
661727 assert x == expected
662728 assert called == [0, expected]
663729
730 def test_leading_zero_literal(self):
731 assert eval("00") == 0
732 raises(SyntaxError, eval, '07')
733 assert int("00", 0) == 0
734 raises(ValueError, int, '07', 0)
735 assert int("07", 10) == 7
736 raises(ValueError, int, '07777777777777777777777777777777777777', 0)
737 raises(ValueError, int, '00000000000000000000000000000000000007', 0)
738 raises(ValueError, int, '00000000000000000077777777777777777777', 0)
664739
665740 class AppTestIntShortcut(AppTestInt):
666741 spaceconfig = {"objspace.std.intshortcut": True}
0 import pytest
01 from pypy.objspace.std.iterobject import W_SeqIterObject
12 from pypy.interpreter.error import OperationError
23
1011 self.body0(w_iter)
1112
1213 def body0(self, w_iter):
13 raises(OperationError, self.space.next, w_iter)
14 raises(OperationError, self.space.next, w_iter)
14 pytest.raises(OperationError, self.space.next, w_iter)
15 pytest.raises(OperationError, self.space.next, w_iter)
1516
1617 def test_iter(self):
1718 w = self.space.wrap
119119 assert self.space.eq_w(self.space.next(w_iter), w(5))
120120 assert self.space.eq_w(self.space.next(w_iter), w(3))
121121 assert self.space.eq_w(self.space.next(w_iter), w(99))
122 raises(OperationError, self.space.next, w_iter)
123 raises(OperationError, self.space.next, w_iter)
122 py.test.raises(OperationError, self.space.next, w_iter)
123 py.test.raises(OperationError, self.space.next, w_iter)
124124
125125 def test_contains(self):
126126 w = self.space.wrap
11 import py
22 from pypy.objspace.std import longobject as lobj
33 from rpython.rlib.rbigint import rbigint
4
54
65 class TestW_LongObject:
76 def test_bigint_w(self):
5958 assert x + 2 + self._long(3) + True == -self._long(14)
6059
6160 def test_sub(self):
62 x = self._long(58543)
63 assert int(x - self._long(12332)) == 58543 - 12332
61 assert int(self._long(58543) - self._long(12332)) == 58543 - 12332
62 assert int(self._long(58543) - 12332) == 58543 - 12332
63 assert int(58543 - self._long(12332)) == 58543 - 12332
6464 x = self._long(237123838281233)
6565 assert x * 12 == x * self._long(12)
6666
7676 x = self._long(31415926)
7777 a = x // self._long(10000000)
7878 assert a == self._long(3)
79
80 def test_int_floordiv(self):
81 import sys
82 long = self._long
83
84 x = long(3000)
85 a = x // 1000
86 assert a == 3
87
88 x = long(3000)
89 a = x // -1000
90 assert a == -3
91
92 x = long(3000)
93 raises(ZeroDivisionError, "x // 0")
94
95 n = sys.maxsize + 1
96 assert n / int(-n) == long(-1)
7997
8098 def test_numerator_denominator(self):
8199 assert (self._long(1)).numerator == self._long(1)
86104 def test_compare(self):
87105 Z = 0
88106 ZL = self._long(0)
107
108 assert Z == ZL
109 assert not (Z != ZL)
110 assert ZL == Z
111 assert not (ZL != Z)
112 assert Z <= ZL
113 assert not (Z < ZL)
114 assert ZL <= ZL
115 assert not (ZL < ZL)
116
89117 for BIG in (self._long(1), self._long(1) << 62, self._long(1) << 9999):
90 assert Z == ZL
91 assert not (Z != ZL)
92 assert ZL == Z
93 assert not (ZL != Z)
94118 assert not (Z == BIG)
95119 assert Z != BIG
96120 assert not (BIG == Z)
97121 assert BIG != Z
98122 assert not (ZL == BIG)
99123 assert ZL != BIG
100 assert Z <= ZL
101 assert not (Z < ZL)
102124 assert Z <= BIG
103125 assert Z < BIG
104126 assert not (BIG <= Z)
105127 assert not (BIG < Z)
106 assert ZL <= ZL
107 assert not (ZL < ZL)
108128 assert ZL <= BIG
109129 assert ZL < BIG
110130 assert not (BIG <= ZL)
178198 assert type(-long2(0)) is int
179199 assert type(long2(5) // 1) is int
180200
201 def test_shift(self):
202 long = self._long
203 assert long(65) >> long(2) == long(16)
204 assert long(65) >> 2 == long(16)
205 assert 65 >> long(2) == long(16)
206 assert long(65) << long(2) == long(65) * 4
207 assert long(65) << 2 == long(65) * 4
208 assert 65 << long(2) == long(65) * 4
209 raises(ValueError, "long(1) << long(-1)")
210 raises(ValueError, "long(1) << -1")
211 raises(OverflowError, "long(1) << (2 ** 100)")
212 raises(ValueError, "long(1) >> long(-1)")
213 raises(ValueError, "long(1) >> -1")
214 raises(OverflowError, "long(1) >> (2 ** 100)")
215
181216 def test_pow(self):
217 long = self._long
182218 x = self._long(0)
183219 assert pow(x, self._long(0), self._long(1)) == self._long(0)
184220 assert pow(-self._long(1), -self._long(1)) == -1.0
221 assert pow(2 ** 68, 0.5) == 2.0 ** 34
222 assert pow(2 ** 68, 2) == 2 ** 136
223 raises(ValueError, pow, long(2), -1, 3)
224 raises(ValueError, pow, long(2), 5, 0)
225
226 # some rpow tests
227 assert pow(0, long(0), long(1)) == long(0)
228 assert pow(-1, long(-1)) == -1.0
229
230 def test_int_pow(self):
231 long = self._long
232 x = long(2)
233 assert pow(x, 2) == long(4)
234 assert pow(x, 2, 2) == long(0)
235 assert pow(x, 2, long(3)) == long(1)
185236
186237 def test_getnewargs(self):
187238 assert self._long(0) .__getnewargs__() == (self._long(0),)
188239 assert (-self._long(1)) .__getnewargs__() == (-self._long(1),)
189240
190241 def test_divmod(self):
242 long = self._long
191243 def check_division(x, y):
192244 q, r = divmod(x, y)
193245 pab, pba = x*y, y*x
194246 assert pab == pba
195 assert q == x//y
196 assert r == x%y
247 assert q == x // y
248 assert r == x % y
197249 assert x == q*y + r
198250 if y > 0:
199251 assert 0 <= r < y
203255 for y in [-self._long(105566530), -self._long(1), self._long(1), self._long(1034522340)]:
204256 print("checking division for %s, %s" % (x, y))
205257 check_division(x, y)
258 check_division(x, int(y))
259 check_division(int(x), y)
206260 # special case from python tests:
207261 s1 = 33
208262 s2 = 2
215269 check_division(x, y)
216270 raises(ZeroDivisionError, "x // self._long(0)")
217271 divmod(3, self._long(4))
272 raises(ZeroDivisionError, "x % long(0)")
273 raises(ZeroDivisionError, divmod, x, long(0))
274 raises(ZeroDivisionError, "x // 0")
275 raises(ZeroDivisionError, "x % 0")
276 raises(ZeroDivisionError, divmod, x, 0)
277
278 def test_int_divmod(self):
279 long = self._long
280 q, r = divmod(long(100), 11)
281 assert q == 9
282 assert r == 1
218283
219284 def test_format(self):
220285 assert repr(12345678901234567890) == '12345678901234567890'
377442 assert (-8388608).to_bytes(3, 'little', signed=True) == b'\x00\x00\x80'
378443 raises(OverflowError, (-5).to_bytes, 1, 'big')
379444 raises(ValueError, (-5).to_bytes, 1, 'foo')
445 assert 65535 .to_bytes(length=2, byteorder='big') == b'\xff\xff'
380446
381447 def test_negative_zero(self):
382448 x = eval("-self._long(0)")
375375 return MockBuffer(space, self.w_list, self.w_dim, self.w_fmt, \
376376 self.w_size, self.w_strides, self.w_shape)
377377
378 W_MockArray.typedef = TypeDef("MockArray",
378 W_MockArray.typedef = TypeDef("MockArray", None, None, "read-write",
379379 __new__ = interp2app(W_MockArray.descr_new),
380380 )
381381
77
88 def test_false(self):
99 assert not self.space.is_true(self.space.w_None)
10
0 import pytest
01 from pypy.objspace.std.setobject import W_SetObject
12 from pypy.objspace.std.setobject import (
23 BytesIteratorImplementation, BytesSetStrategy, EmptySetStrategy,
5758 s1 = W_SetObject(self.space, self.wrapped([1,2,3,4,5]))
5859 s2 = W_SetObject(self.space, self.wrapped([4,5, "six", "seven"]))
5960 s3 = s1.intersect(s2)
60 skip("for now intersection with ObjectStrategy always results in another ObjectStrategy")
61 pytest.skip("for now intersection with ObjectStrategy always results in another ObjectStrategy")
6162 assert s3.strategy is self.space.fromcache(IntegerSetStrategy)
6263
6364 def test_clear(self):
9293
9394 s1 = W_SetObject(self.space, self.wrapped([1,2,3,4,5]))
9495 s1.descr_discard(self.space, self.space.wrap("five"))
95 skip("currently not supported")
96 pytest.skip("currently not supported")
9697 assert s1.strategy is self.space.fromcache(IntegerSetStrategy)
9798
9899 set_discard__Set_ANY(self.space, s1, self.space.wrap(FakeInt(5)))
111112
112113 s1 = W_SetObject(self.space, self.wrapped([1,2,3,4,5]))
113114 assert not s1.has_key(self.space.wrap("five"))
114 skip("currently not supported")
115 pytest.skip("currently not supported")
115116 assert s1.strategy is self.space.fromcache(IntegerSetStrategy)
116117
117118 assert s1.has_key(self.space.wrap(FakeInt(2)))
2222 w_tuple = self.space.newtuple([self.space.wrap(1), self.space.wrap(2)])
2323 assert w_tuple.__class__.__name__ == 'W_SpecialisedTupleObject_ii'
2424
25 def hash_test(self, values, must_be_specialized):
26 N_values_w = [self.space.wrap(value) for value in values]
27 S_values_w = [self.space.wrap(value) for value in values]
28 N_w_tuple = W_TupleObject(N_values_w)
29 S_w_tuple = self.space.newtuple(S_values_w)
30
31 if must_be_specialized:
32 assert 'W_SpecialisedTupleObject' in type(S_w_tuple).__name__
33 assert self.space.is_true(self.space.eq(N_w_tuple, S_w_tuple))
34 assert self.space.is_true(
35 self.space.eq(self.space.hash(N_w_tuple),
36 self.space.hash(S_w_tuple)))
37
2538 def test_hash_against_normal_tuple(self):
2639 def hash_test(values, must_be_specialized=True):
27 N_values_w = [self.space.wrap(value) for value in values]
28 S_values_w = [self.space.wrap(value) for value in values]
29 N_w_tuple = W_TupleObject(N_values_w)
30 S_w_tuple = self.space.newtuple(S_values_w)
31
32 if must_be_specialized:
33 assert 'W_SpecialisedTupleObject' in type(S_w_tuple).__name__
34 assert self.space.is_true(self.space.eq(N_w_tuple, S_w_tuple))
35 assert self.space.is_true(
36 self.space.eq(self.space.hash(N_w_tuple),
37 self.space.hash(S_w_tuple)))
38
40 self.hash_test(values, must_be_specialized=must_be_specialized)
3941 hash_test([-1, -1])
4042 hash_test([-1.0, -1.0])
4143 hash_test([1, 2])
4749 hash_test([1, ('a', 2)])
4850 hash_test([1, ()])
4951 hash_test([1, 2, 3], must_be_specialized=False)
52 hash_test([1 << 62, 0])
53
54 try:
55 from hypothesis import given, strategies
56 except ImportError:
57 pass
58 else:
59 _int_float_text = strategies.one_of(
60 strategies.integers(),
61 strategies.floats(),
62 strategies.text())
63 @given(_int_float_text, _int_float_text)
64 def test_hash_with_hypothesis(self, x, y):
65 self.hash_test([x, y], must_be_specialized=False)
5066
5167
5268 class AppTestW_SpecialisedTupleObject:
0 import pytest
01 from pypy.interpreter.error import OperationError
12 from pypy.objspace.std.tupleobject import W_TupleObject
23
4142 assert self.space.eq_w(self.space.next(w_iter), w(5))
4243 assert self.space.eq_w(self.space.next(w_iter), w(3))
4344 assert self.space.eq_w(self.space.next(w_iter), w(99))
44 raises(OperationError, self.space.next, w_iter)
45 raises(OperationError, self.space.next, w_iter)
45 pytest.raises(OperationError, self.space.next, w_iter)
46 pytest.raises(OperationError, self.space.next, w_iter)
4647
4748 def test_contains(self):
4849 w = self.space.wrap
396396 assert str(123) == '123'
397397 assert str(object=123) == '123'
398398 assert str([2, 3]) == '[2, 3]'
399 assert str(errors='strict') == ''
399 #assert str(errors='strict') == '' --- obscure case, disabled for now
400400 class U(str):
401401 pass
402402 assert str(U()).__class__ is str
403403 assert U().__str__().__class__ is str
404404 assert U('test') == 'test'
405405 assert U('test').__class__ is U
406 assert U(errors='strict') == U('')
406 #assert U(errors='strict') == U('') --- obscure case, disabled for now
407407
408408 def test_call_unicode_2(self):
409409 class X(object):
10871087 assert u'A\u03a3\u0345'.lower() == u'a\u03c2\u0345'
10881088 assert u'\u03a3\u0345 '.lower() == u'\u03c3\u0345 '
10891089
1090 def test_unicode_constructor_misc(self):
1091 x = u'foo'
1092 x += u'bar'
1093 assert str(x) is x
1094 #
1095 class U(str):
1096 def __str__(self):
1097 return u'BOK'
1098 u = U(x)
1099 assert str(u) == u'BOK'
1100 #
1101 class U2(str):
1102 pass
1103 z = U2(u'foobaz')
1104 assert type(str(z)) is str
1105 assert str(z) == u'foobaz'
1106 #
1107 assert str(encoding='supposedly_the_encoding') == u''
1108 assert str(errors='supposedly_the_error') == u''
1109 e = raises(TypeError, str, u'', 'supposedly_the_encoding')
1110 assert str(e.value) == 'decoding str is not supported'
1111 e = raises(TypeError, str, u'', errors='supposedly_the_error')
1112 assert str(e.value) == 'decoding str is not supported'
1113 e = raises(TypeError, str, u, 'supposedly_the_encoding')
1114 assert str(e.value) == 'decoding str is not supported'
1115 e = raises(TypeError, str, z, 'supposedly_the_encoding')
1116 assert str(e.value) == 'decoding str is not supported'
277277 # if it was not actually overriden in the class, we remember this
278278 # fact for the next time.
279279 if w_descr is object_getattribute(self.space):
280 self.uses_object_getattribute = True
280 if self.space._side_effects_ok():
281 self.uses_object_getattribute = True
281282 else:
282283 return w_descr
283284 return None
303304 overrides_eq_cmp_or_hash = (overrides_eq or
304305 self.lookup('__hash__') is not default_hash)
305306 if overrides_eq_cmp_or_hash:
306 self.compares_by_identity_status = OVERRIDES_EQ_CMP_OR_HASH
307 else:
308 self.compares_by_identity_status = COMPARES_BY_IDENTITY
309 return self.compares_by_identity_status == COMPARES_BY_IDENTITY
307 result = OVERRIDES_EQ_CMP_OR_HASH
308 else:
309 result = COMPARES_BY_IDENTITY
310 if self.space._side_effects_ok():
311 self.compares_by_identity_status = result
312 return result == COMPARES_BY_IDENTITY
310313
311314 def ready(self):
312315 for w_base in self.bases_w:
481484 # print "hit", self, name
482485 return tup
483486 tup = self._lookup_where_all_typeobjects(name)
484 cache.versions[method_hash] = version_tag
485 cache.names[method_hash] = name
486 cache.lookup_where[method_hash] = tup
487 if space.config.objspace.std.withmethodcachecounter:
488 cache.misses[name] = cache.misses.get(name, 0) + 1
487 if space._side_effects_ok():
488 cache.versions[method_hash] = version_tag
489 cache.names[method_hash] = name
490 cache.lookup_where[method_hash] = tup
491 if space.config.objspace.std.withmethodcachecounter:
492 cache.misses[name] = cache.misses.get(name, 0) + 1
489493 # print "miss", self, name
490494 return tup
491495
655659 #
656660 w_newfunc = space.get(w_newdescr, space.w_None, w_type=self)
657661 if (space.config.objspace.std.newshortcut and
658 not we_are_jitted() and
662 not we_are_jitted() and space._side_effects_ok() and
659663 isinstance(w_newtype, W_TypeObject)):
660664 self.w_new_function = w_newfunc
661665 w_newobject = space.call_obj_args(w_newfunc, self, __args__)
222222 @staticmethod
223223 def descr_new(space, w_unicodetype, w_object=None, w_encoding=None,
224224 w_errors=None):
225 encoding, errors = _get_encoding_and_errors(space, w_encoding,
226 w_errors)
225227 if w_object is None:
226228 w_value = W_UnicodeObject.EMPTY
229 elif encoding is None and errors is None:
230 # this is very quick if w_object is already a w_unicode
231 w_value = unicode_from_object(space, w_object)
227232 else:
228 encoding, errors = _get_encoding_and_errors(space, w_encoding,
229 w_errors)
230 if encoding is None and errors is None:
231 w_value = unicode_from_object(space, w_object)
232 else:
233 w_value = unicode_from_encoded_object(space, w_object,
234 encoding, errors)
233 if space.isinstance_w(w_object, space.w_unicode):
234 raise oefmt(space.w_TypeError,
235 "decoding str is not supported")
236 w_value = unicode_from_encoded_object(space, w_object,
237 encoding, errors)
235238 if space.is_w(w_unicodetype, space.w_unicode):
236239 return w_value
237240
861861 d = D()
862862 raises(AttributeError, "A().d = 5")
863863
864 def test_not_subscriptable_error_gives_keys(self):
865 d = {'key1': {'key2': {'key3': None}}}
866 excinfo = raises(TypeError, "d['key1']['key2']['key3']['key4']['key5']")
867 assert "key4" in str(excinfo.value)
868
864869 def test_64bit_hash(self):
865870 import sys
866871 class BigHash(object):
44 'translator/c', 'rlib',
55 'memory/test', 'jit/metainterp',
66 'jit/backend/arm', 'jit/backend/x86',
7 'jit/backend/zarch',
7 'jit/backend/zarch', 'module/cpyext/test',
8 # python3 slowness ...
9 'module/_cffi_backend/test', 'module/__pypy__/test',
810 ]
911
1012 def collect_one_testdir(testdirs, reldir, tests):
1010 if ext == '.py':
1111 yield "# Generated by pypy/tool/import_cffi.py\n"
1212 for line in lines:
13 line = line.replace('from testing', 'from pypy.module.test_lib_pypy.cffi_tests')
13 line = line.replace('from testing', 'from extra_tests.cffi_tests')
1414 yield line
1515 elif ext in ('.c', '.h'):
1616 yield "/* Generated by pypy/tool/import_cffi.py */\n"
2121
2222 def main(cffi_dir):
2323 cffi_dir = py.path.local(cffi_dir)
24 pypydir = py.path.local(__file__).join('..', '..')
25 cffi_dest = pypydir.join('..', 'lib_pypy', 'cffi')
24 rootdir = py.path.local(__file__).join('..', '..', '..')
25 cffi_dest = rootdir / 'lib_pypy' / 'cffi'
2626 cffi_dest.ensure(dir=1)
27 test_dest = pypydir.join('module', 'test_lib_pypy', 'cffi_tests')
27 test_dest = rootdir / 'extra_tests' / 'cffi_tests'
2828 test_dest.ensure(dir=1)
2929 for p in (list(cffi_dir.join('cffi').visit(fil='*.py')) +
3030 list(cffi_dir.join('cffi').visit(fil='*.h'))):
686686 assert isinstance(dictkey(s), annmodel.SomeString)
687687 assert isinstance(dictvalue(s), annmodel.SomeInteger)
688688 assert not dictvalue(s).nonneg
689
690 def test_dict_get(self):
691 def f1(i, j):
692 d = {i: ''}
693 return d.get(j)
694 a = self.RPythonAnnotator()
695 s = a.build_types(f1, [int, int])
696 assert isinstance(s, annmodel.SomeString)
697 assert s.can_be_None
698
689699
690700 def test_exception_deduction(self):
691701 a = self.RPythonAnnotator()
495495 return SomeTuple((s_key, s_Int))
496496 raise ValueError(variant)
497497
498 def method_get(self, key, dfl):
498 def method_get(self, key, dfl=s_None):
499499 position = getbookkeeper().position_key
500500 self.dictdef.generalize_key(key)
501501 self.dictdef.generalize_value(dfl)
287287 suggests={"arm": [("translation.gcrootfinder", "shadowstack"),
288288 ("translation.jit_backend", "arm")]}),
289289
290 BoolOption("split_gc_address_space",
291 "Ensure full separation of GC and non-GC pointers", default=False),
292 BoolOption("reverse_debugger",
293 "Give an executable that writes a log file for reverse debugging",
294 default=False, cmdline='--revdb',
295 requires=[('translation.split_gc_address_space', True),
296 ('translation.jit', False),
297 ('translation.gc', 'boehm'),
298 ('translation.continuation', False)]),
290299 ])
291300
292301 def get_combined_translation_config(other_optdescr=None,
33 pytest_plugins = 'rpython.tool.pytest.expecttest'
44
55 option = None
6
7 try:
8 from hypothesis import settings, __version__
9 except ImportError:
10 pass
11 else:
12 if __version__[:2] < '3.6':
13 s = settings(deadline=None)
14 settings.register_profile('default', s)
15 else:
16 settings.register_profile('default', deadline=None)
17 settings.load_profile('default')
618
719 def braindead_deindent(self):
820 """monkeypatch that wont end up doing stupid in the python tokenizer"""
1818 * Typhon, 'A virtual machine for Monte', in active development,
1919 https://github.com/monte-language/typhon
2020 * Tulip, an untyped functional language, in language design mode, maintained,
21 https://github.com/tulip-lang/tulip/
21 https://github.com/tulip-lang/tulip/
2222 * Pycket, a Racket implementation, proof of concept, small language core
2323 working, a lot of primitives are missing. Slow development
2424 https://github.com/samth/pycket
5656 'i486': MODEL_X86,
5757 'i586': MODEL_X86,
5858 'i686': MODEL_X86,
59 'i686-AT386': MODEL_X86, # Hurd
5960 'i86pc': MODEL_X86, # Solaris/Intel
6061 'x86': MODEL_X86, # Apple
6162 'Power Macintosh': MODEL_PPC_64,
6262 def remember_known_length(self, op, val):
6363 self._known_lengths[op] = val
6464
65 def remember_setarrayitem_occured(self, op, index):
65 def remember_setarrayitem_occurred(self, op, index):
6666 op = self.get_box_replacement(op)
6767 try:
6868 subs = self._setarrayitems_occurred[op]
455455 array_box = op.getarg(0)
456456 index_box = op.getarg(1)
457457 if not isinstance(array_box, ConstPtr) and index_box.is_constant():
458 self.remember_setarrayitem_occured(array_box, index_box.getint())
458 self.remember_setarrayitem_occurred(array_box, index_box.getint())
459459
460460 def clear_varsize_gc_fields(self, kind, descr, result, v_length, opnum):
461461 if self.gc_ll_descr.malloc_zero_filled:
4343 if config.translation.jit_profiler == "oprofile":
4444 from rpython.jit.backend.x86 import oprofile
4545 if not oprofile.OPROFILE_AVAILABLE:
46 log.WARNING('oprofile support was explicitly enabled, but oprofile headers seem not to be available')
46 raise Exception('oprofile support was explicitly enabled, but oprofile headers seem not to be available')
4747 profile_agent = oprofile.OProfileAgent()
4848 self.with_threads = config.translation.thread
4949
7373 mc.MLGR(lr, l1)
7474 mc.LGHI(r.SCRATCH, l.imm(-1))
7575 mc.RISBG(r.SCRATCH, r.SCRATCH, l.imm(0), l.imm(0x80 | 0), l.imm(0))
76 # is the value greater than 2**63 ? then an overflow occured
76 # is the value greater than 2**63 ? then an overflow occurred
7777 jmp_xor_lq_overflow = mc.get_relative_pos()
7878 mc.reserve_cond_jump() # CLGRJ lq > 0x8000 ... 00 -> (label_overflow)
7979 jmp_xor_lr_overflow = mc.get_relative_pos()
270270
271271 def rewrite_op_unlikely(self, op):
272272 return None # "no real effect"
273
274 def rewrite_op_revdb_do_next_call(self, op):
275 return [] # ignored, only for revdb
273276
274277 def rewrite_op_raw_malloc_usage(self, op):
275278 if self.cpu.translate_support_code or isinstance(op.args[0], Variable):
1010 from rpython.jit.metainterp.optimizeopt.shortpreamble import PreambleOp
1111 from rpython.jit.metainterp.optimize import InvalidLoop
1212 from rpython.jit.metainterp.resoperation import rop, ResOperation, OpHelpers,\
13 AbstractResOp, GuardResOp
13 GuardResOp
1414 from rpython.rlib.objectmodel import we_are_translated
1515 from rpython.jit.metainterp.optimizeopt import info
1616
259259 # we don't know about this item
260260 return
261261 op = optimizer.get_box_replacement(self._fields[fielddescr.get_index()])
262 if op is None:
263 # XXX same bug as in serialize_opt:
264 # op should never be None, because that's an invariant violation in
265 # AbstractCachedEntry. But it still seems to happen when the info
266 # is attached to a Constant. At least we shouldn't crash.
267 return
262268 opnum = OpHelpers.getfield_for_descr(fielddescr)
263269 getfield_op = ResOperation(opnum, [structbox], descr=fielddescr)
264270 shortboxes.add_heap_op(op, getfield_op)
588594 return
589595 item = self._items[index]
590596 if item is not None:
597 # see comment in AbstractStructPtrInfo.produce_short_preamble_ops
591598 op = optimizer.get_box_replacement(item)
592599 opnum = OpHelpers.getarrayitem_for_descr(descr)
593600 getarrayitem_op = ResOperation(opnum, [structbox, ConstInt(index)],
55 from rpython.jit.metainterp.optimizeopt.optimizer import (Optimization, CONST_1,
66 CONST_0)
77 from rpython.jit.metainterp.optimizeopt.util import make_dispatcher_method
8 from rpython.jit.metainterp.resoperation import rop, AbstractResOp
8 from rpython.jit.metainterp.resoperation import rop
99 from rpython.jit.metainterp.optimizeopt import vstring
1010 from rpython.jit.codewriter.effectinfo import EffectInfo
1111 from rpython.rlib.rarithmetic import intmask
4343 if b.has_lower and b.has_upper and b.lower == b.upper:
4444 self.make_constant_int(box, b.lower)
4545
46 if isinstance(box, AbstractResOp):
47 dispatch_bounds_ops(self, box)
46 box1 = self.optimizer.as_operation(box)
47 if box1 is not None:
48 dispatch_bounds_ops(self, box1)
4849
4950 def _optimize_guard_true_false_value(self, op):
5051 return self.emit(op)
125126 v1, v2 = v2, v1
126127 # if both are constant, the pure optimization will deal with it
127128 if v2.is_constant() and not v1.is_constant():
128 if not self.optimizer.is_inputarg(arg1):
129 arg1 = self.optimizer.as_operation(arg1)
130 if arg1 is not None:
129131 if arg1.getopnum() == rop.INT_ADD:
130 prod_arg1 = arg1.getarg(0)
131 prod_arg2 = arg1.getarg(1)
132 prod_arg1 = self.get_box_replacement(arg1.getarg(0))
133 prod_arg2 = self.get_box_replacement(arg1.getarg(1))
132134 prod_v1 = self.getintbound(prod_arg1)
133135 prod_v2 = self.getintbound(prod_arg2)
134136
278278 self.quasi_immutable_deps = None
279279 self.replaces_guard = {}
280280 self._newoperations = []
281 self._emittedoperations = {}
281282 self.optimizer = self
282283 self.optpure = None
283284 self.optheap = None
290291
291292 self.set_optimizations(optimizations)
292293 self.setup()
293
294 def init_inparg_dict_from(self, lst):
295 self.inparg_dict = {}
296 for box in lst:
297 self.inparg_dict[box] = None
298294
299295 def set_optimizations(self, optimizations):
300296 if optimizations:
383379 return info.force_box(op, optforce)
384380 return op
385381
386 def is_inputarg(self, op):
387 return True
388 return op in self.inparg_dict
382 def as_operation(self, op):
383 # You should never check "isinstance(op, AbstractResOp" directly.
384 # Instead, use this helper.
385 if isinstance(op, AbstractResOp) and op in self._emittedoperations:
386 return op
387 return None
389388
390389 def get_constant_box(self, box):
391390 box = self.get_box_replacement(box)
403402
404403 def clear_newoperations(self):
405404 self._newoperations = []
405 self._emittedoperations = {}
406406
407407 def make_equal_to(self, op, newop):
408408 op = self.get_box_replacement(op)
630630 self._last_guard_op = None
631631 self._really_emitted_operation = op
632632 self._newoperations.append(op)
633 self._emittedoperations[op] = None
633634
634635 def emit_guard_operation(self, op, pendingfields):
635636 guard_op = op # self.replace_op_with(op, op.getopnum())
674675 return
675676 newop = self.replace_op_with_no_ovf(op)
676677 self._newoperations[-1] = newop
678 self._emittedoperations[newop] = None
677679
678680 def replace_op_with_no_ovf(self, op):
679681 if op.getopnum() == rop.INT_MUL_OVF:
718720 new_descr = new_op.getdescr()
719721 new_descr.copy_all_attributes_from(old_descr)
720722 self._newoperations[old_op_pos] = new_op
723 self._emittedoperations[new_op] = None
721724
722725 def store_final_boxes_in_guard(self, op, pendingfields):
723726 assert pendingfields is not None
99 from rpython.jit.metainterp.optimizeopt.info import INFO_NONNULL, INFO_NULL
1010 from rpython.jit.metainterp.optimizeopt.util import _findall, make_dispatcher_method
1111 from rpython.jit.metainterp.resoperation import rop, ResOperation, opclasses,\
12 OpHelpers, AbstractResOp
12 OpHelpers
1313 from rpython.rlib.rarithmetic import highest_bit
1414 from rpython.rtyper.lltypesystem import llmemory
1515 from rpython.rtyper import rclass
388388 def optimize_GUARD_SUBCLASS(self, op):
389389 info = self.getptrinfo(op.getarg(0))
390390 optimizer = self.optimizer
391 # must raise 'InvalidLoop' in all cases where 'info' shows the
392 # class cannot possibly match (see test_issue2926)
391393 if info and info.is_constant():
392394 c = self.get_box_replacement(op.getarg(0))
393395 vtable = optimizer.cpu.ts.cls_of_box(c).getint()
397399 if info is not None and info.is_about_object():
398400 known_class = info.get_known_class(optimizer.cpu)
399401 if known_class:
402 # Class of 'info' is exactly 'known_class'.
403 # We know statically if the 'guard_subclass' will pass or fail.
400404 if optimizer._check_subclass(known_class.getint(),
401405 op.getarg(1).getint()):
402406 return
407 else:
408 raise InvalidLoop(
409 "GUARD_SUBCLASS(known_class) proven to always fail")
403410 elif info.get_descr() is not None:
404 if optimizer._check_subclass(info.get_descr().get_vtable(),
411 # Class of 'info' is either get_descr() or a subclass of it.
412 # We're keeping the 'guard_subclass' at runtime only in the
413 # case where get_descr() is some strict parent class of
414 # the argument to 'guard_subclass'.
415 info_base_descr = info.get_descr().get_vtable()
416 if optimizer._check_subclass(info_base_descr,
405417 op.getarg(1).getint()):
406 return
418 return # guard_subclass always passing
419 elif optimizer._check_subclass(op.getarg(1).getint(),
420 info_base_descr):
421 pass # don't know, must keep the 'guard_subclass'
422 else:
423 raise InvalidLoop(
424 "GUARD_SUBCLASS(base_class) proven to always fail")
407425 return self.emit(op)
408426
409427 def optimize_GUARD_NONNULL(self, op):
489507
490508 def postprocess_GUARD_TRUE(self, op):
491509 box = self.get_box_replacement(op.getarg(0))
492 if (isinstance(box, AbstractResOp) and
493 box.getopnum() == rop.INT_IS_TRUE):
510 box1 = self.optimizer.as_operation(box)
511 if box1 is not None and box1.getopnum() == rop.INT_IS_TRUE:
494512 # we can't use the (current) range analysis for this because
495513 # "anything but 0" is not a valid range
496 self.pure_from_args(rop.INT_IS_ZERO, [box.getarg(0)], CONST_0)
514 self.pure_from_args(rop.INT_IS_ZERO, [box1.getarg(0)], CONST_0)
497515 self.make_constant(box, CONST_1)
498516
499517 def optimize_GUARD_FALSE(self, op):
501519
502520 def postprocess_GUARD_FALSE(self, op):
503521 box = self.get_box_replacement(op.getarg(0))
504 if (isinstance(box, AbstractResOp) and
505 box.getopnum() == rop.INT_IS_ZERO):
522 box1 = self.optimizer.as_operation(box)
523 if box1 is not None and box1.getopnum() == rop.INT_IS_ZERO:
506524 # we can't use the (current) range analysis for this because
507525 # "anything but 0" is not a valid range
508 self.pure_from_args(rop.INT_IS_TRUE, [box.getarg(0)], CONST_1)
526 self.pure_from_args(rop.INT_IS_TRUE, [box1.getarg(0)], CONST_1)
509527 self.make_constant(box, CONST_0)
510528
511529 def optimize_ASSERT_NOT_NONE(self, op):
40164016 strsetitem(p3, i2, i0)
40174017 i5 = int_add(i2, 1)
40184018 strsetitem(p3, i5, i1)
4019 ifoo = int_add(i5, 1)
40204019 jump(i1, i0, p3)
40214020 """
40224021 self.optimize_strunicode_loop(ops, expected)
7373 print "Loop:"
7474 print '\n'.join([str(o) for o in loop.operations])
7575 print
76 if expected_short:
76 if expected_short or getattr(info, 'short_preamble', None):
7777 print "Short Preamble:"
7878 short = info.short_preamble
7979 print '\n'.join([str(o) for o in short])
12991299 preamble = """
13001300 [i0, p1, p3]
13011301 i28 = int_add(i0, 1)
1302 i29 = int_add(i28, 1)
1302 i29 = int_add(i0, 2)
13031303 p30 = new_with_vtable(descr=nodesize)
13041304 setfield_gc(p30, i28, descr=valuedescr)
13051305 setfield_gc(p3, p30, descr=nextdescr)
13091309 expected = """
13101310 [i0, p1, p3]
13111311 i28 = int_add(i0, 1)
1312 i29 = int_add(i28, 1)
1312 i29 = int_add(i0, 2)
13131313 p30 = new_with_vtable(descr=nodesize)
13141314 setfield_gc(p30, i28, descr=valuedescr)
13151315 setfield_gc(p3, p30, descr=nextdescr)
63916391 strsetitem(p3, i2, i0)
63926392 i5 = int_add(i2, 1)
63936393 strsetitem(p3, i5, i1)
6394 i6 = int_add(i5, 1) # will be killed by the backend
63956394 jump(i1, i0, p3)
63966395 """
63976396 self.optimize_strunicode_loop(ops, expected, expected)
90629061 self.optimize_loop(ops, expected)
90639062
90649063 def test_same_as_preserves_info_in_the_preamble_2(self):
9064 py.test.xfail("less efficient loop, investigate")
90659065 ops = """
90669066 [i0, p0]
90679067 ifoo = getfield_gc_i(p0, descr=valuedescr)
94989498 """
94999499 self.optimize_loop(ops, expected)
95009500
9501 def test_issue2904(self):
9502 # we don't store advanced virtualstate information like "i1 = i2 + 1",
9503 # which means that the following loop, when unrolled, cannot be
9504 # optimized based on the knowledge that "i1 = i2 + 1" from the
9505 # preamble---we can't use that knowledge. After the fix, we get
9506 # the value "i2 + 1" passed as a third argument, possibly different
9507 # from "i1".
9508 ops = """
9509 [i1, i2]
9510 guard_value(i1, 10) []
9511 i3 = int_add(i2, 1)
9512 jump(i3, i2)
9513 """
9514 expected = """
9515 [i1, i2, i3]
9516 guard_value(i1, 10) []
9517 jump(i3, i2, i3)
9518 """
9519 self.optimize_loop(ops, expected)
9520
95019521 class TestLLtype(OptimizeOptTest, LLtypeMixin):
95029522 pass
99 from rpython.jit.metainterp.optimizeopt.vstring import StrPtrInfo
1010 from rpython.jit.metainterp.optimizeopt.virtualstate import (
1111 VirtualStateConstructor, VirtualStatesCantMatch)
12 from rpython.jit.metainterp.resoperation import rop, ResOperation, GuardResOp,\
13 AbstractResOp
12 from rpython.jit.metainterp.resoperation import rop, ResOperation, GuardResOp
1413 from rpython.jit.metainterp import compile
1514 from rpython.rlib.debug import debug_print, debug_start, debug_stop,\
1615 have_debug_prints
2120 if self.optunroll.short_preamble_producer is None:
2221 assert False # unreachable code
2322 op = preamble_op.op
24 self.optimizer.inparg_dict[op] = None # XXX ARGH
2523 # special hack for int_add(x, accumulator-const) optimization
2624 self.optunroll.short_preamble_producer.use_box(op,
2725 preamble_op.preamble_op, self)
143141 except VirtualStatesCantMatch:
144142 raise InvalidLoop("Cannot import state, virtual states don't match")
145143 self.potential_extra_ops = {}
146 self.optimizer.init_inparg_dict_from(label_args)
147144 try:
148145 info, _ = self.optimizer.propagate_all_forward(
149146 trace, call_pure_results, flush=False)
430427 for box in self._map_args(mapping, short_jump_args)]
431428
432429 def _expand_info(self, arg, infos):
433 if isinstance(arg, AbstractResOp) and rop.is_same_as(arg.opnum):
434 info = self.optimizer.getinfo(arg.getarg(0))
430 arg1 = self.optimizer.as_operation(arg)
431 if arg1 is not None and rop.is_same_as(arg1.opnum):
432 info = self.optimizer.getinfo(arg1.getarg(0))
435433 else:
436434 info = self.optimizer.getinfo(arg)
437435 if arg in infos:
55 from rpython.jit.metainterp.optimizeopt.optimizer import CONST_0, CONST_1
66 from rpython.jit.metainterp.optimizeopt.optimizer import llhelper, REMOVED
77 from rpython.jit.metainterp.optimizeopt.util import make_dispatcher_method
8 from rpython.jit.metainterp.resoperation import rop, ResOperation,\
9 AbstractResOp
8 from rpython.jit.metainterp.resoperation import rop, ResOperation
109 from rpython.jit.metainterp.optimizeopt import info
1110 from rpython.rlib.objectmodel import specialize, we_are_translated
1211 from rpython.rlib.unroll import unrolling_iterable
429429 for const1 in switchdict.const_keys_in_order:
430430 box = self.execute(rop.INT_EQ, valuebox, const1)
431431 assert box.getint() == 0
432 target = switchdict.dict[const1.getint()]
433432 self.metainterp.generate_guard(rop.GUARD_FALSE, box,
434433 resumepc=orgpc)
435434 else:
47014701 res = self.meta_interp(f, [10])
47024702 assert res == f(10)
47034703
4704 def test_cached_info_missing(self):
4705 py.test.skip("XXX hitting a non-translated assert in optimizeopt/heap.py, but seems not to hurt the rest")
4706 driver = JitDriver(greens = [],
4707 reds=['iterations', 'total', 'c', 'height', 'h'])
4708
4709 class IntVal:
4710 _immutable_fields_ = ['intval']
4711 def __init__(self, value):
4712 self.intval = value
4713
4714 def f(height, iterations):
4715 height = IntVal(height)
4716 c = IntVal(0)
4717 h = height
4718 total = IntVal(0)
4719
4720 while True:
4721 driver.jit_merge_point(iterations=iterations,
4722 total=total, c=c, height=height, h=h)
4723 if h.intval > 0:
4724 h = IntVal(h.intval - 1)
4725 total = IntVal(total.intval + 1)
4726 else:
4727 c = IntVal(c.intval + 1)
4728 if c.intval >= iterations:
4729 return total.intval
4730 h = height
4731
4732 res = self.meta_interp(f, [2, 200])
4733 assert res == f(2, 200)
4734
4735 def test_issue2904(self):
4736 driver = JitDriver(greens = [],
4737 reds=['iterations', 'total', 'c', 'height', 'h'])
4738
4739 def f(height, iterations):
4740 set_param(driver, 'threshold', 4)
4741 set_param(driver, 'trace_eagerness', 1)
4742 c = 0
4743 h = height
4744 total = 0
4745
4746 while True:
4747 driver.jit_merge_point(iterations=iterations,
4748 total=total, c=c, height=height, h=h)
4749 if h != 0:
4750 h = h - 1
4751 total = total + 1
4752 else:
4753 c = c + 1
4754 if c >= iterations:
4755 return total
4756 h = height - 1
4757
4758 res = self.meta_interp(f, [2, 200])
4759 assert res == f(2, 200)
4760
4761 def test_issue2926(self):
4762 driver = JitDriver(greens = [], reds=['i', 'total', 'p'])
4763
4764 class Base(object):
4765 def do_stuff(self):
4766 return 1000
4767 class Int(Base):
4768 def __init__(self, intval):
4769 self.intval = intval
4770 def do_stuff(self):
4771 return self.intval
4772 class SubInt(Int):
4773 pass
4774 class Float(Base):
4775 def __init__(self, floatval):
4776 self.floatval = floatval
4777 def do_stuff(self):
4778 return int(self.floatval)
4779
4780 prebuilt = [Int(i) for i in range(10)]
4781
4782 @dont_look_inside
4783 def forget_intbounds(i):
4784 return i
4785
4786 @dont_look_inside
4787 def escape(p):
4788 pass
4789
4790 def f(i):
4791 total = 0
4792 p = Base()
4793 while True:
4794 driver.jit_merge_point(i=i, total=total, p=p)
4795 #print '>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>', i
4796 if i == 13:
4797 break
4798 total += p.do_stuff()
4799 j = forget_intbounds(i)
4800 if j < 10: # initial loop
4801 p = prebuilt[i]
4802 p.intval = j
4803 elif j < 12:
4804 p = Int(i)
4805 else:
4806 p = Float(3.14)
4807 escape(p)
4808 i += 1
4809 return total
4810
4811 res = self.meta_interp(f, [0])
4812 assert res == f(0)
8080 if not self.supports_vector_ext():
8181 py.test.skip("this cpu %s has no implemented vector backend" % CPU)
8282
83 def meta_interp(self, f, args, policy=None, vec=True, vec_all=False):
84 return ll_meta_interp(f, args, enable_opts=self.enable_opts,
85 policy=policy,
86 CPUClass=self.CPUClass,
87 type_system=self.type_system,
88 vec=vec, vec_all=vec_all)
89
9083 # FLOAT UNARY
9184
92 def _vector_float_unary(self, func, type, data):
85 @pytest.mark.parametrize('func',
86 [lambda v: abs(v), lambda v: -v],
87 ids=['abs', 'neg'])
88 @given(la=st.lists(st.floats(), min_size=10, max_size=150))
89 def test_vector_float_unary(self, func, la):
9390 func = always_inline(func)
94
95 size = rffi.sizeof(type)
96 myjitdriver = JitDriver(greens = [], reds = 'auto', vectorize=True)
91 tp = rffi.DOUBLE
92
93 size = rffi.sizeof(tp)
94 myjitdriver = JitDriver(greens=[], reds='auto', vectorize=True)
95
9796 def f(bytecount, va, vc):
9897 i = 0
9998 while i < bytecount:
10099 myjitdriver.jit_merge_point()
101 a = raw_storage_getitem(type,va,i)
100 a = raw_storage_getitem(tp, va, i)
102101 c = func(a)
103 raw_storage_setitem(vc, i, rffi.cast(type,c))
102 raw_storage_setitem(vc, i, rffi.cast(tp, c))
104103 i += size
105104
106 la = data.draw(st.lists(st.floats(), min_size=10, max_size=150))
107105 l = len(la)
108
109106 rawstorage = RawStorage()
110 va = rawstorage.new(la, type)
111 vc = rawstorage.new(None, type, size=l)
112 self.meta_interp(f, [l*size, va, vc], vec=True)
107 va = rawstorage.new(la, tp)
108 vc = rawstorage.new(None, tp, size=l)
109 self.meta_interp(f, [l * size, va, vc], vec=True)
113110
114111 for i in range(l):
115 c = raw_storage_getitem(type,vc,i*size)
112 c = raw_storage_getitem(tp, vc, i * size)
116113 r = func(la[i])
117114 assert isclose(r, c)
118115
119116 rawstorage.clear()
120
121 def vec_int_unary(test_func, unary_func, type):
122 return pytest.mark.parametrize('func,type', [
123 (unary_func, type)
124 ])(given(data=st.data())(test_func))
125
126 vec_float_unary = functools.partial(vec_int_unary, _vector_float_unary)
127
128 test_vec_float_abs = \
129 vec_float_unary(lambda v: abs(v), rffi.DOUBLE)
130 test_vec_float_neg = \
131 vec_float_unary(lambda v: -v, rffi.DOUBLE)
132117
133118 # FLOAT BINARY
134119
375360 res = self.meta_interp(f, [count], vec=True)
376361 assert res == f(count) == breaks
377362
378 def _vec_reduce(self, strat, func, type, data):
379 func = always_inline(func)
380
381 size = rffi.sizeof(type)
382 myjitdriver = JitDriver(greens = [], reds = 'auto', vectorize=True)
383 def f(accum, bytecount, v):
384 i = 0
385 while i < bytecount:
386 myjitdriver.jit_merge_point()
387 e = raw_storage_getitem(type,v,i)
388 accum = func(accum,e)
389 i += size
390 return accum
391
392 la = data.draw(st.lists(strat, min_size=10, max_size=150))
393 #la = [1.0] * 10
394 l = len(la)
395
396 accum = data.draw(strat)
397 rawstorage = RawStorage()
398 va = rawstorage.new(la, type)
399 res = self.meta_interp(f, [accum, l*size, va], vec=True)
400
401 assert isclose(rffi.cast(type, res), f(accum, l*size, va))
402
403 rawstorage.clear()
404
405 def vec_reduce(test_func, strat, arith_func, type):
406 return pytest.mark.parametrize('strat,func,type', [
407 (strat, arith_func, type)
408 ])(given(data=st.data())(test_func))
409 vec_reduce = functools.partial(vec_reduce, _vec_reduce)
363 def vec_reduce(strat, arith_func, tp):
364 @pytest.mark.parametrize('func, tp', [
365 (arith_func, tp)
366 ])
367 @given(la=st.lists(strat, min_size=11, max_size=150))
368 def _vec_reduce(self, func, tp, la):
369 func = always_inline(func)
370
371 size = rffi.sizeof(tp)
372 myjitdriver = JitDriver(greens=[], reds='auto', vectorize=True)
373
374 def f(accum, bytecount, v):
375 i = 0
376 while i < bytecount:
377 myjitdriver.jit_merge_point()
378 e = raw_storage_getitem(tp, v, i)
379 accum = func(accum, e)
380 i += size
381 return accum
382
383 accum = la[0]
384 la = la[1:]
385 l = len(la)
386 rawstorage = RawStorage()
387 va = rawstorage.new(la, tp)
388 res = self.meta_interp(f, [accum, l * size, va], vec=True)
389
390 assert isclose(rffi.cast(tp, res), f(accum, l * size, va))
391
392 rawstorage.clear()
393 return _vec_reduce
410394
411395 test_vec_int_sum = vec_reduce(st.integers(min_value=-2**(64-1), max_value=2**(64-1)-1),
412396 lambda a,b: lltype.intmask(lltype.intmask(a)+lltype.intmask(b)), lltype.Signed)
147147
148148 def get_size_incl_hash(self, obj):
149149 return self.get_size(obj)
150
151 # these can be overriden by subclasses, called by the GCTransformer
152 def enable(self):
153 pass
154
155 def disable(self):
156 pass
157
158 def isenabled(self):
159 return True
160
161 def collect_step(self):
162 self.collect()
163 return True
150164
151165 def malloc(self, typeid, length=0, zero=False):
152166 """NOT_RPYTHON
6161 # XXX old_objects_pointing_to_young (IRC 2014-10-22, fijal and gregor_w)
6262 import sys
6363 import os
64 import time
6465 from rpython.rtyper.lltypesystem import lltype, llmemory, llarena, llgroup
6566 from rpython.rtyper.lltypesystem.lloperation import llop
6667 from rpython.rtyper.lltypesystem.llmemory import raw_malloc_usage
7273 from rpython.rlib.debug import ll_assert, debug_print, debug_start, debug_stop
7374 from rpython.rlib.objectmodel import specialize
7475 from rpython.rlib import rgc
75 from rpython.rlib.rtimer import read_timestamp
7676 from rpython.memory.gc.minimarkpage import out_of_memory
7777
7878 #
190190 NURSARRAY = lltype.Array(llmemory.Address)
191191
192192 # ____________________________________________________________
193
194
193195
194196 class IncrementalMiniMarkGC(MovingGCBase):
195197 _alloc_flavor_ = "raw"
373375 self.raw_malloc_might_sweep = self.AddressStack()
374376 self.rawmalloced_total_size = r_uint(0)
375377 self.rawmalloced_peak_size = r_uint(0)
378 self.total_gc_time = 0.0
376379
377380 self.gc_state = STATE_SCANNING
381
382 # if the GC is disabled, it runs only minor collections; major
383 # collections need to be manually triggered by explicitly calling
384 # collect()
385 self.enabled = True
378386 #
379387 # Two lists of all objects with finalizers. Actually they are lists
380388 # of pairs (finalization_queue_nr, object). "probably young objects"
509517 # Estimate this number conservatively
510518 bigobj = self.nonlarge_max + 1
511519 self.max_number_of_pinned_objects = self.nursery_size / (bigobj * 2)
520
521 def enable(self):
522 self.enabled = True
523
524 def disable(self):
525 self.enabled = False
526
527 def isenabled(self):
528 return self.enabled
512529
513530 def _nursery_memory_size(self):
514531 extra = self.nonlarge_max + 1
746763 """Do a minor (gen=0), start a major (gen=1), or do a full
747764 major (gen>=2) collection."""
748765 if gen < 0:
749 self._minor_collection() # dangerous! no major GC cycle progress
750 elif gen <= 1:
751 self.minor_collection_with_major_progress()
752 if gen == 1 and self.gc_state == STATE_SCANNING:
766 # Dangerous! this makes no progress on the major GC cycle.
767 # If called too often, the memory usage will keep increasing,
768 # because we'll never completely fill the nursery (and so
769 # never run anything about the major collection).
770 self._minor_collection()
771 elif gen == 0:
772 # This runs a minor collection. This is basically what occurs
773 # when the nursery is full. If a major collection is in
774 # progress, it also runs one more step of it. It might also
775 # decide to start a major collection just now, depending on
776 # current memory pressure.
777 self.minor_collection_with_major_progress(force_enabled=True)
778 elif gen == 1:
779 # This is like gen == 0, but if no major collection is running,
780 # then it forces one to start now.
781 self.minor_collection_with_major_progress(force_enabled=True)
782 if self.gc_state == STATE_SCANNING:
753783 self.major_collection_step()
754784 else:
785 # This does a complete minor and major collection.
755786 self.minor_and_major_collection()
756787 self.rrc_invoke_callback()
757788
758
759 def minor_collection_with_major_progress(self, extrasize=0):
760 """Do a minor collection. Then, if there is already a major GC
761 in progress, run at least one major collection step. If there is
762 no major GC but the threshold is reached, start a major GC.
789 def collect_step(self):
790 """
791 Do a single major collection step. Return True when the major collection
792 is completed.
793
794 This is meant to be used together with gc.disable(), to have a
795 fine-grained control on when the GC runs.
796 """
797 old_state = self.gc_state
798 self._minor_collection()
799 self.major_collection_step()
800 self.rrc_invoke_callback()
801 return rgc._encode_states(old_state, self.gc_state)
802
803 def minor_collection_with_major_progress(self, extrasize=0,
804 force_enabled=False):
805 """Do a minor collection. Then, if the GC is enabled and there
806 is already a major GC in progress, run at least one major collection
807 step. If there is no major GC but the threshold is reached, start a
808 major GC.
763809 """
764810 self._minor_collection()
811 if not self.enabled and not force_enabled:
812 return
765813
766814 # If the gc_state is STATE_SCANNING, we're not in the middle
767815 # of an incremental major collection. In that case, wait
16431691 """Perform a minor collection: find the objects from the nursery
16441692 that remain alive and move them out."""
16451693 #
1646 start = read_timestamp()
1694 start = time.time()
16471695 debug_start("gc-minor")
16481696 #
16491697 # All nursery barriers are invalid from this point on. They
18351883 debug_print("minor collect, total memory used:", total_memory_used)
18361884 debug_print("number of pinned objects:",
18371885 self.pinned_objects_in_nursery)
1886 debug_print("total size of surviving objects:", self.nursery_surviving_size)
18381887 if self.DEBUG >= 2:
18391888 self.debug_check_consistency() # expensive!
18401889 #
18411890 self.root_walker.finished_minor_collection()
18421891 #
18431892 debug_stop("gc-minor")
1844 duration = read_timestamp() - start
1893 duration = time.time() - start
1894 self.total_gc_time += duration
18451895 self.hooks.fire_gc_minor(
18461896 duration=duration,
18471897 total_memory_used=total_memory_used,
22472297 # Note - minor collections seem fast enough so that one
22482298 # is done before every major collection step
22492299 def major_collection_step(self, reserving_size=0):
2250 start = read_timestamp()
2300 start = time.time()
22512301 debug_start("gc-collect-step")
22522302 oldstate = self.gc_state
22532303 debug_print("starting gc state: ", GC_STATES[self.gc_state])
24002450 # a total object size of at least '3 * nursery_size' bytes
24012451 # is processed.
24022452 limit = 3 * self.nursery_size // self.small_request_threshold
2403 self.free_unvisited_rawmalloc_objects_step(limit)
2453 nobjects = self.free_unvisited_rawmalloc_objects_step(limit)
2454 debug_print("freeing raw objects:", limit-nobjects,
2455 "freed, limit was", limit)
24042456 done = False # the 2nd half below must still be done
24052457 else:
24062458 # Ask the ArenaCollection to visit a fraction of the objects.
24102462 limit = 3 * self.nursery_size // self.ac.page_size
24112463 done = self.ac.mass_free_incremental(self._free_if_unvisited,
24122464 limit)
2465 status = done and "No more pages left." or "More to do."
2466 debug_print("freeing GC objects, up to", limit, "pages.", status)
24132467 # XXX tweak the limits above
24142468 #
24152469 if done:
24172471 #
24182472 # We also need to reset the GCFLAG_VISITED on prebuilt GC objects.
24192473 self.prebuilt_root_objects.foreach(self._reset_gcflag_visited, None)
2420 #
2421 # Print statistics
2422 debug_start("gc-collect-done")
2423 debug_print("arenas: ",
2424 self.stat_ac_arenas_count, " => ",
2425 self.ac.arenas_count)
2426 debug_print("bytes used in arenas: ",
2427 self.ac.total_memory_used)
2428 debug_print("bytes raw-malloced: ",
2429 self.stat_rawmalloced_total_size, " => ",
2430 self.rawmalloced_total_size)
2431 debug_stop("gc-collect-done")
2432 self.hooks.fire_gc_collect(
2433 num_major_collects=self.num_major_collects,
2434 arenas_count_before=self.stat_ac_arenas_count,
2435 arenas_count_after=self.ac.arenas_count,
2436 arenas_bytes=self.ac.total_memory_used,
2437 rawmalloc_bytes_before=self.stat_rawmalloced_total_size,
2438 rawmalloc_bytes_after=self.rawmalloced_total_size)
24392474 #
24402475 # Set the threshold for the next major collection to be when we
24412476 # have allocated 'major_collection_threshold' times more than
24492484 min(total_memory_used * self.major_collection_threshold,
24502485 total_memory_used + self.max_delta),
24512486 reserving_size)
2487 #
2488 # Print statistics
2489 debug_start("gc-collect-done")
2490 debug_print("arenas: ",
2491 self.stat_ac_arenas_count, " => ",
2492 self.ac.arenas_count)
2493 debug_print("bytes used in arenas: ",
2494 self.ac.total_memory_used)
2495 debug_print("bytes raw-malloced: ",
2496 self.stat_rawmalloced_total_size, " => ",
2497 self.rawmalloced_total_size)
2498 debug_print("next major collection threshold: ",
2499 self.next_major_collection_threshold)
2500 debug_stop("gc-collect-done")
2501 self.hooks.fire_gc_collect(
2502 num_major_collects=self.num_major_collects,
2503 arenas_count_before=self.stat_ac_arenas_count,
2504 arenas_count_after=self.ac.arenas_count,
2505 arenas_bytes=self.ac.total_memory_used,
2506 rawmalloc_bytes_before=self.stat_rawmalloced_total_size,
2507 rawmalloc_bytes_after=self.rawmalloced_total_size)
24522508 #
24532509 # Max heap size: gives an upper bound on the threshold. If we
24542510 # already have at least this much allocated, raise MemoryError.
24872543
24882544 debug_print("stopping, now in gc state: ", GC_STATES[self.gc_state])
24892545 debug_stop("gc-collect-step")
2490 duration = read_timestamp() - start
2546 duration = time.time() - start
2547 self.total_gc_time += duration
24912548 self.hooks.fire_gc_collect_step(
24922549 duration=duration,
24932550 oldstate=oldstate,
29943051 self.ac.total_memory_used))
29953052 elif stats_no == rgc.NURSERY_SIZE:
29963053 return intmask(self.nursery_size)
3054 elif stats_no == rgc.TOTAL_GC_TIME:
3055 return int(self.total_gc_time * 1000)
29973056 return 0
29983057
29993058
1212 from rpython.memory.gc import minimark, incminimark
1313 from rpython.memory.gctypelayout import zero_gc_pointers_inside, zero_gc_pointers
1414 from rpython.rlib.debug import debug_print
15 from rpython.rlib.test.test_debug import debuglog
1516 import pdb
1617 WORD = LONG_BIT // 8
1718
769770 assert elem.prev == lltype.nullptr(S)
770771 assert elem.next == lltype.nullptr(S)
771772
772
773 def test_collect_0(self, debuglog):
774 self.gc.collect(1) # start a major
775 debuglog.reset()
776 self.gc.collect(-1) # do ONLY a minor
777 assert debuglog.summary() == {'gc-minor': 1}
778
779 def test_enable_disable(self, debuglog):
780 def large_malloc():
781 # malloc an object which is large enough to trigger a major collection
782 threshold = self.gc.next_major_collection_threshold
783 self.malloc(VAR, int(threshold/8))
784 summary = debuglog.summary()
785 debuglog.reset()
786 return summary
787 #
788 summary = large_malloc()
789 assert sorted(summary.keys()) == ['gc-collect-step', 'gc-minor']
790 #
791 self.gc.disable()
792 summary = large_malloc()
793 assert sorted(summary.keys()) == ['gc-minor']
794 #
795 self.gc.enable()
796 summary = large_malloc()
797 assert sorted(summary.keys()) == ['gc-collect-step', 'gc-minor']
798
799 def test_call_collect_when_disabled(self, debuglog):
800 # malloc an object and put it the old generation
801 s = self.malloc(S)
802 s.x = 42
803 self.stackroots.append(s)
804 self.gc.collect()
805 s = self.stackroots.pop()
806 #
807 self.gc.disable()
808 self.gc.collect(1) # start a major collect
809 assert sorted(debuglog.summary()) == ['gc-collect-step', 'gc-minor']
810 assert s.x == 42 # s is not freed yet
811 #
812 debuglog.reset()
813 self.gc.collect(1) # run one more step
814 assert sorted(debuglog.summary()) == ['gc-collect-step', 'gc-minor']
815 assert s.x == 42 # s is not freed yet
816 #
817 debuglog.reset()
818 self.gc.collect() # finish the major collection
819 summary = debuglog.summary()
820 assert sorted(debuglog.summary()) == ['gc-collect-step', 'gc-minor']
821 # s is freed
822 py.test.raises(RuntimeError, 's.x')
823
824 def test_collect_step(self, debuglog):
825 from rpython.rlib import rgc
826 n = 0
827 states = []
828 while True:
829 debuglog.reset()
830 val = self.gc.collect_step()
831 states.append((rgc.old_state(val), rgc.new_state(val)))
832 summary = debuglog.summary()
833 assert summary == {'gc-minor': 1, 'gc-collect-step': 1}
834 if rgc.is_done(val):
835 break
836 n += 1
837 if n == 100:
838 assert False, 'this looks like an endless loop'
839 #
840 assert states == [
841 (incminimark.STATE_SCANNING, incminimark.STATE_MARKING),
842 (incminimark.STATE_MARKING, incminimark.STATE_SWEEPING),
843 (incminimark.STATE_SWEEPING, incminimark.STATE_FINALIZING),
844 (incminimark.STATE_FINALIZING, incminimark.STATE_SCANNING)
845 ]
6969 assert self.gc.hooks.minors == [
7070 {'total_memory_used': 0, 'pinned_objects': 0}
7171 ]
72 assert self.gc.hooks.durations[0] > 0
72 assert self.gc.hooks.durations[0] > 0.
7373 self.gc.hooks.reset()
7474 #
7575 # these objects survive, so the total_memory_used is > 0
102102 ]
103103 assert len(self.gc.hooks.durations) == 4 # 4 steps
104104 for d in self.gc.hooks.durations:
105 assert d > 0
105 assert d > 0.0
106106 self.gc.hooks.reset()
107107 #
108108 self.stackroots.append(self.malloc(S))
99
1010 class BoehmGCTransformer(GCTransformer):
1111 malloc_zero_filled = True
12 FINALIZER_PTR = lltype.Ptr(lltype.FuncType([llmemory.Address], lltype.Void))
13 NO_HEADER = True
12 FINALIZER_PTR = lltype.Ptr(lltype.FuncType([llmemory.GCREF], lltype.Void))
1413
1514 def __init__(self, translator, inline=False):
1615 super(BoehmGCTransformer, self).__init__(translator, inline=inline)
1716 self.finalizer_funcptrs = {}
1817
19 atomic_mh = mallocHelpers()
20 atomic_mh.allocate = lambda size: llop.boehm_malloc_atomic(llmemory.Address, size)
18 atomic_mh = mallocHelpers(gckind='gc')
19 atomic_mh.allocate = lambda size: llop.boehm_malloc_atomic(llmemory.GCREF, size)
2120 ll_malloc_fixedsize_atomic = atomic_mh._ll_malloc_fixedsize
2221
23 mh = mallocHelpers()
24 mh.allocate = lambda size: llop.boehm_malloc(llmemory.Address, size)
22 mh = mallocHelpers(gckind='gc')
23 mh.allocate = lambda size: llop.boehm_malloc(llmemory.GCREF, size)
2524 ll_malloc_fixedsize = mh._ll_malloc_fixedsize
2625
2726 # XXX, do we need/want an atomic version of this function?
2827 ll_malloc_varsize_no_length = mh.ll_malloc_varsize_no_length
2928 ll_malloc_varsize = mh.ll_malloc_varsize
3029
31 def ll_identityhash(addr):
32 h = ~llmemory.cast_adr_to_int(addr)
33 return h
30 fields = []
31 if translator and translator.config.translation.reverse_debugger:
32 fields.append(("hash", lltype.Signed))
33 fields.append(("uid", lltype.SignedLongLong))
34 hints = {'hints': {'gcheader': True}}
35 self.HDR = lltype.Struct("header", *fields, **hints)
3436
3537 if self.translator:
3638 self.malloc_fixedsize_ptr = self.inittime_helper(
37 ll_malloc_fixedsize, [lltype.Signed], llmemory.Address)
39 ll_malloc_fixedsize, [lltype.Signed], llmemory.GCREF)
3840 self.malloc_fixedsize_atomic_ptr = self.inittime_helper(
39 ll_malloc_fixedsize_atomic, [lltype.Signed], llmemory.Address)
41 ll_malloc_fixedsize_atomic, [lltype.Signed], llmemory.GCREF)
4042 self.malloc_varsize_no_length_ptr = self.inittime_helper(
41 ll_malloc_varsize_no_length, [lltype.Signed]*3, llmemory.Address, inline=False)
43 ll_malloc_varsize_no_length, [lltype.Signed]*3, llmemory.GCREF, inline=False)
4244 self.malloc_varsize_ptr = self.inittime_helper(
43 ll_malloc_varsize, [lltype.Signed]*4, llmemory.Address, inline=False)
45 ll_malloc_varsize, [lltype.Signed]*4, llmemory.GCREF, inline=False)
4446 if self.translator.config.translation.rweakref:
47 (ll_weakref_create, ll_weakref_deref,
48 self.WEAKLINK, self.convert_weakref_to
49 ) = build_weakref(self.translator.config)
4550 self.weakref_create_ptr = self.inittime_helper(
46 ll_weakref_create, [llmemory.Address], llmemory.WeakRefPtr,
51 ll_weakref_create, [llmemory.GCREF], llmemory.WeakRefPtr,
4752 inline=False)
4853 self.weakref_deref_ptr = self.inittime_helper(
49 ll_weakref_deref, [llmemory.WeakRefPtr], llmemory.Address)
50 self.identityhash_ptr = self.inittime_helper(
51 ll_identityhash, [llmemory.Address], lltype.Signed,
52 inline=False)
54 ll_weakref_deref, [llmemory.WeakRefPtr], llmemory.GCREF)
55
56 if not translator.config.translation.reverse_debugger:
57 def ll_identityhash(addr):
58 h = ~llmemory.cast_adr_to_int(addr)
59 return h
60 self.identityhash_ptr = self.inittime_helper(
61 ll_identityhash, [llmemory.Address], lltype.Signed,
62 inline=False)
63 self.NO_HEADER = True
64
5365 self.mixlevelannotator.finish() # for now
5466 self.mixlevelannotator.backend_optimize()
5567
6072 # XXX same behavior for zero=True: in theory that's wrong
6173 if TYPE._is_atomic():
6274 funcptr = self.malloc_fixedsize_atomic_ptr
75 opname = 'boehm_malloc_atomic'
6376 else:
6477 funcptr = self.malloc_fixedsize_ptr
65 v_raw = hop.genop("direct_call",
66 [funcptr, c_size],
67 resulttype=llmemory.Address)
78 opname = 'boehm_malloc'
79 tr = self.translator
80 if tr and tr.config.translation.reverse_debugger:
81 # Don't check for NULLs after the operation (it crashes anyway
82 # with an explicit error message in case of out-of-memory).
83 # Avoiding a direct_call lets _RPY_REVDB_PRUID() prints the
84 # right file/line, at least for fixed-size mallocs.
85 v_raw = hop.genop(opname, [c_size], resulttype=llmemory.GCREF)
86 else:
87 v_raw = hop.genop("direct_call",
88 [funcptr, c_size],
89 resulttype=llmemory.GCREF)
6890 finalizer_ptr = self.finalizer_funcptr_for_type(TYPE)
6991 if finalizer_ptr:
7092 c_finalizer_ptr = Constant(finalizer_ptr, self.FINALIZER_PTR)
78100 v_raw = hop.genop("direct_call",
79101 [self.malloc_varsize_no_length_ptr, v_length,
80102 c_const_size, c_item_size],
81 resulttype=llmemory.Address)
103 resulttype=llmemory.GCREF)
82104 else:
83105 v_raw = hop.genop("direct_call",
84106 [self.malloc_varsize_ptr, v_length,
85107 c_const_size, c_item_size, c_offset_to_length],
86 resulttype=llmemory.Address)
108 resulttype=llmemory.GCREF)
87109 return v_raw
88110
89111 def finalizer_funcptr_for_type(self, TYPE):
101123 if destrptr:
102124 EXC_INSTANCE_TYPE = self.translator.rtyper.exceptiondata.lltype_of_exception_value
103125 typename = TYPE.__name__
104 def ll_finalizer(addr):
126 revdb = self.translator.config.translation.reverse_debugger
127 def ll_finalizer(gcref):
105128 exc_instance = llop.gc_fetch_exception(EXC_INSTANCE_TYPE)
106 v = llmemory.cast_adr_to_ptr(addr, DESTR_ARG)
129 if revdb:
130 llop.revdb_call_destructor(lltype.Void, gcref)
131 v = lltype.cast_opaque_ptr(DESTR_ARG, gcref)
107132 ll_call_destructor(destrptr, v, typename)
108133 llop.gc_restore_exception(lltype.Void, exc_instance)
109 fptr = self.annotate_finalizer(ll_finalizer, [llmemory.Address], lltype.Void)
134 fptr = self.annotate_finalizer(ll_finalizer, [llmemory.GCREF], lltype.Void)
110135 else:
111136 fptr = lltype.nullptr(self.FINALIZER_PTR.TO)
112137
148173
149174 def gct_weakref_create(self, hop):
150175 v_instance, = hop.spaceop.args
151 v_addr = hop.genop("cast_ptr_to_adr", [v_instance],
152 resulttype=llmemory.Address)
176 v_gcref = hop.genop("cast_opaque_ptr", [v_instance],
177 resulttype=llmemory.GCREF)
153178 v_wref = hop.genop("direct_call",
154 [self.weakref_create_ptr, v_addr],
179 [self.weakref_create_ptr, v_gcref],
155180 resulttype=llmemory.WeakRefPtr)
156181 hop.cast_result(v_wref)
157182
163188
164189 def gct_weakref_deref(self, hop):
165190 v_wref, = hop.spaceop.args
166 v_addr = hop.genop("direct_call",
167 [self.weakref_deref_ptr, v_wref],
168 resulttype=llmemory.Address)
169 hop.cast_result(v_addr)
191 v_gcref = hop.genop("direct_call",
192 [self.weakref_deref_ptr, v_wref],
193 resulttype=llmemory.GCREF)
194 hop.cast_result(v_gcref)
170195
171196 def gct_gc_writebarrier_before_copy(self, hop):
172197 # no write barrier needed
177202
178203 def gct_gc_identityhash(self, hop):
179204 v_obj = hop.spaceop.args[0]
180 v_adr = hop.genop("cast_ptr_to_adr", [v_obj],
181 resulttype=llmemory.Address)
182 hop.genop("direct_call", [self.identityhash_ptr, v_adr],
183 resultvar=hop.spaceop.result)
205 if not self.translator.config.translation.reverse_debugger:
206 v_addr = hop.genop("cast_ptr_to_adr", [v_obj],
207 resulttype=llmemory.Address)
208 hop.genop("direct_call", [self.identityhash_ptr, v_addr],
209 resultvar=hop.spaceop.result)
210 else:
211 hop.genop("revdb_identityhash", [v_obj],
212 resultvar=hop.spaceop.result)
184213
185214 def gct_gc_id(self, hop):
186215 # this is the logic from the HIDE_POINTER macro in <gc/gc.h>
188217 resulttype = lltype.Signed)
189218 hop.genop('int_invert', [v_int], resultvar=hop.spaceop.result)
190219
220 def gcheader_initdata(self, obj):
221 if not self.translator.config.translation.reverse_debugger:
222 return GCTransform.gcheader_initdata(self, obj)
223 hdr = lltype.malloc(self.HDR, immortal=True, zero=True)
224 return hdr._obj
225
191226
192227 ########## weakrefs ##########
193228 # Boehm: weakref objects are small structures containing only a Boehm
194229 # disappearing link. We don't have to hide the link's value with
195230 # HIDE_POINTER(), because we explicitly use GC_MALLOC_ATOMIC().
196231
197 WEAKLINK = lltype.FixedSizeArray(llmemory.Address, 1)
198 sizeof_weakreflink = llmemory.sizeof(WEAKLINK)
199 empty_weaklink = lltype.malloc(WEAKLINK, immortal=True)
200 empty_weaklink[0] = llmemory.NULL
201
202 def ll_weakref_create(targetaddr):
203 link = llop.boehm_malloc_atomic(llmemory.Address, sizeof_weakreflink)
204 if not link:
205 raise MemoryError
206 plink = llmemory.cast_adr_to_ptr(link, lltype.Ptr(WEAKLINK))
207 plink[0] = targetaddr
208 llop.boehm_disappearing_link(lltype.Void, link, targetaddr)
209 return llmemory.cast_ptr_to_weakrefptr(plink)
210
211 def ll_weakref_deref(wref):
212 plink = llmemory.cast_weakrefptr_to_ptr(lltype.Ptr(WEAKLINK), wref)
213 return plink[0]
214
215 def convert_weakref_to(targetptr):
216 # Prebuilt weakrefs don't really need to be weak at all,
217 # but we need to emulate the structure expected by ll_weakref_deref().
218 # This is essentially the same code as in ll_weakref_create(), but I'm
219 # not sure trying to share it is worth the hassle...
220 if not targetptr:
221 return empty_weaklink
232 def build_weakref(config):
233 revdb = config.translation.reverse_debugger
234 if not revdb:
235 WEAKLINK = lltype.Struct('WEAKLINK',
236 ('addr', llmemory.Address))
222237 else:
223 plink = lltype.malloc(WEAKLINK, immortal=True)
224 plink[0] = llmemory.cast_ptr_to_adr(targetptr)
225 return plink
238 # keep in sync with 'struct WEAKLINK' in revdb.c
239 WEAKLINK = lltype.Struct('REVDB_WEAKLINK',
240 ('addr', llmemory.Address),
241 ('off_prev', lltype.SignedLongLong))
242 sizeof_weakreflink = llmemory.sizeof(WEAKLINK)
243 empty_weaklink = lltype.malloc(WEAKLINK, immortal=True, zero=True)
244
245 def ll_weakref_create(target_gcref):
246 if revdb:
247 plink = llop.revdb_weakref_create(lltype.Ptr(WEAKLINK),
248 target_gcref)
249 else:
250 link = llop.boehm_malloc_atomic(llmemory.Address,
251 sizeof_weakreflink)
252 if not link:
253 raise MemoryError
254 plink = llmemory.cast_adr_to_ptr(link, lltype.Ptr(WEAKLINK))
255 plink.addr = llmemory.cast_ptr_to_adr(target_gcref)
256 llop.boehm_disappearing_link(lltype.Void, link, target_gcref)
257 return llmemory.cast_ptr_to_weakrefptr(plink)
258
259 def ll_weakref_deref(wref):
260 plink = llmemory.cast_weakrefptr_to_ptr(lltype.Ptr(WEAKLINK), wref)
261 if revdb:
262 result = llop.revdb_weakref_deref(llmemory.GCREF, plink)
263 else:
264 result = llmemory.cast_adr_to_ptr(plink.addr, llmemory.GCREF)
265 return result
266
267 def convert_weakref_to(targetptr):
268 # Prebuilt weakrefs don't really need to be weak at all,
269 # but we need to emulate the structure expected by ll_weakref_deref().
270 # This is essentially the same code as in ll_weakref_create(), but I'm
271 # not sure trying to share it is worth the hassle...
272 if not targetptr:
273 return empty_weaklink
274 else:
275 plink = lltype.malloc(WEAKLINK, immortal=True, zero=True)
276 plink.addr = llmemory.cast_ptr_to_adr(targetptr)
277 return plink
278
279 return ll_weakref_create, ll_weakref_deref, WEAKLINK, convert_weakref_to
308308
309309 self.collect_ptr = getfn(GCClass.collect.im_func,
310310 [s_gc, annmodel.SomeInteger()], annmodel.s_None)
311 self.collect_step_ptr = getfn(GCClass.collect_step.im_func, [s_gc],
312 annmodel.SomeInteger())
313 self.enable_ptr = getfn(GCClass.enable.im_func, [s_gc], annmodel.s_None)
314 self.disable_ptr = getfn(GCClass.disable.im_func, [s_gc], annmodel.s_None)
315 self.isenabled_ptr = getfn(GCClass.isenabled.im_func, [s_gc],
316 annmodel.s_Bool)
311317 self.can_move_ptr = getfn(GCClass.can_move.im_func,
312318 [s_gc, SomeAddress()],
313319 annmodel.SomeBool())
882888 hop.genop("direct_call", [self.collect_ptr, self.c_const_gc, v_gen],
883889 resultvar=op.result)
884890 self.pop_roots(hop, livevars)
891
892 def gct_gc__collect_step(self, hop):
893 op = hop.spaceop
894 livevars = self.push_roots(hop)
895 hop.genop("direct_call", [self.collect_step_ptr, self.c_const_gc],
896 resultvar=op.result)
897 self.pop_roots(hop, livevars)
898
899 def gct_gc__enable(self, hop):
900 op = hop.spaceop
901 hop.genop("direct_call", [self.enable_ptr, self.c_const_gc],
902 resultvar=op.result)
903
904 def gct_gc__disable(self, hop):
905 op = hop.spaceop
906 hop.genop("direct_call", [self.disable_ptr, self.c_const_gc],
907 resultvar=op.result)
908
909 def gct_gc__isenabled(self, hop):
910 op = hop.spaceop
911 hop.genop("direct_call", [self.isenabled_ptr, self.c_const_gc],
912 resultvar=op.result)
885913
886914 def gct_gc_can_move(self, hop):
887915 op = hop.spaceop
5252 def ll_no_pointer_dealloc(adr):
5353 llop.gc_free(lltype.Void, adr)
5454
55 mh = mallocHelpers()
55 mh = mallocHelpers(gckind='gc')
5656 mh.allocate = llmemory.raw_malloc
5757 def ll_malloc_fixedsize(size):
5858 size = gc_header_offset + size
00 from rpython.rtyper.lltypesystem import lltype
1 from rpython.rtyper.lltypesystem.lloperation import llop
12 from rpython.rtyper.extregistry import ExtRegistryEntry
23 from rpython.annotator import model as annmodel
34 import os
7778 return c_write(fd, string, len(string))
7879
7980 def ll_call_destructor(destrptr, destr_v, typename):
81 llop.revdb_do_next_call(lltype.Void)
8082 try:
8183 destrptr(destr_v)
8284 except Exception as e:
423423
424424 # ________________________________________________________________
425425
426 def mallocHelpers():
426 def mallocHelpers(gckind):
427427 class _MallocHelpers(object):
428428 def _freeze_(self):
429429 return True
461461 mh._ll_malloc_varsize_no_length = _ll_malloc_varsize_no_length
462462 mh.ll_malloc_varsize_no_length = _ll_malloc_varsize_no_length
463463
464 if gckind == 'raw':
465 llopstore = llop.raw_store
466 elif gckind == 'gc':
467 llopstore = llop.gc_store
468 else:
469 raise AssertionError(gckind)
470
471
464472 def ll_malloc_varsize(length, size, itemsize, lengthoffset):
465473 result = mh.ll_malloc_varsize_no_length(length, size, itemsize)
466 (result + lengthoffset).signed[0] = length
474 llopstore(lltype.Void, result, lengthoffset, length)
467475 return result
468476 mh.ll_malloc_varsize = ll_malloc_varsize
469477
482490 def __init__(self, translator, inline=False):
483491 super(GCTransformer, self).__init__(translator, inline=inline)
484492
485 mh = mallocHelpers()
493 mh = mallocHelpers(gckind='raw')
486494 mh.allocate = llmemory.raw_malloc
487495 ll_raw_malloc_fixedsize = mh._ll_malloc_fixedsize
488496 ll_raw_malloc_fixedsize_zero = mh._ll_malloc_fixedsize_zero
3232 'arpa/inet.h',
3333 'stdint.h',
3434 'errno.h',
35 'limits.h',
3536 )
3637 if _HAS_AF_PACKET:
3738 includes += ('netpacket/packet.h',
112113 F_GETFL = platform.DefinedConstantInteger('F_GETFL')
113114 F_SETFL = platform.DefinedConstantInteger('F_SETFL')
114115 FIONBIO = platform.DefinedConstantInteger('FIONBIO')
116 PIPE_BUF = platform.DefinedConstantInteger('PIPE_BUF')
115117
116118 INVALID_SOCKET = platform.DefinedConstantInteger('INVALID_SOCKET')
117119 INET_ADDRSTRLEN = platform.DefinedConstantInteger('INET_ADDRSTRLEN')
10841086 WSAEWOULDBLOCK = cConfig.WSAEWOULDBLOCK or cConfig.EWOULDBLOCK
10851087 WSAEAFNOSUPPORT = cConfig.WSAEAFNOSUPPORT or cConfig.EAFNOSUPPORT
10861088 EISCONN = cConfig.EISCONN or cConfig.WSAEISCONN
1089 PIPE_BUF = cConfig.PIPE_BUF # may be None
10871090
10881091 linux = cConfig.linux
10891092 WIN32 = cConfig.WIN32
55 from rpython.rtyper.lltypesystem.rstr import STR
66 from rpython.rtyper.lltypesystem.rlist import LIST_OF
77 from rpython.rtyper.annlowlevel import llstr
8 from rpython.rlib.objectmodel import specialize
8 from rpython.rlib.objectmodel import specialize, we_are_translated
99 from rpython.rlib import jit
1010 from rpython.rlib.rgc import (resizable_list_supporting_raw_ptr,
1111 nonmoving_raw_ptr_for_resizable_list,
112112 Write the value of type TP at byte_offset. No bounds checks
113113 """
114114 raise CannotWrite
115
116 def get_raw_address(self):
117 msg = "cannot take the raw address of this buffer"
118 if not we_are_translated():
119 msg += " '%s'" % (self,)
120 raise ValueError(msg)
115121
116122
117123 class RawBuffer(Buffer):
33
44 from rpython.rtyper.tool import rffi_platform
55 from rpython.rtyper.lltypesystem import lltype, rffi
6 from rpython.rtyper.lltypesystem.lloperation import llop
67 from rpython.rtyper.tool import rffi_platform
78 from rpython.rlib.unroll import unrolling_iterable
89 from rpython.rlib.rarithmetic import intmask, is_emulated_long
419420 (what the real callback is for example), casted to VOIDP
420421 """
421422 userdata = rffi.cast(USERDATA_P, ll_userdata)
423 llop.revdb_do_next_call(lltype.Void)
422424 userdata.callback(ll_args, ll_res, userdata)
423425
424426 def ll_callback(ffi_cif, ll_res, ll_args, ll_userdata):
00 import sys
11 import time
2
2 from collections import Counter
3
4 from rpython.rlib.objectmodel import enforceargs
35 from rpython.rtyper.extregistry import ExtRegistryEntry
46 from rpython.rlib.objectmodel import we_are_translated, always_inline
57 from rpython.rlib.rarithmetic import is_valid_int, r_longlong
3638 assert False, ("nesting error: no start corresponding to stop %r" %
3739 (category,))
3840
41 def reset(self):
42 # only for tests: empty the log
43 self[:] = []
44
45 def summary(self, flatten=False):
46 res = Counter()
47 def visit(lst):
48 for section, sublist in lst:
49 if section == 'debug_print':
50 continue
51 res[section] += 1
52 if flatten:
53 visit(sublist)
54 #
55 visit(self)
56 return res
57
3958 def __repr__(self):
4059 import pprint
4160 return pprint.pformat(list(self))
7493 _stop_colors = ""
7594
7695 @always_inline
96 @enforceargs(str, bool)
7797 def debug_start(category, timestamp=False):
7898 """
7999 Start a PYPYLOG section.
84104 return _debug_start(category, timestamp)
85105
86106 @always_inline
107 @enforceargs(str, bool)
87108 def debug_stop(category, timestamp=False):
88109 """
89110 Stop a PYPYLOG section. See debug_start for docs about timestamp
190211
191212
192213 def debug_flush():
193 """ Flushes the debug file
214 """ Flushes the debug file.
215
216 With the reverse-debugger, it also closes the output log.
194217 """
195218 pass
196219
150150 if getattr(func, '_elidable_function_', False):
151151 raise TypeError("it does not make sense for %s to be both elidable and unroll_safe" % func)
152152 if not getattr(func, '_jit_look_inside_', True):
153 raise TypeError("it does not make sense for %s to be both elidable and dont_look_inside" % func)
153 raise TypeError("it does not make sense for %s to be both unroll_safe and dont_look_inside" % func)
154154 func._jit_unroll_safe_ = True
155155 return func
156156
372372 hop.exception_cannot_occur()
373373 return hop.inputconst(lltype.Void, translator.config)
374374
375
376 def revdb_flag_io_disabled():
377 if not revdb_enabled():
378 return False
379 return _revdb_flag_io_disabled()
380
381 def _revdb_flag_io_disabled():
382 # moved in its own function for the import statement
383 from rpython.rlib import revdb
384 return revdb.flag_io_disabled()
385
386 @not_rpython
387 def revdb_enabled():
388 return False
389
390 class Entry(ExtRegistryEntry):
391 _about_ = revdb_enabled
392
393 def compute_result_annotation(self):
394 from rpython.annotator import model as annmodel
395 config = self.bookkeeper.annotator.translator.config
396 if config.translation.reverse_debugger:
397 return annmodel.s_True
398 else:
399 return annmodel.s_False
400
401 def specialize_call(self, hop):
402 from rpython.rtyper.lltypesystem import lltype
403 hop.exception_cannot_occur()
404 return hop.inputconst(lltype.Bool, hop.s_result.const)
405
375406 # ____________________________________________________________
376407
377408 class FREED_OBJECT(object):
959990 items = d.items()
960991 d.clear()
961992 d[key] = value
962 d.update(items)
993 # r_dict.update does not support list of tuples, do it manually
994 for key, value in items:
995 d[key] = value
963996
964997 @specialize.call_location()
965998 def move_to_end(d, key, last=True):
839839 return z
840840
841841
842 @specialize.memo()
843 def check_support_int128():
844 from rpython.rtyper.lltypesystem import rffi
845 return hasattr(rffi, '__INT128_T')
846
847 def mulmod(a, b, c):
848 """Computes (a * b) % c.
849 Assumes c > 0, and returns a nonnegative result.
850 """
851 assert c > 0
852 if LONG_BIT < LONGLONG_BIT:
853 a = r_longlong(a)
854 b = r_longlong(b)
855 return intmask((a * b) % c)
856 elif check_support_int128():
857 a = r_longlonglong(a)
858 b = r_longlonglong(b)
859 return intmask((a * b) % c)
860 else:
861 from rpython.rlib.rbigint import rbigint
862 a = rbigint.fromlong(a)
863 b = rbigint.fromlong(b)
864 return a.mul(b).int_mod(c).toint()
865
866
842867 # String parsing support
843868 # ---------------------------
844869
845 def string_to_int(s, base=10, allow_underscores=False):
870 def string_to_int(s, base=10, allow_underscores=False, no_implicit_octal=False):
846871 """Utility to converts a string to an integer.
847872 If base is 0, the proper base is guessed based on the leading
848873 characters of 's'. Raises ParseStringError in case of error.
852877 NumberStringParser, ParseStringOverflowError, strip_spaces)
853878 s = literal = strip_spaces(s)
854879 p = NumberStringParser(s, literal, base, 'int',
855 allow_underscores=allow_underscores)
880 allow_underscores=allow_underscores,
881 no_implicit_octal=no_implicit_octal)
856882 base = p.base
857883 result = 0
858884 while True:
00 from rpython.rlib.rarithmetic import LONG_BIT, intmask, longlongmask, r_uint, r_ulonglong
11 from rpython.rlib.rarithmetic import ovfcheck, r_longlong, widen
22 from rpython.rlib.rarithmetic import most_neg_value_of_same_type
3 from rpython.rlib.rarithmetic import check_support_int128
34 from rpython.rlib.rstring import StringBuilder
45 from rpython.rlib.debug import make_sure_not_resized, check_regular_int
56 from rpython.rlib.objectmodel import we_are_translated, specialize, not_rpython
910
1011 import math, sys
1112
12 SUPPORT_INT128 = hasattr(rffi, '__INT128_T')
13 SUPPORT_INT128 = check_support_int128()
1314 BYTEORDER = sys.byteorder
1415
1516 # note about digit sizes:
27462747 dec_per_digit -= 1
27472748 return base ** dec_per_digit
27482749
2749 BASE_MAX = [0, 0] + [digits_max_for_base(_base) for _base in range(2, 37)]
2750 BASE_MAX = [0, 1] + [digits_max_for_base(_base) for _base in range(2, 37)]
27502751 DEC_MAX = digits_max_for_base(10)
27512752 assert DEC_MAX == BASE_MAX[10]
27522753
27812782 def parse_digit_string(parser):
27822783 # helper for fromstr
27832784 base = parser.base
2784 if (base & (base - 1)) == 0:
2785 if (base & (base - 1)) == 0 and base >= 2:
27852786 return parse_string_from_binary_base(parser)
27862787 a = rbigint()
27872788 digitmax = BASE_MAX[base]
22 from rpython.translator.tool.cbuild import ExternalCompilationInfo
33 from rpython.translator import cdir
44 from rpython.rtyper.lltypesystem import lltype, rffi
5 from rpython.rlib import jit
5 from rpython.rlib import jit, objectmodel
66 from rpython.rlib.rstring import StringBuilder
77 import py, sys
88
5353 def strtod(input):
5454 if len(input) > _INT_LIMIT:
5555 raise MemoryError
56 if objectmodel.revdb_flag_io_disabled():
57 return _revdb_strtod(input)
5658 end_ptr = lltype.malloc(rffi.CCHARPP.TO, 1, flavor='raw')
5759 try:
5860 # note: don't use the class scoped_view_charp here, it
237239 special_strings=lower_special_strings, upper=False):
238240 if precision > _INT_LIMIT:
239241 raise MemoryError
242 if objectmodel.revdb_flag_io_disabled():
243 return _revdb_dtoa(value)
240244 decpt_ptr = lltype.malloc(rffi.INTP.TO, 1, flavor='raw')
241245 try:
242246 sign_ptr = lltype.malloc(rffi.INTP.TO, 1, flavor='raw')
300304
301305 return dtoa(value, code, mode=mode, precision=precision, flags=flags,
302306 special_strings=special_strings, upper=upper)
307
308 def _revdb_strtod(input):
309 # moved in its own function for the import statement
310 from rpython.rlib import revdb
311 return revdb.emulate_strtod(input)
312
313 def _revdb_dtoa(value):
314 # moved in its own function for the import statement
315 from rpython.rlib import revdb
316 return revdb.emulate_dtoa(value)
232232 raise DLOpenError(ustr.encode('utf-8'))
233233 return res
234234
235 def dlopenex(name):
236 res = rwin32.LoadLibraryExA(name)
237 if not res:
238 err = rwin32.GetLastError_saved()
239 ustr = rwin32.FormatErrorW(err)
240 # DLOpenError unicode msg breaks translation of cpyext create_extension_module
241 raise DLOpenError(ustr.encode('utf-8'))
242 return res
243
244 def dlopenU(name, mode=-1):
245 # mode is unused on windows, but a consistant signature
246 res = rwin32.LoadLibraryW(name)
247 if not res:
248 err = rwin32.GetLastError_saved()
249 ustr = rwin32.FormatErrorW(err)
250 # DLOpenError unicode msg breaks translation of cpyext create_extension_module
251 raise DLOpenError(ustr.encode('utf-8'))
252 return res
253
235254 def dlclose(handle):
236255 res = rwin32.FreeLibrary(handle)
237256 if res:
0 import sys
1 from rpython.rlib.objectmodel import we_are_translated, fetch_translated_config
2 from rpython.rlib.objectmodel import specialize
3 from rpython.rlib.rarithmetic import r_longlong
4 from rpython.rtyper.lltypesystem import lltype, llmemory, rstr
5 from rpython.rtyper.lltypesystem.lloperation import llop
6 from rpython.rtyper.extregistry import ExtRegistryEntry
7 from rpython.rtyper.annlowlevel import llhelper, hlstr
8 from rpython.rtyper.annlowlevel import cast_gcref_to_instance
9 from rpython.rtyper.lltypesystem import lltype, rffi
10
11
12 CMD_PRINT = 1
13 CMD_BACKTRACE = 2
14 CMD_LOCALS = 3
15 CMD_BREAKPOINTS = 4
16 CMD_STACKID = 5
17 CMD_ATTACHID = 6
18 CMD_COMPILEWATCH= 7
19 CMD_CHECKWATCH = 8
20 CMD_WATCHVALUES = 9
21 ANSWER_LINECACHE= 19
22 ANSWER_TEXT = 20
23 ANSWER_STACKID = 21
24 ANSWER_NEXTNID = 22
25 ANSWER_WATCH = 23
26 ANSWER_CHBKPT = 24
27
28
29 def stop_point(place=0):
30 """Indicates a point in the execution of the RPython program where
31 the reverse-debugger can stop. When reverse-debugging, we see
32 the "time" as the index of the stop-point that happened.
33 """
34 if we_are_translated():
35 if fetch_translated_config().translation.reverse_debugger:
36 llop.revdb_stop_point(lltype.Void, place)
37
38 def register_debug_command(command, lambda_func):
39 """Register the extra RPython-implemented debug command."""
40
41 def send_answer(cmd, arg1=0, arg2=0, arg3=0, extra=""):
42 """For RPython debug commands: writes an answer block to stdout"""
43 llop.revdb_send_answer(lltype.Void, cmd, arg1, arg2, arg3, extra)
44
45 def send_output(text):
46 send_answer(ANSWER_TEXT, extra=text)
47
48 def send_print(text):
49 send_answer(ANSWER_TEXT, 1, extra=text) # adds a newline
50
51 def send_nextnid(unique_id):
52 send_answer(ANSWER_NEXTNID, unique_id)
53
54 def send_watch(text, ok_flag):
55 send_answer(ANSWER_WATCH, ok_flag, extra=text)
56
57 def send_linecache(filename, linenum, strip=True):
58 send_answer(ANSWER_LINECACHE, linenum, int(strip), extra=filename)
59
60 def send_change_breakpoint(breakpointnum, newtext=''):
61 send_answer(ANSWER_CHBKPT, breakpointnum, extra=newtext)
62
63 def current_time():
64 """For RPython debug commands: returns the current time."""
65 return llop.revdb_get_value(lltype.SignedLongLong, 'c')
66
67 def current_break_time():
68 """Returns the time configured for the next break. When going forward,
69 this is the target time at which we'll stop going forward."""
70 return llop.revdb_get_value(lltype.SignedLongLong, 'b')
71
72 def total_time():
73 """For RPython debug commands: returns the total time (measured
74 as the total number of stop-points)."""
75 return llop.revdb_get_value(lltype.SignedLongLong, 't')
76
77 def currently_created_objects():
78 """For RPython debug commands: returns the current value of
79 the object creation counter. All objects created so far have
80 a lower unique id; all objects created afterwards will have a
81 unique id greater or equal."""
82 return llop.revdb_get_value(lltype.SignedLongLong, 'u')
83
84 def current_place():
85 """For RPython debug commands: the value of the 'place' argument
86 passed to stop_point().
87 """
88 return llop.revdb_get_value(lltype.Signed, 'p')
89
90 def flag_io_disabled():
91 """Returns True if we're in the debugger typing commands."""
92 if we_are_translated():
93 if fetch_translated_config().translation.reverse_debugger:
94 flag = llop.revdb_get_value(lltype.Signed, 'i')
95 return flag != ord('R') # FID_REGULAR_MODE
96 return False
97
98 ## @specialize.arg(1)
99 ## def go_forward(time_delta, callback):
100 ## """For RPython debug commands: tells that after this function finishes,
101 ## the debugger should run the 'forward <time_delta>' command and then
102 ## invoke the 'callback' with no argument.
103 ## """
104 ## _change_time('f', time_delta, callback)
105
106 def breakpoint(num):
107 llop.revdb_breakpoint(lltype.Void, num)
108
109 def set_thread_breakpoint(tnum):
110 llop.revdb_set_thread_breakpoint(lltype.Void, tnum)
111
112 @specialize.argtype(0)
113 def get_unique_id(x):
114 """Returns the creation number of the object 'x'. For objects created
115 by the program, it is globally unique, monotonic, and reproducible
116 among multiple processes. For objects created by a debug command,
117 this returns a (random) negative number. Right now, this returns 0
118 for all prebuilt objects.
119 """
120 return llop.revdb_get_unique_id(lltype.SignedLongLong, x)
121
122 def track_object(unique_id, callback):
123 """Track the creation of the object given by its unique_id, which must
124 be in the future (i.e. >= currently_created_objects()). Call this
125 before go_forward(). If go_forward() goes over the creation of this
126 object, then 'callback(gcref)' is called. Careful in callback(),
127 gcref is not fully initialized and should not be immediately read from,
128 only stored for later. The purpose of callback() is to possibly
129 call track_object() again to track the next object, and/or to call
130 breakpoint(). Note: object tracking remains activated until one of:
131 (1) we reach the creation time in go_forward(); (2) we call
132 track_object() to track a different object; (3) we call jump_in_time().
133 """
134 ll_callback = llhelper(_CALLBACK_GCREF_FNPTR, callback)
135 llop.revdb_track_object(lltype.Void, unique_id, ll_callback)
136
137 def watch_save_state(force=False):
138 return llop.revdb_watch_save_state(lltype.Bool, force)
139
140 def watch_restore_state(any_watch_point):
141 llop.revdb_watch_restore_state(lltype.Void, any_watch_point)
142
143
144 def split_breakpoints_arg(breakpoints):
145 # RPython generator to help in splitting the string arg in CMD_BREAKPOINTS
146 n = 0
147 i = 0
148 while i < len(breakpoints):
149 kind = breakpoints[i]
150 i += 1
151 if kind != '\x00':
152 length = (ord(breakpoints[i]) |
153 (ord(breakpoints[i + 1]) << 8) |
154 (ord(breakpoints[i + 2]) << 16))
155 assert length >= 0
156 i += 3
157 yield n, kind, breakpoints[i : i + length]
158 i += length
159 n += 1
160 assert i == len(breakpoints)
161
162
163 # ____________________________________________________________
164
165
166 ## @specialize.arg(2)
167 ## def _change_time(mode, time, callback):
168 ## ll_callback = llhelper(_CALLBACK_NOARG_FNPTR, callback)
169 ## llop.revdb_change_time(lltype.Void, mode, time, ll_callback)
170 ## _CALLBACK_NOARG_FNPTR = lltype.Ptr(lltype.FuncType([], lltype.Void))
171 _CALLBACK_GCREF_FNPTR = lltype.Ptr(lltype.FuncType([llmemory.GCREF],
172 lltype.Void))
173 _CMDPTR = rffi.CStructPtr('rpy_revdb_command_s',
174 ('cmd', rffi.INT),
175 ('arg1', lltype.SignedLongLong),
176 ('arg2', lltype.SignedLongLong),
177 ('arg3', lltype.SignedLongLong),
178 hints={'ignore_revdb': True})
179
180
181 class RegisterDebugCommand(ExtRegistryEntry):
182 _about_ = register_debug_command
183
184 def compute_result_annotation(self, s_command_num, s_lambda_func):
185 command_num = s_command_num.const
186 lambda_func = s_lambda_func.const
187 assert isinstance(command_num, (int, str))
188 t = self.bookkeeper.annotator.translator
189 if t.config.translation.reverse_debugger:
190 func = lambda_func()
191 try:
192 cmds = t.revdb_commands
193 except AttributeError:
194 cmds = t.revdb_commands = {}
195 old_func = cmds.setdefault(command_num, func)
196 assert old_func is func
197 s_func = self.bookkeeper.immutablevalue(func)
198 arg_getter = getattr(self, 'arguments_' + str(command_num),
199 self.default_arguments)
200 self.bookkeeper.emulate_pbc_call(self.bookkeeper.position_key,
201 s_func, arg_getter())
202
203 def default_arguments(self):
204 from rpython.annotator import model as annmodel
205 from rpython.rtyper import llannotation
206 return [llannotation.SomePtr(ll_ptrtype=_CMDPTR),
207 annmodel.SomeString()]
208
209 def arguments_ALLOCATING(self):
210 from rpython.annotator import model as annmodel
211 from rpython.rtyper import llannotation
212 return [annmodel.SomeInteger(knowntype=r_longlong),
213 llannotation.lltype_to_annotation(llmemory.GCREF)]
214
215 def arguments_WATCHING(self):
216 raise Exception("XXX remove me")
217
218 def specialize_call(self, hop):
219 hop.exception_cannot_occur()
220
221
222 # ____________________________________________________________
223
224 # Emulation for strtod() and dtoa() when running debugger commands
225 # (we can't easily just call C code there). The emulation can return
226 # a crude result. Hack hack hack.
227
228 _INVALID_STRTOD = -3.46739514239368e+113
229
230 def emulate_strtod(input):
231 d = llop.revdb_strtod(lltype.Float, input)
232 if d == _INVALID_STRTOD:
233 raise ValueError
234 return d
235
236 def emulate_dtoa(value):
237 s = llop.revdb_dtoa(lltype.Ptr(rstr.STR), value)
238 s = hlstr(s)
239 assert s is not None
240 return s
241
242 def emulate_modf(x):
243 return (llop.revdb_modf(lltype.Float, x, 0),
244 llop.revdb_modf(lltype.Float, x, 1))
245
246 def emulate_frexp(x):
247 return (llop.revdb_frexp(lltype.Float, x, 0),
248 int(llop.revdb_frexp(lltype.Float, x, 1)))
1212 # General GC features
1313
1414 collect = gc.collect
15 enable = gc.enable
16 disable = gc.disable
17 isenabled = gc.isenabled
18
19 def collect_step():
20 """
21 If the GC is incremental, run a single gc-collect-step.
22
23 Return an integer which encodes the starting and ending GC state. Use
24 rgc.{old_state,new_state,is_done} to decode it.
25
26 If the GC is not incremental, do a full collection and return a value on
27 which rgc.is_done() return True.
28 """
29 gc.collect()
30 return _encode_states(1, 0)
31
32 def _encode_states(oldstate, newstate):
33 return oldstate << 8 | newstate
34
35 def old_state(states):
36 return (states & 0xFF00) >> 8
37
38 def new_state(states):
39 return states & 0xFF
40
41 def is_done(states):
42 """
43 Return True if the return value of collect_step signals the end of a major
44 collection
45 """
46 old = old_state(states)
47 new = new_state(states)
48 return is_done__states(old, new)
49
50 def is_done__states(oldstate, newstate):
51 "Like is_done, but takes oldstate and newstate explicitly"
52 # a collection is considered done when it ends up in the starting state
53 # (which is usually represented as 0). This logic works for incminimark,
54 # which is currently the only gc actually used and for which collect_step
55 # is implemented. In case we add more GC in the future, we might want to
56 # delegate this logic to the GC itself, but for now it is MUCH simpler to
57 # just write it in plain RPython.
58 return oldstate != 0 and newstate == 0
1559
1660 def set_max_heap_size(nbytes):
1761 """Limit the heap size to n bytes.
1862 """
1963 pass
64
65 def must_split_gc_address_space():
66 """Returns True if we have a "split GC address space", i.e. if
67 we are translating with an option that doesn't support taking raw
68 addresses inside GC objects and "hacking" at them. This is
69 notably the case with --revdb."""
70 return False
2071
2172 # for test purposes we allow objects to be pinned and use
2273 # the following list to keep track of the pinned objects
123174 args_v = hop.inputargs(lltype.Signed)
124175 return hop.genop('gc__collect', args_v, resulttype=hop.r_result)
125176
177
178 class EnableDisableEntry(ExtRegistryEntry):
179 _about_ = (gc.enable, gc.disable)
180
181 def compute_result_annotation(self):
182 from rpython.annotator import model as annmodel
183 return annmodel.s_None
184
185 def specialize_call(self, hop):
186 hop.exception_cannot_occur()
187 opname = self.instance.__name__
188 return hop.genop('gc__%s' % opname, hop.args_v, resulttype=hop.r_result)
189
190
191 class IsEnabledEntry(ExtRegistryEntry):
192 _about_ = gc.isenabled
193
194 def compute_result_annotation(self):
195 from rpython.annotator import model as annmodel
196 return annmodel.s_Bool
197
198 def specialize_call(self, hop):
199 hop.exception_cannot_occur()
200 return hop.genop('gc__isenabled', hop.args_v, resulttype=hop.r_result)
201
202
203 class CollectStepEntry(ExtRegistryEntry):
204 _about_ = collect_step
205
206 def compute_result_annotation(self):
207 from rpython.annotator import model as annmodel
208 return annmodel.SomeInteger()
209
210 def specialize_call(self, hop):
211 hop.exception_cannot_occur()
212 return hop.genop('gc__collect_step', hop.args_v, resulttype=hop.r_result)
213
214
126215 class SetMaxHeapSizeEntry(ExtRegistryEntry):
127216 _about_ = set_max_heap_size
128217
145234 move any more.
146235 """
147236 return True
237
238 class SplitAddrSpaceEntry(ExtRegistryEntry):
239 _about_ = must_split_gc_address_space
240
241 def compute_result_annotation(self):
242 config = self.bookkeeper.annotator.translator.config
243 result = config.translation.split_gc_address_space
244 return self.bookkeeper.immutablevalue(result)
245
246 def specialize_call(self, hop):
247 hop.exception_cannot_occur()
248 return hop.inputconst(lltype.Bool, hop.s_result.const)
148249
149250 class CanMoveEntry(ExtRegistryEntry):
150251 _about_ = can_move
279380
280381 TP = lltype.typeOf(source).TO
281382 assert TP == lltype.typeOf(dest).TO
282 if _contains_gcptr(TP.OF):
383
384 slowpath = False
385 if must_split_gc_address_space():
386 slowpath = True
387 elif _contains_gcptr(TP.OF):
283388 # perform a write barrier that copies necessary flags from
284389 # source to dest
285390 if not llop.gc_writebarrier_before_copy(lltype.Bool, source, dest,
286391 source_start, dest_start,
287392 length):
288 # if the write barrier is not supported, copy by hand
289 i = 0
290 while i < length:
291 copy_item(source, dest, i + source_start, i + dest_start)
292 i += 1
293 return
393 slowpath = True
394 if slowpath:
395 # if the write barrier is not supported, or if we translate with
396 # the option 'split_gc_address_space', then copy by hand
397 i = 0
398 while i < length:
399 copy_item(source, dest, i + source_start, i + dest_start)
400 i += 1
401 return
294402 source_addr = llmemory.cast_ptr_to_adr(source)
295403 dest_addr = llmemory.cast_ptr_to_adr(dest)
296404 cp_source_addr = (source_addr + llmemory.itemoffsetof(TP, 0) +
323431 assert len(TP._names) == 2
324432 field = getattr(p, TP._names[0])
325433 setattr(newp, TP._names[0], field)
434
435 if must_split_gc_address_space():
436 # do the copying element by element
437 i = 0
438 while i < smallerlength:
439 newp.chars[i] = p.chars[i]
440 i += 1
441 return newp
326442
327443 ARRAY = getattr(TP, TP._arrayfld)
328444 offset = (llmemory.offsetof(TP, TP._arrayfld) +
344460
345461 length = len(p)
346462 ARRAY = lltype.typeOf(p).TO
347 offset = llmemory.itemoffsetof(ARRAY, 0)
348 dest_addr = llmemory.cast_ptr_to_adr(p) + offset
349 llmemory.raw_memclear(dest_addr, llmemory.sizeof(ARRAY.OF) * length)
463 if must_split_gc_address_space():
464 # do the clearing element by element
465 from rpython.rtyper.lltypesystem import rffi
466 ZERO = rffi.cast(ARRAY.OF, 0)
467 i = 0
468 while i < length:
469 p[i] = ZERO
470 i += 1
471 else:
472 offset = llmemory.itemoffsetof(ARRAY, 0)
473 dest_addr = llmemory.cast_ptr_to_adr(p) + offset
474 llmemory.raw_memclear(dest_addr, llmemory.sizeof(ARRAY.OF) * length)
350475 keepalive_until_here(p)
351476
352477
660785 (TOTAL_MEMORY, TOTAL_ALLOCATED_MEMORY, TOTAL_MEMORY_PRESSURE,
661786 PEAK_MEMORY, PEAK_ALLOCATED_MEMORY, TOTAL_ARENA_MEMORY,
662787 TOTAL_RAWMALLOCED_MEMORY, PEAK_ARENA_MEMORY, PEAK_RAWMALLOCED_MEMORY,
663 NURSERY_SIZE) = range(10)
788 NURSERY_SIZE, TOTAL_GC_TIME) = range(11)
664789
665790 @not_rpython
666791 def get_stats(stat_no):
834834 # assume -1 and 0 both mean invalid file descriptor
835835 # to 'anonymously' map memory.
836836 if fileno != -1 and fileno != 0:
837 fh = rwin32.get_osfhandle(fileno)
837 fh = rffi.cast(HANDLE, rwin32.get_osfhandle(fileno))
838838 # Win9x appears to need us seeked to zero
839839 # SEEK_SET = 0
840840 # libc._lseek(fileno, 0, SEEK_SET)
136136 RPY_EXTERN void exit_suppress_iph(void* handle) {};
137137 #endif
138138 ''',]
139 post_include_bits=['RPY_EXTERN int _PyVerify_fd(int);']
139 post_include_bits=['RPY_EXTERN int _PyVerify_fd(int);',
140 'RPY_EXTERN void* enter_suppress_iph();',
141 'RPY_EXTERN void exit_suppress_iph(void* handle);',
142 ]
140143 else:
141144 separate_module_sources = []
142145 post_include_bits = []
234237 rthread.tlfield_rpy_errno.setraw(_get_errno())
235238 # ^^^ keep fork() up-to-date too, below
236239 if _WIN32:
237 includes = ['io.h', 'sys/utime.h', 'sys/types.h', 'process.h', 'time.h']
240 includes = ['io.h', 'sys/utime.h', 'sys/types.h', 'process.h', 'time.h',
241 'direct.h']
238242 libraries = []
239243 else:
240244 if sys.platform.startswith(('darwin', 'netbsd', 'openbsd')):
729733 length = rwin32.MAX_PATH + 1
730734 traits = _preferred_traits(path)
731735 win32traits = make_win32_traits(traits)
732 with traits.scoped_alloc_buffer(length) as buf:
733 res = win32traits.GetFullPathName(
734 traits.as_str0(path), rffi.cast(rwin32.DWORD, length),
735 buf.raw, lltype.nullptr(win32traits.LPSTRP.TO))
736 if res == 0:
737 raise rwin32.lastSavedWindowsError("_getfullpathname failed")
738 result = buf.str(intmask(res))
739 assert result is not None
740 result = rstring.assert_str0(result)
741 return result
736 while True: # should run the loop body maximum twice
737 with traits.scoped_alloc_buffer(length) as buf:
738 res = win32traits.GetFullPathName(
739 traits.as_str0(path), rffi.cast(rwin32.DWORD, length),
740 buf.raw, lltype.nullptr(win32traits.LPSTRP.TO))
741 res = intmask(res)
742 if res == 0:
743 raise rwin32.lastSavedWindowsError("_getfullpathname failed")
744 if res >= length:
745 length = res + 1
746 continue
747 result = buf.str(res)
748 assert result is not None
749 result = rstring.assert_str0(result)
750 return result
742751
743752 c_getcwd = external(UNDERSCORE_ON_WIN32 + 'getcwd',
744753 [rffi.CCHARP, rffi.SIZE_T], rffi.CCHARP,
873882
874883 if traits.str is unicode:
875884 if path and path[-1] not in (u'/', u'\\', u':'):
876 path += u'/'
885 path += u'\\'
877886 mask = path + u'*.*'
878887 else:
879888 if path and path[-1] not in ('/', '\\', ':'):
880 path += '/'
889 path += '\\'
881890 mask = path + '*.*'
882891
883892 filedata = lltype.malloc(win32traits.WIN32_FIND_DATA, flavor='raw')
10851094 else:
10861095 return bool(c_func(status))
10871096
1088 WAIT_MACROS = ['WCOREDUMP', 'WIFCONTINUED', 'WIFSTOPPED',
1097 WAIT_MACROS = ['WCOREDUMP', 'WIFSTOPPED',
10891098 'WIFSIGNALED', 'WIFEXITED',
10901099 'WEXITSTATUS', 'WSTOPSIG', 'WTERMSIG']
1100 if not sys.platform.startswith('gnu'):
1101 WAIT_MACROS.append('WIFCONTINUED')
1102
10911103 for name in WAIT_MACROS:
10921104 _make_waitmacro(name)
10931105
1010
1111 str0 = annmodel.s_Str0
1212
13 def llexternal(name, args, result, **kwds):
14 # Issue #2840
15 # All functions defined here should be releasegil=False, both
16 # because it doesn't make much sense to release the GIL and
17 # because the OS environment functions are usually not thread-safe
18 return rffi.llexternal(name, args, result, releasegil=False, **kwds)
19
1320 # ____________________________________________________________
1421 #
1522 # Annotation support to control access to 'os.environ' in the RPython
6572 prefix = ''
6673 if sys.platform.startswith('darwin'):
6774 CCHARPPP = rffi.CArrayPtr(rffi.CCHARPP)
68 _os_NSGetEnviron = rffi.llexternal(
75 _os_NSGetEnviron = llexternal(
6976 '_NSGetEnviron', [], CCHARPPP,
7077 compilation_info=ExternalCompilationInfo(includes=['crt_externs.h'])
7178 )
118125 def r_putenv(name, value):
119126 just_a_placeholder
120127
121 os_getenv = rffi.llexternal('getenv', [rffi.CCHARP], rffi.CCHARP,
122 releasegil=False)
123 os_putenv = rffi.llexternal(prefix + 'putenv', [rffi.CCHARP], rffi.INT,
128 os_getenv = llexternal('getenv', [rffi.CCHARP], rffi.CCHARP)
129 os_putenv = llexternal(prefix + 'putenv', [rffi.CCHARP], rffi.INT,
124130 save_err=rffi.RFFI_SAVE_ERRNO)
125131 if _WIN32:
126 _wgetenv = rffi.llexternal('_wgetenv', [rffi.CWCHARP], rffi.CWCHARP,
127 compilation_info=eci, releasegil=False)
128 _wputenv = rffi.llexternal('_wputenv', [rffi.CWCHARP], rffi.INT,
132 _wgetenv = llexternal('_wgetenv', [rffi.CWCHARP], rffi.CWCHARP,
133 compilation_info=eci)
134 _wputenv = llexternal('_wputenv', [rffi.CWCHARP], rffi.INT,
129135 compilation_info=eci,
130136 save_err=rffi.RFFI_SAVE_LASTERROR)
131137
205211 REAL_UNSETENV = False
206212
207213 if hasattr(__import__(os.name), 'unsetenv'):
208 os_unsetenv = rffi.llexternal('unsetenv', [rffi.CCHARP], rffi.INT,
214 os_unsetenv = llexternal('unsetenv', [rffi.CCHARP], rffi.INT,
209215 save_err=rffi.RFFI_SAVE_ERRNO)
210216
211217 def unsetenv_llimpl(name):
00 from rpython.rtyper.llannotation import lltype_to_annotation
11 from rpython.rlib.objectmodel import specialize
2 from rpython.rlib import jit
2 from rpython.rlib import jit, rgc
33 from rpython.rtyper.lltypesystem import lltype, llmemory
44 from rpython.rtyper.extregistry import ExtRegistryEntry
55 from rpython.tool.pairtype import pair
4949
5050 @jit.dont_look_inside
5151 def ll_copy_list_to_raw_array(ll_list, dst_ptr):
52 if rgc.must_split_gc_address_space():
53 for i in range(ll_list.ll_length()):
54 dst_ptr[i] = ll_list.ll_getitem_fast(i)
55 return
5256 # this code is delicate: we must ensure that there are no GC operations
5357 # around the call to raw_memcopy
5458 #
6367
6468 @jit.dont_look_inside
6569 def ll_populate_list_from_raw_array(ll_list, src_ptr, length):
70 ll_list._ll_resize(length)
71 if rgc.must_split_gc_address_space():
72 for i in range(length):
73 ll_list.ll_setitem_fast(i, src_ptr[i])
74 return
6675 ITEM = lltype.typeOf(src_ptr).TO.OF
6776 size = llmemory.sizeof(ITEM) * length
68 ll_list._ll_resize(length)
6977 # start of no-GC section
7078 src_adr = get_raw_buf(src_ptr)
7179 dst_adr = get_raw_buf(ll_list.ll_items())
8989 pypysig_getaddr_occurred = external('pypysig_getaddr_occurred', [],
9090 lltype.Ptr(LONG_STRUCT), _nowrapper=True,
9191 elidable_function=True)
92 pypysig_check_and_reset = external('pypysig_check_and_reset', [],
93 lltype.Bool, _nowrapper=True)
9294 c_alarm = external('alarm', [rffi.INT], rffi.INT)
9395 c_pause = external('pause', [], rffi.INT, releasegil=True)
9496 c_siginterrupt = external('siginterrupt', [rffi.INT, rffi.INT], rffi.INT,
122122
123123 def compute_result_annotation(self):
124124 translator = self.bookkeeper.annotator.translator
125 if translator.config.translation.reverse_debugger:
126 return # ignore and use the regular hash, with reverse-debugger
125127 if hasattr(translator, 'll_hash_string'):
126128 assert translator.ll_hash_string == ll_hash_string_siphash24
127129 else:
133135
134136 def specialize_call(self, hop):
135137 hop.exception_cannot_occur()
138 translator = hop.rtyper.annotator.translator
139 if translator.config.translation.reverse_debugger:
140 return # ignore and use the regular hash, with reverse-debugger
136141 bk = hop.rtyper.annotator.bookkeeper
137142 s_callable = bk.immutablevalue(initialize_from_env)
138143 r_callable = hop.rtyper.getrepr(s_callable)
549549 self.family = family
550550 self.type = type
551551 self.proto = proto
552 self.timeout = defaults.timeout
552 self.settimeout(defaults.timeout)
553553
554554 @staticmethod
555555 def empty_rsocket():
706706 address.unlock()
707707 errno = _c.geterrno()
708708 timeout = self.timeout
709 if (timeout > 0.0 and res < 0 and
710 errno in (_c.EWOULDBLOCK, _c.WSAEWOULDBLOCK)):
709 if (timeout > 0.0 and res < 0 and
710 errno in (_c.EWOULDBLOCK, _c.WSAEWOULDBLOCK)):
711711 tv = rffi.make(_c.timeval)
712712 rffi.setintfield(tv, 'c_tv_sec', int(timeout))
713713 rffi.setintfield(tv, 'c_tv_usec',
44
55 import py
66
7 from rpython.rlib.objectmodel import we_are_translated
7 from rpython.rlib.objectmodel import we_are_translated, fetch_translated_config
88 from rpython.rlib.rarithmetic import r_uint
99 from rpython.rlib import rgc
1010 from rpython.rtyper.lltypesystem import lltype, rffi
4141 def stack_check():
4242 if not we_are_translated():
4343 return
44 if fetch_translated_config().translation.reverse_debugger:
45 return # XXX for now
4446 #
4547 # Load the "current" stack position, or at least some address that
4648 # points close to the current stack head
433433 raise ParseStringError("invalid literal for %s() with base %d" %
434434 (self.fname, self.original_base))
435435
436 def __init__(self, s, literal, base, fname, allow_underscores=False):
436 def __init__(self, s, literal, base, fname, allow_underscores=False,
437 no_implicit_octal=False):
437438 self.fname = fname
438439 sign = 1
439440 if s.startswith('-'):
444445 self.sign = sign
445446 self.original_base = base
446447 self.allow_underscores = allow_underscores
447 self.last_is_underscore = False
448448
449449 if base == 0:
450450 if s.startswith('0x') or s.startswith('0X'):
452452 elif s.startswith('0b') or s.startswith('0B'):
453453 base = 2
454454 elif s.startswith('0'): # also covers the '0o' case
455 base = 8
455 if no_implicit_octal and not (s.startswith('0o') or
456 s.startswith('0O')):
457 base = 1 # this makes only the digit '0' valid...
458 else:
459 base = 8
456460 else:
457461 base = 10
458462 elif base < 2 or base > 36:
459463 raise InvalidBaseError("%s() base must be >= 2 and <= 36" % fname)
460464 self.base = base
465
466 # Leading underscores are not allowed
467 if s.startswith('_'):
468 self.error()
461469
462470 if base == 16 and (s.startswith('0x') or s.startswith('0X')):
463471 s = s[2:]
477485 def next_digit(self): # -1 => exhausted
478486 if self.i < self.n:
479487 c = self.s[self.i]
488 if self.allow_underscores and c == '_':
489 self.i += 1
490 if self.i >= self.n:
491 self.error()
492 c = self.s[self.i]
480493 digit = ord(c)
481494 if '0' <= c <= '9':
482495 digit -= ord('0')
484497 digit = (digit - ord('A')) + 10
485498 elif 'a' <= c <= 'z':
486499 digit = (digit - ord('a')) + 10
487 elif c == '_' and self.allow_underscores:
488 if self.last_is_underscore:
489 self.error()
490 self.last_is_underscore = True
491 self.i += 1
492 return self.next_digit()
493500 else:
494501 self.error()
495502 if digit >= self.base:
496503 self.error()
497504 self.i += 1
498 self.last_is_underscore = False
499505 return digit
500506 else:
501 if self.last_is_underscore:
502 self.error()
503507 return -1
504508
505509 def prev_digit(self):
119119 if we_are_translated():
120120 return tlfield_thread_ident.get_or_make_raw()
121121 else:
122 try:
123 import thread
124 except ImportError:
125 return 42
126 return thread.get_ident()
122 return get_ident()
127123
128124 @specialize.arg(0)
129125 def start_new_thread(x, y):
353349 def get_or_make_raw():
354350 if we_are_translated():
355351 _threadlocalref_seeme(self)
356 addr = llop.threadlocalref_addr(llmemory.Address)
357 return llop.raw_load(FIELDTYPE, addr, offset)
352 return llop.threadlocalref_load(FIELDTYPE, offset)
358353 else:
359354 return getattr(self.local, 'rawvalue', zero)
360355
362357 def setraw(value):
363358 if we_are_translated():
364359 _threadlocalref_seeme(self)
365 addr = llop.threadlocalref_addr(llmemory.Address)
366 llop.raw_store(lltype.Void, addr, offset, value)
360 llop.threadlocalref_store(lltype.Void, offset, value)
367361 else:
368362 self.local.rawvalue = value
369363
396390 ThreadLocalReference._COUNT += 1
397391 ThreadLocalField.__init__(self, lltype.Signed, 'tlref%d' % unique_id,
398392 loop_invariant=loop_invariant)
399 setraw = self.setraw
400393 offset = self._offset
401394
402395 def get():
413406 def set(value):
414407 assert isinstance(value, Cls) or value is None
415408 if we_are_translated():
416 from rpython.rtyper.annlowlevel import cast_instance_to_gcref
417 gcref = cast_instance_to_gcref(value)
418 value = lltype.cast_ptr_to_int(gcref)
419 setraw(value)
409 from rpython.rtyper.annlowlevel import cast_instance_to_base_ptr
410 ptr = cast_instance_to_base_ptr(value)
411 _threadlocalref_seeme(self)
412 llop.threadlocalref_store(lltype.Void, offset, ptr)
420413 rgc.register_custom_trace_hook(TRACETLREF, _lambda_trace_tlref)
421414 rgc.ll_writebarrier(_tracetlref_obj)
422415 else:
135135 void = lltype.nullptr(rffi.VOIDP.TO)
136136 result = -1.0
137137 if HAVE_GETTIMEOFDAY:
138 with lltype.scoped_alloc(TIMEVAL) as t:
138 # NB: can't use lltype.scoped_malloc, because that will allocate the
139 # with handler in the GC, but we want to use time.time from gc.collect!
140 t = lltype.malloc(TIMEVAL, flavor='raw')
141 try:
139142 errcode = -1
140143 if GETTIMEOFDAY_NO_TZ:
141144 errcode = c_gettimeofday(t)
144147
145148 if rffi.cast(rffi.LONG, errcode) == 0:
146149 result = decode_timeval(t)
150 finally:
151 lltype.free(t, flavor='raw')
147152 if result != -1:
148153 return result
149154 else: # assume using ftime(3)
150 with lltype.scoped_alloc(TIMEB) as t:
155 t = lltype.malloc(TIMEB, flavor='raw')
156 try:
151157 c_ftime(t)
152158 result = (float(intmask(t.c_time)) +
153159 float(intmask(t.c_millitm)) * 0.001)
160 finally:
161 lltype.free(t, flavor='raw')
154162 return result
155163 return float(c_time(void))
156164
17741774 "truncated input",
17751775 s, pos, size)
17761776 result.append(res)
1777 if pos > size - unicode_bytes:
1778 break
17791777 continue
17801778 t = r_uint(0)
17811779 h = 0
1616
1717 # vmprof works only on x86 for now
1818 IS_SUPPORTED = False
19 if sys.platform in ('darwin', 'linux', 'linux2'):
19 if sys.platform in ('darwin', 'linux', 'linux2') or sys.platform.startswith('freebsd'):
2020 try:
2121 IS_SUPPORTED = detect_cpu.autodetect().startswith('x86')
2222 except detect_cpu.ProcessorAutodetectError:
00 from rpython.rlib.objectmodel import specialize
11
22 class DummyVMProf(object):
3 is_enabled = False
34
45 def __init__(self):
56 self._unique_id = 0
2223 pass
2324
2425 def stop_sampling(self):
25 pass
26 return -1
2222 VMPROF_GC_TAG = 5
2323
2424 class VMProfError(Exception):
25 msg = '' # annotation hack
2526 def __init__(self, msg):
2627 self.msg = msg
2728 def __str__(self):
2323
2424 #include "vmprof_mt.h"
2525
26 #ifdef __FreeBSD__
27 #include <ucontext.h>
28 #endif
2629 #include <signal.h>
2730
2831 RPY_EXTERN void vmprof_ignore_signals(int ignored);
1212 array_length). The caller must free array_p. Not for signal handlers:
1313 for these, call vmprof_get_traceback() from C code.
1414 """
15 if not cintf.IS_SUPPORTED:
16 return (None, 0)
1517 _cintf = rvmprof._get_vmprof().cintf
1618 size = estimate_number_of_entries * 2 + 4
1719 stack = cintf.get_rvmprof_stack()
4648 'code_obj' may be None if it can't be determined. 'loc' is one
4749 of the LOC_xxx constants.
4850 """
51 if not cintf.IS_SUPPORTED:
52 return
4953 i = 0
5054 while i < array_length - 1:
5155 tag = array_p[i]
1919
2020 if WIN32:
2121 eci = ExternalCompilationInfo(
22 includes = ['windows.h', 'stdio.h', 'stdlib.h'],
22 includes = ['windows.h', 'stdio.h', 'stdlib.h', 'io.h'],
2323 libraries = ['kernel32'],
2424 )
2525 else:
112112 MB_ERR_INVALID_CHARS ERROR_NO_UNICODE_TRANSLATION
113113 WC_NO_BEST_FIT_CHARS STD_INPUT_HANDLE STD_OUTPUT_HANDLE
114114 STD_ERROR_HANDLE HANDLE_FLAG_INHERIT FILE_TYPE_CHAR
115 LOAD_WITH_ALTERED_SEARCH_PATH
115116 """
116117 from rpython.translator.platform import host_factory
117118 static_platform = host_factory()
194195 GetModuleHandle = winexternal('GetModuleHandleA', [rffi.CCHARP], HMODULE)
195196 LoadLibrary = winexternal('LoadLibraryA', [rffi.CCHARP], HMODULE,
196197 save_err=rffi.RFFI_SAVE_LASTERROR)
198 def wrap_loadlibraryex(func):
199 def loadlibrary(name, flags=LOAD_WITH_ALTERED_SEARCH_PATH):
200 # Requires a full path name with '/' -> '\\'
201 return func(name, NULL_HANDLE, flags)
202 return loadlibrary
203
204 _LoadLibraryExA = winexternal('LoadLibraryExA',
205 [rffi.CCHARP, HANDLE, DWORD], HMODULE,
206 save_err=rffi.RFFI_SAVE_LASTERROR)
207 LoadLibraryExA = wrap_loadlibraryex(_LoadLibraryExA)
208 LoadLibraryW = winexternal('LoadLibraryW', [rffi.CWCHARP], HMODULE,
209 save_err=rffi.RFFI_SAVE_LASTERROR)
210 _LoadLibraryExW = winexternal('LoadLibraryExW',
211 [rffi.CWCHARP, HANDLE, DWORD], HMODULE,
212 save_err=rffi.RFFI_SAVE_LASTERROR)
213 LoadLibraryExW = wrap_loadlibraryex(_LoadLibraryExW)
197214 GetProcAddress = winexternal('GetProcAddress',
198215 [HMODULE, rffi.CCHARP],
199216 rffi.VOIDP)
200217 FreeLibrary = winexternal('FreeLibrary', [HMODULE], BOOL, releasegil=False)
201218
202 LocalFree = winexternal('LocalFree', [HLOCAL], DWORD)
219 LocalFree = winexternal('LocalFree', [HLOCAL], HLOCAL)
203220 CloseHandle = winexternal('CloseHandle', [HANDLE], BOOL, releasegil=False,
204221 save_err=rffi.RFFI_SAVE_LASTERROR)
205222 CloseHandle_no_err = winexternal('CloseHandle', [HANDLE], BOOL,
214231 [DWORD, rffi.VOIDP, DWORD, DWORD, rffi.CWCHARP, DWORD, rffi.VOIDP],
215232 DWORD)
216233
217 _get_osfhandle = rffi.llexternal('_get_osfhandle', [rffi.INT], HANDLE)
234 _get_osfhandle = rffi.llexternal('_get_osfhandle', [rffi.INT], rffi.INTP)
218235
219236 def get_osfhandle(fd):
220237 from rpython.rlib.rposix import FdValidator
221238 with FdValidator(fd):
222 handle = _get_osfhandle(fd)
239 handle = rffi.cast(HANDLE, _get_osfhandle(fd))
223240 if handle == INVALID_HANDLE_VALUE:
224241 raise WindowsError(ERROR_INVALID_HANDLE, "Invalid file handle")
225242 return handle
190190 #endif
191191 assert(result->ob_refcnt == REFCNT_FROM_PYPY);
192192 result->ob_refcnt = 1;
193 result->ob_pypy_link = 0;
193194 p->pyobj = NULL;
194195 *pp = p->next_in_bucket;
195196 p->next_in_bucket = hash_free_list;
22 OP_GC_RAWREFCOUNT_INIT(callback, r): the callback is not supported here
33 OP_GC_RAWREFCOUNT_CREATE_LINK_PYOBJ(): not implemented, maybe not needed
44 */
5 #define RPY_USES_RAWREFCOUNT
56
7 #ifdef RPY_REVERSE_DEBUGGER
8 /* these macros are defined in src-revdb/revdb_include.h */
9 #else
610 #define OP_GC_RAWREFCOUNT_CREATE_LINK_PYPY(gcobj, pyobj, r) \
711 gc_rawrefcount_create_link_pypy(gcobj, pyobj)
812
1418
1519 #define OP_GC_RAWREFCOUNT_NEXT_DEAD(r) \
1620 r = gc_rawrefcount_next_dead()
21 #endif
1722
1823 #define OP_GC_RAWREFCOUNT_MARK_DEALLOCATING(gcobj, pyobj, r) /* nothing */
1924
0
10 import py
1 import pytest
22 from rpython.rlib.debug import (check_annotation, make_sure_not_resized,
33 debug_print, debug_start, debug_stop,
44 have_debug_prints, debug_offset, debug_flush,
88 NotAListOfChars)
99 from rpython.rlib import debug
1010 from rpython.rtyper.test.test_llinterp import interpret, gengraph
11
12 @pytest.fixture
13 def debuglog(monkeypatch):
14 dlog = debug.DebugLog()
15 monkeypatch.setattr(debug, '_log', dlog)
16 return dlog
1117
1218 def test_check_annotation():
1319 class Error(Exception):
9399 py.test.raises(NotAListOfChars, "interpret(g, [3])")
94100
95101
96 def test_debug_print_start_stop():
102 def test_debug_print_start_stop(debuglog):
97103 def f(x):
98104 debug_start("mycat")
99105 debug_print("foo", 2, "bar", x)
102108 debug_offset() # should not explode at least
103109 return have_debug_prints()
104110
105 try:
106 debug._log = dlog = debug.DebugLog()
107 res = f(3)
108 assert res is True
109 finally:
110 debug._log = None
111 assert dlog == [("mycat", [('debug_print', 'foo', 2, 'bar', 3)])]
111 res = f(3)
112 assert res is True
113 assert debuglog == [("mycat", [('debug_print', 'foo', 2, 'bar', 3)])]
114 debuglog.reset()
112115
113 try:
114 debug._log = dlog = debug.DebugLog()
115 res = interpret(f, [3])
116 assert res is True
117 finally:
118 debug._log = None
119 assert dlog == [("mycat", [('debug_print', 'foo', 2, 'bar', 3)])]
116 res = interpret(f, [3])
117 assert res is True
118 assert debuglog == [("mycat", [('debug_print', 'foo', 2, 'bar', 3)])]
120119
120 def test_debuglog_summary(debuglog):
121 debug_start('foo')
122 debug_start('bar') # this is nested, so not counted in the summary by default
123 debug_stop('bar')
124 debug_stop('foo')
125 debug_start('foo')
126 debug_stop('foo')
127 debug_start('bar')
128 debug_stop('bar')
129 #
130 assert debuglog.summary() == {'foo': 2, 'bar': 1}
131 assert debuglog.summary(flatten=True) == {'foo': 2, 'bar': 2}
121132
122133 def test_debug_start_stop_timestamp():
123134 import time
707707 move_to_end(d, 'key1', last=False)
708708 assert d.items() == [('key1', 'val1'), ('key2', 'val2'), ('key3', 'val3')]
709709
710 def test_r_dict_move_to_end():
711 d = r_dict(strange_key_eq, strange_key_hash)
712 d['1key'] = 'val1'
713 d['2key'] = 'val2'
714 d['3key'] = 'val3'
715 # does not crash, we can't check that it actually moves to end on CPython
716 move_to_end(d, '1key')
717 move_to_end(d, '1key', last=False)
718
710719 def test_import_from_mixin():
711720 class M: # old-style
712721 def f(self):
00 from rpython.rtyper.test.tool import BaseRtypingTest
11 from rpython.rtyper.test.test_llinterp import interpret
2 from rpython.rlib import rarithmetic
23 from rpython.rlib.rarithmetic import *
34 from rpython.rlib.rstring import ParseStringError, ParseStringOverflowError
45 from hypothesis import given, strategies, assume
552553 py.test.raises(ParseStringError, string_to_int, '+'+s, base)
553554 py.test.raises(ParseStringError, string_to_int, '-'+s, base)
554555
555 def test_number_underscores(self):
556 VALID_UNDERSCORE_LITERALS = [
557 '0_0_0',
558 '4_2',
559 '1_0000_0000',
560 '0b1001_0100',
561 '0xfff_ffff',
562 '0o5_7_7',
563 '0b_0',
564 '0x_f',
565 '0o_5',
566 ]
567 INVALID_UNDERSCORE_LITERALS = [
568 # Trailing underscores:
569 '0_',
570 '42_',
571 '1.4j_',
572 '0x_',
573 '0b1_',
574 '0xf_',
575 '0o5_',
576 # Underscores in the base selector:
577 '0_b0',
578 '0_xf',
579 '0_o5',
580 # Old-style octal, still disallowed:
581 '09_99',
582 # Multiple consecutive underscores:
583 '4_______2',
584 '0b1001__0100',
585 '0xfff__ffff',
586 '0x___',
587 '0o5__77',
588 '1e1__0',
589 ]
590 for x in VALID_UNDERSCORE_LITERALS:
591 print x
592 y = string_to_int(x, base=0, allow_underscores=True)
593 assert y == int(x.replace('_', ''), base=0)
594 for x in INVALID_UNDERSCORE_LITERALS:
595 print x
596 py.test.raises(ParseStringError, string_to_int, x, base=0,
597 allow_underscores=True)
556 @py.test.mark.parametrize('s', [
557 '0_0_0',
558 '4_2',
559 '1_0000_0000',
560 '0b1001_0100',
561 '0xfff_ffff',
562 '0o5_7_7',
563 '0b_0',
564 '0x_f',
565 '0o_5',
566 ])
567 def test_valid_underscores(self, s):
568 result = string_to_int(
569 s, base=0, allow_underscores=True, no_implicit_octal=True)
570 assert result == int(s.replace('_', ''), base=0)
571
572 @py.test.mark.parametrize('s', [
573 # Leading underscores
574 '_100',
575 '_',
576 '_0b1001_0100',
577 # Trailing underscores:
578 '0_',
579 '42_',
580 '1.4j_',
581 '0x_',
582 '0b1_',
583 '0xf_',
584 '0o5_',
585 # Underscores in the base selector:
586 '0_b0',
587 '0_xf',
588 '0_o5',
589 # Old-style octal, still disallowed:
590 '09_99',
591 # Multiple consecutive underscores:
592 '4_______2',
593 '0b1001__0100',
594 '0xfff__ffff',
595 '0x___',
596 '0o5__77',
597 '1e1__0',
598 ])
599 def test_invalid_underscores(self, s):
600 with py.test.raises(ParseStringError):
601 string_to_int(s, base=0, allow_underscores=True)
602
603 def test_no_implicit_octal(self):
604 TESTS = ['00', '000', '00_00', '02', '0377', '02_34']
605 for x in TESTS:
606 for valid_underscore in [False, True]:
607 for no_implicit_octal in [False, True]:
608 print x, valid_underscore, no_implicit_octal
609 expected_ok = True
610 if no_implicit_octal and any('1' <= c <= '7' for c in x):
611 expected_ok = False
612 if not valid_underscore and '_' in x:
613 expected_ok = False
614 if expected_ok:
615 y = string_to_int(x, base=0,
616 allow_underscores=valid_underscore,
617 no_implicit_octal=no_implicit_octal)
618 assert y == int(x.replace('_', ''), base=8)
619 else:
620 py.test.raises(ParseStringError, string_to_int, x,
621 base=0,
622 allow_underscores=valid_underscore,
623 no_implicit_octal=no_implicit_octal)
598624
599625
600626 class TestExplicitIntsizes:
730756 py.test.raises(OverflowError, ovfcheck_int32_sub, 2**30, -2**30)
731757 assert ovfcheck_int32_mul(-2**16, 2**15) == -2**31
732758 py.test.raises(OverflowError, ovfcheck_int32_mul, -2**16, -2**15)
759
760 @given(strategies.integers(min_value=-sys.maxint-1, max_value=sys.maxint),
761 strategies.integers(min_value=-sys.maxint-1, max_value=sys.maxint),
762 strategies.integers(min_value=1, max_value=sys.maxint))
763 def test_mulmod(a, b, c):
764 assert mulmod(a, b, c) == (a * b) % c
765 #
766 import rpython.rlib.rbigint # import before patching check_support_int128
767 prev = rarithmetic.check_support_int128
768 try:
769 rarithmetic.check_support_int128 = lambda: False
770 assert mulmod(a, b, c) == (a * b) % c
771 finally:
772 rarithmetic.check_support_int128 = prev
55 from random import random, randint, sample, seed
66
77 import py
8 import pytest
89
910 from rpython.rlib import rbigint as lobj
1011 from rpython.rlib.rarithmetic import r_uint, r_longlong, r_ulonglong, intmask
1415 from rpython.rtyper.test.test_llinterp import interpret
1516 from rpython.translator.c.test.test_standalone import StandaloneTests
1617
17 from hypothesis import given, strategies
18 from hypothesis import given, strategies, example
19
20 longs = strategies.builds(
21 long, strategies.integers())
22 ints = strategies.integers(-sys.maxint-1, sys.maxint)
23
24 def makelong(data):
25 numbits = data.draw(strategies.integers(1, 2000))
26 r = data.draw(strategies.integers(0, 1 << numbits))
27 if data.draw(strategies.booleans()):
28 return -r
29 return r
30
31 biglongs = strategies.builds(makelong, strategies.data())
32
1833
1934 def gen_signs(l):
2035 for s in l:
4358
4459 class TestRLong(object):
4560 def test_simple(self):
46 for op1 in [-2, -1, 0, 1, 2, 50]:
47 for op2 in [-2, -1, 0, 1, 2, 50]:
61 for op1 in [-2, -1, 0, 1, 2, 10, 50]:
62 for op2 in [-2, -1, 0, 1, 2, 10, 50]:
4863 rl_op1 = rbigint.fromint(op1)
4964 rl_op2 = rbigint.fromint(op2)
5065 for op in "add sub mul".split():
154169
155170 def test_pow(self):
156171 for op1 in gen_signs(long_vals_not_too_big):
172 rl_op1 = rbigint.fromlong(op1)
157173 for op2 in [0, 1, 2, 8, 9, 10, 11]:
158 rl_op1 = rbigint.fromlong(op1)
159174 rl_op2 = rbigint.fromint(op2)
160175 r1 = rl_op1.pow(rl_op2)
161176 r2 = op1 ** op2
162177 assert r1.tolong() == r2
163178
179 for op3 in gen_signs([1, 2, 5, 1000, 12312312312312235659969696l]):
180 if not op3:
181 continue
182 print op1, op2, op3
183 r3 = rl_op1.pow(rl_op2, rbigint.fromlong(op3))
184 r4 = pow(op1, op2, op3)
185 assert r3.tolong() == r4
186
187 def test_pow_raises(self):
188 r1 = rbigint.fromint(2)
189 r0 = rbigint.fromint(0)
190 py.test.raises(ValueError, r1.pow, r1, r0)
164191
165192 def test_touint(self):
166193 result = r_uint(sys.maxint + 42)
266293 from rpython.rlib.rstring import NumberStringParser
267294 parser = NumberStringParser("1231231241", "1231231241", 10, "long")
268295 assert rbigint._from_numberstring_parser(parser).tolong() == 1231231241
296
297 def test_from_numberstring_parser_no_implicit_octal(self):
298 from rpython.rlib.rstring import NumberStringParser, ParseStringError
299 s = "077777777777777777777777777777"
300 parser = NumberStringParser(s, s, 0, "long",
301 no_implicit_octal=True)
302 py.test.raises(ParseStringError, rbigint._from_numberstring_parser,
303 parser)
304 parser = NumberStringParser("000", "000", 0, "long",
305 no_implicit_octal=True)
306 assert rbigint._from_numberstring_parser(parser).tolong() == 0
269307
270308 def test_add(self):
271309 for x in gen_signs(long_vals):
491529 f1, f2, f3 = [rbigint.fromlong(i)
492530 for i in (10L, 5L, 0L)]
493531 py.test.raises(ValueError, f1.pow, f2, f3)
494 #
495 MAX = 1E20
496 x = long(random() * MAX) + 1
497 y = long(random() * MAX) + 1
498 z = long(random() * MAX) + 1
499 f1 = rbigint.fromlong(x)
500 f2 = rbigint.fromlong(y)
501 f3 = rbigint.fromlong(z)
502 print f1
503 print f2
504 print f3
505 v = f1.pow(f2, f3)
506 print '--->', v
507 assert v.tolong() == pow(x, y, z)
508532
509533 def test_pow_lll_bug(self):
510534 two = rbigint.fromint(2)
572596 for mask in masks_list:
573597 res3 = f1.abs_rshift_and_mask(r_ulonglong(y), mask)
574598 assert res3 == (abs(x) >> y) & mask
599
600 # test special optimization case in rshift:
601 assert rbigint.fromlong(-(1 << 100)).rshift(5).tolong() == -(1 << 100) >> 5
602
603 def test_qshift(self):
604 for x in range(10):
605 for y in range(1, 161, 16):
606 num = (x << y) + x
607 f1 = rbigint.fromlong(num)
608 nf1 = rbigint.fromlong(-num)
609
610 for z in range(1, 31):
611 res1 = f1.lqshift(z).tolong()
612 res3 = nf1.lqshift(z).tolong()
613
614 assert res1 == num << z
615 assert res3 == -num << z
616
575617
576618 def test_from_list_n_bits(self):
577619 for x in ([3L ** 30L, 5L ** 20L, 7 ** 300] +
662704 def test_hash(self):
663705 for i in [0, 1, 2, 3, 4, 5, 6, 7, 8, 9,
664706 sys.maxint-3, sys.maxint-2, sys.maxint-1, sys.maxint,
665 ] + [randint(0, sys.maxint) for _ in range(100)]:
707 ]:
666708 # hash of machine-sized integers
667709 assert rbigint.fromint(i).hash() == i
668710 # hash of negative machine-sized integers
669711 assert rbigint.fromint(-i-1).hash() == -i-1
670712 #
671 for i in range(200):
672 # hash of large integers: should be equal to the hash of the
673 # integer reduced modulo 2**64-1, to make decimal.py happy
674 x = randint(0, sys.maxint**5)
675 y = x % (2**64-1)
676 assert rbigint.fromlong(x).hash() == rbigint.fromlong(y).hash()
677 assert rbigint.fromlong(-x).hash() == rbigint.fromlong(-y).hash()
678713
679714 def test_log(self):
680715 from rpython.rlib.rfloat import ulps_check
744779 f1 = rbigint.fromlong(x)
745780 f2 = y
746781 remainder = lobj._inplace_divrem1(f1, f1, f2)
782 f1._normalize()
747783 assert (f1.tolong(), remainder) == divmod(x, y)
748784 out = bigint([99, 99], 1)
749785 remainder = lobj._inplace_divrem1(out, out, 100)
775811 y += randint(1, 1 << 60)
776812 if y > x:
777813 x <<= 100
778
814
779815 f1 = rbigint.fromlong(x)
780816 f2 = rbigint.fromlong(y)
781817 div, rem = lobj._x_divrem(f1, f2)
815851 assert rem.tolong() == _rem
816852 py.test.raises(ZeroDivisionError, rbigint.fromlong(x).divmod, rbigint.fromlong(0))
817853
854 # an explicit example for a very rare case in _x_divrem:
855 # "add w back if q was too large (this branch taken rarely)"
856 x = 2401064762424988628303678384283622960038813848808995811101817752058392725584695633
857 y = 510439143470502793407446782273075179624699774495710665331026
858 f1 = rbigint.fromlong(x)
859 f2 = rbigint.fromlong(y)
860 div, rem = f1.divmod(f2)
861 _div, _rem = divmod(x, y)
862 assert div.tolong() == _div
863 assert rem.tolong() == _rem
864
865
818866 # testing Karatsuba stuff
819867 def test__v_iadd(self):
820868 f1 = bigint([lobj.MASK] * 10, 1)
844892 f1 = bigint([lobj.MASK] * digs, 1)
845893 f2 = lobj._x_add(f1, bigint([1], 1))
846894 ret = lobj._k_mul(f1, f2)
847 assert ret.tolong() == f1.tolong() * f2.tolong()
848
849 def test__k_lopsided_mul(self):
850 digs_a = KARATSUBA_CUTOFF + 3
851 digs_b = 3 * digs_a
852 f1 = bigint([lobj.MASK] * digs_a, 1)
853 f2 = bigint([lobj.MASK] * digs_b, 1)
854 ret = lobj._k_lopsided_mul(f1, f2)
855895 assert ret.tolong() == f1.tolong() * f2.tolong()
856896
857897 def test_longlong(self):
10141054 t, cbuilder = self.compile(entry_point)
10151055 data = cbuilder.cmdexec('hi there')
10161056 assert data == '[%d]\n[0, 1]\n' % sys.maxint
1057
1058 class TestHypothesis(object):
1059 @given(longs, longs, longs)
1060 def test_pow(self, x, y, z):
1061 f1 = rbigint.fromlong(x)
1062 f2 = rbigint.fromlong(y)
1063 f3 = rbigint.fromlong(z)
1064 try:
1065 res = pow(x, y, z)
1066 except Exception as e:
1067 pytest.raises(type(e), f1.pow, f2, f3)
1068 else:
1069 v = f1.pow(f2, f3)
1070 assert v.tolong() == res
1071
1072 @given(biglongs, biglongs)
1073 @example(510439143470502793407446782273075179618477362188870662225920,
1074 108089693021945158982483698831267549521)
1075 def test_divmod(self, x, y):
1076 if x < y:
1077 x, y = y, x
1078
1079 f1 = rbigint.fromlong(x)
1080 f2 = rbigint.fromlong(y)
1081 try:
1082 res = divmod(x, y)
1083 except Exception as e:
1084 pytest.raises(type(e), f1.divmod, f2)
1085 else:
1086 print x, y
1087 a, b = f1.divmod(f2)
1088 assert (a.tolong(), b.tolong()) == res
1089
1090 @given(longs)
1091 def test_hash(self, x):
1092 # hash of large integers: should be equal to the hash of the
1093 # integer reduced modulo 2**64-1, to make decimal.py happy
1094 x = randint(0, sys.maxint**5)
1095 y = x % (2**64-1)
1096 assert rbigint.fromlong(x).hash() == rbigint.fromlong(y).hash()
1097 assert rbigint.fromlong(-x).hash() == rbigint.fromlong(-y).hash()
1098
1099 @given(ints)
1100 def test_hash_int(self, x):
1101 # hash of machine-sized integers
1102 assert rbigint.fromint(x).hash() == x
1103 # hash of negative machine-sized integers
1104 assert rbigint.fromint(-x-1).hash() == -x-1
1105
1106 @given(longs)
1107 def test_abs(self, x):
1108 assert rbigint.fromlong(x).abs().tolong() == abs(x)
1109
1110 @given(longs, longs)
1111 def test_truediv(self, a, b):
1112 ra = rbigint.fromlong(a)
1113 rb = rbigint.fromlong(b)
1114 if not b:
1115 pytest.raises(ZeroDivisionError, ra.truediv, rb)
1116 else:
1117 assert ra.truediv(rb) == a / b
1118
1119 @given(longs, longs)
1120 def test_bitwise(self, x, y):
1121 lx = rbigint.fromlong(x)
1122 ly = rbigint.fromlong(y)
1123 for mod in "xor and_ or_".split():
1124 res1 = getattr(lx, mod)(ly).tolong()
1125 res2 = getattr(operator, mod)(x, y)
1126 assert res1 == res2
3737 res = interpret(f, [])
3838
3939 assert res is None
40
41 def test_enable_disable():
42 def f():
43 gc.enable()
44 a = gc.isenabled()
45 gc.disable()
46 b = gc.isenabled()
47 return a and not b
48
49 t, typer, graph = gengraph(f, [])
50 blockops = list(graph.iterblockops())
51 opnames = [op.opname for block, op in blockops
52 if op.opname.startswith('gc__')]
53 assert opnames == ['gc__enable', 'gc__isenabled',
54 'gc__disable', 'gc__isenabled']
55 res = interpret(f, [])
56 assert res
57
58 def test_collect_step():
59 def f():
60 return rgc.collect_step()
61
62 assert f()
63 t, typer, graph = gengraph(f, [])
64 blockops = list(graph.iterblockops())
65 opnames = [op.opname for block, op in blockops
66 if op.opname.startswith('gc__')]
67 assert opnames == ['gc__collect_step']
68 res = interpret(f, [])
69 assert res
70
71 def test__encode_states():
72 val = rgc._encode_states(42, 43)
73 assert rgc.old_state(val) == 42
74 assert rgc.new_state(val) == 43
75 assert not rgc.is_done(val)
76 #
77 val = rgc.collect_step()
78 assert rgc.is_done(val)
4079
4180 def test_can_move():
4281 T0 = lltype.GcStruct('T')
8181 assert data == posix._getfullpathname(stuff)
8282 # the most intriguing failure of ntpath.py should not repeat, here:
8383 assert not data.endswith(stuff)
84
85 @win_only
86 def test__getfullpathname_long(self):
87 stuff = "C:" + "\\abcd" * 100
88 py.test.raises(WindowsError, rposix.getfullpathname, stuff)
89 ustuff = u"C:" + u"\\abcd" * 100
90 res = rposix.getfullpathname(ustuff)
91 assert res == ustuff
8492
8593 def test_getcwd(self):
8694 assert rposix.getcwd() == os.getcwd()
464464 s.connect(INETAddress('python.org', 80))
465465 s.close()
466466
467 def test_connect_with_default_timeout_fail():
468 rsocket.setdefaulttimeout(0.1)
469 s = RSocket()
470 rsocket.setdefaulttimeout(None)
471 assert s.gettimeout() == 0.1
472 with py.test.raises(SocketTimeout):
473 s.connect(INETAddress('172.30.172.30', 12345))
474 s.close()
475
467476 def test_getsetsockopt():
468477 import struct
469478 assert struct.calcsize("i") == rffi.sizeof(rffi.INT)
307307 _assert_decu7(' +AOQ- ', u' \xe4 ')
308308 _assert_decu7('+AOQ-+AOQ-', u'\xe4\xe4')
309309
310 s_utf7 = 'Die M+AOQ-nner +AOQ-rgen sich!'
311 s_utf8 = u'Die Männer ärgen sich!'
312 s_utf8_esc = u'Die M\xe4nner \xe4rgen sich!'
310 s_utf7 = 'Die M+AOQ-nner +AOQ-rgern sich!'
311 s_utf8 = u'Die Männer ärgern sich!'
312 s_utf8_esc = u'Die M\xe4nner \xe4rgern sich!'
313313
314314 _assert_decu7(s_utf7, s_utf8_esc)
315315 _assert_decu7(s_utf7, s_utf8)
55 from rpython.rlib import rwin32
66 from rpython.tool.udir import udir
77
8 loadtest_dir = os.path.dirname(__file__) + '/loadtest'
9 test1 = os.path.abspath(loadtest_dir + '/loadtest1.dll')
10 test0 = os.path.abspath(loadtest_dir + '/loadtest0.dll')
11
12 if not os.path.exists(test1) or not os.path.exists(test0):
13 # This is how the files, which are checked into the repo, were created
14 from rpython.translator.tool.cbuild import ExternalCompilationInfo
15 from rpython.translator.platform import platform
16 from rpython.translator import cdir
17 if not os.path.exists(loadtest_dir):
18 os.mkdir(loadtest_dir)
19 c_file = udir.ensure("test_rwin32", dir=1).join("test0.c")
20 c_file.write(py.code.Source('''
21 #include "src/precommondefs.h"
22 RPY_EXPORTED
23 int internal_sum(int a, int b) {
24 return a + b;
25 }
26 '''))
27 eci = ExternalCompilationInfo(include_dirs=[cdir])
28 lib_name = str(platform.compile([c_file], eci, test0[:-4],
29 standalone=False))
30 assert os.path.abspath(lib_name) == os.path.abspath(test0)
31
32 c_file = udir.ensure("test_rwin32", dir=1).join("test1.c")
33 c_file.write(py.code.Source('''
34 #include "src/precommondefs.h"
35 int internal_sum(int a, int b);
36 RPY_EXPORTED
37 int sum(int a, int b) {
38 return internal_sum(a, b);
39 }
40 '''))
41 eci = ExternalCompilationInfo(include_dirs=[cdir],
42 libraries=[loadtest_dir + '/loadtest0'])
43 lib_name = str(platform.compile([c_file], eci, test1[:-4],
44 standalone=False, ))
45 assert os.path.abspath(lib_name) == os.path.abspath(test1)
846
947 def test_get_osfhandle():
1048 fid = open(str(udir.join('validate_test.txt')), 'w')
2765 "import time;"
2866 "time.sleep(10)",
2967 ],
30 )
68 )
3169 print proc.pid
3270 handle = rwin32.OpenProcess(rwin32.PROCESS_ALL_ACCESS, False, proc.pid)
3371 assert rwin32.TerminateProcess(handle, signal.SIGTERM) == 1
3472 rwin32.CloseHandle(handle)
3573 assert proc.wait() == signal.SIGTERM
36
74
3775 @py.test.mark.dont_track_allocations('putenv intentionally keeps strings alive')
3876 def test_wenviron():
3977 name, value = u'PYPY_TEST_日本', u'foobar日本'
5492 msg = rwin32.FormatErrorW(34)
5593 assert type(msg) is unicode
5694 assert u'%2' in msg
95
96 def test_loadlibraryA():
97 # test0 can be loaded alone, but test1 requires the modified search path
98 hdll = rwin32.LoadLibrary(test0)
99 assert hdll
100 faddr = rwin32.GetProcAddress(hdll, 'internal_sum')
101 assert faddr
102 assert rwin32.FreeLibrary(hdll)
103
104 hdll = rwin32.LoadLibrary(test1)
105 assert not hdll
106
107 assert os.path.exists(test1)
108
109 hdll = rwin32.LoadLibraryExA(test1)
110 assert hdll
111 faddr = rwin32.GetProcAddress(hdll, 'sum')
112 assert faddr
113 assert rwin32.FreeLibrary(hdll)
114
115 def test_loadlibraryW():
116 # test0 can be loaded alone, but test1 requires the modified search path
117 hdll = rwin32.LoadLibraryW(unicode(test0))
118 assert hdll
119 faddr = rwin32.GetProcAddress(hdll, 'internal_sum')
120 assert faddr
121 assert rwin32.FreeLibrary(hdll)
122
123 hdll = rwin32.LoadLibraryW(unicode(test1))
124 assert not hdll
125
126 assert os.path.exists(unicode(test1))
127
128 hdll = rwin32.LoadLibraryExW(unicode(test1))
129 assert hdll
130 faddr = rwin32.GetProcAddress(hdll, 'sum')
131 assert faddr
132 assert rwin32.FreeLibrary(hdll)
133
134 def test_loadlibrary_unicode():
135 import shutil
136 test0u = unicode(udir.join(u'load\u03betest.dll'))
137 shutil.copyfile(test0, test0u)
138 hdll = rwin32.LoadLibraryW(test0u)
139 assert hdll
912912
913913 casefolds = {}
914914 for code, char in table.enum_chars():
915 if char.casefolding and char.casefolding != [char.lower]:
916 casefolds[code] = char.casefolding
915 full_casefold = char.casefolding
916 if full_casefold is None:
917 full_casefold = [code]
918 full_lower = char.lower
919 if full_lower is None:
920 full_lower = code
921 # if we don't write anything into the file, then the RPython
922 # program would compute the result 'full_lower' instead.
923 # Is that the right answer?
924 if full_casefold != [full_lower]:
925 casefolds[code] = full_casefold
917926 writeDict(outfile, '_casefolds', casefolds, base_mod)
918927 print >> outfile, '''
919928
147147 def test_changed_in_version_8(self):
148148 assert unicodedb_6_2_0.toupper_full(0x025C) == [0x025C]
149149 assert unicodedb_8_0_0.toupper_full(0x025C) == [0xA7AB]
150
151 def test_casefold(self):
152 # returns None when we have no special casefolding rule,
153 # which means that tolower_full() should be used instead
154 assert unicodedb_8_0_0.casefold_lookup(0x1000) == None
155 assert unicodedb_8_0_0.casefold_lookup(0x0061) == None
156 assert unicodedb_8_0_0.casefold_lookup(0x0041) == None
157 # a case where casefold() != lower()
158 assert unicodedb_8_0_0.casefold_lookup(0x00DF) == [ord('s'), ord('s')]
159 # returns the argument itself, and not None, in rare cases
160 # where tolower_full() would return something different
161 assert unicodedb_8_0_0.casefold_lookup(0x13A0) == [0x13A0]
2130621306 return code
2130721307
2130821308 _casefolds = {
21309 5024: [5024],
21310 5025: [5025],
21311 5026: [5026],
21312 5027: [5027],
21313 5028: [5028],
21314 5029: [5029],
21315 5030: [5030],
21316 5031: [5031],
21317 5032: [5032],
21318 5033: [5033],
21319 5034: [5034],
21320 5035: [5035],
21321 5036: [5036],
21322 5037: [5037],
21323 5038: [5038],
21324 5039: [5039],
21325 5040: [5040],
21326 5041: [5041],
21327 5042: [5042],
21328 5043: [5043],
21329 5044: [5044],
21330 5045: [5045],
21331 5046: [5046],
21332 5047: [5047],
21333 5048: [5048],
21334 5049: [5049],
21335 5050: [5050],
21336 5051: [5051],
21337 5052: [5052],
21338 5053: [5053],
21339 5054: [5054],
21340 5055: [5055],
21341 5056: [5056],
21342 5057: [5057],
21343 5058: [5058],
21344 5059: [5059],
21345 5060: [5060],
21346 5061: [5061],
21347 5062: [5062],
21348 5063: [5063],
21349 5064: [5064],
21350 5065: [5065],
21351 5066: [5066],
21352 5067: [5067],
21353 5068: [5068],
21354 5069: [5069],
21355 5070: [5070],
21356 5071: [5071],
21357 5072: [5072],
21358 5073: [5073],
21359 5074: [5074],
21360 5075: [5075],
21361 5076: [5076],
21362 5077: [5077],
21363 5078: [5078],
21364 5079: [5079],
21365 5080: [5080],
21366 5081: [5081],
21367 5082: [5082],
21368 5083: [5083],
21369 5084: [5084],
21370 5085: [5085],
21371 5086: [5086],
21372 5087: [5087],
21373 5088: [5088],
21374 5089: [5089],
21375 5090: [5090],
21376 5091: [5091],
21377 5092: [5092],
21378 5093: [5093],
21379 5094: [5094],
21380 5095: [5095],
21381 5096: [5096],
21382 5097: [5097],
21383 5098: [5098],
21384 5099: [5099],
21385 5100: [5100],
21386 5101: [5101],
21387 5102: [5102],
21388 5103: [5103],
21389 5104: [5104],
21390 5105: [5105],
21391 5106: [5106],
21392 5107: [5107],
21393 5108: [5108],
21394 5109: [5109],
2130921395 5112: [5104],
2131021396 5113: [5105],
2131121397 5114: [5106],
2442924429 return code
2443024430
2443124431 _casefolds = {
24432 5024: [5024],
24433 5025: [5025],
24434 5026: [5026],
24435 5027: [5027],
24436 5028: [5028],
24437 5029: [5029],
24438 5030: [5030],
24439 5031: [5031],
24440 5032: [5032],
24441 5033: [5033],
24442 5034: [5034],
24443 5035: [5035],
24444 5036: [5036],
24445 5037: [5037],
24446 5038: [5038],
24447 5039: [5039],
24448 5040: [5040],
24449 5041: [5041],
24450 5042: [5042],
24451 5043: [5043],
24452 5044: [5044],
24453 5045: [5045],
24454 5046: [5046],
24455 5047: [5047],
24456 5048: [5048],
24457 5049: [5049],
24458 5050: [5050],
24459 5051: [5051],
24460 5052: [5052],
24461 5053: [5053],
24462 5054: [5054],
24463 5055: [5055],
24464 5056: [5056],
24465 5057: [5057],
24466 5058: [5058],
24467 5059: [5059],
24468 5060: [5060],
24469 5061: [5061],
24470 5062: [5062],
24471 5063: [5063],
24472 5064: [5064],
24473 5065: [5065],
24474 5066: [5066],
24475 5067: [5067],
24476 5068: [5068],
24477 5069: [5069],
24478 5070: [5070],
24479 5071: [5071],
24480 5072: [5072],
24481 5073: [5073],
24482 5074: [5074],
24483 5075: [5075],
24484 5076: [5076],
24485 5077: [5077],
24486 5078: [5078],
24487 5079: [5079],
24488 5080: [5080],
24489 5081: [5081],
24490 5082: [5082],
24491 5083: [5083],
24492 5084: [5084],
24493 5085: [5085],
24494 5086: [5086],
24495 5087: [5087],
24496 5088: [5088],
24497 5089: [5089],
24498 5090: [5090],
24499 5091: [5091],
24500 5092: [5092],
24501 5093: [5093],
24502 5094: [5094],
24503 5095: [5095],
24504 5096: [5096],
24505 5097: [5097],
24506 5098: [5098],
24507 5099: [5099],
24508 5100: [5100],
24509 5101: [5101],
24510 5102: [5102],
24511 5103: [5103],
24512 5104: [5104],
24513 5105: [5105],
24514 5106: [5106],
24515 5107: [5107],
24516 5108: [5108],
24517 5109: [5109],
2443224518 5112: [5104],
2443324519 5113: [5105],
2443424520 5114: [5106],
818818 def op_gc__collect(self, *gen):
819819 self.heap.collect(*gen)
820820
821 def op_gc__collect_step(self):
822 return self.heap.collect_step()
823
824 def op_gc__enable(self):
825 self.heap.enable()
826
827 def op_gc__disable(self):
828 self.heap.disable()
829
830 def op_gc__isenabled(self):
831 return self.heap.isenabled()
832
821833 def op_gc_heap_stats(self):
822834 raise NotImplementedError
823835
9991011 return self.op_raw_load(RESTYPE, _address_of_thread_local(), offset)
10001012 op_threadlocalref_get.need_result_type = True
10011013
1014 op_threadlocalref_load = op_threadlocalref_get
1015
1016 def op_threadlocalref_store(self, offset, value):
1017 self.op_raw_store(_address_of_thread_local(), offset, value)
1018
10021019 def op_threadlocalref_acquire(self, prev):
10031020 raise NotImplementedError
10041021 def op_threadlocalref_release(self, prev):
10151032
10161033 def op_boehm_malloc(self, size):
10171034 assert lltype.typeOf(size) == lltype.Signed
1018 return llmemory.raw_malloc(size)
1035 raw = llmemory.raw_malloc(size)
1036 return llmemory.cast_adr_to_ptr(raw, llmemory.GCREF)
10191037 op_boehm_malloc_atomic = op_boehm_malloc
10201038
10211039 def op_boehm_register_finalizer(self, p, finalizer):
10801098 elif getattr(addr, 'is_fake_thread_local_addr', False):
10811099 assert type(offset) is CDefinedIntSymbolic
10821100 self.llinterpreter.get_tlobj()[offset.expr] = value
1101 elif isinstance(offset, llmemory.ArrayLengthOffset):
1102 assert len(addr.ptr) == value # invalid ArrayLengthOffset
10831103 else:
10841104 assert offset.TYPE == ARGTYPE
10851105 getattr(addr, str(ARGTYPE).lower())[offset.repeat] = value
12041224
12051225 def op_gc_move_out_of_nursery(self, obj):
12061226 raise NotImplementedError("gc_move_out_of_nursery")
1227
1228 def op_revdb_stop_point(self, *args):
1229 pass
1230 def op_revdb_send_answer(self, *args):
1231 raise NotImplementedError
1232 def op_revdb_breakpoint(self, *args):
1233 raise NotImplementedError
1234 def op_revdb_get_value(self, *args):
1235 raise NotImplementedError
1236 def op_revdb_get_unique_id(self, *args):
1237 raise NotImplementedError
1238 def op_revdb_watch_save_state(self, *args):
1239 return False
1240 def op_revdb_watch_restore_state(self, *args):
1241 raise NotImplementedError
1242 def op_revdb_weakref_create(self, *args):
1243 raise NotImplementedError
1244 def op_revdb_weakref_deref(self, *args):
1245 raise NotImplementedError
1246 def op_revdb_call_destructor(self, *args):
1247 raise NotImplementedError
1248 def op_revdb_strtod(self, *args):
1249 raise NotImplementedError
1250 def op_revdb_frexp(self, *args):
1251 raise NotImplementedError
1252 def op_revdb_modf(self, *args):
1253 raise NotImplementedError
1254 def op_revdb_dtoa(self, *args):
1255 raise NotImplementedError
1256 def op_revdb_do_next_call(self):
1257 pass
1258 def op_revdb_set_thread_breakpoint(self, *args):
1259 raise NotImplementedError
12071260
12081261
12091262 class Tracer(object):
44
55 setfield = setattr
66 from operator import setitem as setarrayitem
7 from rpython.rlib.rgc import can_move, collect, add_memory_pressure
7 from rpython.rlib.rgc import can_move, collect, enable, disable, isenabled, add_memory_pressure, collect_step
88
99 def setinterior(toplevelcontainer, inneraddr, INNERTYPE, newvalue,
1010 offsets=None):
77 class LLOp(object):
88
99 def __init__(self, sideeffects=True, canfold=False, canraise=(),
10 canmallocgc=False, canrun=False, tryfold=False):
10 canmallocgc=False, canrun=False, tryfold=False,
11 revdb_protect=False):
1112 # self.opname = ... (set afterwards)
1213
1314 if canfold:
3940
4041 # The operation can be run directly with __call__
4142 self.canrun = canrun or canfold
43
44 # RevDB: the operation must always be protected with RPY_REVDB_EMIT()
45 self.revdb_protect = revdb_protect
4246
4347 # __________ make the LLOp instances callable from LL helpers __________
4448
385389 'boehm_malloc_atomic': LLOp(),
386390 'boehm_register_finalizer': LLOp(),
387391 'boehm_disappearing_link': LLOp(),
388 'raw_malloc': LLOp(),
392 'raw_malloc': LLOp(revdb_protect=True),
389393 'raw_malloc_usage': LLOp(sideeffects=False),
390 'raw_free': LLOp(),
391 'raw_memclear': LLOp(),
392 'raw_memset': LLOp(),
393 'raw_memcopy': LLOp(),
394 'raw_memmove': LLOp(),
395 'raw_load': LLOp(sideeffects=False, canrun=True),
396 'raw_store': LLOp(canrun=True),
397 'bare_raw_store': LLOp(),
394 'raw_free': LLOp(revdb_protect=True),
395 'raw_memclear': LLOp(revdb_protect=True),
396 'raw_memset': LLOp(revdb_protect=True),
397 'raw_memcopy': LLOp(revdb_protect=True),
398 'raw_memmove': LLOp(revdb_protect=True),
399 'raw_load': LLOp(revdb_protect=True, sideeffects=False,
400 canrun=True),
401 'raw_store': LLOp(revdb_protect=True, canrun=True),
402 'bare_raw_store': LLOp(revdb_protect=True),
398403 'gc_load_indexed': LLOp(sideeffects=False, canrun=True),
404 'gc_store': LLOp(canrun=True), # only used by the boehm gc
399405 'gc_store_indexed': LLOp(canrun=True),
400406 'track_alloc_start': LLOp(),
401407 'track_alloc_stop': LLOp(),
443449 'get_write_barrier_failing_case': LLOp(sideeffects=False),
444450 'get_write_barrier_from_array_failing_case': LLOp(sideeffects=False),
445451 'gc_get_type_info_group': LLOp(sideeffects=False),
446 'll_read_timestamp': LLOp(canrun=True),
447 'll_get_timestamp_unit': LLOp(canrun=True),
452 'll_read_timestamp': LLOp(revdb_protect=True, canrun=True),
453 'll_get_timestamp_unit': LLOp(revdb_protect=True, canrun=True),
448454
449455 # __________ GC operations __________
450456
451457 'gc__collect': LLOp(canmallocgc=True),
458 'gc__collect_step': LLOp(canmallocgc=True),
459 'gc__enable': LLOp(),
460 'gc__disable': LLOp(),
461 'gc__isenabled': LLOp(),
452462 'gc_free': LLOp(),
453463 'gc_fetch_exception': LLOp(),
454464 'gc_restore_exception': LLOp(),
458468 # see rlib/objectmodel for gc_identityhash and gc_id
459469 'gc_identityhash': LLOp(sideeffects=False, canmallocgc=True),
460470 'gc_id': LLOp(sideeffects=False, canmallocgc=True),
461 'gc_obtain_free_space': LLOp(),
462 'gc_set_max_heap_size': LLOp(),
471 'gc_obtain_free_space': LLOp(revdb_protect=True),
472 'gc_set_max_heap_size': LLOp(revdb_protect=True),
463473 'gc_can_move' : LLOp(sideeffects=False),
464474 'gc_thread_run' : LLOp(),
465475 'gc_thread_start' : LLOp(),
539549
540550 # __________ misc operations __________
541551
542 'stack_current': LLOp(sideeffects=False),
552 'stack_current': LLOp(revdb_protect=True, sideeffects=False),
543553 'keepalive': LLOp(),
544554 'same_as': LLOp(canfold=True),
545555 'hint': LLOp(),
552562
553563 'threadlocalref_addr': LLOp(), # get (or make) addr of tl
554564 'threadlocalref_get': LLOp(sideeffects=False), # read field (no check)
565 'threadlocalref_load': LLOp(sideeffects=False), # read field (with check)
566 'threadlocalref_store': LLOp(), # write field (with check)
555567 'threadlocalref_acquire': LLOp(), # lock for enum
556568 'threadlocalref_release': LLOp(), # lock for enum
557569 'threadlocalref_enum': LLOp(sideeffects=False), # enum all threadlocalrefs
581593
582594 # __________ instrumentation _________
583595 'instrument_count': LLOp(),
596
597 'revdb_stop_point': LLOp(),
598 'revdb_send_answer': LLOp(),
599 'revdb_breakpoint': LLOp(),
600 'revdb_get_value': LLOp(sideeffects=False),
601 'revdb_get_unique_id': LLOp(sideeffects=False),
602 'revdb_watch_save_state': LLOp(),
603 'revdb_watch_restore_state': LLOp(),
604 'revdb_weakref_create': LLOp(),
605 'revdb_weakref_deref': LLOp(),
606 'revdb_call_destructor': LLOp(),
607 'revdb_set_thread_breakpoint': LLOp(),
608 'revdb_strtod': LLOp(sideeffects=False),
609 'revdb_dtoa': LLOp(sideeffects=False),
610 'revdb_modf': LLOp(sideeffects=False),
611 'revdb_frexp': LLOp(sideeffects=False),
612 'revdb_do_next_call': LLOp(canrun=True),
584613 }
585614 # ***** Run test_lloperation after changes. *****
586615
33 import sys
44
55 from rpython.translator import cdir
6 from rpython.rlib import jit, rposix
6 from rpython.rlib import jit, rposix, objectmodel
77 from rpython.rlib.rfloat import INFINITY, NAN, isfinite
88 from rpython.rlib.rposix import UNDERSCORE_ON_WIN32
99 from rpython.rtyper.lltypesystem import lltype, rffi
184184 mantissa = x
185185 exponent = 0
186186 else:
187 if objectmodel.revdb_flag_io_disabled():
188 return _revdb_frexp(x)
187189 exp_p = lltype.malloc(rffi.INTP.TO, 1, flavor='raw')
188190 try:
189191 mantissa = math_frexp(x, exp_p)
220222 def ll_math_modf(x):
221223 # some platforms don't do the right thing for NaNs and
222224 # infinities, so we take care of special cases directly.
225 if objectmodel.revdb_flag_io_disabled():
226 return _revdb_modf(x)
223227 if not isfinite(x):
224228 if math.isnan(x):
225229 return (x, x)
406410
407411 return func_with_new_name(ll_math, 'll_math_' + name)
408412
413
414 def _revdb_frexp(x):
415 # moved in its own function for the import statement
416 from rpython.rlib import revdb
417 return revdb.emulate_frexp(x)
418
419 def _revdb_modf(x):
420 # moved in its own function for the import statement
421 from rpython.rlib import revdb
422 return revdb.emulate_modf(x)
423
424
409425 # ____________________________________________________________
410426
411427 unary_math_functions = [
713713 p = rffi.cast(rffi.CArrayPtr(TVAL), p + ofs)
714714 p[0] = newvalue
715715
716 def op_gc_store(p, ofs, newvalue):
717 from rpython.rtyper.lltypesystem import rffi
718 if lltype.typeOf(p) is not llmemory.Address:
719 p = llmemory.cast_ptr_to_adr(p)
720 TVAL = lltype.typeOf(newvalue)
721 p = llmemory.cast_adr_to_ptr(p + ofs, lltype.Ptr(lltype.FixedSizeArray(TVAL, 1)))
722 p[0] = newvalue
723
716724 def op_raw_load(TVAL, p, ofs):
717725 from rpython.rtyper.lltypesystem import rffi
718726 p = rffi.cast(llmemory.Address, p)
756764 def op_gc_move_out_of_nursery(obj):
757765 return obj
758766
767 def op_revdb_do_next_call():
768 pass
769
759770 # ____________________________________________________________
760771
761772 def get_op_impl(opname):
808808 lltype.free(cp, flavor='raw', track_allocation=True)
809809 else:
810810 lltype.free(cp, flavor='raw', track_allocation=False)
811 free_charp._annenforceargs_ = [None, bool]
811812
812813 # str -> already-existing char[maxsize]
813814 def str2chararray(s, array, maxsize):
856857 lldata = llstrtype(data)
857858 count = len(data)
858859
859 if we_are_translated_to_c() and not rgc.can_move(data):
860 flag = '\x04'
860 if rgc.must_split_gc_address_space():
861 flag = '\x06' # always make a copy in this case
862 elif we_are_translated_to_c() and not rgc.can_move(data):
863 flag = '\x04' # no copy needed
861864 else:
862865 if we_are_translated_to_c() and rgc.pin(data):
863 flag = '\x05'
866 flag = '\x05' # successfully pinned
864867 else:
865 buf = lltype.malloc(TYPEP.TO, count + (TYPEP is CCHARP),
866 flavor='raw')
867 copy_string_to_raw(lldata, buf, 0, count)
868 return buf, '\x06'
869 # ^^^ raw malloc used to get a nonmovable copy
868 flag = '\x06' # must still make a copy
869 if flag == '\x06':
870 buf = lltype.malloc(TYPEP.TO, count + (TYPEP is CCHARP),
871 flavor='raw')
872 copy_string_to_raw(lldata, buf, 0, count)
873 return buf, '\x06'
874 # ^^^ raw malloc used to get a nonmovable copy
870875 #
871876 # following code is executed after we're translated to C, if:
872877 # - rgc.can_move(data) and rgc.pin(data) both returned true
922927 """
923928 new_buf = mallocfn(count)
924929 pinned = 0
925 if rgc.can_move(new_buf):
930 fallback = False
931 if rgc.must_split_gc_address_space():
932 fallback = True
933 elif rgc.can_move(new_buf):
926934 if rgc.pin(new_buf):
927935 pinned = 1
928936 else:
929 raw_buf = lltype.malloc(TYPEP.TO, count, flavor='raw')
930 return raw_buf, new_buf, 2
937 fallback = True
938 if fallback:
939 raw_buf = lltype.malloc(TYPEP.TO, count, flavor='raw')
940 return raw_buf, new_buf, 2
931941 #
932942 # following code is executed if:
933943 # - rgc.can_move(data) and rgc.pin(data) both returned true
13201330 )
13211331
13221332
1323 if not we_are_translated():
1324 class RawBytes(object):
1325 # literal copy of _cffi_backend/func.py
1326 def __init__(self, string):
1327 self.ptr = str2charp(string, track_allocation=False)
1328 def __del__(self):
1329 if free_charp is not None: # CPython shutdown
1330 free_charp(self.ptr, track_allocation=False)
1331
1332 TEST_RAW_ADDR_KEEP_ALIVE = {}
1333 # NOTE: This is not a weak key dictionary, thus keeping a lot of stuff alive.
1334 TEST_RAW_ADDR_KEEP_ALIVE = {}
13331335
13341336 @jit.dont_look_inside
13351337 def get_raw_address_of_string(string):
13361338 """Returns a 'char *' that is valid as long as the rpython string object is alive.
13371339 Two calls to to this function, given the same string parameter,
13381340 are guaranteed to return the same pointer.
1339
1340 The extra parameter key is necessary to create a weak reference.
1341 The buffer of the returned pointer (if object is young) lives as long
1342 as key is alive. If key goes out of scope, the buffer will eventually
1343 be freed. `string` cannot go out of scope until the RawBytes object
1344 referencing it goes out of scope.
1345
1346 NOTE: may raise ValueError on some GCs, but not the default one.
13471341 """
13481342 assert isinstance(string, str)
13491343 from rpython.rtyper.annlowlevel import llstr
13521346 from rpython.rlib import rgc
13531347
13541348 if we_are_translated():
1349 if rgc.must_split_gc_address_space():
1350 return _get_raw_address_buf_from_string(string)
13551351 if rgc.can_move(string):
13561352 string = rgc.move_out_of_nursery(string)
13571353 if rgc.can_move(string):
1358 raise ValueError("cannot make string immovable")
1354 return _get_raw_address_buf_from_string(string)
13591355
13601356 # string cannot move now! return the address
13611357 lldata = llstr(string)
13681364 else:
13691365 global TEST_RAW_ADDR_KEEP_ALIVE
13701366 if string in TEST_RAW_ADDR_KEEP_ALIVE:
1371 return TEST_RAW_ADDR_KEEP_ALIVE[string].ptr
1372 TEST_RAW_ADDR_KEEP_ALIVE[string] = rb = RawBytes(string)
1373 return rb.ptr
1367 return TEST_RAW_ADDR_KEEP_ALIVE[string]
1368 result = str2charp(string, track_allocation=False)
1369 TEST_RAW_ADDR_KEEP_ALIVE[string] = result
1370 return result
1371
1372 class _StrFinalizerQueue(rgc.FinalizerQueue):
1373 Class = None # to use GCREFs directly
1374 print_debugging = False # set to True from test_rffi
1375 def finalizer_trigger(self):
1376 from rpython.rtyper.annlowlevel import hlstr
1377 from rpython.rtyper.lltypesystem import rstr
1378 from rpython.rlib import objectmodel
1379 while True:
1380 gcptr = self.next_dead()
1381 if not gcptr:
1382 break
1383 ll_string = lltype.cast_opaque_ptr(lltype.Ptr(rstr.STR), gcptr)
1384 string = hlstr(ll_string)
1385 key = objectmodel.compute_unique_id(string)
1386 ptr = self.raw_copies.get(key, lltype.nullptr(CCHARP.TO))
1387 if ptr:
1388 if self.print_debugging:
1389 from rpython.rlib.debug import debug_print
1390 debug_print("freeing str [", ptr, "]")
1391 free_charp(ptr, track_allocation=False)
1392 _fq_addr_from_string = _StrFinalizerQueue()
1393 _fq_addr_from_string.raw_copies = {} # {GCREF: CCHARP}
1394
1395 def _get_raw_address_buf_from_string(string):
1396 # Slowish but ok because it's not supposed to be used from a
1397 # regular PyPy. It's only used with non-standard GCs like RevDB
1398 from rpython.rtyper.annlowlevel import llstr
1399 from rpython.rlib import objectmodel
1400 key = objectmodel.compute_unique_id(string)
1401 try:
1402 ptr = _fq_addr_from_string.raw_copies[key]
1403 except KeyError:
1404 ptr = str2charp(string, track_allocation=False)
1405 _fq_addr_from_string.raw_copies[key] = ptr
1406 ll_string = llstr(string)
1407 gcptr = lltype.cast_opaque_ptr(llmemory.GCREF, ll_string)
1408 _fq_addr_from_string.register_finalizer(gcptr)
1409 return ptr
282282 return DictIteratorRepr(self, *variant)
283283
284284 def rtype_method_get(self, hop):
285 v_dict, v_key, v_default = hop.inputargs(self, self.key_repr,
286 self.value_repr)
285 if hop.nb_args == 3:
286 v_dict, v_key, v_default = hop.inputargs(self, self.key_repr,
287 self.value_repr)
288 else:
289 v_dict, v_key = hop.inputargs(self, self.key_repr)
290 v_default = hop.inputconst(self.value_repr, None)
287291 hop.exception_cannot_occur()
288292 v_res = hop.gendirectcall(ll_dict_get, v_dict, v_key, v_default)
289293 return self.recast_value(hop.llops, v_res)
00 from weakref import WeakValueDictionary
11
22 from rpython.annotator import model as annmodel
3 from rpython.rlib import jit, types, objectmodel
3 from rpython.rlib import jit, types, objectmodel, rgc
44 from rpython.rlib.objectmodel import (malloc_zero_filled, we_are_translated,
55 ll_hash_string, keepalive_until_here, specialize, enforceargs, dont_inline)
66 from rpython.rlib.signature import signature
8989 ll_assert(srcstart + length <= len(src.chars), "copystrc: src ovf")
9090 ll_assert(dststart >= 0, "copystrc: negative dststart")
9191 ll_assert(dststart + length <= len(dst.chars), "copystrc: dst ovf")
92 #
93 # If the 'split_gc_address_space' option is set, we must copy
94 # manually, character-by-character
95 if rgc.must_split_gc_address_space():
96 i = 0
97 while i < length:
98 dst.chars[dststart + i] = src.chars[srcstart + i]
99 i += 1
100 return
101 #
102 #
92103 # from here, no GC operations can happen
93104 asrc = _get_raw_buf(SRC_TP, src, srcstart)
94105 adst = _get_raw_buf(DST_TP, dst, dststart)
109120 """
110121 # xxx Warning: same note as above apply: don't do this at home
111122 assert length >= 0
123 #
124 # If the 'split_gc_address_space' option is set, we must copy
125 # manually, character-by-character
126 if rgc.must_split_gc_address_space():
127 i = 0
128 while i < length:
129 ptrdst[i] = src.chars[srcstart + i]
130 i += 1
131 return
132 #
112133 # from here, no GC operations can happen
113134 asrc = _get_raw_buf(SRC_TP, src, srcstart)
114135 adst = llmemory.cast_ptr_to_adr(ptrdst)
125146 def copy_raw_to_string(ptrsrc, dst, dststart, length):
126147 # xxx Warning: same note as above apply: don't do this at home
127148 assert length >= 0
149 #
150 # If the 'split_gc_address_space' option is set, we must copy
151 # manually, character-by-character
152 if rgc.must_split_gc_address_space():
153 i = 0
154 while i < length:
155 dst.chars[dststart + i] = ptrsrc[i]
156 i += 1
157 return
158 #
128159 # from here, no GC operations can happen
129160 adst = _get_raw_buf(SRC_TP, dst, dststart)
130161 asrc = llmemory.cast_ptr_to_adr(ptrsrc)
12341265 SRC = typeOf(src).TO # STR or UNICODE
12351266 DST = typeOf(dst).TO # GcArray
12361267 assert DST.OF is SRC.chars.OF
1268 #
1269 # If the 'split_gc_address_space' option is set, we must copy
1270 # manually, character-by-character
1271 if rgc.must_split_gc_address_space():
1272 i = 0
1273 while i < length:
1274 dst[i] = src.chars[i]
1275 i += 1
1276 return lst
1277 #
12371278 # from here, no GC operations can happen
12381279 asrc = llmemory.cast_ptr_to_adr(src) + (
12391280 llmemory.offsetof(SRC, 'chars') +
813813 def test_generate_return_char_tests(self):
814814 py.test.skip("GenC does not handle char return values correctly")
815815
816 def test__get_raw_address_buf_from_string(self):
817 from rpython.rlib import rgc
818 from rpython.rtyper.lltypesystem import rffi
819
820 def check_content(strings, rawptrs):
821 for i in range(len(strings)):
822 p = rawptrs[i]
823 expected = strings[i] + '\x00'
824 for j in range(len(expected)):
825 assert p[j] == expected[j]
826
827 def f(n):
828 strings = ["foo%d" % i for i in range(n)]
829 rawptrs = [rffi._get_raw_address_buf_from_string(s)
830 for s in strings]
831 check_content(strings, rawptrs)
832 rgc.collect(); rgc.collect(); rgc.collect()
833 check_content(strings, rawptrs)
834 for i in range(len(strings)): # check that it still returns the
835 # same raw ptrs
836 p1 = rffi._get_raw_address_buf_from_string(strings[i])
837 assert rawptrs[i] == p1
838 del strings
839 rgc.collect(); rgc.collect(); rgc.collect()
840 return 42
841
842 rffi._StrFinalizerQueue.print_debugging = True
843 try:
844 xf = self.compile(f, [int], gcpolicy="incminimark",
845 return_stderr=True)
846 finally:
847 rffi._StrFinalizerQueue.print_debugging = False
848
849 os.environ['PYPYLOG'] = ':-'
850 try:
851 error = xf(10000)
852 finally:
853 del os.environ['PYPYLOG']
854
855 import re
856 r = re.compile(r"freeing str [[] [0-9a-fx]+ []]")
857 matches = r.findall(error)
858 assert len(matches) == 10000 # must be all 10000 strings,
859 assert len(set(matches)) == 10000 # and no duplicates
860
861
816862 def test_enforced_args():
817863 from rpython.annotator.model import s_None
818864 from rpython.rtyper.annlowlevel import MixLevelHelperAnnotator
6464 def test_compiled_semispace():
6565 fn = compile(main, [], gcpolicy="semispace")
6666 res = fn()
67 assert res == 42 # get_raw_address_of_string() raises ValueError
67 # get_raw_address_of_string() never raise ValueError any more
68 assert res == 0
6869
6970 def test_compiled_boehm():
7071 fn = compile(main, [], gcpolicy="boehm")
171171 ('rtti', Ptr(RuntimeTypeInfo)),
172172 ('name', Ptr(rstr.STR)),
173173 ('instantiate', Ptr(FuncType([], OBJECTPTR))),
174 hints={'immutable': True}))
174 hints={'immutable': True,
175 'static_immutable': True}))
175176 # non-gc case
176177 NONGCOBJECT = Struct('nongcobject', ('typeptr', CLASSTYPE))
177178 NONGCOBJECTPTR = Ptr(NONGCOBJECT)
272273 #
273274 self.rbase = getclassrepr(self.rtyper, self.classdef.basedef)
274275 self.rbase.setup()
275 kwds = {'hints': {'immutable': True}}
276 kwds = {'hints': {'immutable': True, 'static_immutable': True}}
276277 vtable_type = Struct('%s_vtable' % self.classdef.name,
277278 ('super', self.rbase.vtable_type),
278279 *llfields, **kwds)
242242 fields = []
243243 for row in self.uniquerows:
244244 fields.append((row.attrname, row.fntype))
245 kwds = {'hints': {'immutable': True}}
245 kwds = {'hints': {'immutable': True, 'static_immutable': True}}
246246 return Ptr(Struct('specfunc', *fields, **kwds))
247247
248248 def create_specfunc(self):
413413 if self.s_pbc.can_be_None:
414414 self.descriptions.insert(0, None)
415415 POINTER_TABLE = Array(self.pointer_repr.lowleveltype,
416 hints={'nolength': True, 'immutable': True})
416 hints={'nolength': True, 'immutable': True,
417 'static_immutable': True})
417418 pointer_table = malloc(POINTER_TABLE, len(self.descriptions),
418419 immortal=True)
419420 for i, desc in enumerate(self.descriptions):
563564 if r_to in r_from._conversion_tables:
564565 return r_from._conversion_tables[r_to]
565566 else:
566 t = malloc(Array(Char, hints={'nolength': True, 'immutable': True}),
567 t = malloc(Array(Char, hints={'nolength': True, 'immutable': True,
568 'static_immutable': True}),
567569 len(r_from.descriptions), immortal=True)
568570 l = []
569571 for i, d in enumerate(r_from.descriptions):
663665 """For a SomePBC of frozen PBCs that have no common access set.
664666 The only possible operation on such a thing is comparison with 'is'."""
665667 lowleveltype = llmemory.Address
666 EMPTY = Struct('pbc', hints={'immutable': True})
668 EMPTY = Struct('pbc', hints={'immutable': True, 'static_immutable': True})
667669
668670 def __init__(self, rtyper):
669671 self.rtyper = rtyper
724726
725727 def _setup_repr(self):
726728 llfields = self._setup_repr_fields()
727 kwds = {'hints': {'immutable': True}}
729 kwds = {'hints': {'immutable': True, 'static_immutable': True}}
728730 self.pbc_type.become(Struct('pbc', *llfields, **kwds))
729731
730732 def create_instance(self):
9981000 classdef.has_no_attrs()):
9991001 # special case for instanciating simple built-in
10001002 # exceptions: always return the same prebuilt instance,
1001 # and ignore any arguments passed to the contructor.
1003 # and ignore any arguments passed to the constructor.
10021004 r_instance = rclass.getinstancerepr(hop.rtyper, classdef)
10031005 example = r_instance.get_reusable_prebuilt_instance()
10041006 hop.exception_cannot_occur()
00 import sys
11 from contextlib import contextmanager
22 import signal
3 from collections import OrderedDict
34
45 from rpython.translator.translator import TranslationContext
56 from rpython.annotator.model import (
206207 return x1 * 10 + x2
207208 res = self.interpret(func, ())
208209 assert res == 421
210
211 def test_dict_get_no_second_arg(self):
212 def func():
213 dic = self.newdict()
214 x1 = dic.get('hi', 'a')
215 x2 = dic.get('blah')
216 return (x1 == 'a') * 10 + (x2 is None)
217 return x1 * 10 + x2
218 res = self.interpret(func, ())
219 assert res == 11
209220
210221 def test_dict_get_empty(self):
211222 def func():
11851196 DictValue(None, s_value))
11861197 dictrepr.setup()
11871198 self.l_dict = self.newdict(dictrepr)
1188 self.reference = self.new_reference()
1199 self.reference = OrderedDict()
11891200 self.ll_key = r_key.convert_const
11901201 self.ll_value = r_value.convert_const
11911202 self.removed_keys = []
13121323
13131324 class DictSpace(MappingSpace):
13141325 MappingRepr = rdict.DictRepr
1315 new_reference = dict
13161326 ll_getitem = staticmethod(rdict.ll_dict_getitem)
13171327 ll_setitem = staticmethod(rdict.ll_dict_setitem)
13181328 ll_delitem = staticmethod(rdict.ll_dict_delitem)
421421
422422 class ODictSpace(MappingSpace):
423423 MappingRepr = rodct.OrderedDictRepr
424 new_reference = OrderedDict
425424 moved_around = False
426425 ll_getitem = staticmethod(rodct.ll_dict_getitem)
427426 ll_setitem = staticmethod(rodct.ll_dict_setitem)
2626 import platform
2727 import itertools
2828 import distutils.errors
29 from pkg_resources.extern.packaging.version import LegacyVersion
3029
3130 from setuptools.extern.six.moves import filterfalse
3231
200199 """
201200 if "numpy.distutils" in sys.modules:
202201 import numpy as np
202 from pkg_resources.extern.packaging.version import LegacyVersion
203203 if LegacyVersion(np.__version__) < LegacyVersion('1.11.2'):
204204 return np.distutils.ccompiler.gen_lib_options(*args, **kwargs)
205205 return get_unpatched(msvc14_gen_lib_options)(*args, **kwargs)
178178 t, graph = rtype(entry_point, [int])
179179 total0 = preparation(t, t.graphs)
180180 total = clever_inlining_and_malloc_removal(t)
181 assert total0 + total == 10
181 assert total0 + total == 9
182182
183183 def test_loop():
184184 l = [10, 12, 15, 1]
3131 gchooks=None,
3232 exctransformer=None,
3333 thread_enabled=False,
34 sandbox=False):
34 sandbox=False,
35 split_gc_address_space=False,
36 reverse_debugger=False):
3537 self.translator = translator
3638 self.standalone = standalone
3739 self.sandbox = sandbox
40 self.split_gc_address_space = split_gc_address_space
41 self.reverse_debugger = reverse_debugger
3842 if gcpolicyclass is None:
3943 gcpolicyclass = gc.RefcountingGcPolicy
4044 self.gcpolicy = gcpolicyclass(self, thread_enabled)
1616 yield ('RPYTHON_EXCEPTION_MATCH', exceptiondata.fn_exception_match)
1717 yield ('RPYTHON_TYPE_OF_EXC_INST', exceptiondata.fn_type_of_exc_inst)
1818
19 yield ('RPyExceptionOccurred1', exctransformer.rpyexc_occured_ptr.value)
19 yield ('RPyExceptionOccurred1', exctransformer.rpyexc_occurred_ptr.value)
2020 yield ('RPyFetchExceptionType', exctransformer.rpyexc_fetch_type_ptr.value)
2121 yield ('RPyFetchExceptionValue', exctransformer.rpyexc_fetch_value_ptr.value)
2222 yield ('RPyClearException', exctransformer.rpyexc_clear_ptr.value)
169169
170170 # ____________________________________________________________
171171
172 extra_return_text = None
173
172174 def cfunction_body(self):
175 if self.db.reverse_debugger:
176 from rpython.translator.revdb import gencsupp
177 (extra_enter_text, self.extra_return_text) = (
178 gencsupp.prepare_function(self))
179 if extra_enter_text:
180 yield extra_enter_text
173181 graph = self.graph
174182
175183 # ----- for gc_enter_roots_frame
224232 retval = self.expr(block.inputargs[0])
225233 if self.exception_policy != "exc_helper":
226234 yield 'RPY_DEBUG_RETURN();'
235 if self.extra_return_text:
236 yield self.extra_return_text
227237 yield 'return %s;' % retval
228238 return
229239 elif block.exitswitch is None:
311321 macro = 'OP_%s' % op.opname.upper()
312322 line = None
313323 if (op.opname.startswith('gc_') and
314 op.opname not in ('gc_load_indexed', 'gc_store_indexed')):
324 op.opname not in ('gc_load_indexed', 'gc_store',
325 'gc_store_indexed')):
315326 meth = getattr(self.gcpolicy, macro, None)
316327 if meth:
317328 line = meth(self, op)
323334 lst = [self.expr(v) for v in op.args]
324335 lst.append(self.expr(op.result))
325336 line = '%s(%s);' % (macro, ', '.join(lst))
337 if self.db.reverse_debugger:
338 from rpython.translator.revdb import gencsupp
339 if op.opname in gencsupp.set_revdb_protected:
340 line = gencsupp.emit(line, self.lltypename(op.result),
341 self.expr(op.result))
326342 if "\n" not in line:
327343 yield line
328344 else:
436452 # skip assignment of 'void' return value
437453 r = self.expr(v_result)
438454 line = '%s = %s' % (r, line)
439 if targets:
455 else:
456 r = None
457 if targets is not None:
440458 for graph in targets:
441459 if getattr(graph, 'inhibit_tail_call', False):
442460 line += '\nPYPY_INHIBIT_TAIL_CALL();'
443461 break
462 elif self.db.reverse_debugger:
463 from rpython.translator.revdb import gencsupp
464 line = gencsupp.emit_residual_call(self, line, v_result, r)
444465 return line
445466
446467 def OP_DIRECT_CALL(self, op):
473494 return 'abort(); /* jit_conditional_call_value */'
474495
475496 # low-level operations
476 def generic_get(self, op, sourceexpr):
497 def generic_get(self, op, sourceexpr, accessing_mem=True):
477498 T = self.lltypemap(op.result)
478499 newvalue = self.expr(op.result, special_case_void=False)
479500 result = '%s = %s;' % (newvalue, sourceexpr)
480501 if T is Void:
481502 result = '/* %s */' % result
503 if self.db.reverse_debugger:
504 S = self.lltypemap(op.args[0]).TO
505 if (S._gckind != 'gc' and not S._hints.get('is_excdata')
506 and not S._hints.get('static_immutable')
507 and not S._hints.get('ignore_revdb')
508 and accessing_mem):
509 from rpython.translator.revdb import gencsupp
510 result = gencsupp.emit(result, self.lltypename(op.result),
511 newvalue)
482512 return result
483513
484514 def generic_set(self, op, targetexpr):
487517 T = self.lltypemap(op.args[-1])
488518 if T is Void:
489519 result = '/* %s */' % result
520 if self.db.reverse_debugger:
521 S = self.lltypemap(op.args[0]).TO
522 if S._gckind != 'gc' and not S._hints.get('is_excdata'):
523 from rpython.translator.revdb import gencsupp
524 result = gencsupp.emit_void(result)
490525 return result
491526
492 def OP_GETFIELD(self, op, ampersand=''):
527 def OP_GETFIELD(self, op, ampersand='', accessing_mem=True):
493528 assert isinstance(op.args[1], Constant)
494529 STRUCT = self.lltypemap(op.args[0]).TO
495530 structdef = self.db.gettypedefnode(STRUCT)
497532 expr = ampersand + structdef.ptr_access_expr(self.expr(op.args[0]),
498533 op.args[1].value,
499534 baseexpr_is_const)
500 return self.generic_get(op, expr)
535 return self.generic_get(op, expr, accessing_mem=accessing_mem)
501536
502537 def OP_BARE_SETFIELD(self, op):
503538 assert isinstance(op.args[1], Constant)
513548 RESULT = self.lltypemap(op.result).TO
514549 if (isinstance(RESULT, FixedSizeArray) or
515550 (isinstance(RESULT, Array) and barebonearray(RESULT))):
516 return self.OP_GETFIELD(op, ampersand='')
517 else:
518 return self.OP_GETFIELD(op, ampersand='&')
551 return self.OP_GETFIELD(op, ampersand='', accessing_mem=False)
552 else:
553 return self.OP_GETFIELD(op, ampersand='&', accessing_mem=False)
519554
520555 def OP_GETARRAYSIZE(self, op):
521556 ARRAY = self.lltypemap(op.args[0]).TO
523558 return '%s = %d;' % (self.expr(op.result),
524559 ARRAY.length)
525560 else:
526 return '%s = %s->length;' % (self.expr(op.result),
527 self.expr(op.args[0]))
561 return self.generic_get(op, '%s->length;' % self.expr(op.args[0]))
528562
529563 def OP_GETARRAYITEM(self, op):
530564 ARRAY = self.lltypemap(op.args[0]).TO
588622 return '%s = %d;'%(self.expr(op.result), ARRAY.length)
589623 else:
590624 assert isinstance(ARRAY, Array)
591 return '%s = %s.length;'%(self.expr(op.result), expr)
592
625 return self.generic_get(op, '%s.length;' % expr)
593626
594627
595628 def OP_PTR_NONZERO(self, op):
609642 self.expr(op.args[0]),
610643 self.expr(op.args[1]))
611644
645 def _op_boehm_malloc(self, op, is_atomic):
646 expr_result = self.expr(op.result)
647 res = 'OP_BOEHM_ZERO_MALLOC(%s, %s, void*, %d, 0);' % (
648 self.expr(op.args[0]),
649 expr_result,
650 is_atomic)
651 if self.db.reverse_debugger:
652 from rpython.translator.revdb import gencsupp
653 res += gencsupp.record_malloc_uid(expr_result)
654 return res
655
612656 def OP_BOEHM_MALLOC(self, op):
613 return 'OP_BOEHM_ZERO_MALLOC(%s, %s, void*, 0, 0);' % (self.expr(op.args[0]),
614 self.expr(op.result))
657 return self._op_boehm_malloc(op, 0)
615658
616659 def OP_BOEHM_MALLOC_ATOMIC(self, op):
617 return 'OP_BOEHM_ZERO_MALLOC(%s, %s, void*, 1, 0);' % (self.expr(op.args[0]),
618 self.expr(op.result))
660 return self._op_boehm_malloc(op, 1)
619661
620662 def OP_BOEHM_REGISTER_FINALIZER(self, op):
663 if self.db.reverse_debugger:
664 from rpython.translator.revdb import gencsupp
665 return gencsupp.boehm_register_finalizer(self, op)
621666 return 'GC_REGISTER_FINALIZER(%s, (GC_finalization_proc)%s, NULL, NULL, NULL);' \
622667 % (self.expr(op.args[0]), self.expr(op.args[1]))
623668
624669 def OP_DIRECT_FIELDPTR(self, op):
625 return self.OP_GETFIELD(op, ampersand='&')
670 return self.OP_GETFIELD(op, ampersand='&', accessing_mem=False)
626671
627672 def OP_DIRECT_ARRAYITEMS(self, op):
628673 ARRAY = self.lltypemap(op.args[0]).TO
644689 self.expr(op.args[0]),
645690 self.expr(op.args[1]))
646691
692 def _check_split_gc_address_space(self, op):
693 if self.db.split_gc_address_space:
694 TYPE = self.lltypemap(op.result)
695 TSRC = self.lltypemap(op.args[0])
696 gcdst = isinstance(TYPE, Ptr) and TYPE.TO._gckind == 'gc'
697 gcsrc = isinstance(TSRC, Ptr) and TSRC.TO._gckind == 'gc'
698 if gcsrc != gcdst:
699 raise Exception(
700 "cast between pointer types changes the address\n"
701 "space, but the 'split_gc_address_space' option is enabled:\n"
702 " func: %s\n"
703 " op: %s\n"
704 " from: %s\n"
705 " to: %s" % (self.graph, op, TSRC, TYPE))
706
647707 def OP_CAST_POINTER(self, op):
708 self._check_split_gc_address_space(op)
648709 TYPE = self.lltypemap(op.result)
649710 typename = self.db.gettype(TYPE)
650711 result = []
657718 OP_CAST_ADR_TO_PTR = OP_CAST_POINTER
658719 OP_CAST_OPAQUE_PTR = OP_CAST_POINTER
659720
721 def OP_CAST_PTR_TO_INT(self, op):
722 if self.db.reverse_debugger:
723 TSRC = self.lltypemap(op.args[0])
724 if isinstance(TSRC, Ptr) and TSRC.TO._gckind == 'gc':
725 from rpython.translator.revdb import gencsupp
726 return gencsupp.cast_gcptr_to_int(self, op)
727 return self.OP_CAST_POINTER(op)
728
729 def OP_REVDB_DO_NEXT_CALL(self, op):
730 self.revdb_do_next_call = True
731 return "/* revdb_do_next_call */"
732
660733 def OP_LENGTH_OF_SIMPLE_GCARRAY_FROM_OPAQUE(self, op):
661734 return ('%s = *(long *)(((char *)%s) + RPY_SIZE_OF_GCHEADER);'
662735 ' /* length_of_simple_gcarray_from_opaque */'
663736 % (self.expr(op.result), self.expr(op.args[0])))
664737
665738 def OP_CAST_INT_TO_PTR(self, op):
739 self._check_split_gc_address_space(op)
666740 TYPE = self.lltypemap(op.result)
667741 typename = self.db.gettype(TYPE)
668742 return "%s = (%s)%s;" % (self.expr(op.result), cdecl(typename, ""),
703777 '((%(typename)s) (((char *)%(addr)s) + %(offset)s))[0] = %(value)s;'
704778 % locals())
705779 OP_BARE_RAW_STORE = OP_RAW_STORE
780 OP_GC_STORE = OP_RAW_STORE # the difference is only in 'revdb_protect'
706781
707782 def OP_RAW_LOAD(self, op):
708783 addr = self.expr(op.args[0])
741816 % locals())
742817
743818 def OP_CAST_PRIMITIVE(self, op):
819 self._check_split_gc_address_space(op)
744820 TYPE = self.lltypemap(op.result)
745821 val = self.expr(op.args[0])
746822 result = self.expr(op.result)
764840 from rpython.rtyper.lltypesystem.rstr import STR
765841 format = []
766842 argv = []
843 if self.db.reverse_debugger:
844 format.append('{%d} ')
845 argv.append('(int)getpid()')
767846 free_line = ""
768847 for arg in op.args:
769848 T = arg.concretetype
9581037 return None # use the default
9591038
9601039 def OP_THREADLOCALREF_GET(self, op):
961 typename = self.db.gettype(op.result.concretetype)
9621040 if isinstance(op.args[0], Constant):
1041 typename = self.db.gettype(op.result.concretetype)
9631042 assert isinstance(op.args[0].value, CDefinedIntSymbolic)
9641043 fieldname = op.args[0].value.expr
9651044 assert fieldname.startswith('RPY_TLOFS_')
9691048 cdecl(typename, ''),
9701049 fieldname)
9711050 else:
972 return 'OP_THREADLOCALREF_GET_NONCONST(%s, %s, %s);' % (
973 cdecl(typename, ''),
974 self.expr(op.args[0]),
975 self.expr(op.result))
1051 # this is used for the fall-back path in the JIT
1052 return self.OP_THREADLOCALREF_LOAD(op)
1053
1054 def OP_THREADLOCALREF_LOAD(self, op):
1055 typename = self.db.gettype(op.result.concretetype)
1056 return 'OP_THREADLOCALREF_LOAD(%s, %s, %s);' % (
1057 cdecl(typename, ''),
1058 self.expr(op.args[0]),
1059 self.expr(op.result))
1060
1061 def OP_THREADLOCALREF_STORE(self, op):
1062 typename = self.db.gettype(op.args[1].concretetype)
1063 return 'OP_THREADLOCALREF_STORE(%s, %s, %s);' % (
1064 cdecl(typename, ''),
1065 self.expr(op.args[0]),
1066 self.expr(op.args[1]))
204204 # GC_REDIRECT_TO_LOCAL is not supported on Win32 by gc6.8
205205 pre_include_bits += ["#define GC_REDIRECT_TO_LOCAL 1"]
206206
207 hdr_flag = ''
208 if not getattr(self.db.gctransformer, 'NO_HEADER', False):
209 hdr_flag = '-DPYPY_BOEHM_WITH_HEADER'
210
207211 eci = eci.merge(ExternalCompilationInfo(
208212 pre_include_bits=pre_include_bits,
209213 # The following define is required by the thread module,
210214 # See module/thread/test/test_rthread.py
211 compile_extra=['-DPYPY_USING_BOEHM_GC'],
215 compile_extra=['-DPYPY_USING_BOEHM_GC', hdr_flag],
212216 ))
213217
214218 gct = self.db.gctransformer
239243 yield 'boehm_gc_startup_code();'
240244
241245 def get_real_weakref_type(self):
242 from rpython.memory.gctransform import boehm
243 return boehm.WEAKLINK
246 return self.db.gctransformer.WEAKLINK
244247
245248 def convert_weakref_to(self, ptarget):
246 from rpython.memory.gctransform import boehm
247 return boehm.convert_weakref_to(ptarget)
249 return self.db.gctransformer.convert_weakref_to(ptarget)
248250
249251 def OP_GC__COLLECT(self, funcgen, op):
250252 return 'GC_gcollect();'
7777 def get_eci(self):
7878 pypy_include_dir = py.path.local(__file__).join('..')
7979 include_dirs = [pypy_include_dir]
80 if self.config.translation.reverse_debugger:
81 include_dirs.append(pypy_include_dir.join('..', 'revdb'))
8082 return ExternalCompilationInfo(include_dirs=include_dirs)
8183
8284 def build_database(self):
9496 gchooks=self.gchooks,
9597 exctransformer=exctransformer,
9698 thread_enabled=self.config.translation.thread,
97 sandbox=self.config.translation.sandbox)
99 sandbox=self.config.translation.sandbox,
100 split_gc_address_space=
101 self.config.translation.split_gc_address_space,
102 reverse_debugger=
103 self.config.translation.reverse_debugger)
98104 self.db = db
99105
100106 # give the gc a chance to register interest in the start-up functions it
115121 db.get(getfunctionptr(bk.getdesc(func).getuniquegraph()))
116122
117123 self.c_entrypoint_name = pfname
124
125 if self.config.translation.reverse_debugger:
126 from rpython.translator.revdb import gencsupp
127 gencsupp.prepare_database(db)
118128
119129 for obj in exports.EXPORTS_obj2name.keys():
120130 db.getcontainernode(obj)
160170 # use generate_source(defines=DEBUG_DEFINES) to force the #definition
161171 # of the macros that enable debugging assertions
162172 DEBUG_DEFINES = {'RPY_ASSERT': 1,
163 'RPY_LL_ASSERT': 1}
173 'RPY_LL_ASSERT': 1,
174 'RPY_REVDB_PRINT_ALL': 1}
164175
165176 def generate_source(self, db=None, defines={}, exe_name=None):
166177 assert self.c_source_filename is None
180191 defines['COUNT_OP_MALLOCS'] = 1
181192 if self.config.translation.sandbox:
182193 defines['RPY_SANDBOXED'] = 1
194 if self.config.translation.reverse_debugger:
195 defines['RPY_REVERSE_DEBUGGER'] = 1
183196 if CBuilder.have___thread is None:
184197 CBuilder.have___thread = self.translator.platform.check___thread()
185198 if not self.standalone:
289302 SetErrorMode(old_mode)
290303 if res.returncode != 0:
291304 if expect_crash:
305 if type(expect_crash) is int and expect_crash != res.returncode:
306 raise Exception("Returned %d, but expected %d" % (
307 res.returncode, expect_crash))
292308 return res.out, res.err
293309 print >> sys.stderr, res.err
294310 raise Exception("Returned %d" % (res.returncode,))
724740
725741 print >> f, '#define PYPY_FILE_NAME "%s"' % os.path.basename(f.name)
726742 print >> f, '#include "src/g_include.h"'
743 if self.database.reverse_debugger:
744 print >> f, '#include "revdb_def.h"'
727745 print >> f
728746
729747 nextralines = 11 + 1
764782 print >> fc, '#include "preimpl.h"'
765783 print >> fc, '#define PYPY_FILE_NAME "%s"' % name
766784 print >> fc, '#include "src/g_include.h"'
785 if self.database.reverse_debugger:
786 print >> fc, '#include "revdb_def.h"'
767787 print >> fc
768788 print >> fc, MARKER
769789 for node, impl in nodeiter:
802822 for field in fields:
803823 print >> f, ('#define RPY_TLOFS_%s offsetof(' % field.fieldname +
804824 'struct pypy_threadlocal_s, %s)' % field.fieldname)
825 if fields:
826 print >> f, '#define RPY_TLOFSFIRST RPY_TLOFS_%s' % fields[0].fieldname
827 else:
828 print >> f, '#define RPY_TLOFSFIRST sizeof(struct pypy_threadlocal_s)'
805829 print >> f, 'struct pypy_threadlocal_s {'
806830 print >> f, '\tint ready;'
807831 print >> f, '\tchar *stack_end;'
867891 defines['PYPY_LONG_BIT'] = LONG_BIT
868892 defines['PYPY_LONGLONG_BIT'] = LONGLONG_BIT
869893
870 def add_extra_files(eci):
894 def add_extra_files(database, eci):
871895 srcdir = py.path.local(__file__).join('..', 'src')
872896 files = [
873897 srcdir / 'entrypoint.c', # ifdef PYPY_STANDALONE
886910 ]
887911 if _CYGWIN:
888912 files.append(srcdir / 'cygwin_wait.c')
913 if database.reverse_debugger:
914 from rpython.translator.revdb import gencsupp
915 files += gencsupp.extra_files()
889916 return eci.merge(ExternalCompilationInfo(separate_module_files=files))
890917
891918
933960 n = database.instrument_ncounter
934961 print >>fi, "#define PYPY_INSTRUMENT_NCOUNTER %d" % n
935962 fi.close()
936
937 eci = add_extra_files(eci)
963 if database.reverse_debugger:
964 from rpython.translator.revdb import gencsupp
965 gencsupp.write_revdb_def_file(database, targetdir.join('revdb_def.h'))
966
967 eci = add_extra_files(database, eci)
938968 eci = eci.convert_sources_to_files()
939969 return eci, filename, sg.getextrafiles(), headers_to_precompile
502502 assert self.implementationtypename.startswith('struct ')
503503 assert self.implementationtypename.endswith(' @')
504504 uniontypename = 'union %su @' % self.implementationtypename[7:-2]
505 return uniontypename, self.name[:-2]
506 else:
507 return self.implementationtypename, self.name
505 return uniontypename, self.name[:-2], True
506 else:
507 return self.implementationtypename, self.name, False
508508
509509 def forward_declaration(self):
510510 if llgroup.member_of_group(self.obj):
511511 return
512 type, name = self.get_declaration()
512 type, name, is_union = self.get_declaration()
513513 yield '%s;' % (
514514 forward_cdecl(type, name, self.db.standalone,
515515 is_thread_local=self.is_thread_local(),
519519 if llgroup.member_of_group(self.obj):
520520 return []
521521 lines = list(self.initializationexpr())
522 type, name = self.get_declaration()
523 if name != self.name and len(lines) < 2:
522 type, name, is_union = self.get_declaration()
523 if is_union and len(lines) < 2:
524524 # a union with length 0
525525 lines[0] = cdecl(type, name, self.is_thread_local())
526526 else:
527 if name != self.name:
527 if is_union:
528528 lines[0] = '{ ' + lines[0] # extra braces around the 'a' part
529529 lines[-1] += ' }' # of the union
530530 lines[0] = '%s = %s' % (
612612 padding_drop = T._hints['get_padding_drop'](d)
613613 else:
614614 padding_drop = []
615 type, name = self.get_declaration()
616 if name != self.name and self.getvarlength() < 1 and len(data) < 2:
615 type, name, is_union = self.get_declaration()
616 if is_union and self.getvarlength() < 1 and len(data) < 2:
617617 # an empty union
618618 yield ''
619619 return
3535 #define OP_DEBUG_OFFSET(res) res = pypy_debug_offset()
3636 #define OP_DEBUG_FORKED(ofs, _) pypy_debug_forked(ofs)
3737 #define OP_HAVE_DEBUG_PRINTS(r) r = (pypy_have_debug_prints & 1)
38 #define OP_DEBUG_FLUSH() fflush(pypy_debug_file)
38
39 #ifdef RPY_REVERSE_DEBUGGER
40 RPY_EXTERN void rpy_reverse_db_teardown(void);
41 # define OP_DEBUG_FLUSH() fflush(pypy_debug_file); rpy_reverse_db_teardown()
42 #else
43 # define OP_DEBUG_FLUSH() fflush(pypy_debug_file)
44 #endif
3945
4046 /************************************************************/
4147
3434
3535 #ifdef RPY_WITH_GIL
3636 # include <src/thread.h>
37 #endif
38
39 #ifdef RPY_REVERSE_DEBUGGER
40 # include <src-revdb/revdb_include.h>
3741 #endif
3842
3943 RPY_EXPORTED
8286 pypy_asm_stack_bottom();
8387 instrument_setup();
8488
89 #ifdef RPY_REVERSE_DEBUGGER
90 rpy_reverse_db_setup(&argc, &argv);
91 #endif
92
8593 #ifndef MS_WINDOWS
8694 /* this message does no longer apply to win64 :-) */
8795 if (sizeof(void*) != SIZEOF_LONG) {
93101
94102 RPython_StartupCode();
95103
104 #ifndef RPY_REVERSE_DEBUGGER
96105 exitcode = STANDALONE_ENTRY_POINT(argc, argv);
106 #else
107 exitcode = rpy_reverse_db_main(STANDALONE_ENTRY_POINT, argc, argv);
108 #endif
97109
98110 pypy_debug_alloc_results();
99111
4949 #ifdef __CYGWIN__
5050 #include "src/cygwin_wait.h"
5151 #endif
52
53 #ifdef RPY_REVERSE_DEBUGGER
54 #include "src-revdb/revdb_include.h"
55 #endif
2222 # define RPY_LENGTH0 1 /* array decl [0] are bad */
2323 # define RPY_DUMMY_VARLENGTH /* nothing */
2424 #endif
25
26 #ifdef RPY_REVERSE_DEBUGGER
27 #include "src-revdb/revdb_preinclude.h"
28 #endif
159159 #define OP_CAST_INT_TO_LONGLONGLONG(x,r) r = (__int128_t)(x)
160160 #define OP_CAST_CHAR_TO_INT(x,r) r = (Signed)((unsigned char)(x))
161161 #define OP_CAST_INT_TO_CHAR(x,r) r = (char)(x)
162 #define OP_CAST_PTR_TO_INT(x,r) r = (Signed)(x) /* XXX */
163162
164163 #define OP_TRUNCATE_LONGLONG_TO_INT(x,r) r = (Signed)(x)
165164 #define OP_TRUNCATE_LONGLONGLONG_TO_INT(x,r) r = (Signed)(x)
7979 RPY_EXTERN void (*boehm_fq_trigger[])(void);
8080
8181 int boehm_gc_finalizer_lock = 0;
82 void boehm_gc_finalizer_notifier(void);
83
84 #ifndef RPY_REVERSE_DEBUGGER
8285 void boehm_gc_finalizer_notifier(void)
8386 {
8487 int i;
100103
101104 boehm_gc_finalizer_lock--;
102105 }
106 #else
107 /* see revdb.c */
108 RPY_EXTERN void *rpy_reverse_db_next_dead(void *);
109 RPY_EXTERN int rpy_reverse_db_fq_register(void *);
110 #endif
103111
104112 static void mem_boehm_ignore(char *msg, GC_word arg)
105113 {
113121 GC_set_warn_proc(mem_boehm_ignore);
114122 }
115123
116 void boehm_fq_callback(void *obj, void *rawfqueue)
124 static void boehm_fq_callback(void *obj, void *rawfqueue)
117125 {
118126 struct boehm_fq_s **fqueue = rawfqueue;
119127 struct boehm_fq_s *node = GC_malloc(sizeof(void *) * 2);
124132 *fqueue = node;
125133 }
126134
135 void boehm_fq_register(struct boehm_fq_s **fqueue, void *obj)
136 {
137 #ifdef RPY_REVERSE_DEBUGGER
138 /* this function returns 0 when recording, or 1 when replaying */
139 if (rpy_reverse_db_fq_register(obj))
140 return;
141 #endif
142 GC_REGISTER_FINALIZER(obj, boehm_fq_callback, fqueue, NULL, NULL);
143 }
144
127145 void *boehm_fq_next_dead(struct boehm_fq_s **fqueue)
128146 {
129147 struct boehm_fq_s *node = *fqueue;
148 void *result;
130149 if (node != NULL) {
131150 *fqueue = node->next;
132 return node->obj;
151 result = node->obj;
133152 }
134153 else
135 return NULL;
154 result = NULL;
155 #ifdef RPY_REVERSE_DEBUGGER
156 result = rpy_reverse_db_next_dead(result);
157 #endif
158 return result;
136159 }
137160 #endif /* BOEHM GC */
138161
105105 struct boehm_fq_s;
106106 RPY_EXTERN struct boehm_fq_s *boehm_fq_queues[];
107107 RPY_EXTERN void (*boehm_fq_trigger[])(void);
108 RPY_EXTERN void boehm_fq_callback(void *, void *);
108 RPY_EXTERN void boehm_fq_register(struct boehm_fq_s **, void *);
109109 RPY_EXTERN void *boehm_fq_next_dead(struct boehm_fq_s **);
110110
111111 #define OP_GC__DISABLE_FINALIZERS(r) boehm_gc_finalizer_lock++
112112 #define OP_GC__ENABLE_FINALIZERS(r) (boehm_gc_finalizer_lock--, \
113113 boehm_gc_finalizer_notifier())
114 #define OP_GC__DISABLE(r) /* nothing */
115 #define OP_GC__ENABLE(r) /* nothing */
114116
115117 #define OP_BOEHM_FQ_REGISTER(tagindex, obj, r) \
116 GC_REGISTER_FINALIZER(obj, boehm_fq_callback, \
117 boehm_fq_queues + tagindex, NULL, NULL)
118 boehm_fq_register(boehm_fq_queues + tagindex, obj)
118119 #define OP_BOEHM_FQ_NEXT_DEAD(tagindex, r) \
119120 r = boehm_fq_next_dead(boehm_fq_queues + tagindex)
120121
127128 #define OP_BOEHM_DISAPPEARING_LINK(link, obj, r) /* nothing */
128129 #define OP_GC__DISABLE_FINALIZERS(r) /* nothing */
129130 #define OP_GC__ENABLE_FINALIZERS(r) /* nothing */
131 #define OP_GC__DISABLE(r) /* nothing */
132 #define OP_GC__ENABLE(r) /* nothing */
130133 #define GC_REGISTER_FINALIZER(a, b, c, d, e) /* nothing */
131134 #define GC_gcollect() /* nothing */
132135 #define GC_set_max_heap_size(a) /* nothing */
134137 #define OP_GC_FQ_NEXT_DEAD(tag, r) (r = NULL)
135138 #endif
136139
137 #if defined(PYPY_USING_BOEHM_GC) || defined(PYPY_USING_NO_GC_AT_ALL)
140 #if (defined(PYPY_USING_BOEHM_GC) || defined(PYPY_USING_NO_GC_AT_ALL)) && !defined(PYPY_BOEHM_WITH_HEADER)
138141 # define RPY_SIZE_OF_GCHEADER 0
139142 #else
140143 # define RPY_SIZE_OF_GCHEADER sizeof(struct pypy_header0)
7272 # define RPY_EXTERN extern _RPY_HIDDEN
7373 #endif
7474
75 #ifdef _WIN32
76 # define inline _inline
77 #endif
7578
7679 #endif /* __PYPY_PRECOMMONDEFS_H */
7780
3636 void *pypysig_getaddr_occurred(void);
3737 #define pypysig_getaddr_occurred() ((void *)(&pypysig_counter))
3838
39 inline static char pypysig_check_and_reset(void) {
40 /* used by reverse_debugging */
41 char result = --pypysig_counter.value < 0;
42 if (result)
43 pypysig_counter.value = 100;
44 return result;
45 }
46
3947 #endif
1313 #ifdef _WIN32
1414 #define RPYTHREAD_NAME "nt"
1515 #include "thread_nt.h"
16 #define inline _inline
1716 #else
1817
1918 /* We should check if unistd.h defines _POSIX_THREADS, but sometimes
117117 RPY_EXTERN pthread_key_t pypy_threadlocal_key;
118118
119119
120 /* only for the fall-back path in the JIT */
121 #define OP_THREADLOCALREF_GET_NONCONST(RESTYPE, offset, r) \
120 #define OP_THREADLOCALREF_LOAD(RESTYPE, offset, r) \
122121 do { \
123122 char *a; \
124123 OP_THREADLOCALREF_ADDR(a); \
125124 r = *(RESTYPE *)(a + offset); \
126125 } while (0)
127126
127 #define OP_THREADLOCALREF_STORE(VALTYPE, offset, value) \
128 do { \
129 char *a; \
130 OP_THREADLOCALREF_ADDR(a); \
131 *(VALTYPE *)(a + offset) = value; \
132 } while (0)
133
128134
129135 #endif /* _SRC_THREADLOCAL_H */
18111811 res = self.run("ignore_finalizer")
18121812 assert res == 1 # translated: x1 is removed from the list
18131813
1814
1814 def define_enable_disable(self):
1815 class Counter(object):
1816 val = 0
1817 counter = Counter()
1818 class X(object):
1819 def __del__(self):
1820 counter.val += 1
1821 def f(should_disable):
1822 x1 = X()
1823 rgc.collect() # make x1 old
1824 assert not rgc.can_move(x1)
1825 x1 = None
1826 #
1827 if should_disable:
1828 gc.disable()
1829 assert not gc.isenabled()
1830 # try to trigger a major collection
1831 N = 100 # this should be enough, increase if not
1832 lst = []
1833 for i in range(N):
1834 lst.append(chr(i%256) * (1024*1024))
1835 #print i, counter.val
1836 #
1837 gc.enable()
1838 assert gc.isenabled()
1839 return counter.val
1840 return f
1841
1842 def test_enable_disable(self):
1843 # first, run with normal gc. If the assert fails it means that in the
1844 # loop we don't allocate enough mem to trigger a major collection. Try
1845 # to increase N
1846 deleted = self.run("enable_disable", 0)
1847 assert deleted == 1, 'This should not fail, try to increment N'
1848 #
1849 # now, run with gc.disable: this should NOT free x1
1850 deleted = self.run("enable_disable", 1)
1851 assert deleted == 0
1852
1853 def define_collect_step(self):
1854 class Counter(object):
1855 val = 0
1856 counter = Counter()
1857 class X(object):
1858 def __del__(self):
1859 counter.val += 1
1860 def f():
1861 x1 = X()
1862 rgc.collect() # make x1 old
1863 assert not rgc.can_move(x1)
1864 x1 = None
1865 #
1866 gc.disable()
1867 n = 0
1868 states = []
1869 while True:
1870 n += 1
1871 val = rgc.collect_step()
1872 states.append((rgc.old_state(val), rgc.new_state(val)))
1873 if rgc.is_done(val):
1874 break
1875 if n == 100:
1876 print 'Endless loop!'
1877 assert False, 'this looks like an endless loop'
1878
1879 if n < 4: # we expect at least 4 steps
1880 print 'Too few steps! n =', n
1881 assert False
1882
1883 # check that the state transitions are reasonable
1884 first_state, _ = states[0]
1885 for i, (old_state, new_state) in enumerate(states):
1886 is_last = (i == len(states) - 1)
1887 is_valid = False
1888 if is_last:
1889 assert old_state != new_state == first_state
1890 else:
1891 assert new_state == old_state or new_state == old_state+1
1892
1893 return counter.val
1894 return f
1895
1896 def test_collect_step(self):
1897 deleted = self.run("collect_step")
1898 assert deleted == 1
1899
1900 def define_total_gc_time(cls):
1901 def f():
1902 l = []
1903 for i in range(1000000):
1904 l.append(str(i))
1905 l = []
1906 for i in range(10):
1907 rgc.collect()
1908 return rgc.get_stats(rgc.TOTAL_GC_TIME)
1909 return f
1910
1911 def test_total_gc_time(self):
1912 res = self.run("total_gc_time")
1913 assert res > 0 # should take a few microseconds
18151914 # ____________________________________________________________________
18161915
18171916 class TaggedPointersTest(object):
520520 assert path.check(file=0)
521521
522522 def test_debug_start_stop_timestamp(self):
523 import sys
524 import time
525523 from rpython.rlib.rtimer import read_timestamp
526524 def entry_point(argv):
527 timestamp = int(argv[1])
525 timestamp = bool(int(argv[1]))
528526 ts1 = debug_start("foo", timestamp=timestamp)
529527 ts2 = read_timestamp()
530528 ts3 = debug_stop("foo", timestamp=timestamp)
961961 f = self.getcompiled(func, [int])
962962 res = f(2)
963963 assert res == 1 # and not 2
964
965 def test_mulmod(self):
966 from rpython.rlib.rarithmetic import mulmod
967
968 def func(a, b, c):
969 return mulmod(a, b, c)
970 f = self.getcompiled(func, [int, int, int])
971 res = f(1192871273, 1837632879, 2001286281)
972 assert res == 1573897320
6565 assertion_error_ll_exc_type)
6666 self.c_n_i_error_ll_exc_type = constant_value(n_i_error_ll_exc_type)
6767
68 def rpyexc_occured():
68 def rpyexc_occurred():
6969 exc_type = exc_data.exc_type
7070 return bool(exc_type)
7171
108108 exc_data.exc_type = ll_inst_type(evalue)
109109 exc_data.exc_value = evalue
110110
111 self.rpyexc_occured_ptr = self.build_func(
111 self.rpyexc_occurred_ptr = self.build_func(
112112 "RPyExceptionOccurred",
113 rpyexc_occured,
113 rpyexc_occurred,
114114 [], lltype.Bool)
115115
116116 self.rpyexc_fetch_type_ptr = self.build_func(
451451 def setup_excdata(self):
452452 EXCDATA = lltype.Struct('ExcData',
453453 ('exc_type', self.lltype_of_exception_type),
454 ('exc_value', self.lltype_of_exception_value))
454 ('exc_value', self.lltype_of_exception_value),
455 hints={'is_excdata': True})
455456 self.EXCDATA = EXCDATA
456457
457458 exc_data = lltype.malloc(EXCDATA, immortal=True)
4343 # - Results are sensitive to locking cost, but we dont
4444 # check for proper locking
4545 import time
46
47 USAGE = """gcbench [num_repetitions] [--depths=N,N,N..] [--threads=N]"""
46 import gc
47
48 USAGE = """gcbench [num_repetitions] [--depths=N,N,N..] [--threads=N] [--gc=off|--gc=manual]"""
4849 ENABLE_THREADS = True
4950
5051
172173 depths = DEFAULT_DEPTHS
173174 threads = 0
174175 repeatcount = 1
176 gc_policy = 'on'
175177 for arg in argv[1:]:
176178 if arg.startswith('--threads='):
177179 arg = arg[len('--threads='):]
188190 depths = [int(s) for s in arg]
189191 except ValueError:
190192 return argerror()
193 elif arg.startswith('--gc=off'):
194 gc_policy = 'off'
195 elif arg.startswith('--gc=manual'):
196 gc_policy = 'manual'
191197 else:
192198 try:
193199 repeatcount = int(arg)
194200 except ValueError:
195201 return argerror()
202 #
203 if gc_policy == 'off' or gc_policy == 'manual':
204 gc.disable()
196205 for i in range(repeatcount):
197206 main(depths, threads)
207 if gc_policy == 'manual':
208 gc.collect(1)
198209 return 0
199210
200211
307307 host_factory = OpenBSD
308308 else:
309309 host_factory = OpenBSD_64
310 elif sys.platform.startswith('gnu'):
311 from rpython.translator.platform.hurd import Hurd
312 import platform
313 if platform.architecture()[0] == '32bit':
314 host_factory = Hurd
315 else:
316 host_factory = Hurd_64
310317 elif os.name == 'nt':
311318 from rpython.translator.platform.windows import Windows, Windows_x64
312319 import platform
0 """Support for Hurd."""
1
2 import os
3 import platform
4 import sys
5 from rpython.translator.platform.posix import BasePosix
6
7 class BaseHurd(BasePosix):
8 name = "hurd"
9
10 link_flags = tuple(
11 ['-pthread',]
12 + os.environ.get('LDFLAGS', '').split())
13 extra_libs = ('-lrt',)
14 cflags = tuple(
15 ['-O3', '-pthread', '-fomit-frame-pointer',
16 '-Wall', '-Wno-unused', '-Wno-address']
17 + os.environ.get('CFLAGS', '').split())
18 standalone_only = ()
19 shared_only = ('-fPIC',)
20 so_ext = 'so'
21
22 def _args_for_shared(self, args, **kwds):
23 return ['-shared'] + args
24
25 def _include_dirs_for_libffi(self):
26 return self._pkg_config("libffi", "--cflags-only-I",
27 ['/usr/include/libffi'],
28 check_result_dir=True)
29
30 def _library_dirs_for_libffi(self):
31 return self._pkg_config("libffi", "--libs-only-L",
32 ['/usr/lib/libffi'],
33 check_result_dir=True)
34
35
36 class Hurd(BaseHurd):
37 shared_only = () # it seems that on 32-bit GNU, compiling with -fPIC
38 # gives assembler that asmgcc is not happy about.
39
40 class HurdPIC(BaseHurd):
41 pass
88 import rpython
99 rpydir = str(py.path.local(rpython.__file__).join('..'))
1010
11 def _get_compiler_type(cc, x64_flag, ver0=None):
11 def _get_compiler_type(cc, x64_flag):
1212 if not cc:
1313 cc = os.environ.get('CC','')
1414 if not cc:
15 return MsvcPlatform(x64=x64_flag, ver0=ver0)
15 return MsvcPlatform(x64=x64_flag)
1616 elif cc.startswith('mingw') or cc == 'gcc':
1717 return MingwPlatform(cc)
18 return MsvcPlatform(cc=cc, x64=x64_flag, ver0=ver0)
18 return MsvcPlatform(cc=cc, x64=x64_flag)
1919
2020 def _get_vcver0():
2121 # try to get the compiler which served to compile python
2727 return vsver
2828 return None
2929
30 def Windows(cc=None, ver0=None):
31 #if ver0 is None:
32 # ver0 = _get_vcver0()
33 return _get_compiler_type(cc, False, ver0=ver0)
30 def Windows(cc=None):
31 return _get_compiler_type(cc, False)
3432
3533 def Windows_x64(cc=None, ver0=None):
3634 raise Exception("Win64 is not supported. You must either build for Win32"
3735 " or contribute the missing support in PyPy.")
38 if ver0 is None:
39 ver0 = _get_vcver0()
40 return _get_compiler_type(cc, True, ver0=ver0)
36 return _get_compiler_type(cc, True)
4137
4238 def _find_vcvarsall(version, x64flag):
4339 import rpython.tool.setuptools_msvc as msvc
4945 return msvc.msvc14_get_vc_env(arch)
5046 else:
5147 return msvc.msvc9_query_vcvarsall(version / 10.0, arch)
52
48
5349 def _get_msvc_env(vsver, x64flag):
5450 vcdict = None
5551 toolsdir = None
5955 # use setuptools from python3 to find tools
6056 try:
6157 vcdict = _find_vcvarsall(vsver, x64flag)
58 except ImportError as e:
59 if 'setuptools' in str(e):
60 log.error('is setuptools installed (perhaps try %s -mensurepip)?' % sys.executable)
61 log.error('looking for compiler %s raised exception "%s' % (vsver, str(e)))
6262 except Exception as e:
63 log.error('looking for compiler %s raised exception "%s' % (vsver, str(e)))
6364 return None
6465 else:
6566 if x64flag:
7374 # even msdn does not know which to run
7475 # see https://msdn.microsoft.com/en-us/library/1700bbwd(v=vs.90).aspx
7576 # which names both
76 vcvars = os.path.join(toolsdir, 'vcvars32.bat')
77 vcvars = os.path.join(toolsdir, 'vcvars32.bat')
7778
7879 import subprocess
7980 try:
8283 stderr=subprocess.PIPE)
8384
8485 stdout, stderr = popen.communicate()
85 if popen.wait() != 0:
86 if popen.wait() != 0 or stdout[:5].lower() == 'error':
87 log.msg('Running "%s" errored: \n\nstdout:\n%s\n\nstderr:\n%s' % (
88 vcvars, stdout.split()[0], stderr))
8689 return None
87 except:
90 else:
91 log.msg('Running "%s" succeeded' %(vcvars,))
92 except Exception as e:
93 log.msg('Running "%s" failed: "%s"' % (vcvars, str(e)))
8894 return None
8995
9096 stdout = stdout.replace("\r\n", "\n")
98104 for key, value in vcdict.items():
99105 if key.upper() in ['PATH', 'INCLUDE', 'LIB']:
100106 env[key.upper()] = value
107 if 'PATH' not in env:
108 log.msg('Did not find "PATH" in stdout\n%s' %(stdout))
101109 if not _find_executable('mt.exe', env['PATH']):
102110 # For some reason the sdk bin path is missing?
103111 # put it together from some other env variables that happened to exist
109117 log.msg('Could not find mt.exe on path=%s' % env['PATH'])
110118 log.msg('Running vsver %s set this env' % vsver)
111119 for key, value in vcdict.items():
112 log.msg('%s=%s' %(key, value))
120 log.msg('%s=%s' %(key, value))
113121 log.msg("Updated environment with vsver %d, using x64 %s" % (vsver, x64flag,))
114122 return env
115123
118126 if ver0 in vcvers:
119127 vcvers.insert(0, ver0)
120128 errs = []
121 for vsver in vcvers:
129 for vsver in vcvers:
122130 env = _get_msvc_env(vsver, x64flag)
123131 if env is not None:
124132 return env, vsver
185193 self.cc = cc
186194
187195 # detect version of current compiler
188 returncode, stdout, stderr = _run_subprocess(self.cc, '',
196 try:
197 returncode, stdout, stderr = _run_subprocess(self.cc, [],
189198 env=self.c_environ)
199 except EnvironmentError:
200 log.msg('Could not run %s using PATH=\n%s' %(self.cc,
201 '\n'.join(self.c_environ['PATH'].split(';'))))
202 raise
190203 r = re.search(r'Microsoft.+C/C\+\+.+\s([0-9]+)\.([0-9]+).*', stderr)
191204 if r is not None:
192205 self.version = int(''.join(r.groups())) / 10 - 60
195208 self.version = 0
196209
197210 # Try to find a masm assembler
198 returncode, stdout, stderr = _run_subprocess('ml.exe', '',
211 returncode, stdout, stderr = _run_subprocess('ml.exe', [],
199212 env=self.c_environ)
200213 r = re.search('Macro Assembler', stderr)
201214 if r is None and os.path.exists('c:/masm32/bin/ml.exe'):
272285 if not standalone:
273286 args = self._args_for_shared(args)
274287
275 if self.version >= 80:
276 # Tell the linker to generate a manifest file
277 temp_manifest = exe_name.dirpath().join(
278 exe_name.purebasename + '.manifest')
279 args += ["/MANIFEST", "/MANIFESTFILE:%s" % (temp_manifest,)]
288 # Tell the linker to generate a manifest file
289 temp_manifest = exe_name.dirpath().join(
290 exe_name.purebasename + '.manifest')
291 args += ["/MANIFEST", "/MANIFESTFILE:%s" % (temp_manifest,)]
280292
281293 self._execute_c_compiler(self.link, args, exe_name)
282294
283 if self.version >= 80:
284 # Now, embed the manifest into the program
285 if standalone:
286 mfid = 1
287 else:
288 mfid = 2
289 out_arg = '-outputresource:%s;%s' % (exe_name, mfid)
290 args = ['-nologo', '-manifest', str(temp_manifest), out_arg]
291 self._execute_c_compiler('mt.exe', args, exe_name)
295 # Now, embed the manifest into the program
296 if standalone:
297 mfid = 1
298 else:
299 mfid = 2
300 out_arg = '-outputresource:%s;%s' % (exe_name, mfid)
301 args = ['-nologo', '-manifest', str(temp_manifest), out_arg]
302 self._execute_c_compiler('mt.exe', args, exe_name)
292303
293304 return exe_name
294305
392403
393404 if len(headers_to_precompile)>0:
394405 if shared:
395 no_precompile_cfiles += [m.makefile_dir / 'main.c',
406 no_precompile_cfiles += [m.makefile_dir / 'main.c',
396407 m.makefile_dir / 'wmain.c']
397408 stdafx_h = path.join('stdafx.h')
398409 txt = '#ifndef PYPY_STDAFX_H\n'
0 import py, random, sys
1 from rpython.rtyper.lltypesystem import lltype, llmemory, rffi, rstr
2 from rpython.rtyper.lltypesystem.lloperation import LL_OPERATIONS
3 from rpython.translator.c.support import cdecl
4 from rpython.rlib import exports, revdb
5
6 #
7 # How It Works: we arrange things so that when replaying, all variables
8 # have the "same" content as they had during recording. More precisely,
9 # we divide all variables according to their type in two categories:
10 #
11 # * non-GC pointers, whose values are bitwise identical.
12 #
13 # * GC pointers: these things are "moving", in the sense that the
14 # bitwise value of a GC pointer during recording is different from
15 # its bitwise value during replaying. The object at the new
16 # address contains the "same" content as the original one, using
17 # this definition of "same".
18 #
19 # Note that most non-GC pointers are not followed during replaying: we
20 # never call external libraries nor call malloc to get pieces of raw
21 # memory. Writes to raw memory are ignored, and reads return a value
22 # recorded in the log file. However, the following are still needed:
23 #
24 # * function pointers pointing to RPython functions;
25 #
26 # * "static-immutable" structs like vtables.
27 #
28 # For now. we must make sure that these are at the same address as
29 # they were. This is very roughly checked. On Linux, it means you
30 # must run with Address Space Layout Randomization disabled. This
31 # might be fixed in the future.
32 #
33
34
35 def extra_files():
36 srcdir = py.path.local(__file__).join('..', 'src-revdb')
37 return [
38 srcdir / 'revdb.c',
39 ]
40
41 ## def mangle_name_prebuilt_raw(database, node, S):
42 ## if (S._gckind != 'gc' and not S._hints.get('is_excdata')
43 ## and not S._hints.get('static_immutable')
44 ## and not S._hints.get('ignore_revdb')
45 ## and not S._hints.get('gcheader')):
46 ## database.all_raw_structures.append(node)
47 ## node.name = 'RPY_RDB_A(%s)' % (node.name,)
48 ## return True
49 ## else:
50 ## return False
51
52 def prepare_function(funcgen):
53 if getattr(getattr(funcgen.graph, 'func', None), '_revdb_c_only_', False):
54 extra_enter_text = 'RPY_REVDB_C_ONLY_ENTER'
55 extra_return_text = 'RPY_REVDB_C_ONLY_LEAVE'
56 return extra_enter_text, extra_return_text
57 stack_bottom = False
58 for block in funcgen.graph.iterblocks():
59 for op in block.operations:
60 if op.opname == 'gc_stack_bottom':
61 stack_bottom = True
62 if stack_bottom:
63 name = funcgen.functionname
64 funcgen.db.stack_bottom_funcnames.append(name)
65 extra_enter_text = '\n'.join(
66 ['/* this function is a callback */',
67 'RPY_REVDB_CALLBACKLOC(RPY_CALLBACKLOC_%s);' % name] +
68 ['\t' + emit('/*arg*/', funcgen.lltypename(v), funcgen.expr(v))
69 for v in funcgen.graph.getargs()])
70 extra_return_text = '/* RPY_CALLBACK_LEAVE(); */'
71 return extra_enter_text, extra_return_text
72 else:
73 return None, None
74
75 def emit_void(normal_code):
76 return 'RPY_REVDB_EMIT_VOID(%s);' % (normal_code,)
77
78 def emit(normal_code, tp, value):
79 if tp == 'void @':
80 return emit_void(normal_code)
81 return 'RPY_REVDB_EMIT(%s, %s, %s);' % (normal_code, cdecl(tp, '_e'), value)
82
83 def emit_residual_call(funcgen, call_code, v_result, expr_result):
84 if hasattr(funcgen, 'revdb_do_next_call'):
85 del funcgen.revdb_do_next_call
86 return call_code # a hack for ll_call_destructor() to mean
87 # that the calls should really be done.
88 # Also used in rpython.rlib.clibffi.
89 #
90 if call_code in ('RPyGilAcquire();', 'RPyGilRelease();'):
91 # Could also work with a regular RPY_REVDB_CALL_VOID, but we
92 # use a different byte (0xFD, 0xFE instead of 0xFC) to detect more
93 # sync misses. In a single-threaded environment this 0xFD or 0xFE
94 # byte is not needed at all, but in a multi-threaded
95 # environment it ensures that during replaying, just after
96 # reading the 0xFD or 0xFE, we switch to a different thread if needed
97 # (actually implemented with stacklets).
98 if call_code == 'RPyGilAcquire();':
99 return 'RPY_REVDB_CALL_GIL_ACQUIRE();'
100 else:
101 return 'RPY_REVDB_CALL_GIL_RELEASE();'
102 #
103 tp = funcgen.lltypename(v_result)
104 if tp == 'void @':
105 return 'RPY_REVDB_CALL_VOID(%s);' % (call_code,)
106 return 'RPY_REVDB_CALL(%s, %s, %s);' % (call_code, cdecl(tp, '_e'),
107 expr_result)
108
109 def record_malloc_uid(expr):
110 return ' RPY_REVDB_REC_UID(%s);' % (expr,)
111
112 def boehm_register_finalizer(funcgen, op):
113 return 'rpy_reverse_db_register_destructor(%s, %s);' % (
114 funcgen.expr(op.args[0]), funcgen.expr(op.args[1]))
115
116 def cast_gcptr_to_int(funcgen, op):
117 return '%s = RPY_REVDB_CAST_PTR_TO_INT(%s);' % (
118 funcgen.expr(op.result), funcgen.expr(op.args[0]))
119
120 set_revdb_protected = set(opname for opname, opdesc in LL_OPERATIONS.items()
121 if opdesc.revdb_protect)
122
123
124 def prepare_database(db):
125 FUNCPTR = lltype.Ptr(lltype.FuncType([revdb._CMDPTR, lltype.Ptr(rstr.STR)],
126 lltype.Void))
127 ALLOCFUNCPTR = lltype.Ptr(lltype.FuncType([rffi.LONGLONG, llmemory.GCREF],
128 lltype.Void))
129
130 bk = db.translator.annotator.bookkeeper
131 cmds = getattr(db.translator, 'revdb_commands', {})
132 numcmds = [(num, func) for (num, func) in cmds.items()
133 if isinstance(num, int)]
134
135 S = lltype.Struct('RPY_REVDB_COMMANDS',
136 ('names', lltype.FixedSizeArray(rffi.INT, len(numcmds) + 1)),
137 ('funcs', lltype.FixedSizeArray(FUNCPTR, len(numcmds))),
138 ('alloc', ALLOCFUNCPTR))
139 s = lltype.malloc(S, flavor='raw', immortal=True, zero=True)
140
141 i = 0
142 for name, func in cmds.items():
143 fnptr = lltype.getfunctionptr(bk.getdesc(func).getuniquegraph())
144 if isinstance(name, int):
145 assert name != 0
146 s.names[i] = rffi.cast(rffi.INT, name)
147 s.funcs[i] = fnptr
148 i += 1
149 elif name == "ALLOCATING":
150 s.alloc = fnptr
151 else:
152 raise AssertionError("bad tag in register_debug_command(): %r"
153 % (name,))
154
155 exports.EXPORTS_obj2name[s._as_obj()] = 'rpy_revdb_commands'
156 db.get(s)
157
158 db.stack_bottom_funcnames = []
159 ## db.all_raw_structures = []
160
161 def write_revdb_def_file(db, target_path):
162 f = target_path.open('w')
163 funcnames = sorted(db.stack_bottom_funcnames)
164 ## print >> f, "#define RDB_VERSION 0x%x" % random.randrange(0, sys.maxint)
165 ## print >> f
166 for i, fn in enumerate(funcnames):
167 print >> f, '#define RPY_CALLBACKLOC_%s %d' % (fn, i)
168 print >> f
169 print >> f, '#define RPY_CALLBACKLOCS \\'
170 funcnames = funcnames or ['NULL']
171 for i, fn in enumerate(funcnames):
172 if i == len(funcnames) - 1:
173 tail = ''
174 else:
175 tail = ', \\'
176 print >> f, '\t(void *)%s%s' % (fn, tail)
177 ## print >> f
178
179 ## def _base(name):
180 ## assert name.startswith('RPY_RDB_A(')
181 ## if name.endswith('.b'):
182 ## name = name[:-2]
183 ## name = name[len('RPY_RDB_A('):-1]
184 ## return name
185
186 ## rawstructs = sorted(db.all_raw_structures, key=lambda node: node.name)
187 ## print >> f, '#define RPY_RDB_A(name) (*rpy_rdb_struct.name)'
188 ## print >> f, 'struct rpy_rdb_a_s {'
189 ## for i, node in enumerate(rawstructs):
190 ## print >> f, '\t%s;' % (cdecl(node.typename, '*'+_base(node.name)),)
191 ## if not rawstructs:
192 ## print >> f, '\tchar dummy;'
193 ## print >> f, '};'
194 ## print >> f, 'RPY_EXTERN struct rpy_rdb_a_s rpy_rdb_struct;'
195 ## print >> f
196 ## print >> f, '#define RPY_RDB_STRUCT_CONTENT \\'
197 ## if not rawstructs:
198 ## print >> f, '\t0'
199 ## else:
200 ## for i, node in enumerate(rawstructs):
201 ## if i == len(rawstructs) - 1:
202 ## tail = ''
203 ## else:
204 ## tail = ', \\'
205 ## name = '&' + _base(node.name)
206 ## if node.typename != node.implementationtypename:
207 ## name = '(%s)%s' % (cdecl(node.typename, '*'), name)
208 ## print >> f, '\t%s%s' % (name, tail)
209 f.close()
0 #!/usr/bin/env pypy
1
2 # Post-process log files to make them diff-able.
3 #
4 # When you get errors caused by revdb.py getting out of sync with the
5 # original log file, recompile the program (e.g. pypy-c) by editing
6 # revdb_include.h, enabling the "#if 0" (at least the first one,
7 # possibly the second one too). This prints locations to stderr of
8 # all the EMITs. Then create the log file by redirecting stderr to
9 # "log.err1", and then run revdb.py by redirecting stderr to
10 # "log.err2" (typically, entering the "c" command to continue to the
11 # end). Then diff them both after applying this filter:
12 #
13 # diff -u <(cat log.err1 | .../rpython/translator/revdb/pplog.py) \
14 # <(cat log.err2 | .../rpython/translator/revdb/pplog.py) | less
15
16
17 import sys, re
18
19 r_hide_tail = re.compile(r"revdb[.]c:\d+: ([0-9a-f]+)")
20
21 r_remove = re.compile(r"\w+[.]c:\d+: obj 92233720368|"
22 r"PID \d+ starting, log file disabled|"
23 r"\[")
24
25
26 def post_process(fin, fout):
27 for line in fin:
28 match = r_hide_tail.match(line)
29 if match:
30 line = 'revdb.c:after pplog.py: %s\n' % ('#' * len(match.group(1)),)
31 elif r_remove.match(line):
32 continue
33 fout.write(line)
34
35
36 if __name__ == '__main__':
37 post_process(sys.stdin, sys.stdout)
0 /***************************************************************************
1 * libancillary - black magic on Unix domain sockets
2 * (C) Nicolas George
3 * ancillary.h - public header
4 ***************************************************************************/
5
6 /*
7 * Redistribution and use in source and binary forms, with or without
8 * modification, are permitted provided that the following conditions are met:
9 *
10 * 1. Redistributions of source code must retain the above copyright notice,
11 * this list of conditions and the following disclaimer.
12 * 2. Redistributions in binary form must reproduce the above copyright
13 * notice, this list of conditions and the following disclaimer in the
14 * documentation and/or other materials provided with the distribution.
15 * 3. The name of the author may not be used to endorse or promote products
16 * derived from this software without specific prior written permission.
17 *
18 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR IMPLIED
19 * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
20 * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO
21 * EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
22 * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
23 * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS;
24 * OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
25 * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
26 * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
27 * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
28 */
29
30 #ifndef ANCILLARY_H__
31 #define ANCILLARY_H__
32
33 /***************************************************************************
34 * Start of the readable part.
35 ***************************************************************************/
36
37 #define ANCIL_MAX_N_FDS 960
38 /*
39 * Maximum number of fds that can be sent or received using the "esay"
40 * functions; this is so that all can fit in one page.
41 */
42
43 extern int
44 ancil_send_fds_with_buffer(int, const int *, unsigned, void *);
45 /*
46 * ancil_send_fds_with_buffer(sock, n_fds, fds, buffer)
47 *
48 * Sends the file descriptors in the array pointed by fds, of length n_fds
49 * on the socket sock.
50 * buffer is a writeable memory area large enough to hold the required data
51 * structures.
52 * Returns: -1 and errno in case of error, 0 in case of success.
53 */
54
55 extern int
56 ancil_recv_fds_with_buffer(int, int *, unsigned, void *);
57 /*
58 * ancil_recv_fds_with_buffer(sock, n_fds, fds, buffer)
59 *
60 * Receives *n_fds file descriptors into the array pointed by fds
61 * from the socket sock.
62 * buffer is a writeable memory area large enough to hold the required data
63 * structures.
64 * Returns: -1 and errno in case of error, the actual number of received fd
65 * in case of success
66 */
67
68 #define ANCIL_FD_BUFFER(n) \
69 struct { \
70 struct cmsghdr h; \
71 int fd[n]; \
72 }
73 /* ANCIL_FD_BUFFER(n)
74 *
75 * A structure type suitable to be used as buffer for n file descriptors.
76 * Requires <sys/socket.h>.
77 * Example:
78 * ANCIL_FD_BUFFER(42) buffer;
79 * ancil_recv_fds_with_buffer(sock, 42, my_fds, &buffer);
80 */
81
82 extern int
83 ancil_send_fds(int, const int *, unsigned);
84 /*
85 * ancil_send_fds(sock, n_fds, fds)
86 *
87 * Sends the file descriptors in the array pointed by fds, of length n_fds
88 * on the socket sock.
89 * n_fds must not be greater than ANCIL_MAX_N_FDS.
90 * Returns: -1 and errno in case of error, 0 in case of success.
91 */
92
93 extern int
94 ancil_recv_fds(int, int *, unsigned);
95 /*
96 * ancil_recv_fds(sock, n_fds, fds)
97 *
98 * Receives *n_fds file descriptors into the array pointed by fds
99 * from the socket sock.
100 * *n_fds must not be greater than ANCIL_MAX_N_FDS.
101 * Returns: -1 and errno in case of error, the actual number of received fd
102 * in case of success.
103 */
104
105
106 extern int
107 ancil_send_fd(int, int);
108 /* ancil_recv_fd(sock, fd);
109 *
110 * Sends the file descriptor fd on the socket sock.
111 * Returns : -1 and errno in case of error, 0 in case of success.
112 */
113
114 extern int
115 ancil_recv_fd(int, int *);
116 /* ancil_send_fd(sock, &fd);
117 *
118 * Receives the file descriptor fd from the socket sock.
119 * Returns : -1 and errno in case of error, 0 in case of success.
120 */
121
122 #endif /* ANCILLARY_H__ */
0 /***************************************************************************
1 * libancillary - black magic on Unix domain sockets
2 * (C) Nicolas George
3 * fd_send.c - receiving file descriptors
4 ***************************************************************************/
5
6 /*
7 * Redistribution and use in source and binary forms, with or without
8 * modification, are permitted provided that the following conditions are met:
9 *
10 * 1. Redistributions of source code must retain the above copyright notice,
11 * this list of conditions and the following disclaimer.
12 * 2. Redistributions in binary form must reproduce the above copyright
13 * notice, this list of conditions and the following disclaimer in the
14 * documentation and/or other materials provided with the distribution.
15 * 3. The name of the author may not be used to endorse or promote products
16 * derived from this software without specific prior written permission.
17 *
18 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR IMPLIED
19 * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
20 * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO
21 * EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
22 * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
23 * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS;
24 * OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
25 * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
26 * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
27 * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
28 */
29
30 #ifndef _XPG4_2 /* Solaris sucks */
31 # define _XPG4_2
32 #endif
33
34 #include <stdlib.h>
35 #include <sys/types.h>
36 #include <sys/socket.h>
37 #include <sys/uio.h>
38 #include <assert.h>
39 #if defined(__FreeBSD__)
40 # include <sys/param.h> /* FreeBSD sucks */
41 #endif
42
43 #include "ancillary.h"
44
45 int
46 ancil_recv_fds_with_buffer(int sock, int *fds, unsigned n_fds, void *buffer)
47 {
48 struct msghdr msghdr;
49 char nothing;
50 struct iovec nothing_ptr;
51 struct cmsghdr *cmsg;
52 int i;
53
54 nothing_ptr.iov_base = &nothing;
55 nothing_ptr.iov_len = 1;
56 msghdr.msg_name = NULL;
57 msghdr.msg_namelen = 0;
58 msghdr.msg_iov = &nothing_ptr;
59 msghdr.msg_iovlen = 1;
60 msghdr.msg_flags = 0;
61 msghdr.msg_control = buffer;
62 msghdr.msg_controllen = sizeof(struct cmsghdr) + sizeof(int) * n_fds;
63 cmsg = CMSG_FIRSTHDR(&msghdr);
64 cmsg->cmsg_len = msghdr.msg_controllen;
65 cmsg->cmsg_level = SOL_SOCKET;
66 cmsg->cmsg_type = SCM_RIGHTS;
67 for(i = 0; i < n_fds; i++)
68 ((int *)CMSG_DATA(cmsg))[i] = -1;
69
70 if(recvmsg(sock, &msghdr, 0) < 0)
71 return(-1);
72 for(i = 0; i < n_fds; i++)
73 fds[i] = ((int *)CMSG_DATA(cmsg))[i];
74 n_fds = (cmsg->cmsg_len - sizeof(struct cmsghdr)) / sizeof(int);
75 return(n_fds);
76 }
77
78 #ifndef SPARE_RECV_FDS
79 int
80 ancil_recv_fds(int sock, int *fd, unsigned n_fds)
81 {
82 ANCIL_FD_BUFFER(ANCIL_MAX_N_FDS) buffer;
83
84 assert(n_fds <= ANCIL_MAX_N_FDS);
85 return(ancil_recv_fds_with_buffer(sock, fd, n_fds, &buffer));
86 }
87 #endif /* SPARE_RECV_FDS */
88
89 #ifndef SPARE_RECV_FD
90 int
91 ancil_recv_fd(int sock, int *fd)
92 {
93 ANCIL_FD_BUFFER(1) buffer;
94
95 return(ancil_recv_fds_with_buffer(sock, fd, 1, &buffer) == 1 ? 0 : -1);
96 }
97 #endif /* SPARE_RECV_FD */
0 #include "common_header.h"
1 #include <stdlib.h>
2 #include <stdio.h>
3 #include <stddef.h>
4 #include <string.h>
5 #include <assert.h>
6 #include <sys/stat.h>
7 #include <sys/types.h>
8 #include <fcntl.h>
9 #include <unistd.h>
10 #include <ctype.h>
11 #include <signal.h>
12 #include <search.h>
13 #include <sched.h>
14
15 #ifdef __linux__
16 # define HAVE_PERSONALITY
17 #endif
18 #ifdef HAVE_PERSONALITY
19 # include <sys/personality.h>
20 #endif
21
22 #include "structdef.h"
23 #include "forwarddecl.h"
24 #include "preimpl.h"
25 #include "revdb_def.h"
26 #include "src/rtyper.h"
27 #include "src/mem.h"
28 #include "src/threadlocal.h"
29 #include "src-revdb/revdb_include.h"
30
31 #define RDB_SIGNATURE "RevDB:"
32 #define RDB_VERSION 0x00FF0003
33
34 #define WEAKREF_AFTERWARDS_DEAD ((char)0xf2)
35 #define WEAKREF_AFTERWARDS_ALIVE ((char)0xeb)
36
37 #define ASYNC_FINALIZER_TRIGGER ((int16_t)0xff46)
38 #define ASYNC_THREAD_SWITCH ((int16_t)0xff54)
39
40 #define FID_REGULAR_MODE 'R'
41 #define FID_SAVED_STATE 'S'
42 #define FID_POTENTIAL_IO 'I'
43
44
45 typedef struct {
46 Signed version;
47 uint64_t main_thread_id;
48 uint64_t reserved2;
49 void *ptr1, *ptr2;
50 int reserved3;
51 int argc;
52 char **argv;
53 } rdb_header_t;
54
55
56 rpy_revdb_t rpy_revdb;
57 static char rpy_rev_buffer[16384]; /* max. 32768 */
58 int rpy_rev_fileno = -1;
59 static char flag_io_disabled = FID_REGULAR_MODE;
60 __thread int rpy_active_thread;
61 static int *rpy_active_thread_ptr;
62
63
64 static void setup_record_mode(int argc, char *argv[]);
65 static void setup_replay_mode(int *argc_p, char **argv_p[]);
66 static void check_at_end(uint64_t stop_points);
67
68 static void ensure_fixed_address_space(char *argv[])
69 {
70 #ifdef HAVE_PERSONALITY
71 int pers = personality(0xffffffff);
72 if (pers == -1) {
73 perror("personality");
74 exit(1);
75 }
76 if (!(pers & ADDR_NO_RANDOMIZE)) {
77 pers |= ADDR_NO_RANDOMIZE;
78 if (personality(pers) == -1) {
79 perror("personality");
80 exit(1);
81 }
82 pers = personality(0xffffffff);
83 if (pers == -1 || !(pers & ADDR_NO_RANDOMIZE)) {
84 fprintf(stderr, "cannot set ADDR_NO_RANDOMIZE\n");
85 exit(1);
86 }
87 /* After setting this personality(), we need to restart the
88 current process. It will then reload the libpypy-c.so at a
89 non-randomized address.
90
91 Potentially buggy to use argv[0] here, but good enough I
92 suppose. For this reason ensure_fixed_address_space() is
93 not called when running manually without any REVDB
94 environment variable set.
95 */
96 execv(argv[0], argv);
97
98 perror("execv");
99 exit(1);
100 }
101 #endif
102 }
103
104 RPY_EXTERN
105 void rpy_reverse_db_setup(int *argc_p, char **argv_p[])
106 {
107 /* init-time setup */
108
109 int replay_asked = (*argc_p >= 2 && !strcmp((*argv_p)[1],"--revdb-replay"));
110
111 #ifdef RPY_RDB_DYNAMIC_REPLAY
112 RPY_RDB_REPLAY = replay_asked;
113 #else
114 if (replay_asked != RPY_RDB_REPLAY) {
115 fprintf(stderr, "This executable was only compiled for %s mode.\n",
116 RPY_RDB_REPLAY ? "replay" : "record");
117 exit(1);
118 }
119 #endif
120
121 if (RPY_RDB_REPLAY)
122 setup_replay_mode(argc_p, argv_p);
123 else
124 setup_record_mode(*argc_p, *argv_p);
125 }
126
127 static void reverse_db_lock_and_flush(void)
128 {
129 _RPY_REVDB_LOCK();
130 rpy_reverse_db_flush();
131 _RPY_REVDB_UNLOCK();
132 }
133
134 RPY_EXTERN
135 void rpy_reverse_db_teardown(void)
136 {
137 uint64_t stop_points;
138 if (!RPY_RDB_REPLAY) {
139 _RPY_REVDB_LOCK();
140 }
141 else {
142 /* hack: prevents RPY_REVDB_EMIT() from calling
143 rpy_reverse_db_fetch(), which has nothing more to fetch now */
144 rpy_revdb.buf_limit += 1;
145 }
146 _RPY_REVDB_EMIT_L(stop_points = rpy_revdb.stop_point_seen;,
147 uint64_t _e, stop_points);
148
149 if (!RPY_RDB_REPLAY) {
150 rpy_reverse_db_flush();
151 if (rpy_rev_fileno >= 0) {
152 close(rpy_rev_fileno);
153 rpy_rev_fileno = -1;
154 }
155 _RPY_REVDB_UNLOCK();
156 }
157 else
158 check_at_end(stop_points);
159 }
160
161 static void record_stop_point(void);
162 static void replay_stop_point(void);
163 static long current_place;
164
165 RPY_EXTERN
166 void rpy_reverse_db_stop_point(long place)
167 {
168 if (!RPY_RDB_REPLAY)
169 record_stop_point();
170 else {
171 current_place = place;
172 replay_stop_point();
173 }
174 }
175
176
177 /* ------------------------------------------------------------ */
178 /* Recording mode */
179 /* ------------------------------------------------------------ */
180
181
182 static void write_all(const void *buf, ssize_t count)
183 {
184 while (count > 0) {
185 ssize_t wsize = write(rpy_rev_fileno, buf, count);
186 if (wsize <= 0) {
187 if (wsize == 0)
188 fprintf(stderr, "writing to RevDB file: "
189 "unexpected non-blocking mode\n");
190 else
191 fprintf(stderr, "Fatal error: writing to RevDB file: %m\n");
192 abort();
193 }
194 buf += wsize;
195 count -= wsize;
196 }
197 }
198
199 static void close_revdb_fileno_in_fork_child(void)
200 {
201 if (rpy_rev_fileno >= 0) {
202 close(rpy_rev_fileno);
203 rpy_rev_fileno = -1;
204 }
205 }
206
207 static void setup_record_mode(int argc, char *argv[])
208 {
209 char *filename = getenv("REVDB");
210 rdb_header_t h;
211 int i;
212
213 assert(RPY_RDB_REPLAY == 0);
214
215 if (filename && *filename) {
216 ensure_fixed_address_space(argv);
217
218 putenv("REVDB=");
219 rpy_rev_fileno = open(filename, O_RDWR | O_CLOEXEC |
220 O_CREAT | O_NOCTTY | O_TRUNC, 0600);
221 if (rpy_rev_fileno < 0) {
222 fprintf(stderr, "Fatal error: can't create REVDB file '%s'\n",
223 filename);
224 abort();
225 }
226 atexit(reverse_db_lock_and_flush);
227
228 write_all(RDB_SIGNATURE, strlen(RDB_SIGNATURE));
229 for (i = 0; i < argc; i++) {
230 write_all("\t", 1);
231 write_all(argv[i], strlen(argv[i]));
232 }
233 write_all("\n\0", 2);
234
235 memset(&h, 0, sizeof(h));
236 h.version = RDB_VERSION;
237 h.ptr1 = &rpy_reverse_db_stop_point;
238 h.ptr2 = &rpy_revdb;
239 h.argc = argc;
240 h.argv = argv;
241 h.main_thread_id = (uint64_t)pthread_self();
242 write_all((const char *)&h, sizeof(h));
243
244 /* write the whole content of rpy_rdb_struct */
245 /*write_all((const char *)&rpy_rdb_struct, sizeof(rpy_rdb_struct));*/
246
247 fprintf(stderr, "PID %d: recording revdb log to '%s'\n",
248 (int)getpid(), filename);
249 }
250 else {
251 fprintf(stderr, "PID %d starting, log file disabled "
252 "(use REVDB=logfile)\n", (int)getpid());
253 }
254
255 if (rpy_rev_fileno >= 0)
256 rpy_revdb.buf_p = rpy_rev_buffer + sizeof(int16_t);
257 else
258 rpy_revdb.buf_p = NULL;
259 rpy_revdb.buf_limit = rpy_rev_buffer + sizeof(rpy_rev_buffer) - 32;
260 rpy_revdb.unique_id_seen = 1;
261
262 rpy_active_thread = 1;
263 rpy_active_thread_ptr = &rpy_active_thread;
264
265 pthread_atfork(NULL, NULL, close_revdb_fileno_in_fork_child);
266 }
267
268 static void flush_buffer(void)
269 {
270 /* must be called with the lock held */
271 ssize_t full_size;
272 assert(rpy_revdb.lock);
273
274 if (rpy_revdb.buf_p == NULL)
275 return;
276 assert(rpy_rev_fileno >= 0);
277
278 /* write the current buffer content to the OS */
279 full_size = rpy_revdb.buf_p - rpy_rev_buffer;
280 rpy_revdb.buf_p = rpy_rev_buffer + sizeof(int16_t);
281 write_all(rpy_rev_buffer, full_size);
282 }
283
284 static ssize_t current_packet_size(void)
285 {
286 /* must be called with the lock held */
287 if (rpy_revdb.buf_p != NULL)
288 return rpy_revdb.buf_p - (rpy_rev_buffer + sizeof(int16_t));
289 else
290 return 0;
291 }
292
293 RPY_EXTERN
294 void rpy_reverse_db_flush(void)
295 {
296 /* must be called with the lock held */
297 ssize_t content_size;
298 assert(rpy_revdb.lock);
299
300 content_size = current_packet_size();
301 if (content_size != 0) {
302 char *p = rpy_rev_buffer;
303 assert(0 < content_size && content_size <= 32767);
304 *(int16_t *)p = content_size;
305 flush_buffer();
306 }
307 }
308
309 void boehm_gc_finalizer_notifier(void)
310 {
311 /* This is called by Boehm when there are pending finalizers.
312 They are only invoked when we call GC_invoke_finalizers(),
313 which we only do at stop points in the case of revdb.
314 */
315 assert(!RPY_RDB_REPLAY);
316 assert(rpy_revdb.stop_point_break <= rpy_revdb.stop_point_seen + 1);
317 rpy_revdb.stop_point_break = rpy_revdb.stop_point_seen + 1;
318 }
319
320 static void fq_trigger(void)
321 {
322 int i = 0;
323 while (boehm_fq_trigger[i])
324 boehm_fq_trigger[i++]();
325 }
326
327 static long in_invoke_finalizers;
328
329 static void emit_async_block(int async_code, uint64_t content)
330 {
331 /* must be called with the lock held */
332 char *p = rpy_rev_buffer;
333 assert(rpy_revdb.lock);
334
335 rpy_reverse_db_flush();
336 assert(current_packet_size() == 0);
337
338 if (rpy_rev_fileno < 0)
339 return;
340 /* should not be here from the middle of a @c_only function */
341 assert(rpy_revdb.buf_p != NULL);
342
343 *(int16_t *)p = async_code;
344 memcpy(rpy_revdb.buf_p, &content, sizeof(uint64_t));
345 rpy_revdb.buf_p += sizeof(uint64_t);
346 flush_buffer();
347 }
348
349 RPY_EXTERN
350 void rpy_reverse_db_lock_acquire(bool_t lock_contention)
351 {
352 uint64_t pself;
353 assert(!RPY_RDB_REPLAY);
354 while (lock_contention) {
355 if (rpy_revdb.lock == 0) {
356 if (pypy_lock_test_and_set(&rpy_revdb.lock, 1) == 0)
357 break; /* done */
358 }
359 sched_yield();
360 }
361 /* we have acquired the lock here */
362 *rpy_active_thread_ptr = 0;
363 rpy_active_thread = 1;
364 rpy_active_thread_ptr = &rpy_active_thread;
365 pself = (uint64_t)pthread_self();
366 emit_async_block(ASYNC_THREAD_SWITCH, pself);
367 _RPY_REVDB_PRINT("[THRD]", pself);
368 }
369
370 static void record_stop_point(void)
371 {
372 /* ===== FINALIZERS =====
373
374 When the GC wants to invoke some finalizers, it causes this to
375 be called at the stop point. (This is not called at *every*
376 stop point.) The new-style finalizers are only enqueued at
377 this point. The old-style finalizers run immediately,
378 conceptually just *after* the stop point.
379 */
380 int i;
381 int64_t done;
382
383 /* Write an ASYNC_FINALIZER_TRIGGER packet */
384 _RPY_REVDB_LOCK();
385 emit_async_block(ASYNC_FINALIZER_TRIGGER, rpy_revdb.stop_point_seen);
386 _RPY_REVDB_UNLOCK();
387
388 /* Invoke all Boehm finalizers. For new-style finalizers, this
389 will only cause them to move to the queues, where
390 boehm_fq_next_dead() will be able to fetch them later. For
391 old-style finalizers, this will really call the finalizers,
392 which first emit to the rdb log the uid of the object. So
393 after we do that any number of times, we emit the uid -1 to
394 mean "now done, continue with the rest of the program".
395 */
396 in_invoke_finalizers++;
397 GC_invoke_finalizers();
398 in_invoke_finalizers--;
399 RPY_REVDB_EMIT(done = -1;, int64_t _e, done);
400
401 /* Now we're back in normal mode. We trigger the finalizer
402 queues here. */
403 fq_trigger();
404 }
405
406 RPY_EXTERN
407 void rpy_reverse_db_call_destructor(void *obj)
408 {
409 /* old-style finalizers. Should occur only from the
410 GC_invoke_finalizers() call above.
411 */
412 int64_t uid;
413
414 if (RPY_RDB_REPLAY)
415 return;
416 if (!in_invoke_finalizers) {
417 fprintf(stderr, "call_destructor: called at an unexpected time\n");
418 exit(1);
419 }
420 RPY_REVDB_EMIT(uid = ((struct pypy_header0 *)obj)->h_uid;, int64_t _e, uid);
421 }
422
423 RPY_EXTERN
424 Signed rpy_reverse_db_identityhash(struct pypy_header0 *obj)
425 {
426 /* Boehm only */
427 if (obj->h_hash == 0) {
428 /* We never need to record anything: if h_hash is zero (which
429 is the case for all newly allocated objects), then we just
430 copy h_uid. This gives a stable answer. This would give
431 0 for all prebuilt objects, but these should not have a
432 null h_hash anyway.
433 */
434 obj->h_hash = obj->h_uid;
435 }
436 return obj->h_hash;
437 }
438
439 RPY_EXTERN
440 Signed rpy_reverse_db_cast_ptr_to_int(struct pypy_header0 *obj)
441 {
442 /* Returns the "id" of the object. Should return a unique number
443 among all objects, including prebuilt ones.
444 */
445 if (obj->h_uid == 0) {
446 /* prebuilt object: the object address is good enough, because
447 such addresses should not change between recording and
448 replaying. The address is even and non-null, so the
449 following formula gives a unique negative result.
450 */
451 return (Signed)(-(((Unsigned)obj) >> 1));
452 }
453 else {
454 /* regular object: for now, may fail to work on 32-bit, where
455 h_uid is a 64-bit number that may grow bigger than 31 bits
456 if the program runs for long enough. Print a warning if it
457 is the case. */
458 if (((Signed)(obj->h_uid)) != obj->h_uid) {
459 static int warning_printed = 0;
460 if (!warning_printed) {
461 fprintf(stderr, "WARNING: the program executes for long enough "
462 "that it creates more than 2**31 objects. In "
463 "this situation, the id() function may return "
464 "non-unique results.\n");
465 warning_printed = 1;
466 }
467 }
468 /* on 64-bit, the range is large enough anyway, so shift 3 times
469 to get a result that is a multiple of 8. The Boehm translation
470 will additionally return the 'int_invert' of that. So
471 we add 7 to make the user-level id() be a multiple of 8. */
472 if (sizeof(obj->h_uid) == sizeof(Signed))
473 return (obj->h_uid << 3) + 7;
474 else
475 return (Signed)(obj->h_uid);
476 }
477 }
478
479 static uint64_t recording_offset(void)
480 {
481 /* must be called with the lock held */
482 off_t base_offset;
483 ssize_t extra_size = rpy_revdb.buf_p - rpy_rev_buffer;
484 assert(rpy_revdb.lock);
485
486 if (rpy_rev_fileno < 0)
487 return 1;
488 /* should not be here from the middle of a @c_only function */
489 assert(rpy_revdb.buf_p != NULL);
490
491 base_offset = lseek(rpy_rev_fileno, 0, SEEK_CUR);
492 if (base_offset < 0) {
493 perror("lseek");
494 exit(1);
495 }
496 return base_offset + extra_size;
497 }
498
499 static void patch_prev_offset(int64_t offset, char old, char new)
500 {
501 /* must be called with the lock held */
502 off_t base_offset;
503 assert(rpy_revdb.lock);
504
505 if (rpy_rev_fileno < 0)
506 return;
507 /* should not be here from the middle of a @c_only function */
508 assert(rpy_revdb.buf_p != NULL);
509
510 base_offset = lseek(rpy_rev_fileno, 0, SEEK_CUR);
511 if (base_offset < 0) {
512 perror("lseek");
513 exit(1);
514 }
515 if (offset < base_offset) {
516 char got;
517 if (pread(rpy_rev_fileno, &got, 1, offset) != 1) {
518 fprintf(stderr, "can't read log position %lld for checking: %m\n",
519 (long long)offset);
520 exit(1);
521 }
522 if (got != old) {
523 fprintf(stderr,
524 "bad byte at log position %lld (%d instead of %d)\n",
525 (long long)offset, got, old);
526 exit(1);
527 }
528 if (pwrite(rpy_rev_fileno, &new, 1, offset) != 1) {
529 fprintf(stderr, "can't patch log position %lld\n",
530 (long long)offset);
531 exit(1);
532 }
533 }
534 else {
535 ssize_t buffered_size = rpy_revdb.buf_p - rpy_rev_buffer;
536 int64_t buf_ofs = offset - base_offset;
537 if (buf_ofs >= buffered_size) {
538 fprintf(stderr, "invalid patch position %lld\n",
539 (long long)offset);
540 exit(1);
541 }
542 if (rpy_rev_buffer[buf_ofs] != old) {
543 fprintf(stderr,
544 "bad byte at log position %lld (%d instead of %d)\n",
545 (long long)offset, rpy_rev_buffer[buf_ofs], old);
546 exit(1);
547 }
548 rpy_rev_buffer[buf_ofs] = new;
549 }
550 }
551
552 /* keep in sync with 'REVDB_WEAKLINK' in rpython.memory.gctransform.boehm */
553 struct WEAKLINK {
554 void *re_addr;
555 long long re_off_prev;
556 };
557
558 RPY_EXTERN
559 void *rpy_reverse_db_weakref_create(void *target)
560 {
561 /* see comments in ../test/test_weak.py */
562 struct WEAKLINK *r;
563 if (!RPY_RDB_REPLAY)
564 r = GC_MALLOC_ATOMIC(sizeof(struct WEAKLINK));
565 else
566 r = GC_MALLOC(sizeof(struct WEAKLINK));
567
568 if (!r) {
569 fprintf(stderr, "out of memory for a weakref\n");
570 exit(1);
571 }
572 r->re_addr = target;
573 r->re_off_prev = 0;
574
575 if (flag_io_disabled == FID_REGULAR_MODE) {
576 char alive;
577 /* Emit WEAKREF_AFTERWARDS_DEAD, but remember where we emit it.
578 If we deref the weakref and it is still alive, we will patch
579 it with WEAKREF_AFTERWARDS_ALIVE. */
580 if (!RPY_RDB_REPLAY) {
581 _RPY_REVDB_LOCK();
582 r->re_off_prev = recording_offset();
583 }
584 else
585 r->re_off_prev = 1; /* any number > 0 */
586
587 _RPY_REVDB_EMIT_L(alive = WEAKREF_AFTERWARDS_DEAD;, char _e, alive);
588
589 if (!RPY_RDB_REPLAY) {
590 _RPY_REVDB_UNLOCK();
591 OP_BOEHM_DISAPPEARING_LINK(&r->re_addr, target, /*nothing*/);
592 }
593 else {
594 /* replaying: we don't make the weakref actually weak at all,
595 but instead we always know if we're going to need the
596 weakref value later or not */
597 switch (alive) {
598 case WEAKREF_AFTERWARDS_DEAD:
599 r->re_addr = NULL;
600 break;
601 case WEAKREF_AFTERWARDS_ALIVE:
602 break;
603 default:
604 fprintf(stderr, "bad weakref_create byte in log\n");
605 exit(1);
606 }
607 }
608 }
609 return r;
610 }
611
612 RPY_EXTERN
613 void *rpy_reverse_db_weakref_deref(void *weakref)
614 {
615 struct WEAKLINK *r = (struct WEAKLINK *)weakref;
616 void *result = r->re_addr;
617 if (result && flag_io_disabled == FID_REGULAR_MODE) {
618 if (r->re_off_prev < 0) {
619 fprintf(stderr, "bug in weakrefs: bad previous offset %lld\n",
620 (long long)r->re_off_prev);
621 exit(1);
622 }
623 if (r->re_off_prev == 0) {
624 /* A prebuilt weakref. Don't record anything */
625 }
626 else {
627 char alive;
628 if (!RPY_RDB_REPLAY) {
629 _RPY_REVDB_LOCK();
630 patch_prev_offset(r->re_off_prev, WEAKREF_AFTERWARDS_DEAD,
631 WEAKREF_AFTERWARDS_ALIVE);
632 r->re_off_prev = recording_offset();
633 }
634 _RPY_REVDB_EMIT_L(alive = WEAKREF_AFTERWARDS_DEAD;, char _e, alive);
635
636 if (!RPY_RDB_REPLAY) {
637 _RPY_REVDB_UNLOCK();
638 }
639 else {
640 switch (alive) {
641 case WEAKREF_AFTERWARDS_DEAD:
642 r->re_addr = NULL;
643 break;
644 case WEAKREF_AFTERWARDS_ALIVE:
645 break;
646 default:
647 fprintf(stderr, "bad weakref_deref byte in log\n");
648 exit(1);
649 }
650 }
651 }
652 }
653 return result;
654 }
655
656 RPY_EXTERN
657 void rpy_reverse_db_callback_loc(int locnum)
658 {
659 locnum += 300;
660 assert(locnum < 0xFC00);
661 if (!RPY_RDB_REPLAY) {
662 _RPY_REVDB_LOCK();
663 _RPY_REVDB_EMIT_RECORD_L(unsigned char _e, (locnum >> 8));
664 _RPY_REVDB_EMIT_RECORD_L(unsigned char _e, (locnum & 0xFF));
665 _RPY_REVDB_UNLOCK();
666 }
667 }
668
669
670 /* ------------------------------------------------------------ */
671 /* Replaying mode */
672 /* ------------------------------------------------------------ */
673
674
675 /* How it works: we run the same executable with different flags to
676 run it in "replay" mode. In this mode, it reads commands from
677 stdin (in binary format) and writes the results to stdout.
678 Notably, there is a command to ask it to fork, passing a new pair
679 of pipes to the forked copy as its new stdin/stdout. This is how
680 we implement the illusion of going backward: we throw away the
681 current fork, start from an earlier fork, make a new fork again,
682 and go forward by the correct number of steps. This is all
683 controlled by a pure Python wrapper that is roughly generic
684 (i.e. able to act as a debugger for any language).
685 */
686
687 #include "src-revdb/fd_recv.c"
688 #include "src/stacklet/stacklet.c" /* for replaying threads */
689
690 #define INIT_VERSION_NUMBER 0xd80100
691
692 #define CMD_FORK (-1)
693 #define CMD_QUIT (-2)
694 #define CMD_FORWARD (-3)
695 #define CMD_FUTUREIDS (-4)
696 #define CMD_PING (-5)
697
698 #define ANSWER_INIT (-20)
699 #define ANSWER_READY (-21)
700 #define ANSWER_FORKED (-22)
701 #define ANSWER_AT_END (-23)
702 #define ANSWER_BREAKPOINT (-24)
703 #define ANSWER_ATTEMPT_IO (-25)
704
705 #define RECORD_BKPT_NUM 50
706
707 typedef void (*rpy_revdb_command_fn)(rpy_revdb_command_t *, RPyString *);
708
709 static int rpy_rev_sockfd;
710 static const char *rpy_rev_filename;
711 static uint64_t interactive_break = 1, finalizer_break = -1, uid_break = -1;
712 static uint64_t total_stop_points;
713 static void (*pending_after_forward)(void);
714 static RPyString *empty_string;
715 static uint64_t last_recorded_breakpoint_loc;
716 static int n_last_recorded_breakpoints;
717 static int last_recorded_breakpoint_nums[RECORD_BKPT_NUM];
718 static char breakpoint_mode = 'i';
719 static uint64_t *future_ids, *future_next_id;
720 static void *finalizer_tree, *destructor_tree;
721
722 static stacklet_thread_handle st_thread;
723 static stacklet_handle st_outer_controller_h;
724 static uint64_t current_thread_id, target_thread_id;
725 static uint64_t current_thread_num, next_thread_num, break_thread_num;
726 static void *thread_tree_root;
727
728
729 struct replay_thread_main_s {
730 Signed (*entry_point)(Signed, char **);
731 int argc;
732 char **argv;
733 };
734 struct replay_thread_s {
735 uint64_t tid, tnum;
736 stacklet_handle h;
737 struct pypy_threadlocal_s tloc;
738 };
739
740 static stacklet_handle replay_thread_main(stacklet_handle h, void *arg)
741 {
742 /* main thread starts */
743 struct replay_thread_main_s *m = arg;
744 st_outer_controller_h = h;
745 m->entry_point(m->argc, m->argv);
746
747 /* main thread finished, program stops */
748 rpy_reverse_db_teardown();
749
750 /* unreachable */
751 abort();
752 }
753
754 static void replay_invoke_callback(unsigned char e);
755
756 static stacklet_handle replay_thread_sub(stacklet_handle h, void *ignored)
757 {
758 /* A non-main thread starts. What is does is invoke a "callback",
759 which is the argument passed to rthread.ll_start_new_thread().
760 We get it here because the first thing stored in the log about
761 this thread should be a callback identifier.
762 */
763 unsigned char e1;
764 st_outer_controller_h = h;
765
766 if (rpy_revdb.buf_limit >= rpy_revdb.buf_p)
767 rpy_reverse_db_fetch(__FILE__, __LINE__);
768
769 _RPY_REVDB_EMIT_REPLAY(unsigned char _e, e1)
770 replay_invoke_callback(e1);
771
772 /* the thread finishes here. Return to the outer controller. */
773 return st_outer_controller_h;
774 }
775
776 static int compare_replay_thread(const void *a, const void *b)
777 {
778 uint64_t ta = ((const struct replay_thread_s *)a)->tid;
779 uint64_t tb = ((const struct replay_thread_s *)b)->tid;
780 if (ta < tb)
781 return -1;
782 if (ta == tb)
783 return 0;
784 else
785 return 1;
786 }
787
788 static void set_current_thread_num(uint64_t tnum)
789 {
790 if (break_thread_num == current_thread_num || break_thread_num == tnum)
791 rpy_reverse_db_breakpoint(-4);
792 current_thread_num = tnum;
793 }
794
795 RPY_EXTERN
796 int rpy_reverse_db_main(Signed entry_point(Signed, char**),
797 int argc, char **argv)
798 {
799 if (!RPY_RDB_REPLAY) {
800 int exitcode = (int)entry_point(argc, argv);
801 rpy_reverse_db_teardown();
802 return exitcode;
803 }
804 else {
805 /* start the entry point inside a new stacklet, so that we
806 can switch it away at any point later */
807 struct replay_thread_main_s m;
808 stacklet_handle h;
809 struct pypy_threadlocal_s *real_tloc = NULL;
810 m.entry_point = entry_point;
811 m.argc = argc;
812 m.argv = argv;
813 h = stacklet_new(st_thread, replay_thread_main, &m);
814
815 /* We reach this point only if we start a second thread. This
816 is done by revdb_switch_thread(), which switches back to
817 'st_outer_controller_h'. This is the outer controller
818 loop.
819 */
820 while (1) {
821 struct replay_thread_s *node, **item, dummy;
822
823 if (real_tloc == NULL) {
824 char *p;
825 _OP_THREADLOCALREF_ADDR_SIGHANDLER(p);
826 real_tloc = (struct pypy_threadlocal_s *)p;
827 }
828
829 if (h == NULL)
830 goto out_of_memory;
831
832 if (h != EMPTY_STACKLET_HANDLE) {
833 /* save 'h' as the stacklet handle for the thread
834 'current_thread_id' */
835 node = malloc(sizeof(struct replay_thread_s));
836 if (!node)
837 goto out_of_memory;
838 node->tid = current_thread_id;
839 node->tnum = current_thread_num;
840 node->h = h;
841 /* save the thread-locals, if any */
842 if (real_tloc != NULL)
843 node->tloc = *real_tloc;
844 else
845 memset(&node->tloc, 0, sizeof(node->tloc));
846
847 item = tsearch(node, &thread_tree_root, compare_replay_thread);
848 if (item == NULL)
849 goto out_of_memory;
850
851 if (*item != node) {
852 fprintf(stderr, "thread switch: duplicate thread\n");
853 exit(1);
854 }
855 }
856 else {
857 /* current_thread_id terminated */
858 }
859
860 /* fetch out (and delete) the handle for the target thread */
861 current_thread_id = target_thread_id;
862 dummy.tid = target_thread_id;
863 item = tfind(&dummy, &thread_tree_root, compare_replay_thread);
864 if (item == NULL) {
865 /* it's a new thread, start it now */
866 set_current_thread_num(next_thread_num++);
867 if (real_tloc != NULL)
868 memset(((char *)real_tloc) + RPY_TLOFSFIRST, 0,
869 sizeof(struct pypy_threadlocal_s) - RPY_TLOFSFIRST);
870 h = stacklet_new(st_thread, replay_thread_sub, NULL);
871 }
872 else {
873 node = *item;
874 assert(node->tid == target_thread_id);
875 set_current_thread_num(node->tnum);
876 h = node->h;
877 tdelete(node, &thread_tree_root, compare_replay_thread);
878 if (real_tloc != NULL)
879 *real_tloc = node->tloc;
880 free(node);
881
882 h = stacklet_switch(h);
883 }
884 }
885 abort(); /* unreachable */
886
887 out_of_memory:
888 fprintf(stderr, "thread switch: out of memory\n");
889 exit(1);
890 }
891 }
892
893 RPY_EXTERN
894 void attach_gdb(void)
895 {
896 char cmdline[80];
897 sprintf(cmdline, "term -c \"gdb --pid=%d\"", getpid());
898 system(cmdline);
899 sleep(1);
900 }
901
902 static ssize_t read_at_least(void *buf, ssize_t count_min, ssize_t count_max)
903 {
904 ssize_t result = 0;
905 assert(count_min <= count_max);
906 while (result < count_min) {
907 ssize_t rsize = read(rpy_rev_fileno, buf + result, count_max - result);
908 if (rsize <= 0) {
909 if (rsize == 0)
910 fprintf(stderr, "RevDB file appears truncated (cannot read "
911 "more after offset %lld)\n",
912 (long long)lseek(rpy_rev_fileno, 0, SEEK_CUR));
913 else
914 fprintf(stderr, "RevDB file read error: %m\n");
915 exit(1);
916 }
917 result += rsize;
918 }
919 return result;
920 }
921
922 static void read_all(void *buf, ssize_t count)
923 {
924 (void)read_at_least(buf, count, count);
925 }
926
927 static void read_sock(void *buf, ssize_t count)
928 {
929 while (count > 0) {
930 ssize_t got = read(rpy_rev_sockfd, buf, count);
931 if (got <= 0) {
932 fprintf(stderr, "subprocess: cannot read from control socket\n");
933 exit(1);
934 }
935 count -= got;
936 buf += got;
937 }
938 }
939
940 static void write_sock(const void *buf, ssize_t count)
941 {
942 while (count > 0) {
943 ssize_t wrote = write(rpy_rev_sockfd, buf, count);
944 if (wrote <= 0) {
945 fprintf(stderr, "subprocess: cannot write to control socket\n");
946 exit(1);
947 }
948 count -= wrote;
949 buf += wrote;
950 }
951 }
952
953 static void write_answer(int cmd, int64_t arg1, int64_t arg2, int64_t arg3)
954 {
955 rpy_revdb_command_t c;
956 memset(&c, 0, sizeof(c));
957 c.cmd = cmd;
958 c.arg1 = arg1;
959 c.arg2 = arg2;
960 c.arg3 = arg3;
961 write_sock(&c, sizeof(c));
962 }
963
964 static RPyString *make_rpy_string(size_t length)
965 {
966 RPyString *s = malloc(sizeof(RPyString) + length);
967 if (s == NULL) {
968 fprintf(stderr, "out of memory for a string of %llu chars\n",
969 (unsigned long long)length);
970 exit(1);
971 }
972 /* xxx assumes Boehm here for now */
973 memset(s, 0, sizeof(RPyString));
974 RPyString_Size(s) = length;
975 return s;
976 }
977
978 static void reopen_revdb_file(const char *filename)
979 {
980 rpy_rev_fileno = open(filename, O_RDONLY | O_NOCTTY);
981 if (rpy_rev_fileno < 0) {
982 fprintf(stderr, "Can't open file '%s': %m\n", filename);
983 exit(1);
984 }
985 }
986
987 static void set_revdb_breakpoints(void)
988 {
989 /* note: these are uint64_t, so '-1' is bigger than positive values */
990 rpy_revdb.stop_point_break = (interactive_break < finalizer_break ?
991 interactive_break : finalizer_break);
992 rpy_revdb.unique_id_break = uid_break;
993 rpy_revdb.watch_enabled = (breakpoint_mode != 'i');
994 }
995
996 static void setup_replay_mode(int *argc_p, char **argv_p[])
997 {
998 int argc = *argc_p;
999 char **argv = *argv_p;
1000 rdb_header_t h;
1001 char input[16];
1002 ssize_t count;
1003
1004 if (argc != 4) {
1005 fprintf(stderr, "syntax: %s --revdb-replay <RevDB-file> <socket_fd>\n",
1006 argv[0]);
1007 exit(2);
1008 }
1009 ensure_fixed_address_space(*argv_p);
1010
1011 rpy_rev_filename = argv[2];
1012 reopen_revdb_file(rpy_rev_filename);
1013 rpy_rev_sockfd = atoi(argv[3]);
1014
1015 assert(RPY_RDB_REPLAY == 1);
1016
1017 read_all(input, strlen(RDB_SIGNATURE));
1018 if (strncmp(input, RDB_SIGNATURE, strlen(RDB_SIGNATURE)) != 0) {
1019 fprintf(stderr, "'%s' is not a RevDB file (or wrong platform)\n",
1020 rpy_rev_filename);
1021 exit(1);
1022 }
1023 fprintf(stderr, "%s", RDB_SIGNATURE);
1024 while ((read_all(input, 1), input[0] != 0))
1025 fputc(input[0] == '\t' ? ' ' : input[0], stderr);
1026
1027 read_all(&h, sizeof(h));
1028 if (h.version != RDB_VERSION) {
1029 fprintf(stderr, "RevDB file version mismatch (got %lx, expected %lx)\n",
1030 (long)h.version, (long)RDB_VERSION);
1031 exit(1);
1032 }
1033 current_thread_id = h.main_thread_id;
1034 current_thread_num = 0;
1035 next_thread_num = 1;
1036 break_thread_num = (uint64_t)-1;
1037 if (h.ptr1 != &rpy_reverse_db_stop_point ||
1038 h.ptr2 != &rpy_revdb) {
1039 fprintf(stderr,
1040 "\n"
1041 "In the replaying process, the addresses are different than\n"
1042 "in the recording process. Make sure that the executable\n"
1043 "\n"
1044 " %s\n"
1045 "\n"
1046 "is the same one as the one that was used during recording.\n"
1047 "If it is, then you may be hitting an issue with Address\n"
1048 "Space Layout Randomization. On Linux, ASLR should be\n"
1049 "automatically disabled, but just in case, the following\n"
1050 "command disables it manually:\n"
1051 "\n"
1052 " echo 0 | sudo tee /proc/sys/kernel/randomize_va_space\n"
1053 "\n"
1054 "It has been reported that on Linux kernel 4.12.4-1-ARCH,\n"
1055 "ASLR cannot be disabled at all for libpypy-c.so. It works\n"
1056 "again in kernel 4.19 (and maybe sooner). Either change\n"
1057 "kernels, or translate with --no-shared (but then you loose\n"
1058 "PyPy's cpyext ability).\n"
1059 "\n", argv[0]);
1060 exit(1);
1061 }
1062 *argc_p = h.argc;
1063 *argv_p = h.argv;
1064
1065 count = lseek(rpy_rev_fileno, 0, SEEK_CUR);
1066 if (count < 0 ||
1067 lseek(rpy_rev_fileno, -(off_t)sizeof(uint64_t), SEEK_END) < 0 ||
1068 (read_all(&total_stop_points, sizeof(uint64_t)),
1069 lseek(rpy_rev_fileno, count, SEEK_SET)) != count) {
1070 fprintf(stderr, "%s: invalid total_stop_points (%m)\n",
1071 rpy_rev_filename);
1072 exit(1);
1073 }
1074
1075 /* read the whole content of rpy_rdb_struct */
1076 /*read_all((char *)&rpy_rdb_struct, sizeof(rpy_rdb_struct));*/
1077
1078 rpy_revdb.buf_p = rpy_rev_buffer;
1079 rpy_revdb.buf_limit = rpy_rev_buffer;
1080 rpy_revdb.buf_readend = rpy_rev_buffer;
1081 rpy_revdb.stop_point_seen = 0;
1082 rpy_revdb.unique_id_seen = 1;
1083 set_revdb_breakpoints();
1084
1085 empty_string = make_rpy_string(0);
1086 st_thread = stacklet_newthread(); /* replaying doesn't use real threads */
1087
1088 write_answer(ANSWER_INIT, INIT_VERSION_NUMBER, total_stop_points, 0);
1089
1090 /* ignore the SIGCHLD signals so that child processes don't become
1091 zombies */
1092 signal(SIGCHLD, SIG_IGN);
1093
1094 /* initiate the read, which is always at least one byte ahead of
1095 RPY_REVDB_EMIT() in order to detect the ASYNC_* operations
1096 early enough. */
1097 rpy_reverse_db_fetch(__FILE__, __LINE__);
1098 }
1099
1100 static void fetch_more(ssize_t keep, ssize_t expected_size)
1101 {
1102 ssize_t rsize;
1103 if (rpy_revdb.buf_p != rpy_rev_buffer)
1104 memmove(rpy_rev_buffer, rpy_revdb.buf_p, keep);
1105 rsize = read_at_least(rpy_rev_buffer + keep,
1106 expected_size - keep,
1107 sizeof(rpy_rev_buffer) - keep);
1108 rpy_revdb.buf_p = rpy_rev_buffer;
1109 rpy_revdb.buf_readend = rpy_rev_buffer + keep + rsize;
1110 /* rpy_revdb.buf_limit is not set */
1111 }
1112
1113 static uint64_t fetch_async_block(void)
1114 {
1115 ssize_t full_packet_size = sizeof(int16_t) + sizeof(int64_t);
1116 ssize_t keep = rpy_revdb.buf_readend - rpy_revdb.buf_p;
1117 uint64_t result;
1118 if (keep < full_packet_size)
1119 fetch_more(keep, full_packet_size);
1120 memcpy(&result, rpy_revdb.buf_p + sizeof(int16_t), sizeof(int64_t));
1121 rpy_revdb.buf_p += full_packet_size;
1122 return result;
1123 }
1124
1125 RPY_EXTERN
1126 void rpy_reverse_db_fetch(const char *file, int line)
1127 {
1128 if (flag_io_disabled == FID_REGULAR_MODE) {
1129 ssize_t keep;
1130 ssize_t full_packet_size;
1131 int16_t header;
1132
1133 if (finalizer_break != (uint64_t)-1) {
1134 fprintf(stderr, "reverse_db_fetch: finalizer_break != -1\n");
1135 exit(1);
1136 }
1137 if (rpy_revdb.buf_limit != rpy_revdb.buf_p) {
1138 fprintf(stderr, "bad log format: incomplete packet\n");
1139 exit(1);
1140 }
1141 keep = rpy_revdb.buf_readend - rpy_revdb.buf_p;
1142 assert(keep >= 0);
1143
1144 if (keep < sizeof(int16_t)) {
1145 /* 'keep' does not even contain the next packet header */
1146 fetch_more(keep, sizeof(int16_t));
1147 keep = rpy_revdb.buf_readend - rpy_rev_buffer;
1148 }
1149 header = *(int16_t *)rpy_revdb.buf_p;
1150 if (header < 0) {
1151 int64_t bp;
1152
1153 switch (header) {
1154
1155 case ASYNC_FINALIZER_TRIGGER:
1156 //fprintf(stderr, "ASYNC_FINALIZER_TRIGGER\n");
1157 if (finalizer_break != (uint64_t)-1) {
1158 fprintf(stderr, "unexpected multiple "
1159 "ASYNC_FINALIZER_TRIGGER\n");
1160 exit(1);
1161 }
1162 bp = fetch_async_block();
1163 if (bp <= rpy_revdb.stop_point_seen) {
1164 fprintf(stderr, "invalid finalizer break point\n");
1165 exit(1);
1166 }
1167 finalizer_break = bp;
1168 set_revdb_breakpoints();
1169 /* Now we should not fetch anything more until we reach
1170 that finalizer_break point. */
1171 rpy_revdb.buf_limit = rpy_revdb.buf_p;
1172 return;
1173
1174 case ASYNC_THREAD_SWITCH:
1175 target_thread_id = fetch_async_block();
1176 _RPY_REVDB_PRINT("[THRD]", target_thread_id);
1177 rpy_revdb.buf_limit = rpy_revdb.buf_p;
1178 if (target_thread_id != current_thread_id) {
1179 st_outer_controller_h = stacklet_switch(
1180 st_outer_controller_h);
1181 }
1182 if (rpy_revdb.buf_limit == rpy_revdb.buf_p)
1183 rpy_reverse_db_fetch(__FILE__, __LINE__);
1184 return;
1185
1186 default:
1187 fprintf(stderr, "bad packet header %d\n", (int)header);
1188 exit(1);
1189 }
1190 }
1191 full_packet_size = sizeof(int16_t) + header;
1192 if (keep < full_packet_size)
1193 fetch_more(keep, full_packet_size);
1194 rpy_revdb.buf_limit = rpy_revdb.buf_p + full_packet_size;
1195 rpy_revdb.buf_p += sizeof(int16_t);
1196 }
1197 else {
1198 /* this is called when we are in execute_rpy_command(): we are
1199 running some custom code now, and we can't just perform I/O
1200 or access raw memory---because there is no raw memory!
1201 */
1202 fprintf(stderr, "%s:%d: Attempted to do I/O or access raw memory\n",
1203 file, line);
1204 if (flag_io_disabled != FID_POTENTIAL_IO) {
1205 fprintf(stderr, "but we are not in a protected section\n");
1206 exit(1);
1207 }
1208 write_answer(ANSWER_ATTEMPT_IO, 0, 0, 0);
1209 exit(0);
1210 }
1211 }
1212
1213 static rpy_revdb_t saved_state;
1214 static void *saved_exc[2];
1215
1216 static void change_flag_io_disabled(char oldval, char newval)
1217 {
1218 if (flag_io_disabled != oldval) {
1219 fprintf(stderr, "change_flag_io_disabled(%c, %c) but got %c\n",
1220 oldval, newval, flag_io_disabled);
1221 exit(1);
1222 }
1223 flag_io_disabled = newval;
1224 }
1225
1226 static void save_state(void)
1227 {
1228 /* The program is switching from replaying execution to
1229 time-paused mode. In time-paused mode, we can run more
1230 app-level code like watch points or interactive prints,
1231 but they must not be matched against the log, and they must
1232 not involve generic I/O.
1233 */
1234 change_flag_io_disabled(FID_REGULAR_MODE, FID_SAVED_STATE);
1235
1236 saved_state = rpy_revdb; /* save the complete struct */
1237
1238 rpy_revdb.unique_id_seen = (-1ULL) << 63;
1239 rpy_revdb.watch_enabled = 0;
1240 rpy_revdb.stop_point_break = -1;
1241 rpy_revdb.unique_id_break = -1;
1242 rpy_revdb.buf_p = rpy_rev_buffer; /* anything readable */
1243 rpy_revdb.buf_limit = rpy_rev_buffer; /* same as buf_p */
1244 }
1245
1246 static void restore_state(void)
1247 {
1248 /* The program is switching from time-paused mode to replaying
1249 execution. */
1250 change_flag_io_disabled(FID_SAVED_STATE, FID_REGULAR_MODE);
1251
1252 /* restore the complete struct */
1253 rpy_revdb = saved_state;
1254
1255 /* set the breakpoint fields to the current value of the *_break
1256 global variables, which may be different from what is in
1257 'save_state' */
1258 set_revdb_breakpoints();
1259 }
1260
1261 static void protect_potential_io(void)
1262 {
1263 change_flag_io_disabled(FID_SAVED_STATE, FID_POTENTIAL_IO);
1264 saved_exc[0] = pypy_g_ExcData.ed_exc_type;
1265 saved_exc[1] = pypy_g_ExcData.ed_exc_value;
1266 pypy_g_ExcData.ed_exc_type = NULL;
1267 pypy_g_ExcData.ed_exc_value = NULL;
1268 }
1269
1270 static void unprotect_potential_io(void)
1271 {
1272 change_flag_io_disabled(FID_POTENTIAL_IO, FID_SAVED_STATE);
1273 if (pypy_g_ExcData.ed_exc_type != NULL) {
1274 fprintf(stderr, "Command crashed with %.*s\n",
1275 (int)(pypy_g_ExcData.ed_exc_type->ov_name->rs_chars.length),
1276 pypy_g_ExcData.ed_exc_type->ov_name->rs_chars.items);
1277 write_answer(ANSWER_ATTEMPT_IO, 1, 0, 0);
1278 exit(0);
1279 }
1280 pypy_g_ExcData.ed_exc_type = saved_exc[0];
1281 pypy_g_ExcData.ed_exc_value = saved_exc[1];
1282 }
1283
1284 static void execute_rpy_function(rpy_revdb_command_fn func,
1285 rpy_revdb_command_t *cmd,
1286 RPyString *extra)
1287 {
1288 protect_potential_io();
1289 func(cmd, extra);
1290 unprotect_potential_io();
1291 }
1292
1293 static void check_at_end(uint64_t stop_points)
1294 {
1295 char dummy[1];
1296 if (rpy_revdb.buf_p != rpy_revdb.buf_limit - 1 ||
1297 read(rpy_rev_fileno, dummy, 1) > 0) {
1298 fprintf(stderr, "RevDB file error: too much data: corrupted file, "
1299 "revdb bug, or non-deterministic run, e.g. a "
1300 "watchpoint with side effects)\n");
1301 exit(1);
1302 }
1303 if (stop_points != rpy_revdb.stop_point_seen) {
1304 fprintf(stderr, "Bad number of stop points "
1305 "(seen %lld, recorded %lld)\n",
1306 (long long)rpy_revdb.stop_point_seen,
1307 (long long)stop_points);
1308 exit(1);
1309 }
1310 if (stop_points != total_stop_points) {
1311 fprintf(stderr, "RevDB file modified while reading?\n");
1312 exit(1);
1313 }
1314
1315 write_answer(ANSWER_AT_END, 0, 0, 0);
1316 exit(0);
1317 }
1318
1319 static void command_fork(int activate)
1320 {
1321 int child_sockfd;
1322 int child_pid;
1323 off_t rev_offset = lseek(rpy_rev_fileno, 0, SEEK_CUR);
1324
1325 if (ancil_recv_fd(rpy_rev_sockfd, &child_sockfd) < 0) {
1326 fprintf(stderr, "cannot fetch child control socket: %m\n");
1327 exit(1);
1328 }
1329 child_pid = fork();
1330 if (child_pid == -1) {
1331 perror("fork");
1332 exit(1);
1333 }
1334 if (child_pid == 0) {
1335 /* in the child */
1336 if (close(rpy_rev_sockfd) < 0) {
1337 perror("close");
1338 exit(1);
1339 }
1340 rpy_rev_sockfd = child_sockfd;
1341
1342 /* The 'activate' flag of CMD_FORK tells if the child process
1343 must die or not when receiving SIGINT. Active children
1344 die; inactive children (stored in 'pgroup.paused') don't. */
1345 signal(SIGINT, activate ? SIG_DFL : SIG_IGN);
1346
1347 /* Close and re-open the revdb log file in the child process.
1348 This is the simplest way I found to give 'rpy_rev_fileno'
1349 its own offset, independent from the parent. It assumes
1350 that the revdb log file is still the same. So for Linux,
1351 we try to open "/proc/self/fd/%d" instead. */
1352 char fd_filename[48];
1353 struct stat st;
1354 const char *filename;
1355 int old_fd = rpy_rev_fileno;
1356
1357 sprintf(fd_filename, "/proc/self/fd/%d", old_fd);
1358 if (lstat(fd_filename, &st) == 0)
1359 filename = fd_filename;
1360 else
1361 filename = rpy_rev_filename;
1362 reopen_revdb_file(filename);
1363
1364 if (close(old_fd) < 0) {
1365 perror("close");
1366 exit(1);
1367 }
1368 if (lseek(rpy_rev_fileno, rev_offset, SEEK_SET) < 0) {
1369 perror("lseek");
1370 exit(1);
1371 }
1372 }
1373 else {
1374 /* in the parent */
1375 write_answer(ANSWER_FORKED, child_pid, 0, 0);
1376 close(child_sockfd);
1377 }
1378 }
1379
1380 static void answer_recorded_breakpoint(void)
1381 {
1382 int i;
1383 for (i = 0; i < n_last_recorded_breakpoints; i++)
1384 write_answer(ANSWER_BREAKPOINT, last_recorded_breakpoint_loc,
1385 0, last_recorded_breakpoint_nums[i]);
1386 n_last_recorded_breakpoints = 0;
1387 }
1388
1389 static void command_forward(rpy_revdb_command_t *cmd)
1390 {
1391 if (cmd->arg1 < 0) {
1392 fprintf(stderr, "CMD_FORWARD: negative step\n");
1393 exit(1);
1394 }
1395 assert(flag_io_disabled == FID_SAVED_STATE);
1396 interactive_break = saved_state.stop_point_seen + cmd->arg1;
1397 breakpoint_mode = (char)cmd->arg2;
1398 if (breakpoint_mode == 'r') {
1399 n_last_recorded_breakpoints = 0;
1400 pending_after_forward = &answer_recorded_breakpoint;
1401 }
1402 }
1403
1404 static void command_future_ids(rpy_revdb_command_t *cmd, char *extra)
1405 {
1406 free(future_ids);
1407 if (cmd->extra_size == 0) {
1408 future_ids = NULL;
1409 uid_break = 0;
1410 }
1411 else {
1412 assert(cmd->extra_size % sizeof(uint64_t) == 0);
1413 future_ids = malloc(cmd->extra_size + sizeof(uint64_t));
1414 if (future_ids == NULL) {
1415 fprintf(stderr, "out of memory for a buffer of %llu chars\n",
1416 (unsigned long long)cmd->extra_size);
1417 exit(1);
1418 }
1419 memcpy(future_ids, extra, cmd->extra_size);
1420 future_ids[cmd->extra_size / sizeof(uint64_t)] = 0;
1421 uid_break = *future_ids;
1422 }
1423 future_next_id = future_ids;
1424 }
1425
1426 static void command_default(rpy_revdb_command_t *cmd, char *extra)
1427 {
1428 RPyString *s;
1429 int i;
1430 for (i = 0; rpy_revdb_commands.rp_names[i] != cmd->cmd; i++) {
1431 if (rpy_revdb_commands.rp_names[i] == 0) {
1432 fprintf(stderr, "unknown command %d\n", cmd->cmd);
1433 exit(1);
1434 }
1435 }
1436
1437 if (cmd->extra_size == 0) {
1438 s = empty_string;
1439 }
1440 else {
1441 s = make_rpy_string(cmd->extra_size);
1442 memcpy(_RPyString_AsString(s), extra, cmd->extra_size);
1443 }
1444 execute_rpy_function(rpy_revdb_commands.rp_funcs[i], cmd, s);
1445 }
1446
1447 RPY_EXTERN
1448 void rpy_reverse_db_watch_save_state(void)
1449 {
1450 save_state();
1451 }
1452
1453 RPY_EXTERN
1454 void rpy_reverse_db_watch_restore_state(bool_t any_watch_point)
1455 {
1456 restore_state();
1457 rpy_revdb.watch_enabled = any_watch_point;
1458 }
1459
1460 static void replay_call_destructors(void);
1461
1462 static void replay_stop_point(void)
1463 {
1464 if (finalizer_break != (uint64_t)-1)
1465 replay_call_destructors();
1466
1467 if (rpy_revdb.stop_point_break != interactive_break) {
1468 fprintf(stderr, "mismatch between interactive_break and "
1469 "stop_point_break\n");
1470 exit(1);
1471 }
1472
1473 while (rpy_revdb.stop_point_break == rpy_revdb.stop_point_seen) {
1474 save_state();
1475
1476 if (pending_after_forward) {
1477 void (*fn)(void) = pending_after_forward;
1478 pending_after_forward = NULL;
1479 fn();
1480 }
1481 else {
1482 rpy_revdb_command_t cmd;
1483 write_answer(ANSWER_READY,
1484 saved_state.stop_point_seen,
1485 saved_state.unique_id_seen,
1486 current_thread_num);
1487 read_sock(&cmd, sizeof(cmd));
1488
1489 char extra[cmd.extra_size + 1];
1490 extra[cmd.extra_size] = 0;
1491 if (cmd.extra_size > 0)
1492 read_sock(extra, cmd.extra_size);
1493
1494 switch (cmd.cmd) {
1495
1496 case CMD_FORK:
1497 command_fork(cmd.arg1);
1498 break;
1499
1500 case CMD_QUIT:
1501 exit(0);
1502 break;
1503
1504 case CMD_FORWARD:
1505 command_forward(&cmd);
1506 break;
1507
1508 case CMD_FUTUREIDS:
1509 command_future_ids(&cmd, extra);
1510 break;
1511
1512 case CMD_PING: /* to get only the ANSWER_READY */
1513 break;
1514
1515 default:
1516 command_default(&cmd, extra);
1517 break;
1518 }
1519 }
1520 restore_state();
1521 }
1522 }
1523
1524 RPY_EXTERN
1525 void rpy_reverse_db_send_answer(int cmd, int64_t arg1, int64_t arg2,
1526 int64_t arg3, RPyString *extra)
1527 {
1528 rpy_revdb_command_t c;
1529 size_t extra_size = RPyString_Size(extra);
1530 c.cmd = cmd;
1531 c.extra_size = extra_size;
1532 if (c.extra_size != extra_size) {
1533 fprintf(stderr, "string too large (more than 4GB)\n");
1534 exit(1);
1535 }
1536 c.arg1 = arg1;
1537 c.arg2 = arg2;
1538 c.arg3 = arg3;
1539 write_sock(&c, sizeof(c));
1540 if (extra_size > 0)
1541 write_sock(_RPyString_AsString(extra), extra_size);
1542 }
1543
1544 RPY_EXTERN
1545 void rpy_reverse_db_breakpoint(int64_t num)
1546 {
1547 if (flag_io_disabled != FID_REGULAR_MODE) {
1548 /* called from a debug command, ignore */
1549 return;
1550 }
1551
1552 switch (breakpoint_mode) {
1553 case 'i':
1554 return; /* ignored breakpoints */
1555
1556 case 'r': /* record the breakpoint but continue */
1557 if (last_recorded_breakpoint_loc != rpy_revdb.stop_point_seen) {
1558 last_recorded_breakpoint_loc = rpy_revdb.stop_point_seen;
1559 n_last_recorded_breakpoints = 0;
1560 }
1561 if (n_last_recorded_breakpoints < RECORD_BKPT_NUM) {
1562 last_recorded_breakpoint_nums[n_last_recorded_breakpoints] = num;
1563 n_last_recorded_breakpoints++;
1564 }
1565 return;
1566
1567 case 'b': /* default handling of breakpoints */
1568 interactive_break = rpy_revdb.stop_point_seen + 1;
1569 set_revdb_breakpoints();
1570 write_answer(ANSWER_BREAKPOINT, rpy_revdb.stop_point_break, 0, num);
1571 return;
1572
1573 default:
1574 fprintf(stderr, "bad value %d of breakpoint_mode\n",
1575 (int)breakpoint_mode);
1576 exit(1);
1577 }
1578 }
1579
1580 RPY_EXTERN
1581 long long rpy_reverse_db_get_value(char value_id)
1582 {
1583 switch (value_id) {
1584 case 'c': /* current_time() */
1585 return (flag_io_disabled == FID_REGULAR_MODE ?
1586 rpy_revdb.stop_point_seen :
1587 saved_state.stop_point_seen);
1588 case 't': /* total_time() */
1589 return total_stop_points;
1590 case 'b': /* current_break_time() */
1591 return interactive_break;
1592 case 'u': /* currently_created_objects() */
1593 return (flag_io_disabled == FID_REGULAR_MODE ?
1594 rpy_revdb.unique_id_seen :
1595 saved_state.unique_id_seen);
1596 case 'p': /* current_place() */
1597 return current_place;
1598 case 'i': /* flag_io_disabled() */
1599 return flag_io_disabled;
1600 default:
1601 return -1;
1602 }
1603 }
1604
1605 RPY_EXTERN
1606 uint64_t rpy_reverse_db_unique_id_break(void *new_object)
1607 {
1608 uint64_t uid = rpy_revdb.unique_id_seen;
1609 bool_t watch_enabled = rpy_revdb.watch_enabled;
1610
1611 if (!new_object) {
1612 fprintf(stderr, "out of memory: allocation failed, cannot continue\n");
1613 exit(1);
1614 }
1615
1616 save_state();
1617 if (rpy_revdb_commands.rp_alloc) {
1618 protect_potential_io();
1619 /* invoke the "ALLOCATING" callback from RPython */
1620 rpy_revdb_commands.rp_alloc(uid, new_object);
1621 unprotect_potential_io();
1622 }
1623 uid_break = *++future_next_id;
1624 restore_state();
1625 rpy_revdb.watch_enabled = watch_enabled;
1626 return uid;
1627 }
1628
1629 struct destructor_s {
1630 void *d_obj;
1631 void (*d_callback)(void *);
1632 };
1633
1634 static int _ftree_compare(const void *obj1, const void *obj2)
1635 {
1636 const struct destructor_s *d1 = obj1;
1637 const struct destructor_s *d2 = obj2;
1638 struct pypy_header0 *h1 = d1->d_obj;
1639 struct pypy_header0 *h2 = d2->d_obj;
1640 if (h1->h_uid < h2->h_uid)
1641 return -1;
1642 if (h1->h_uid == h2->h_uid)
1643 return 0;
1644 else
1645 return 1;
1646 }
1647
1648 static void _ftree_add(void **tree, void *obj, void (*callback)(void *))
1649 {
1650 /* Note: we always allocate an indirection through a
1651 struct destructor_s, so that Boehm knows that 'obj' must be
1652 kept alive. */
1653 struct destructor_s *node, **item;
1654 node = GC_MALLOC_UNCOLLECTABLE(sizeof(struct destructor_s));
1655 node->d_obj = obj;
1656 node->d_callback = callback;
1657 item = tsearch(node, tree, _ftree_compare);
1658 if (item == NULL) {
1659 fprintf(stderr, "_ftree_add: out of memory\n");
1660 exit(1);
1661 }
1662 if (*item != node) {
1663 fprintf(stderr, "_ftree_add: duplicate object\n");
1664 exit(1);
1665 }
1666 }
1667
1668 static struct pypy_header0 *_ftree_pop(void **tree, uint64_t uid,
1669 void (**callback_out)(void *))
1670 {
1671 struct destructor_s d_dummy, *entry, **item;
1672 struct pypy_header0 o_dummy, *result;
1673
1674 d_dummy.d_obj = &o_dummy;
1675 o_dummy.h_uid = uid;
1676 item = tfind(&d_dummy, tree, _ftree_compare);
1677 if (item == NULL) {
1678 fprintf(stderr, "_ftree_pop: object not found\n");
1679 exit(1);
1680 }
1681 entry = *item;
1682 result = entry->d_obj;
1683 if (callback_out)
1684 *callback_out = entry->d_callback;
1685 assert(result->h_uid == uid);
1686 tdelete(entry, tree, _ftree_compare);
1687 GC_FREE(entry);
1688 return result;
1689 }
1690
1691 RPY_EXTERN
1692 int rpy_reverse_db_fq_register(void *obj)
1693 {
1694 /*fprintf(stderr, "FINALIZER_TREE: %lld -> %p\n",
1695 ((struct pypy_header0 *)obj)->h_uid, obj);*/
1696 if (!RPY_RDB_REPLAY) {
1697 return 0; /* recording */
1698 }
1699 else {
1700 /* add the object into the finalizer_tree, keyed by the h_uid. */
1701 _ftree_add(&finalizer_tree, obj, NULL);
1702 return 1; /* replaying */
1703 }
1704 }
1705
1706 RPY_EXTERN
1707 void *rpy_reverse_db_next_dead(void *result)
1708 {
1709 int64_t uid;
1710 RPY_REVDB_EMIT(uid = result ? ((struct pypy_header0 *)result)->h_uid : -1;,
1711 int64_t _e, uid);
1712 /*fprintf(stderr, "next_dead: object %lld\n", uid);*/
1713 if (RPY_RDB_REPLAY) {
1714 if (uid == -1) {
1715 result = NULL;
1716 }
1717 else {
1718 /* fetch and remove the object from the finalizer_tree */
1719 result = _ftree_pop(&finalizer_tree, uid, NULL);
1720 }
1721 }
1722 return result;
1723 }
1724
1725 RPY_EXTERN
1726 void rpy_reverse_db_register_destructor(void *obj, void (*callback)(void *))
1727 {
1728 if (!RPY_RDB_REPLAY) {
1729 GC_REGISTER_FINALIZER(obj, (GC_finalization_proc)callback,
1730 NULL, NULL, NULL);
1731 }
1732 else {
1733 _ftree_add(&destructor_tree, obj, callback);
1734 }
1735 }
1736
1737 static void replay_call_destructors(void)
1738 {
1739 /* Re-enable fetching (disabled when we saw ASYNC_FINALIZER_TRIGGER),
1740 and fetch the uid's of dying objects with old-style destructors.
1741 */
1742 finalizer_break = -1;
1743 set_revdb_breakpoints();
1744 rpy_reverse_db_fetch(__FILE__, __LINE__);
1745
1746 while (1) {
1747 int64_t uid;
1748 struct pypy_header0 *obj;
1749 void (*callback)(void *);
1750
1751 RPY_REVDB_EMIT(abort();, int64_t _e, uid);
1752 if (uid == -1)
1753 break;
1754
1755 obj = _ftree_pop(&destructor_tree, uid, &callback);
1756 callback(obj);
1757 }
1758
1759 /* Now we're back in normal mode. We trigger the finalizer
1760 queues here. */
1761 fq_trigger();
1762 }
1763
1764 static void *callbacklocs[] = {
1765 RPY_CALLBACKLOCS /* macro from revdb_def.h */
1766 };
1767
1768 static void replay_invoke_callback(unsigned char e)
1769 {
1770 unsigned long index;
1771 unsigned char e2;
1772 void (*pfn)(void);
1773 _RPY_REVDB_EMIT_REPLAY(unsigned char _e, e2)
1774 index = (e << 8) | e2;
1775 index -= 300;
1776 if (index >= (sizeof(callbacklocs) / sizeof(callbacklocs[0]))) {
1777 fprintf(stderr, "bad callback index %lx\n", index);
1778 exit(1);
1779 }
1780 pfn = callbacklocs[index];
1781 pfn();
1782 }
1783
1784 RPY_EXTERN
1785 void rpy_reverse_db_invoke_callback(unsigned char e)
1786 {
1787 /* Replaying: we have read the byte which follows calls, expecting
1788 to see 0xFC, but we saw something else. It's part of a two-bytes
1789 callback identifier. */
1790
1791 do {
1792 replay_invoke_callback(e);
1793 _RPY_REVDB_EMIT_REPLAY(unsigned char _e, e)
1794 } while (e != 0xFC);
1795 }
1796
1797 RPY_EXTERN
1798 void rpy_reverse_db_bad_acquire_gil(const char *name)
1799 {
1800 fprintf(stderr, "out of sync: unexpected byte in log "
1801 " (at %s_gil)\n", name);
1802 exit(1);
1803 }
1804
1805 RPY_EXTERN
1806 void rpy_reverse_db_set_thread_breakpoint(int64_t tnum)
1807 {
1808 break_thread_num = (uint64_t)tnum;
1809 }
1810
1811 #define INVALID_STRTOD (-3.46739514239368e+113)
1812
1813 RPY_EXTERN
1814 double rpy_reverse_db_strtod(RPyString *s)
1815 {
1816 /* approximate hacks only */
1817 double result;
1818 char *endptr = NULL;
1819 char buffer[8192];
1820 size_t size = RPyString_Size(s);
1821
1822 if (size >= sizeof(buffer))
1823 return INVALID_STRTOD;
1824 memcpy(buffer, _RPyString_AsString(s), size);
1825 buffer[size] = '\0';
1826 result = strtod(buffer, &endptr);
1827 if (endptr == NULL || *endptr != '\0')
1828 return INVALID_STRTOD;
1829 return result;
1830 }
1831
1832 RPY_EXTERN
1833 RPyString *rpy_reverse_db_dtoa(double d)
1834 {
1835 char buffer[128], *p;
1836 RPyString *result;
1837 int size;
1838 size = snprintf(buffer, sizeof(buffer) - 3, "%.17g", d);
1839 if (size < 0)
1840 size = 0;
1841 for (p = buffer; '0' <= *p && *p <= '9'; p++) {
1842 }
1843 if (*p == 0) { /* a pure integer */
1844 buffer[size++] = '.';
1845 buffer[size++] = '0';
1846 }
1847 result = make_rpy_string(size);
1848 memcpy(_RPyString_AsString(result), buffer, size);
1849 return result;
1850 }
1851
1852
1853 #ifdef RPY_USES_RAWREFCOUNT
1854
1855 static void *rawrefcount_tree; /* {pyobj: gcobj} */
1856
1857 struct rawrefcount_link2_s {
1858 void *pyobj;
1859 void *gcobj;
1860 };
1861
1862 static int _rrtree_compare(const void *obj1, const void *obj2)
1863 {
1864 const struct rawrefcount_link2_s *r1 = obj1;
1865 const struct rawrefcount_link2_s *r2 = obj2;
1866 void *p1 = r1->pyobj;
1867 void *p2 = r2->pyobj;
1868 if (p1 < p2)
1869 return -1;
1870 if (p1 == p2)
1871 return 0;
1872 else
1873 return 1;
1874 }
1875
1876 static void _rrtree_add(void *pyobj, void *gcobj)
1877 {
1878 /* Note: we always allocate an indirection through a
1879 struct rawrefcount_link2_s, so that Boehm knows that
1880 'gcobj' must be kept alive. */
1881 struct rawrefcount_link2_s *node, **item;
1882 node = GC_MALLOC_UNCOLLECTABLE(sizeof(struct rawrefcount_link2_s));
1883 node->pyobj = pyobj;
1884 node->gcobj = gcobj;
1885 item = tsearch(node, &rawrefcount_tree, _rrtree_compare);
1886 if (item == NULL) {
1887 fprintf(stderr, "_rrtree_add: out of memory\n");
1888 exit(1);
1889 }
1890 if (*item != node) {
1891 fprintf(stderr, "_rrtree_add: duplicate object\n");
1892 exit(1);
1893 }
1894 }
1895
1896 RPY_EXTERN
1897 void rpy_reverse_db_rawrefcount_create_link_pypy(void *gcobj, void *pyobj)
1898 {
1899 if (!RPY_RDB_REPLAY) {
1900 gc_rawrefcount_create_link_pypy(gcobj, pyobj);
1901 }
1902 else {
1903 _rrtree_add(pyobj, gcobj);
1904 }
1905 }
1906
1907 RPY_EXTERN
1908 void *rpy_reverse_db_rawrefcount_from_obj(void *gcobj)
1909 {
1910 void *r;
1911 RPY_REVDB_EMIT(r = gc_rawrefcount_from_obj(gcobj);, void *_e, r);
1912 return r;
1913 }
1914
1915 RPY_EXTERN
1916 void *rpy_reverse_db_rawrefcount_to_obj(void *pyobj)
1917 {
1918 unsigned char flag;
1919
1920 if (!RPY_RDB_REPLAY) {
1921 void *r = gc_rawrefcount_to_obj(pyobj);
1922 RPY_REVDB_EMIT(flag = 0xEE + !r;, unsigned char _e, flag);
1923 return r;
1924 }
1925 else {
1926 RPY_REVDB_EMIT(abort();, unsigned char _e, flag);
1927 switch (flag) {
1928
1929 case 0xEF:
1930 /* when recording, this call to to_obj() returned NULL */
1931 return NULL;
1932
1933 case 0xEE:
1934 /* when recording, this call to to_obj() didn't return NULL */
1935 break;
1936
1937 default:
1938 fprintf(stderr, "bad byte in rawrefcount_to_obj\n");
1939 exit(1);
1940 }
1941
1942 struct rawrefcount_link2_s **item, dummy;
1943 dummy.pyobj = pyobj;
1944 item = tfind(&dummy, &rawrefcount_tree, _rrtree_compare);
1945 if (item == NULL) {
1946 fprintf(stderr, "rawrefcount_to_obj: not found in tree\n");
1947 exit(1);
1948 }
1949 return (*item)->gcobj;
1950 }
1951 }
1952
1953 RPY_EXTERN
1954 void *rpy_reverse_db_rawrefcount_next_dead(void)
1955 {
1956 unsigned char flag;
1957
1958 if (!RPY_RDB_REPLAY) {
1959 void *r = gc_rawrefcount_next_dead();
1960 RPY_REVDB_EMIT(flag = 0xEC + !r;, unsigned char _e, flag);
1961 if (r) {
1962 RPY_REVDB_EMIT(;, void *_e, r);
1963 }
1964 return r;
1965 }
1966 else {
1967 /* Note: when replaying, the lifetime of the gcobj is a bit
1968 extended when compared with recording. That shouldn't have
1969 a visible effect. More precisely, when replaying,
1970 create_link_pypy() calls _rrtree_add(), which makes a
1971 struct rawrefcount_link2_s, which keeps gcobj alive; and
1972 that structure is only freed here, when we call next_dead()
1973 and return the corresponding pyobj. When recording, the
1974 cause-and-effect relationship is in the opposite direction:
1975 when Boehm frees the gcobj, it causes the pyobj to show up
1976 (sometimes later) in a next_dead() call.
1977 */
1978 RPY_REVDB_EMIT(abort();, unsigned char _e, flag);
1979 switch (flag) {
1980
1981 case 0xED:
1982 /* when recording, this call to next_dead() returned NULL */
1983 return NULL;
1984
1985 case 0xEC:
1986 /* when recording, this call to next_dead() didn't return NULL */
1987 break;
1988
1989 default:
1990 fprintf(stderr, "bad byte in rawrefcount_next_dead\n");
1991 exit(1);
1992 }
1993
1994 void *pyobj;
1995 RPY_REVDB_EMIT(abort();, void *_e, pyobj);
1996
1997 struct rawrefcount_link2_s **item, *entry, dummy;
1998 dummy.pyobj = pyobj;
1999 item = tfind(&dummy, &rawrefcount_tree, _rrtree_compare);
2000 if (item == NULL) {
2001 fprintf(stderr, "rawrefcount_next_dead: not found in tree\n");
2002 exit(1);
2003 }
2004 entry = *item;
2005 tdelete(entry, &rawrefcount_tree, _rrtree_compare);
2006 GC_FREE(entry);
2007
2008 return pyobj;
2009 }
2010 }
2011
2012 #endif /* RPY_USES_RAWREFCOUNT */
2013
2014
2015 /* ------------------------------------------------------------ */
2016
2017
2018 RPY_EXTERN
2019 void seeing_uid(uint64_t uid)
2020 {
2021 }
0 #include <string.h>
1 #include "src/thread.h"
2
3 /************************************************************
4 *** RevDB --- record and replay debugging ***
5 ************************************************************/
6
7
8 typedef struct {
9 #ifndef RPY_RDB_REPLAY
10 bool_t replay;
11 #define RPY_RDB_REPLAY rpy_revdb.replay
12 #define RPY_RDB_DYNAMIC_REPLAY
13 #else
14 # error "explicit RPY_RDB_REPLAY: not really supported"
15 #endif
16 bool_t watch_enabled;
17 int lock;
18 char *buf_p; /* NULL during recording if recording is actually disabled */
19 char *buf_limit, *buf_readend;
20 uint64_t stop_point_seen, stop_point_break;
21 uint64_t unique_id_seen, unique_id_break;
22 } rpy_revdb_t;
23
24 RPY_EXTERN rpy_revdb_t rpy_revdb;
25 RPY_EXTERN int rpy_rev_fileno;
26 RPY_EXTERN __thread int rpy_active_thread;
27
28
29 /* ------------------------------------------------------------ */
30
31 RPY_EXTERN void rpy_reverse_db_setup(int *argc_p, char **argv_p[]);
32 RPY_EXTERN int rpy_reverse_db_main(Signed entry_point(Signed, char**),
33 int argc, char **argv);
34
35 /* enable to print locations to stderr of all the EMITs */
36 #ifdef RPY_REVDB_PRINT_ALL
37 # define _RPY_REVDB_PRINT(mode, _e) \
38 if (rpy_rev_fileno >= 0) { \
39 fprintf(stderr, \
40 "%s %s:%d: %0*llx\n", \
41 mode, __FILE__, (int)__LINE__, (int)(2 * sizeof(_e)), \
42 ((unsigned long long)_e) & ((2ULL << (8*sizeof(_e)-1)) - 1)); \
43 }
44 #endif
45
46 /* enable to print all mallocs to stderr */
47 #ifdef RPY_REVDB_PRINT_ALL
48 RPY_EXTERN void seeing_uid(uint64_t uid);
49 # define _RPY_REVDB_PRUID() \
50 if (rpy_rev_fileno >= 0) { \
51 seeing_uid(uid); \
52 fprintf(stderr, \
53 "[nobj] %s:%d: obj %llu\n", \
54 __FILE__, (int)__LINE__, (unsigned long long) uid); \
55 }
56 #endif
57
58 #ifndef _RPY_REVDB_PRINT
59 # define _RPY_REVDB_PRINT(mode, _e) /* nothing */
60 #endif
61 #ifndef _RPY_REVDB_PRUID
62 # define _RPY_REVDB_PRUID() /* nothing */
63 #endif
64
65
66 /* Acquire/release the lock around EMIT_RECORD, because it may be
67 called without holding the GIL. Note that we're always
68 single-threaded during replaying: the lock is only useful during
69 recording.
70
71 Implementation trick: use 'a >= b' to mean 'a || !b' (the two
72 variables can only take the values 0 or 1).
73 */
74 #define _RPY_REVDB_LOCK() \
75 { \
76 int _lock_contention = pypy_lock_test_and_set(&rpy_revdb.lock, 1); \
77 if (_lock_contention >= rpy_active_thread) \
78 rpy_reverse_db_lock_acquire(_lock_contention); \
79 }
80 #define _RPY_REVDB_UNLOCK() \
81 pypy_lock_release(&rpy_revdb.lock)
82
83
84 #define _RPY_REVDB_EMIT_RECORD_L(decl_e, variable) \
85 { \
86 decl_e = variable; \
87 _RPY_REVDB_PRINT("[ wr ]", _e); \
88 char *_dst = rpy_revdb.buf_p; \
89 if (_dst) { \
90 memcpy(_dst, &_e, sizeof(_e)); \
91 if ((rpy_revdb.buf_p = _dst + sizeof(_e)) \
92 > rpy_revdb.buf_limit) \
93 rpy_reverse_db_flush(); \
94 } \
95 }
96
97 #define _RPY_REVDB_EMIT_REPLAY(decl_e, variable) \
98 { \
99 decl_e; \
100 char *_src = rpy_revdb.buf_p; \
101 char *_end1 = _src + sizeof(_e); \
102 memcpy(&_e, _src, sizeof(_e)); \
103 rpy_revdb.buf_p = _end1; \
104 _RPY_REVDB_PRINT("[ rd ]", _e); \
105 if (_end1 >= rpy_revdb.buf_limit) \
106 rpy_reverse_db_fetch(__FILE__, __LINE__); \
107 variable = _e; \
108 }
109
110 #define _RPY_REVDB_EMIT_L(normal_code, decl_e, variable) \
111 if (!RPY_RDB_REPLAY) { \
112 normal_code \
113 _RPY_REVDB_EMIT_RECORD_L(decl_e, variable) \
114 } else \
115 _RPY_REVDB_EMIT_REPLAY(decl_e, variable)
116
117 #define RPY_REVDB_EMIT(normal_code, decl_e, variable) \
118 if (!RPY_RDB_REPLAY) { \
119 normal_code \
120 _RPY_REVDB_LOCK(); \
121 _RPY_REVDB_EMIT_RECORD_L(decl_e, variable) \
122 _RPY_REVDB_UNLOCK(); \
123 } else \
124 _RPY_REVDB_EMIT_REPLAY(decl_e, variable)
125
126 #define RPY_REVDB_EMIT_VOID(normal_code) \
127 if (!RPY_RDB_REPLAY) { normal_code } else { }
128
129 #define RPY_REVDB_CALL(call_code, decl_e, variable) \
130 if (!RPY_RDB_REPLAY) { \
131 call_code \
132 _RPY_REVDB_LOCK(); \
133 _RPY_REVDB_EMIT_RECORD_L(unsigned char _e, 0xFC) \
134 _RPY_REVDB_EMIT_RECORD_L(decl_e, variable) \
135 _RPY_REVDB_UNLOCK(); \
136 } else { \
137 unsigned char _re; \
138 _RPY_REVDB_EMIT_REPLAY(unsigned char _e, _re) \
139 if (_re != 0xFC) \
140 rpy_reverse_db_invoke_callback(_re); \
141 _RPY_REVDB_EMIT_REPLAY(decl_e, variable) \
142 }
143
144 #define RPY_REVDB_CALL_VOID(call_code) \
145 if (!RPY_RDB_REPLAY) { \
146 call_code \
147 _RPY_REVDB_LOCK(); \
148 _RPY_REVDB_EMIT_RECORD_L(unsigned char _e, 0xFC) \
149 _RPY_REVDB_UNLOCK(); \
150 } \
151 else { \
152 unsigned char _re; \
153 _RPY_REVDB_EMIT_REPLAY(unsigned char _e, _re) \
154 if (_re != 0xFC) \
155 rpy_reverse_db_invoke_callback(_re); \
156 }
157
158 #define RPY_REVDB_CALL_GIL_ACQUIRE() \
159 if (!RPY_RDB_REPLAY) { \
160 RPyGilAcquire(); \
161 _RPY_REVDB_LOCK(); \
162 _RPY_REVDB_EMIT_RECORD_L(unsigned char _e, 0xFD) \
163 _RPY_REVDB_UNLOCK(); \
164 } \
165 else { \
166 unsigned char _re; \
167 _RPY_REVDB_EMIT_REPLAY(unsigned char _e, _re) \
168 if (_re != 0xFD) \
169 rpy_reverse_db_bad_acquire_gil("acquire"); \
170 }
171
172 #define RPY_REVDB_CALL_GIL_RELEASE() \
173 if (!RPY_RDB_REPLAY) { \
174 _RPY_REVDB_LOCK(); \
175 _RPY_REVDB_EMIT_RECORD_L(unsigned char _e, 0xFE) \
176 _RPY_REVDB_UNLOCK(); \
177 RPyGilRelease(); \
178 } \
179 else { \
180 unsigned char _re; \
181 _RPY_REVDB_EMIT_REPLAY(unsigned char _e, _re) \
182 if (_re != 0xFE) \
183 rpy_reverse_db_bad_acquire_gil("release"); \
184 }
185
186 #define RPY_REVDB_C_ONLY_ENTER \
187 char *saved_bufp = rpy_revdb.buf_p; \
188 rpy_revdb.buf_p = NULL;
189
190 #define RPY_REVDB_C_ONLY_LEAVE \
191 rpy_revdb.buf_p = saved_bufp;
192
193 #define RPY_REVDB_CALLBACKLOC(locnum) \
194 rpy_reverse_db_callback_loc(locnum)
195
196 #define RPY_REVDB_REC_UID(expr) \
197 do { \
198 uint64_t uid = rpy_revdb.unique_id_seen; \
199 if (uid == rpy_revdb.unique_id_break || !expr) \
200 uid = rpy_reverse_db_unique_id_break(expr); \
201 rpy_revdb.unique_id_seen = uid + 1; \
202 ((struct pypy_header0 *)expr)->h_uid = uid; \
203 _RPY_REVDB_PRUID(); \
204 } while (0)
205
206 #define OP_REVDB_STOP_POINT(place, r) \
207 if (++rpy_revdb.stop_point_seen == rpy_revdb.stop_point_break) \
208 rpy_reverse_db_stop_point(place)
209
210 #define OP_REVDB_SEND_ANSWER(cmd, arg1, arg2, arg3, ll_string, r) \
211 rpy_reverse_db_send_answer(cmd, arg1, arg2, arg3, ll_string)
212
213 #define OP_REVDB_BREAKPOINT(num, r) \
214 rpy_reverse_db_breakpoint(num)
215
216 #define OP_REVDB_GET_VALUE(value_id, r) \
217 r = rpy_reverse_db_get_value(value_id)
218
219 #define OP_REVDB_IDENTITYHASH(obj, r) \
220 r = rpy_reverse_db_identityhash((struct pypy_header0 *)(obj))
221
222 #define OP_REVDB_GET_UNIQUE_ID(x, r) \
223 r = ((struct pypy_header0 *)x)->h_uid
224
225 #define OP_REVDB_TRACK_OBJECT(uid, callback, r) \
226 rpy_reverse_db_track_object(uid, callback)
227
228 #define OP_REVDB_WATCH_SAVE_STATE(force, r) do { \
229 r = rpy_revdb.watch_enabled; \
230 if ((force) || r) rpy_reverse_db_watch_save_state(); \
231 } while (0)
232
233 #define OP_REVDB_WATCH_RESTORE_STATE(any_watch_point, r) \
234 rpy_reverse_db_watch_restore_state(any_watch_point)
235
236 #define OP_REVDB_WEAKREF_CREATE(target, r) \
237 r = rpy_reverse_db_weakref_create(target)
238
239 #define OP_REVDB_WEAKREF_DEREF(weakref, r) \
240 r = rpy_reverse_db_weakref_deref(weakref)
241
242 #define OP_REVDB_CALL_DESTRUCTOR(obj, r) \
243 rpy_reverse_db_call_destructor(obj)
244
245 #define RPY_REVDB_CAST_PTR_TO_INT(obj) \
246 rpy_reverse_db_cast_ptr_to_int((struct pypy_header0 *)(obj))
247
248 #define OP_REVDB_SET_THREAD_BREAKPOINT(tnum, r) \
249 rpy_reverse_db_set_thread_breakpoint(tnum)
250
251 #define OP_REVDB_STRTOD(s, r) \
252 r = rpy_reverse_db_strtod(s)
253
254 #define OP_REVDB_DTOA(d, r) \
255 r = rpy_reverse_db_dtoa(d)
256
257 #define OP_REVDB_MODF(x, index, r) \
258 do { \
259 double _r0, _r1; \
260 _r0 = modf(x, &_r1); \
261 r = (index == 0) ? _r0 : _r1; \
262 } while (0)
263
264 #define OP_REVDB_FREXP(x, index, r) \
265 do { \
266 double _r0; int _r1; \
267 _r0 = frexp(x, &_r1); \
268 r = (index == 0) ? _r0 : _r1; \
269 } while (0)
270
271
272 #define OP_GC_RAWREFCOUNT_CREATE_LINK_PYPY(gcobj, pyobj, r) \
273 rpy_reverse_db_rawrefcount_create_link_pypy(gcobj, pyobj)
274
275 #define OP_GC_RAWREFCOUNT_CREATE_LINK_PYOBJ(gcobj, pyobj, r) \
276 rpy_reverse_db_rawrefcount_create_link_pypy(gcobj, pyobj)
277
278 #define OP_GC_RAWREFCOUNT_FROM_OBJ(gcobj, r) \
279 r = rpy_reverse_db_rawrefcount_from_obj(gcobj)
280
281 #define OP_GC_RAWREFCOUNT_TO_OBJ(pyobj, r) \
282 r = rpy_reverse_db_rawrefcount_to_obj(pyobj)
283
284 #define OP_GC_RAWREFCOUNT_NEXT_DEAD(r) \
285 r = rpy_reverse_db_rawrefcount_next_dead()
286
287
288 RPY_EXTERN void rpy_reverse_db_flush(void); /* must be called with the lock */
289 RPY_EXTERN void rpy_reverse_db_fetch(const char *file, int line);
290 RPY_EXTERN void rpy_reverse_db_stop_point(long place);
291 RPY_EXTERN void rpy_reverse_db_send_answer(int cmd, int64_t arg1, int64_t arg2,
292 int64_t arg3, RPyString *extra);
293 RPY_EXTERN Signed rpy_reverse_db_identityhash(struct pypy_header0 *obj);
294 RPY_EXTERN Signed rpy_reverse_db_cast_ptr_to_int(struct pypy_header0 *obj);
295 RPY_EXTERN void rpy_reverse_db_breakpoint(int64_t num);
296 RPY_EXTERN long long rpy_reverse_db_get_value(char value_id);
297 RPY_EXTERN uint64_t rpy_reverse_db_unique_id_break(void *new_object);
298 RPY_EXTERN void rpy_reverse_db_watch_save_state(void);
299 RPY_EXTERN void rpy_reverse_db_watch_restore_state(bool_t any_watch_point);
300 RPY_EXTERN void *rpy_reverse_db_weakref_create(void *target);
301 RPY_EXTERN void *rpy_reverse_db_weakref_deref(void *weakref);
302 RPY_EXTERN int rpy_reverse_db_fq_register(void *obj);
303 RPY_EXTERN void *rpy_reverse_db_next_dead(void *result);
304 RPY_EXTERN void rpy_reverse_db_register_destructor(void *obj, void(*)(void *));
305 RPY_EXTERN void rpy_reverse_db_call_destructor(void *obj);
306 RPY_EXTERN void rpy_reverse_db_invoke_callback(unsigned char);
307 RPY_EXTERN void rpy_reverse_db_callback_loc(int);
308 RPY_EXTERN void rpy_reverse_db_lock_acquire(bool_t lock_contention);
309 RPY_EXTERN void rpy_reverse_db_bad_acquire_gil(const char *name);
310 RPY_EXTERN void rpy_reverse_db_set_thread_breakpoint(int64_t tnum);
311 RPY_EXTERN double rpy_reverse_db_strtod(RPyString *s);
312 RPY_EXTERN RPyString *rpy_reverse_db_dtoa(double d);
313 RPY_EXTERN void rpy_reverse_db_rawrefcount_create_link_pypy(void *gcobj,
314 void *pyobj);
315 RPY_EXTERN void *rpy_reverse_db_rawrefcount_from_obj(void *gcobj);
316 RPY_EXTERN void *rpy_reverse_db_rawrefcount_to_obj(void *pyobj);
317 RPY_EXTERN void *rpy_reverse_db_rawrefcount_next_dead(void);
318
319 /* ------------------------------------------------------------ */
0 #include <stdint.h>
1
2 typedef struct rpy_revdb_command_s {
3 int32_t cmd; /* neg for standard commands, pos for interp-specific */
4 uint32_t extra_size;
5 int64_t arg1;
6 int64_t arg2;
7 int64_t arg3;
8 /* char extra[extra_size]; */
9 } rpy_revdb_command_t;
0 The tests are located in the external repository:
1
2 https://bitbucket.org/pypy/revdb/
2020 pypyopt,
2121 "--timeout=3600",
2222 "-rs",
23 "--duration=10",
2324 "--resultlog=cpython.log", "lib-python",
2425 ] + sys.argv[1:],
2526 cwd=rootdir)