Skip to content

Commit 5cacbb1

Browse files
encukoumiss-islington
authored andcommitted
gh-108907: ctypes: Document _type_ codes (GH-145837)
Add `_SimpleCData._type_` docs. Add type codes to the summary table. Cross-link `struct`, `array`, and `ctypes`; throw in `numpy` too. (Anyone wanting to add a code should be aware of those.) Add `py_object`, and `VARIANT_BOOL` for completeness. (cherry picked from commit 1114d7f) Co-authored-by: Petr Viktorin <encukou@gmail.com>
1 parent 8e7c62b commit 5cacbb1

File tree

3 files changed

+214
-79
lines changed

3 files changed

+214
-79
lines changed

Doc/library/array.rst

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -63,6 +63,13 @@ Notes:
6363
(2)
6464
.. versionadded:: 3.13
6565

66+
.. seealso::
67+
68+
The :ref:`ctypes <ctypes-fundamental-data-types>` and
69+
:ref:`struct <format-characters>` modules,
70+
as well as third-party modules like `numpy <https://numpy.org/doc/stable/reference/arrays.interface.html#object.__array_interface__>`__,
71+
use similar -- but slightly different -- type codes.
72+
6673

6774
The actual representation of values is determined by the machine architecture
6875
(strictly speaking, by the C implementation). The actual size can be accessed

Doc/library/ctypes.rst

Lines changed: 201 additions & 79 deletions
Original file line numberDiff line numberDiff line change
@@ -223,87 +223,164 @@ Fundamental data types
223223

224224
:mod:`!ctypes` defines a number of primitive C compatible data types:
225225

