diff options
author | Petr Viktorin <encukou@gmail.com> | 2024-12-20 13:28:18 (GMT) |
---|---|---|
committer | GitHub <noreply@github.com> | 2024-12-20 13:28:18 (GMT) |
commit | 78ffba4221dcb2e39fd5db80c297d1777588bb59 (patch) | |
tree | 1b5d16b0bac6d061035486b644f303c305935206 /Objects | |
parent | ba45e5cdd41a39ce0b3de08bdcfa9d8e28e0e4f3 (diff) | |
download | cpython-78ffba4221dcb2e39fd5db80c297d1777588bb59.zip cpython-78ffba4221dcb2e39fd5db80c297d1777588bb59.tar.gz cpython-78ffba4221dcb2e39fd5db80c297d1777588bb59.tar.bz2 |
gh-127295: ctypes: Switch field accessors to fixed-width integers (GH-127297)
This should be a pure refactoring, without user-visible behaviour changes.
Before this change, ctypes uses traditional native C types, usually identified
by [`struct` format characters][struct-chars] when a short (and
identifier-friendly) name is needed:
- `signed char` (`b`) / `unsigned char` (`B`)
- `short` (`h`) / `unsigned short` (`h`)
- `int` (`i`) / `unsigned int` (`i`)
- `long` (`l`) / `unsigned long` (`l`)
- `long long` (`q`) / `unsigned long long` (`q`)
These map to C99 fixed-width types, which this PR switches to: -
- `int8_t`/`uint8_t`
- `int16_t`/`uint16_t`
- `int32_t`/`uint32_t`
- `int64_t`/`uint64_t`
The C standard doesn't guarantee that the “traditional” types must map to the
fixints. But, [`ctypes` currently requires it][swapdefs], so the assumption won't
break anything.
By “map” I mean that the *size* of the types matches. The *alignment*
requirements might not. This needs to be kept in mind but is not an issue in
`ctypes` accessors, which [explicitly handle unaligned memory][memcpy] for the
integer types.
Note that there are 5 “traditional” C type sizes, but 4 fixed-width ones. Two of
the former are functionally identical to one another; which ones they are is
platform-specific (e.g. `int`==`long`==`int32_t`.) This means that one of the
[current][current-impls-1] [implementations][current-impls-2] is redundant on
any given platform.
The fixint types are parametrized by the number of bytes/bits, and one bit for
signedness. This makes it easier to autogenerate code for them or to write
generic macros (though generic API like
[`PyLong_AsNativeBytes`][PyLong_AsNativeBytes] is problematic for performance
reasons -- especially compared to a `memcpy` with compile-time-constant size).
When one has a *different* integer type, determining the corresponding fixint
means a `sizeof` and signedness check. This is easier and more robust than the
current implementations (see [`wchar_t`][sizeof-wchar_t] or
[`_Bool`][sizeof-bool]).
[swapdefs]: https://github.com/python/cpython/blob/v3.13.0/Modules/_ctypes/cfield.c#L420-L444
[struct-chars]: https://docs.python.org/3/library/struct.html#format-characters
[current-impls-1]: https://github.com/python/cpython/blob/v3.13.0/Modules/_ctypes/cfield.c#L470-L653
[current-impls-2]: https://github.com/python/cpython/blob/v3.13.0/Modules/_ctypes/cfield.c#L703-L944
[memcpy]: https://github.com/python/cpython/blob/v3.13.0/Modules/_ctypes/cfield.c#L613
[PyLong_AsNativeBytes]: https://docs.python.org/3/c-api/long.html#c.PyLong_AsNativeBytes
[sizeof-wchar_t]: https://github.com/python/cpython/blob/v3.13.0/Modules/_ctypes/cfield.c#L1547-L1555
[sizeof-bool]: https://github.com/python/cpython/blob/v3.13.0/Modules/_ctypes/cfield.c#L1562-L1572
Co-authored-by: Bénédikt Tran <10796600+picnixz@users.noreply.github.com>
Diffstat (limited to 'Objects')
0 files changed, 0 insertions, 0 deletions