Skip to content

Commit 1114d7f

Browse files
authored
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.
1 parent 91cd2e5 commit 1114d7f

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
@@ -221,87 +221,164 @@ Fundamental data types
221221

222222
:mod:`!ctypes` defines a number of primitive C compatible data types:
223223

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

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

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

306383

307384
All these types can be created by calling them with an optional initializer of
@@ -315,6 +392,16 @@ the correct type and value::
315392
c_ushort(65533)
316393
>>>
317394

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

320407
>>> i = c_int(42)
@@ -2478,6 +2565,29 @@ Fundamental data types
24782565
original object return, always a new object is constructed. The same is
24792566
true for all other ctypes object instances.
24802567

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

24822592
Fundamental data types, when returned as foreign function call results, or, for
24832593
example, by retrieving structure field members or array items, are transparently
@@ -2599,6 +2709,8 @@ These are the fundamental ctypes data types:
25992709

26002710
Represents the C :c:expr:`signed long long` datatype. The constructor accepts
26012711
an optional integer initializer; no overflow checking is done.
2712+
On platforms where ``sizeof(long long) == sizeof(long)`` it is an alias
2713+
to :class:`c_long`.
26022714

26032715

26042716
.. class:: c_short
@@ -2610,18 +2722,23 @@ These are the fundamental ctypes data types:
26102722
.. class:: c_size_t
26112723

26122724
Represents the C :c:type:`size_t` datatype.
2725+
Usually an alias for another unsigned integer type.
26132726

26142727

26152728
.. class:: c_ssize_t
26162729

2617-
Represents the C :c:type:`ssize_t` datatype.
2730+
Represents the :c:type:`Py_ssize_t` datatype.
2731+
This is a signed version of :c:type:`size_t`;
2732+
that is, the POSIX :c:type:`ssize_t` type.
2733+
Usually an alias for another integer type.
26182734

26192735
.. versionadded:: 3.2
26202736

26212737

26222738
.. class:: c_time_t
26232739

26242740
Represents the C :c:type:`time_t` datatype.
2741+
Usually an alias for another integer type.
26252742

26262743
.. versionadded:: 3.12
26272744

@@ -2674,6 +2791,8 @@ These are the fundamental ctypes data types:
26742791

26752792
Represents the C :c:expr:`unsigned long long` datatype. The constructor
26762793
accepts an optional integer initializer; no overflow checking is done.
2794+
On platforms where ``sizeof(long long) == sizeof(long)`` it is an alias
2795+
to :class:`c_long`.
26772796

26782797

26792798
.. class:: c_ushort
@@ -2725,8 +2844,11 @@ These are the fundamental ctypes data types:
27252844
.. versionchanged:: 3.14
27262845
:class:`!py_object` is now a :term:`generic type`.
27272846

2847+
.. _ctypes-wintypes:
2848+
27282849
The :mod:`!ctypes.wintypes` module provides quite some other Windows specific
2729-
data types, for example :c:type:`!HWND`, :c:type:`!WPARAM`, or :c:type:`!DWORD`.
2850+
data types, for example :c:type:`!HWND`, :c:type:`!WPARAM`,
2851+
:c:type:`!VARIANT_BOOL` or :c:type:`!DWORD`.
27302852
Some useful structures like :c:type:`!MSG` or :c:type:`!RECT` are also defined.
27312853

27322854

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)