226-
+----------------------+------------------------------------------+----------------------------+
227-
| ctypes type | C type | Python type |
228-
+======================+==========================================+============================+
229-
| :class:`c_bool` | :c:expr:`_Bool` | bool (1) |
230-
+----------------------+------------------------------------------+----------------------------+
231-
| :class:`c_char` | :c:expr:`char` | 1-character bytes object |
232-
+----------------------+------------------------------------------+----------------------------+
233-
| :class:`c_wchar` | :c:type:`wchar_t` | 1-character string |
234-
+----------------------+------------------------------------------+----------------------------+
235-
| :class:`c_byte` | :c:expr:`char` | int |
236-
+----------------------+------------------------------------------+----------------------------+
237-
| :class:`c_ubyte` | :c:expr:`unsigned char` | int |
238-
+----------------------+------------------------------------------+----------------------------+
239-
| :class:`c_short` | :c:expr:`short` | int |
240-
+----------------------+------------------------------------------+----------------------------+
241-
| :class:`c_ushort` | :c:expr:`unsigned short` | int |
242-
+----------------------+------------------------------------------+----------------------------+
243-
| :class:`c_int` | :c:expr:`int` | int |
244-
+----------------------+------------------------------------------+----------------------------+
245-
| :class:`c_int8` | :c:type:`int8_t` | int |
246-
+----------------------+------------------------------------------+----------------------------+
247-
| :class:`c_int16` | :c:type:`int16_t` | int |
248-
+----------------------+------------------------------------------+----------------------------+
249-
| :class:`c_int32` | :c:type:`int32_t` | int |
250-
+----------------------+------------------------------------------+----------------------------+
251-
| :class:`c_int64` | :c:type:`int64_t` | int |
252-
+----------------------+------------------------------------------+----------------------------+
253-
| :class:`c_uint` | :c:expr:`unsigned int` | int |
254-
+----------------------+------------------------------------------+----------------------------+
255-
| :class:`c_uint8` | :c:type:`uint8_t` | int |
256-
+----------------------+------------------------------------------+----------------------------+
257-
| :class:`c_uint16` | :c:type:`uint16_t` | int |
258-
+----------------------+------------------------------------------+----------------------------+
259-
| :class:`c_uint32` | :c:type:`uint32_t` | int |
260-
+----------------------+------------------------------------------+----------------------------+
261-
| :class:`c_uint64` | :c:type:`uint64_t` | int |
262-
+----------------------+------------------------------------------+----------------------------+
263-
| :class:`c_long` | :c:expr:`long` | int |
264-
+----------------------+------------------------------------------+----------------------------+
265-
| :class:`c_ulong` | :c:expr:`unsigned long` | int |
266-
+----------------------+------------------------------------------+----------------------------+
267-
| :class:`c_longlong` | :c:expr:`__int64` or :c:expr:`long long` | int |
268-
+----------------------+------------------------------------------+----------------------------+
269-
| :class:`c_ulonglong` | :c:expr:`unsigned __int64` or | int |
270-
| | :c:expr:`unsigned long long` | |
271-
+----------------------+------------------------------------------+----------------------------+
272-
| :class:`c_size_t` | :c:type:`size_t` | int |
273-
+----------------------+------------------------------------------+----------------------------+
274-
| :class:`c_ssize_t` | :c:type:`ssize_t` or | int |
275-
| | :c:expr:`Py_ssize_t` | |
276-
+----------------------+------------------------------------------+----------------------------+
277-
| :class:`c_time_t` | :c:type:`time_t` | int |
278-
+----------------------+------------------------------------------+----------------------------+
279-
| :class:`c_float` | :c:expr:`float` | float |
280-
+----------------------+------------------------------------------+----------------------------+
281-
| :class:`c_double` | :c:expr:`double` | float |
282-
+----------------------+------------------------------------------+----------------------------+
283-
| :class:`c_longdouble`| :c:expr:`long double` | float |
284-
+----------------------+------------------------------------------+----------------------------+
285-
| :class:`c_char_p` | :c:expr:`char *` (NUL terminated) | bytes object or ``None`` |
286-
+----------------------+------------------------------------------+----------------------------+
287-
| :class:`c_wchar_p` | :c:expr:`wchar_t *` (NUL terminated) | string or ``None`` |
288-
+----------------------+------------------------------------------+----------------------------+
289-
| :class:`c_void_p` | :c:expr:`void *` | int or ``None`` |
290-
+----------------------+------------------------------------------+----------------------------+
291-
292-
(1)
293-
The constructor accepts any object with a truth value.
226+
.. list-table::
227+
:header-rows: 1
228+
229+
* - ctypes type
230+
- C type
231+
- Python type
232+
- :py:attr:`~_SimpleCData._type_`
233+
* - :class:`c_bool`
234+
- :c:expr:`_Bool`
235+
- :py:class:`bool`
236+
- ``'?'``
237+
* - :class:`c_char`
238+
- :c:expr:`char`
239+
- 1-character :py:class:`bytes`
240+
- ``'c'``
241+
* - :class:`c_wchar`
242+
- :c:type:`wchar_t`
243+
- 1-character :py:class:`str`
244+
- ``'u'``
245+
* - :class:`c_byte`
246+
- :c:expr:`char`
247+
- :py:class:`int`
248+
- ``'b'``
249+
* - :class:`c_ubyte`
250+
- :c:expr:`unsigned char`
251+
- :py:class:`int`
252+
- ``'B'``
253+
* - :class:`c_short`
254+
- :c:expr:`short`
255+
- :py:class:`int`
256+
- ``'h'``
257+
* - :class:`c_ushort`
258+
- :c:expr:`unsigned short`
259+
- :py:class:`int`
260+
- ``'H'``
261+
* - :class:`c_int`
262+
- :c:expr:`int`
263+
- :py:class:`int`
264+
- ``'i'`` \*
265+
* - :class:`c_int8`
266+
- :c:type:`int8_t`
267+
- :py:class:`int`
268+
- \*
269+
* - :class:`c_int16`
270+
- :c:type:`int16_t`
271+
- :py:class:`int`
272+
- \*
273+
* - :class:`c_int32`
274+
- :c:type:`int32_t`
275+
- :py:class:`int`
276+
- \*
277+
* - :class:`c_int64`
278+
- :c:type:`int64_t`
279+
- :py:class:`int`
280+
- \*
281+
* - :class:`c_uint`
282+
- :c:expr:`unsigned int`
283+
- :py:class:`int`
284+
- ``'I'`` \*
285+
* - :class:`c_uint8`
286+
- :c:type:`uint8_t`
287+
- :py:class:`int`
288+
- \*
289+
* - :class:`c_uint16`
290+
- :c:type:`uint16_t`
291+
- :py:class:`int`
292+
- \*
293+
* - :class:`c_uint32`
294+
- :c:type:`uint32_t`
295+
- :py:class:`int`
296+
- \*
297+
* - :class:`c_uint64`
298+
- :c:type:`uint64_t`
299+
- :py:class:`int`
300+
- \*
301+
* - :class:`c_long`
302+
- :c:expr:`long`
303+
- :py:class:`int`
304+
- ``'l'``
305+
* - :class:`c_ulong`
306+
- :c:expr:`unsigned long`
307+
- :py:class:`int`
308+
- ``'L'``
309+
* - :class:`c_longlong`
310+
- :c:expr:`long long`
311+
- :py:class:`int`
312+
- ``'q'`` \*
313+
* - :class:`c_ulonglong`
314+
- :c:expr:`unsigned long long`
315+
- :py:class:`int`
316+
- ``'Q'`` \*
317+
* - :class:`c_size_t`
318+
- :c:type:`size_t`
319+
- :py:class:`int`
320+
- \*
321+
* - :class:`c_ssize_t`
322+
- :c:type:`Py_ssize_t`
323+
- :py:class:`int`
324+
- \*
325+
* - :class:`c_time_t`
326+
- :c:type:`time_t`
327+
- :py:class:`int`
328+
- \*
329+
* - :class:`c_float`
330+
- :c:expr:`float`
331+
- :py:class:`float`
332+
- ``'f'``
333+
* - :class:`c_double`
334+
- :c:expr:`double`
335+
- :py:class:`float`
336+
- ``'d'``
337+
* - :class:`c_longdouble`
338+
- :c:expr:`long double`
339+
- :py:class:`float`
340+
- ``'g'`` \*
341+
* - :class:`c_char_p`
342+
- :c:expr:`char *` (NUL terminated)
343+
- :py:class:`bytes` or ``None``
344+
- ``'z'``
345+
* - :class:`c_wchar_p`
346+
- :c:expr:`wchar_t *` (NUL terminated)
347+
- :py:class:`str` or ``None``
348+
- ``'Z'``
349+
* - :class:`c_void_p`
350+
- :c:expr:`void *`
351+
- :py:class:`int` or ``None``
352+
- ``'P'``
353+
* - :class:`py_object`
354+
- :c:expr:`PyObject *`
355+
- :py:class:`object`
356+
- ``'O'``
357+
* - :ref:`VARIANT_BOOL <ctypes-wintypes>`
358+
- :c:expr:`short int`
359+
- :py:class:`bool`
360+
- ``'v'``
294361

