Various ctypes improvements (#11186)

Mostly more attention paid to which classes are actually the same class
This commit is contained in:
Stephen Morton
2024-01-30 22:18:00 -08:00
committed by GitHub
parent 8010e9fef0
commit 9877ed8092
4 changed files with 153 additions and 67 deletions

View File

@@ -3,7 +3,6 @@ from _ctypes import (
POINTER as POINTER,
RTLD_GLOBAL as RTLD_GLOBAL,
RTLD_LOCAL as RTLD_LOCAL,
ArgumentError as ArgumentError,
Array as Array,
CFuncPtr as _CFuncPtr,
Structure as Structure,
@@ -27,12 +26,16 @@ from _ctypes import (
set_errno as set_errno,
sizeof as sizeof,
)
from ctypes._endian import BigEndianStructure as BigEndianStructure, LittleEndianStructure as LittleEndianStructure
from typing import Any, ClassVar, Generic, TypeVar
from typing_extensions import TypeAlias
if sys.platform == "win32":
from _ctypes import FormatError as FormatError, get_last_error as get_last_error, set_last_error as set_last_error
if sys.version_info >= (3, 11):
from ctypes._endian import BigEndianUnion as BigEndianUnion, LittleEndianUnion as LittleEndianUnion
if sys.version_info >= (3, 9):
from types import GenericAlias
@@ -41,6 +44,8 @@ _DLLT = TypeVar("_DLLT", bound=CDLL)
DEFAULT_MODE: int
class ArgumentError(Exception): ...
class CDLL:
_func_flags_: ClassVar[int]
_func_restype_: ClassVar[_CData]
@@ -137,30 +142,36 @@ class c_char_p(_PointerLike, _SimpleCData[bytes | None]):
def __init__(self, value: int | bytes | None = ...) -> None: ...
class c_double(_SimpleCData[float]): ...
class c_longdouble(_SimpleCData[float]): ...
class c_longdouble(_SimpleCData[float]): ... # can be an alias for c_double
class c_float(_SimpleCData[float]): ...
class c_int(_SimpleCData[int]): ...
class c_int8(_SimpleCData[int]): ...
class c_int16(_SimpleCData[int]): ...
class c_int32(_SimpleCData[int]): ...
class c_int64(_SimpleCData[int]): ...
class c_int(_SimpleCData[int]): ... # can be an alias for c_long
class c_long(_SimpleCData[int]): ...
class c_longlong(_SimpleCData[int]): ...
class c_longlong(_SimpleCData[int]): ... # can be an alias for c_long
class c_short(_SimpleCData[int]): ...
class c_size_t(_SimpleCData[int]): ...
class c_ssize_t(_SimpleCData[int]): ...
class c_size_t(_SimpleCData[int]): ... # alias for c_uint, c_ulong, or c_ulonglong
class c_ssize_t(_SimpleCData[int]): ... # alias for c_int, c_long, or c_longlong
class c_ubyte(_SimpleCData[int]): ...
class c_uint(_SimpleCData[int]): ...
class c_uint8(_SimpleCData[int]): ...
class c_uint16(_SimpleCData[int]): ...
class c_uint32(_SimpleCData[int]): ...
class c_uint64(_SimpleCData[int]): ...
class c_uint(_SimpleCData[int]): ... # can be an alias for c_ulong
class c_ulong(_SimpleCData[int]): ...
class c_ulonglong(_SimpleCData[int]): ...
class c_ulonglong(_SimpleCData[int]): ... # can be an alias for c_ulong
class c_ushort(_SimpleCData[int]): ...
class c_void_p(_PointerLike, _SimpleCData[int | None]): ...
class c_wchar(_SimpleCData[str]): ...
c_int8 = c_byte
# these are actually dynamic aliases for c_short, c_int, c_long, or c_longlong
class c_int16(_SimpleCData[int]): ...
class c_int32(_SimpleCData[int]): ...
class c_int64(_SimpleCData[int]): ...
c_uint8 = c_ubyte
# these are actually dynamic aliases for c_ushort, c_uint, c_ulong, or c_ulonglong
class c_uint16(_SimpleCData[int]): ...
class c_uint32(_SimpleCData[int]): ...
class c_uint64(_SimpleCData[int]): ...
class c_wchar_p(_PointerLike, _SimpleCData[str | None]):
def __init__(self, value: int | str | None = ...) -> None: ...
@@ -171,8 +182,6 @@ if sys.platform == "win32":
class HRESULT(_SimpleCData[int]): ... # TODO undocumented
if sys.version_info >= (3, 12):
c_time_t: type[c_int32 | c_int64]
c_time_t: type[c_int32 | c_int64] # alias for one or the other at runtime
class py_object(_CanCastTo, _SimpleCData[_T]): ...
class BigEndianStructure(Structure): ...
class LittleEndianStructure(Structure): ...

19
stdlib/ctypes/_endian.pyi Normal file
View File

@@ -0,0 +1,19 @@
import sys
from _ctypes import RTLD_GLOBAL as RTLD_GLOBAL, RTLD_LOCAL as RTLD_LOCAL, Structure, Union
from ctypes import DEFAULT_MODE as DEFAULT_MODE, cdll as cdll, pydll as pydll, pythonapi as pythonapi
if sys.version_info >= (3, 12):
from _ctypes import SIZEOF_TIME_T as SIZEOF_TIME_T
if sys.platform == "win32":
from ctypes import oledll as oledll, windll as windll
# At runtime, the native endianness is an alias for Structure,
# while the other is a subclass with a metaclass added in.
class BigEndianStructure(Structure): ...
class LittleEndianStructure(Structure): ...
# Same thing for these: one is an alias of Union at runtime
if sys.version_info >= (3, 11):
class BigEndianUnion(Union): ...
class LittleEndianUnion(Union): ...

View File

@@ -186,53 +186,113 @@ class WIN32_FIND_DATAW(Structure):
cFileName: _CField[Array[WCHAR], str, str]
cAlternateFileName: _CField[Array[WCHAR], str, str]
class PBOOL(_Pointer[BOOL]): ...
class LPBOOL(_Pointer[BOOL]): ...
class PBOOLEAN(_Pointer[BOOLEAN]): ...
class PBYTE(_Pointer[BYTE]): ...
class LPBYTE(_Pointer[BYTE]): ...
class PCHAR(_Pointer[CHAR]): ...
class LPCOLORREF(_Pointer[COLORREF]): ...
class PDWORD(_Pointer[DWORD]): ...
class LPDWORD(_Pointer[DWORD]): ...
class PFILETIME(_Pointer[FILETIME]): ...
class LPFILETIME(_Pointer[FILETIME]): ...
class PFLOAT(_Pointer[FLOAT]): ...
class PHANDLE(_Pointer[HANDLE]): ...
class LPHANDLE(_Pointer[HANDLE]): ...
class PHKEY(_Pointer[HKEY]): ...
class LPHKL(_Pointer[HKL]): ...
class PINT(_Pointer[INT]): ...
class LPINT(_Pointer[INT]): ...
class PLARGE_INTEGER(_Pointer[LARGE_INTEGER]): ...
class PLCID(_Pointer[LCID]): ...
class PLONG(_Pointer[LONG]): ...
class LPLONG(_Pointer[LONG]): ...
class PMSG(_Pointer[MSG]): ...
class LPMSG(_Pointer[MSG]): ...
class PPOINT(_Pointer[POINT]): ...
class LPPOINT(_Pointer[POINT]): ...
class PPOINTL(_Pointer[POINTL]): ...
class PRECT(_Pointer[RECT]): ...
class LPRECT(_Pointer[RECT]): ...
class PRECTL(_Pointer[RECTL]): ...
class LPRECTL(_Pointer[RECTL]): ...
class LPSC_HANDLE(_Pointer[SC_HANDLE]): ...
# These are all defined with the POINTER() function, which keeps a cache and will
# return a previously created class if it can. The self-reported __name__
# of these classes is f"LP_{typ.__name__}", where typ is the original class
# passed in to the POINTER() function.
# LP_c_short
class PSHORT(_Pointer[SHORT]): ...
class PSIZE(_Pointer[SIZE]): ...
class LPSIZE(_Pointer[SIZE]): ...
class PSIZEL(_Pointer[SIZEL]): ...
class LPSIZEL(_Pointer[SIZEL]): ...
class PSMALL_RECT(_Pointer[SMALL_RECT]): ...
class PUINT(_Pointer[UINT]): ...
class LPUINT(_Pointer[UINT]): ...
class PULARGE_INTEGER(_Pointer[ULARGE_INTEGER]): ...
class PULONG(_Pointer[ULONG]): ...
# LP_c_ushort
class PUSHORT(_Pointer[USHORT]): ...
PWORD = PUSHORT
LPWORD = PUSHORT
# LP_c_long
class PLONG(_Pointer[LONG]): ...
LPLONG = PLONG
PBOOL = PLONG
LPBOOL = PLONG
# LP_c_ulong
class PULONG(_Pointer[ULONG]): ...
PDWORD = PULONG
LPDWORD = PDWORD
LPCOLORREF = PDWORD
PLCID = PDWORD
# LP_c_int (or LP_c_long if int and long have the same size)
class PINT(_Pointer[INT]): ...
LPINT = PINT
# LP_c_uint (or LP_c_ulong if int and long have the same size)
class PUINT(_Pointer[UINT]): ...
LPUINT = PUINT
# LP_c_float
class PFLOAT(_Pointer[FLOAT]): ...
# LP_c_longlong (or LP_c_long if long and long long have the same size)
class PLARGE_INTEGER(_Pointer[LARGE_INTEGER]): ...
# LP_c_ulonglong (or LP_c_ulong if long and long long have the same size)
class PULARGE_INTEGER(_Pointer[ULARGE_INTEGER]): ...
# LP_c_byte types
class PBYTE(_Pointer[BYTE]): ...
LPBYTE = PBYTE
PBOOLEAN = PBYTE
# LP_c_char
class PCHAR(_Pointer[CHAR]): ...
# LP_c_wchar
class PWCHAR(_Pointer[WCHAR]): ...
# LP_c_void_p
class PHANDLE(_Pointer[HANDLE]): ...
LPHANDLE = PHANDLE
PHKEY = PHANDLE
LPHKL = PHANDLE
LPSC_HANDLE = PHANDLE
# LP_FILETIME
class PFILETIME(_Pointer[FILETIME]): ...
LPFILETIME = PFILETIME
# LP_MSG
class PMSG(_Pointer[MSG]): ...
LPMSG = PMSG
# LP_POINT
class PPOINT(_Pointer[POINT]): ...
LPPOINT = PPOINT
PPOINTL = PPOINT
# LP_RECT
class PRECT(_Pointer[RECT]): ...
LPRECT = PRECT
PRECTL = PRECT
LPRECTL = PRECT
# LP_SIZE
class PSIZE(_Pointer[SIZE]): ...
LPSIZE = PSIZE
PSIZEL = PSIZE
LPSIZEL = PSIZE
# LP__SMALL_RECT
class PSMALL_RECT(_Pointer[SMALL_RECT]): ...
# LP_WIN32_FIND_DATAA
class PWIN32_FIND_DATAA(_Pointer[WIN32_FIND_DATAA]): ...
class LPWIN32_FIND_DATAA(_Pointer[WIN32_FIND_DATAA]): ...
LPWIN32_FIND_DATAA = PWIN32_FIND_DATAA
# LP_WIN32_FIND_DATAW
class PWIN32_FIND_DATAW(_Pointer[WIN32_FIND_DATAW]): ...
class LPWIN32_FIND_DATAW(_Pointer[WIN32_FIND_DATAW]): ...
class PWORD(_Pointer[WORD]): ...
class LPWORD(_Pointer[WORD]): ...
LPWIN32_FIND_DATAW = PWIN32_FIND_DATAW