1# Stubs for ctypes
2
3from array import array
4from typing import (
5    Any, Callable, ClassVar, Iterator, Iterable, List, Mapping, Optional, Sequence, Sized, Text,
6    Tuple, Type, Generic, TypeVar, overload,
7)
8from typing import Union as _UnionT
9import sys
10
11_T = TypeVar('_T')
12_DLLT = TypeVar('_DLLT', bound=CDLL)
13_CT = TypeVar('_CT', bound=_CData)
14
15
16RTLD_GLOBAL: int = ...
17RTLD_LOCAL: int = ...
18DEFAULT_MODE: int = ...
19
20
21class CDLL(object):
22    _func_flags_: ClassVar[int] = ...
23    _func_restype_: ClassVar[_CData] = ...
24    _name: str = ...
25    _handle: int = ...
26    _FuncPtr: Type[_FuncPointer] = ...
27    def __init__(
28        self,
29        name: Optional[str],
30        mode: int = ...,
31        handle: Optional[int] = ...,
32        use_errno: bool = ...,
33        use_last_error: bool = ...,
34        winmode: Optional[int] = ...,
35    ) -> None: ...
36    def __getattr__(self, name: str) -> _FuncPointer: ...
37    def __getitem__(self, name: str) -> _FuncPointer: ...
38if sys.platform == 'win32':
39    class OleDLL(CDLL): ...
40    class WinDLL(CDLL): ...
41class PyDLL(CDLL): ...
42
43class LibraryLoader(Generic[_DLLT]):
44    def __init__(self, dlltype: Type[_DLLT]) -> None: ...
45    def __getattr__(self, name: str) -> _DLLT: ...
46    def __getitem__(self, name: str) -> _DLLT: ...
47    def LoadLibrary(self, name: str) -> _DLLT: ...
48
49cdll: LibraryLoader[CDLL] = ...
50if sys.platform == 'win32':
51    windll: LibraryLoader[WinDLL] = ...
52    oledll: LibraryLoader[OleDLL] = ...
53pydll: LibraryLoader[PyDLL] = ...
54pythonapi: PyDLL = ...
55
56# Anything that implements the read-write buffer interface.
57# The buffer interface is defined purely on the C level, so we cannot define a normal Protocol
58# for it. Instead we have to list the most common stdlib buffer classes in a Union.
59_WritableBuffer = _UnionT[bytearray, memoryview, array, _CData]
60# Same as _WritableBuffer, but also includes read-only buffer types (like bytes).
61_ReadOnlyBuffer = _UnionT[_WritableBuffer, bytes]
62
63class _CDataMeta(type):
64    # By default mypy complains about the following two methods, because strictly speaking cls
65    # might not be a Type[_CT]. However this can never actually happen, because the only class that
66    # uses _CDataMeta as its metaclass is _CData. So it's safe to ignore the errors here.
67    def __mul__(cls: Type[_CT], other: int) -> Type[Array[_CT]]: ...  # type: ignore
68    def __rmul__(cls: Type[_CT], other: int) -> Type[Array[_CT]]: ...  # type: ignore
69class _CData(metaclass=_CDataMeta):
70    _b_base: int = ...
71    _b_needsfree_: bool = ...
72    _objects: Optional[Mapping[Any, int]] = ...
73    @classmethod
74    def from_buffer(cls: Type[_CT], source: _WritableBuffer, offset: int = ...) -> _CT: ...
75    @classmethod
76    def from_buffer_copy(cls: Type[_CT], source: _ReadOnlyBuffer, offset: int = ...) -> _CT: ...
77    @classmethod
78    def from_address(cls: Type[_CT], address: int) -> _CT: ...
79    @classmethod
80    def from_param(cls: Type[_CT], obj: Any) -> _UnionT[_CT, _CArgObject]: ...
81    @classmethod
82    def in_dll(cls: Type[_CT], library: CDLL, name: str) -> _CT: ...
83
84class _PointerLike(_CData): ...
85
86_ECT = Callable[[Optional[Type[_CData]],
87                 _FuncPointer,
88                 Tuple[_CData, ...]],
89                _CData]
90_PF = _UnionT[
91    Tuple[int],
92    Tuple[int, str],
93    Tuple[int, str, Any]
94]
95class _FuncPointer(_PointerLike, _CData):
96    restype: _UnionT[Type[_CData], Callable[[int], None], None] = ...
97    argtypes: Sequence[Type[_CData]] = ...
98    errcheck: _ECT = ...
99    @overload
100    def __init__(self, address: int) -> None: ...
101    @overload
102    def __init__(self, callable: Callable[..., Any]) -> None: ...
103    @overload
104    def __init__(self, func_spec: Tuple[_UnionT[str, int], CDLL],
105                 paramflags: Tuple[_PF, ...] = ...) -> None: ...
106    @overload
107    def __init__(self, vtlb_index: int, name: str,
108                 paramflags: Tuple[_PF, ...] = ...,
109                 iid: pointer[c_int] = ...) -> None: ...
110    def __call__(self, *args: Any, **kwargs: Any) -> Any: ...
111
112class ArgumentError(Exception): ...
113
114
115def CFUNCTYPE(restype: Optional[Type[_CData]],
116              *argtypes: Type[_CData],
117              use_errno: bool = ...,
118              use_last_error: bool = ...) -> Type[_FuncPointer]: ...
119if sys.platform == 'win32':
120    def WINFUNCTYPE(restype: Optional[Type[_CData]],
121                    *argtypes: Type[_CData],
122                    use_errno: bool = ...,
123                    use_last_error: bool = ...) -> Type[_FuncPointer]: ...
124def PYFUNCTYPE(restype: Optional[Type[_CData]],
125               *argtypes: Type[_CData]) -> Type[_FuncPointer]: ...
126
127class _CArgObject: ...
128
129# Any type that can be implicitly converted to c_void_p when passed as a C function argument.
130# (bytes is not included here, see below.)
131_CVoidPLike = _UnionT[_PointerLike, Array[Any], _CArgObject, int]
132# Same as above, but including types known to be read-only (i. e. bytes).
133# This distinction is not strictly necessary (ctypes doesn't differentiate between const
134# and non-const pointers), but it catches errors like memmove(b'foo', buf, 4)
135# when memmove(buf, b'foo', 4) was intended.
136_CVoidConstPLike = _UnionT[_CVoidPLike, bytes]
137
138def addressof(obj: _CData) -> int: ...
139def alignment(obj_or_type: _UnionT[_CData, Type[_CData]]) -> int: ...
140def byref(obj: _CData, offset: int = ...) -> _CArgObject: ...
141_PT = TypeVar('_PT', bound=_PointerLike)
142def cast(obj: _UnionT[_CData, _CArgObject], type: Type[_PT]) -> _PT: ...
143def create_string_buffer(init_or_size: _UnionT[int, bytes],
144                         size: Optional[int] = ...) -> Array[c_char]: ...
145c_buffer = create_string_buffer
146def create_unicode_buffer(init_or_size: _UnionT[int, Text],
147                          size: Optional[int] = ...) -> Array[c_wchar]: ...
148if sys.platform == 'win32':
149    def DllCanUnloadNow() -> int: ...
150    def DllGetClassObject(rclsid: Any, riid: Any, ppv: Any) -> int: ...  # TODO not documented
151    def FormatError(code: int) -> str: ...
152    def GetLastError() -> int: ...
153def get_errno() -> int: ...
154if sys.platform == 'win32':
155    def get_last_error() -> int: ...
156def memmove(dst: _CVoidPLike, src: _CVoidConstPLike, count: int) -> None: ...
157def memset(dst: _CVoidPLike, c: int, count: int) -> None: ...
158def POINTER(type: Type[_CT]) -> Type[pointer[_CT]]: ...
159
160# The real ctypes.pointer is a function, not a class. The stub version of pointer behaves like
161# ctypes._Pointer in that it is the base class for all pointer types. Unlike the real _Pointer,
162# it can be instantiated directly (to mimic the behavior of the real pointer function).
163class pointer(Generic[_CT], _PointerLike, _CData):
164    _type_: ClassVar[Type[_CT]] = ...
165    contents: _CT = ...
166    def __init__(self, arg: _CT = ...) -> None: ...
167    @overload
168    def __getitem__(self, i: int) -> _CT: ...
169    @overload
170    def __getitem__(self, s: slice) -> List[_CT]: ...
171    @overload
172    def __setitem__(self, i: int, o: _CT) -> None: ...
173    @overload
174    def __setitem__(self, s: slice, o: Iterable[_CT]) -> None: ...
175
176def resize(obj: _CData, size: int) -> None: ...
177if sys.version_info < (3,):
178    def set_conversion_mode(encoding: str, errors: str) -> Tuple[str, str]: ...
179def set_errno(value: int) -> int: ...
180if sys.platform == 'win32':
181    def set_last_error(value: int) -> int: ...
182def sizeof(obj_or_type: _UnionT[_CData, Type[_CData]]) -> int: ...
183def string_at(address: _CVoidConstPLike, size: int = ...) -> bytes: ...
184if sys.platform == 'win32':
185    def WinError(code: Optional[int] = ...,
186                 descr: Optional[str] = ...) -> OSError: ...
187def wstring_at(address: _CVoidConstPLike, size: int = ...) -> str: ...
188
189class _SimpleCData(Generic[_T], _CData):
190    value: _T = ...
191    def __init__(self, value: _T = ...) -> None: ...
192
193class c_byte(_SimpleCData[int]): ...
194
195class c_char(_SimpleCData[bytes]):
196    def __init__(self, value: _UnionT[int, bytes] = ...) -> None: ...
197class c_char_p(_PointerLike, _SimpleCData[Optional[bytes]]):
198    def __init__(self, value: Optional[_UnionT[int, bytes]] = ...) -> None: ...
199
200class c_double(_SimpleCData[float]): ...
201class c_longdouble(_SimpleCData[float]): ...
202class c_float(_SimpleCData[float]): ...
203
204class c_int(_SimpleCData[int]): ...
205class c_int8(_SimpleCData[int]): ...
206class c_int16(_SimpleCData[int]): ...
207class c_int32(_SimpleCData[int]): ...
208class c_int64(_SimpleCData[int]): ...
209
210class c_long(_SimpleCData[int]): ...
211class c_longlong(_SimpleCData[int]): ...
212
213class c_short(_SimpleCData[int]): ...
214
215class c_size_t(_SimpleCData[int]): ...
216class c_ssize_t(_SimpleCData[int]): ...
217
218class c_ubyte(_SimpleCData[int]): ...
219
220class c_uint(_SimpleCData[int]): ...
221class c_uint8(_SimpleCData[int]): ...
222class c_uint16(_SimpleCData[int]): ...
223class c_uint32(_SimpleCData[int]): ...
224class c_uint64(_SimpleCData[int]): ...
225
226class c_ulong(_SimpleCData[int]): ...
227class c_ulonglong(_SimpleCData[int]): ...
228
229class c_ushort(_SimpleCData[int]): ...
230
231class c_void_p(_PointerLike, _SimpleCData[Optional[int]]): ...
232
233class c_wchar(_SimpleCData[Text]): ...
234class c_wchar_p(_PointerLike, _SimpleCData[Optional[Text]]):
235    def __init__(self, value: Optional[_UnionT[int, Text]] = ...) -> None: ...
236
237class c_bool(_SimpleCData[bool]):
238    def __init__(self, value: bool = ...) -> None: ...
239
240if sys.platform == 'win32':
241    class HRESULT(_SimpleCData[int]): ...  # TODO undocumented
242
243class py_object(_SimpleCData[_T]): ...
244
245class _CField:
246    offset: int = ...
247    size: int = ...
248class _StructUnionMeta(_CDataMeta):
249    _fields_: Sequence[_UnionT[Tuple[str, Type[_CData]], Tuple[str, Type[_CData], int]]] = ...
250    _pack_: int = ...
251    _anonymous_: Sequence[str] = ...
252    def __getattr__(self, name: str) -> _CField: ...
253class _StructUnionBase(_CData, metaclass=_StructUnionMeta):
254    def __init__(self, *args: Any, **kw: Any) -> None: ...
255    def __getattr__(self, name: str) -> Any: ...
256    def __setattr__(self, name: str, value: Any) -> None: ...
257
258class Union(_StructUnionBase): ...
259class Structure(_StructUnionBase): ...
260class BigEndianStructure(Structure): ...
261class LittleEndianStructure(Structure): ...
262
263class Array(Generic[_CT], _CData):
264    _length_: ClassVar[int] = ...
265    _type_: ClassVar[Type[_CT]] = ...
266    raw: bytes = ...  # Note: only available if _CT == c_char
267    value: Any = ...  # Note: bytes if _CT == c_char, Text if _CT == c_wchar, unavailable otherwise
268    # TODO These methods cannot be annotated correctly at the moment.
269    # All of these "Any"s stand for the array's element type, but it's not possible to use _CT
270    # here, because of a special feature of ctypes.
271    # By default, when accessing an element of an Array[_CT], the returned object has type _CT.
272    # However, when _CT is a "simple type" like c_int, ctypes automatically "unboxes" the object
273    # and converts it to the corresponding Python primitive. For example, when accessing an element
274    # of an Array[c_int], a Python int object is returned, not a c_int.
275    # This behavior does *not* apply to subclasses of "simple types".
276    # If MyInt is a subclass of c_int, then accessing an element of an Array[MyInt] returns
277    # a MyInt, not an int.
278    # This special behavior is not easy to model in a stub, so for now all places where
279    # the array element type would belong are annotated with Any instead.
280    def __init__(self, *args: Any) -> None: ...
281    @overload
282    def __getitem__(self, i: int) -> Any: ...
283    @overload
284    def __getitem__(self, s: slice) -> List[Any]: ...
285    @overload
286    def __setitem__(self, i: int, o: Any) -> None: ...
287    @overload
288    def __setitem__(self, s: slice, o: Iterable[Any]) -> None: ...
289    def __iter__(self) -> Iterator[Any]: ...
290    # Can't inherit from Sized because the metaclass conflict between
291    # Sized and _CData prevents using _CDataMeta.
292    def __len__(self) -> int: ...
293