295362
Additionally, if IEC 60559 compatible complex arithmetic (Annex G) is supported
296363
in both C and ``libffi``, the following complex types are available:
297364

298-
+----------------------------------+---------------------------------+-----------------+
299-
| ctypes type | C type | Python type |
300-
+==================================+=================================+=================+
301-
| :class:`c_float_complex` | :c:expr:`float complex` | complex |
302-
+----------------------------------+---------------------------------+-----------------+
303-
| :class:`c_double_complex` | :c:expr:`double complex` | complex |
304-
+----------------------------------+---------------------------------+-----------------+
305-
| :class:`c_longdouble_complex` | :c:expr:`long double complex` | complex |
306-
+----------------------------------+---------------------------------+-----------------+
365+
.. list-table::
366+
:header-rows: 1
367+
368+
* - ctypes type
369+
- C type
370+
- Python type
371+
- :py:attr:`~_SimpleCData._type_`
372+
* - :class:`c_float_complex`
373+
- :c:expr:`float complex`
374+
- :py:class:`complex`
375+
- ``'F'``
376+
* - :class:`c_double_complex`
377+
- :c:expr:`double complex`
378+
- :py:class:`complex`
379+
- ``'D'``
380+
* - :class:`c_longdouble_complex`
381+
- :c:expr:`long double complex`
382+
- :py:class:`complex`
383+
- ``'G'``
307384

308385

309386
All these types can be created by calling them with an optional initializer of
@@ -317,6 +394,16 @@ the correct type and value::
317394
c_ushort(65533)
318395
>>>
319396

397+
The constructors for numeric types will convert input using
398+
:py:meth:`~object.__bool__`,
399+
:py:meth:`~object.__index__` (for ``int``),
400+
:py:meth:`~object.__float__` or :py:meth:`~object.__complex__`.
401+
This means :py:class:`~ctypes.c_bool` accepts any object with a truth value::
402+
403+
>>> empty_list = []
404+
>>> c_bool(empty_list)
405+
c_bool(False)
406+
320407
Since these types are mutable, their value can also be changed afterwards::
321408

322409
>>> i = c_int(42)
@@ -2470,6 +2557,29 @@ Fundamental data types
24702557
original object return, always a new object is constructed. The same is
24712558
true for all other ctypes object instances.
24722559

2560+
Each subclass has a class attribute:
2561+
2562+
.. attribute:: _type_
2563+
2564+
Class attribute that contains an internal type code, as a
2565+
single-character string.
2566+
See :ref:`ctypes-fundamental-data-types` for a summary.
2567+
2568+
Types marked \* in the summary may be (or always are) aliases of a
2569+
different :class:`_SimpleCData` subclass, and will not necessarily
2570+
use the listed type code.
2571+
For example, if the platform's :c:expr:`long`, :c:expr:`long long`
2572+
and :c:expr:`time_t` C types are the same, then :class:`c_long`,
2573+
:class:`c_longlong` and :class:`c_time_t` all refer to a single class,
2574+
:class:`c_long`, whose :attr:`_type_` code is ``'l'``.
2575+
The ``'L'`` code will be unused.
2576+
2577+
.. seealso::
2578+
2579+
The :mod:`array` and :ref:`struct <format-characters>` modules,
2580+
as well as third-party modules like `numpy <https://numpy.org/doc/stable/reference/arrays.interface.html#object.__array_interface__>`__,
2581+
use similar -- but slightly different -- type codes.
2582+
24732583

24742584
Fundamental data types, when returned as foreign function call results, or, for
24752585
example, by retrieving structure field members or array items, are transparently
@@ -2591,6 +2701,8 @@ These are the fundamental ctypes data types:
25912701

25922702
Represents the C :c:expr:`signed long long` datatype. The constructor accepts
25932703
an optional integer initializer; no overflow checking is done.
2704+
On platforms where ``sizeof(long long) == sizeof(long)`` it is an alias
2705+
to :class:`c_long`.
25942706

25952707

25962708
.. class:: c_short
@@ -2602,18 +2714,23 @@ These are the fundamental ctypes data types:
26022714
.. class:: c_size_t
26032715

26042716
Represents the C :c:type:`size_t` datatype.
2717+
Usually an alias for another unsigned integer type.
26052718

26062719

26072720
.. class:: c_ssize_t
26082721

2609-
Represents the C :c:type:`ssize_t` datatype.
2722+
Represents the :c:type:`Py_ssize_t` datatype.
2723+
This is a signed version of :c:type:`size_t`;
2724+
that is, the POSIX :c:type:`ssize_t` type.
2725+
Usually an alias for another integer type.
26102726

26112727
.. versionadded:: 3.2
26122728

26132729

26142730
.. class:: c_time_t
26152731

26162732
Represents the C :c:type:`time_t` datatype.
2733+
Usually an alias for another integer type.
26172734

26182735
.. versionadded:: 3.12
26192736

@@ -2666,6 +2783,8 @@ These are the fundamental ctypes data types:
26662783

26672784
Represents the C :c:expr:`unsigned long long` datatype. The constructor
26682785
accepts an optional integer initializer; no overflow checking is done.
2786+
On platforms where ``sizeof(long long) == sizeof(long)`` it is an alias
2787+
to :class:`c_long`.
26692788

26702789

26712790
.. class:: c_ushort
@@ -2717,8 +2836,11 @@ These are the fundamental ctypes data types:
27172836
.. versionchanged:: 3.14
27182837
:class:`!py_object` is now a :term:`generic type`.
27192838

2839+
.. _ctypes-wintypes:
2840+
27202841
The :mod:`!ctypes.wintypes` module provides quite some other Windows specific
2721-
data types, for example :c:type:`!HWND`, :c:type:`!WPARAM`, or :c:type:`!DWORD`.
2842+
data types, for example :c:type:`!HWND`, :c:type:`!WPARAM`,
2843+
:c:type:`!VARIANT_BOOL` or :c:type:`!DWORD`.
27222844
Some useful structures like :c:type:`!MSG` or :c:type:`!RECT` are also defined.
27232845

27242846

Doc/library/struct.rst

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -280,6 +280,12 @@ platform-dependent.
280280
.. versionchanged:: 3.14
281281
Added support for the ``'F'`` and ``'D'`` formats.
282282

283+
.. seealso::
284+
285+
The :mod:`array` and :ref:`ctypes <ctypes-fundamental-data-types>` modules,
286+
as well as third-party modules like `numpy <https://numpy.org/doc/stable/reference/arrays.interface.html#object.__array_interface__>`__,
287+
use similar -- but slightly different -- type codes.
288+
283289

284290
Notes:
285291

0 commit comments

Comments
 (0)