cbridge 0.1.0__tar.gz

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
cbridge-0.1.0/PKG-INFO ADDED
@@ -0,0 +1,205 @@
1
+ Metadata-Version: 2.4
2
+ Name: cbridge
3
+ Version: 0.1.0
4
+ Summary: Creating ctype structure like dataclass
5
+ Author: ZhengYu, Xu
6
+ Author-email: ZhengYu, Xu <zen-xu@outlook.com>
7
+ License-Expression: MIT
8
+ Classifier: License :: OSI Approved :: MIT License
9
+ Classifier: Programming Language :: Python
10
+ Classifier: Programming Language :: Python :: 3
11
+ Classifier: Programming Language :: Python :: 3 :: Only
12
+ Classifier: Programming Language :: Python :: 3.9
13
+ Classifier: Programming Language :: Python :: 3.10
14
+ Classifier: Programming Language :: Python :: 3.11
15
+ Classifier: Programming Language :: Python :: 3.12
16
+ Classifier: Programming Language :: Python :: 3.13
17
+ Requires-Dist: typing-extensions ; python_full_version < '3.12'
18
+ Requires-Python: >=3.9
19
+ Project-URL: homepage, https://github.com/zen-xu/cbridge
20
+ Project-URL: issues, https://github.com/zen-xu/cbridge/issues
21
+ Project-URL: repository, https://github.com/zen-xu/cbridge.git
22
+ Description-Content-Type: text/markdown
23
+
24
+ # cbridge
25
+
26
+ [![uv](https://img.shields.io/endpoint?url=https://raw.githubusercontent.com/astral-sh/uv/main/assets/badge/v0.json)](https://github.com/astral-sh/uv)
27
+ [![ruff](https://img.shields.io/endpoint?url=https://raw.githubusercontent.com/astral-sh/ruff/main/assets/badge/v2.json)](https://github.com/astral-sh/ruff)
28
+ ![GitHub License](https://img.shields.io/github/license/zen-xu/cbridge)
29
+ ![PyPI - Version](https://img.shields.io/pypi/v/cbridge)
30
+ ![PyPI - Python Version](https://img.shields.io/pypi/pyversions/cbridge)
31
+ [![Tests](https://github.com/zen-xu/cbridge/actions/workflows/test.yaml/badge.svg)](https://github.com/zen-xu/cbridge/actions/workflows/test.yaml)
32
+ [![codecov](https://codecov.io/gh/zen-xu/cbridge/graph/badge.svg?token=6HeWXTrTvn)](https://codecov.io/gh/zen-xu/cbridge)
33
+
34
+ A Python library that provides a dataclass-like interface for creating ctypes structures, making it easier to work with C libraries and data structures in Python.
35
+
36
+ ## Features
37
+
38
+ - **Dataclass-like syntax**: Define C structures using familiar Python class syntax with type hints
39
+ - **Automatic field management**: Fields are automatically converted to ctypes types based on type annotations
40
+ - **Array support**: Built-in support for fixed-size arrays with proper type checking
41
+ - **Pointer support**: Easy handling of C pointers with type safety
42
+ - **Default values**: Support for default field values and factories
43
+ - **Inheritance**: Full support for class inheritance in C structures
44
+ - **Memory layout control**: Control structure packing and alignment
45
+ - **C function binding**: Decorator for easy binding to C library functions
46
+
47
+ ## Installation
48
+
49
+ ```bash
50
+ pip install cbridge
51
+ ```
52
+
53
+ ## Quick Start
54
+
55
+ ### Creating C Structures
56
+
57
+ ```python
58
+ from cbridge import CStruct
59
+ from cbridge import types
60
+
61
+ class Point(CStruct):
62
+ x: types.int32
63
+ y: types.int32
64
+
65
+ class Rectangle(CStruct):
66
+ top_left: Point
67
+ bottom_right: Point
68
+ color: types.uint32 = 0xFF0000 # Default value
69
+
70
+ # Create instances
71
+ point = Point(x=10, y=20)
72
+ rect = Rectangle(
73
+ top_left=Point(x=0, y=0),
74
+ bottom_right=Point(x=100, y=100)
75
+ )
76
+
77
+ print(rect) # Rectangle(top_left=Point(x=0, y=0), bottom_right=Point(x=100, y=100), color=16711680)
78
+ ```
79
+
80
+ ### Working with Arrays
81
+
82
+ ```python
83
+ from typing import Literal
84
+
85
+ from cbridge import CStruct
86
+ from cbridge import types
87
+
88
+
89
+ class Data(CStruct):
90
+ id: types.int32
91
+ values: types.Array[types.int8, Literal[4]] # Array of 4 int8 values
92
+ name: types.char_ptr
93
+
94
+
95
+ # Create with array data
96
+ data = Data(id=1, values=[1, 2, 3, 4], name=b"test")
97
+ print(data.values) # [1, 2, 3, 4]
98
+ ```
99
+
100
+ ### C Function Binding
101
+
102
+ ```python
103
+ from cbridge import cfunc
104
+ from cbridge import types
105
+
106
+ @cfunc("c") # Bind to libc
107
+ def time(t: types.Pointer[types.ctime_t]) -> types.ctime_t: ...
108
+
109
+ # Call the C function
110
+ current_time = time(None)
111
+ print(current_time)
112
+ ```
113
+
114
+ ### Memory Operations
115
+
116
+ ```python
117
+ import array
118
+
119
+ from cbridge import CStruct
120
+ from cbridge import types
121
+
122
+ class Point(CStruct):
123
+ x: types.int32
124
+ y: types.int32
125
+
126
+
127
+ # Create from buffer
128
+ buffer = array.array("B", b"\x01\x00\x00\x00\x02\x00\x00\x00")
129
+ point = Point.from_buffer(buffer)
130
+ print(point) # Point(x=1, y=2)
131
+ ```
132
+
133
+ ## Advanced Usage
134
+
135
+ ### Structure Packing
136
+
137
+ ```python
138
+ import ctypes
139
+
140
+ from cbridge import CStruct
141
+ from cbridge import types
142
+
143
+
144
+ class DefaultPackData(CStruct): # 1-byte alignment
145
+ a: types.char
146
+ b: types.int32
147
+
148
+
149
+ class Pack1Data(CStruct, pack=1): # 1-byte alignment
150
+ a: types.char
151
+ b: types.int32
152
+
153
+
154
+ print(ctypes.sizeof(DefaultPackData)) # 8 bytes
155
+ print(ctypes.sizeof(Pack1Data)) # 5 bytes
156
+
157
+ ```
158
+
159
+ ### Default Values and Factories
160
+
161
+ ```python
162
+ from typing import Literal
163
+
164
+ from cbridge import CStruct
165
+ from cbridge import field
166
+ from cbridge import types
167
+
168
+
169
+ class Config(CStruct):
170
+ name: types.char_ptr
171
+ timeout: types.int32 = 30
172
+ flags: types.Array[types.int32, Literal[2]] = field(default_factory=lambda: [0, 1])
173
+
174
+
175
+ print(Config(name=b"test")) # Config(name=b'test', timeout=30, flags=[0, 1])
176
+ ```
177
+
178
+ ### Pointer Operations
179
+
180
+ > [!WARNING]
181
+ > Python 3.13 and above are currently not supported forward declarations
182
+
183
+ ```python
184
+ from cbridge import CStruct
185
+ from cbridge import types
186
+ from cbridge.types import pointer
187
+
188
+
189
+ class Node(CStruct):
190
+ data: types.int32
191
+ next: "types.Pointer[Node]"
192
+
193
+
194
+ # Create linked list
195
+ node1 = Node(data=1, next=None)
196
+ node2 = Node(data=2, next=pointer(node1))
197
+ node1.next = pointer(node2)
198
+
199
+ node = node1
200
+ data = []
201
+ for _ in range(8):
202
+ data.append(node.data)
203
+ node = node.next[0] # same as *node.next
204
+ assert data == [1, 2, 1, 2, 1, 2, 1, 2]
205
+ ```
@@ -0,0 +1,182 @@
1
+ # cbridge
2
+
3
+ [![uv](https://img.shields.io/endpoint?url=https://raw.githubusercontent.com/astral-sh/uv/main/assets/badge/v0.json)](https://github.com/astral-sh/uv)
4
+ [![ruff](https://img.shields.io/endpoint?url=https://raw.githubusercontent.com/astral-sh/ruff/main/assets/badge/v2.json)](https://github.com/astral-sh/ruff)
5
+ ![GitHub License](https://img.shields.io/github/license/zen-xu/cbridge)
6
+ ![PyPI - Version](https://img.shields.io/pypi/v/cbridge)
7
+ ![PyPI - Python Version](https://img.shields.io/pypi/pyversions/cbridge)
8
+ [![Tests](https://github.com/zen-xu/cbridge/actions/workflows/test.yaml/badge.svg)](https://github.com/zen-xu/cbridge/actions/workflows/test.yaml)
9
+ [![codecov](https://codecov.io/gh/zen-xu/cbridge/graph/badge.svg?token=6HeWXTrTvn)](https://codecov.io/gh/zen-xu/cbridge)
10
+
11
+ A Python library that provides a dataclass-like interface for creating ctypes structures, making it easier to work with C libraries and data structures in Python.
12
+
13
+ ## Features
14
+
15
+ - **Dataclass-like syntax**: Define C structures using familiar Python class syntax with type hints
16
+ - **Automatic field management**: Fields are automatically converted to ctypes types based on type annotations
17
+ - **Array support**: Built-in support for fixed-size arrays with proper type checking
18
+ - **Pointer support**: Easy handling of C pointers with type safety
19
+ - **Default values**: Support for default field values and factories
20
+ - **Inheritance**: Full support for class inheritance in C structures
21
+ - **Memory layout control**: Control structure packing and alignment
22
+ - **C function binding**: Decorator for easy binding to C library functions
23
+
24
+ ## Installation
25
+
26
+ ```bash
27
+ pip install cbridge
28
+ ```
29
+
30
+ ## Quick Start
31
+
32
+ ### Creating C Structures
33
+
34
+ ```python
35
+ from cbridge import CStruct
36
+ from cbridge import types
37
+
38
+ class Point(CStruct):
39
+ x: types.int32
40
+ y: types.int32
41
+
42
+ class Rectangle(CStruct):
43
+ top_left: Point
44
+ bottom_right: Point
45
+ color: types.uint32 = 0xFF0000 # Default value
46
+
47
+ # Create instances
48
+ point = Point(x=10, y=20)
49
+ rect = Rectangle(
50
+ top_left=Point(x=0, y=0),
51
+ bottom_right=Point(x=100, y=100)
52
+ )
53
+
54
+ print(rect) # Rectangle(top_left=Point(x=0, y=0), bottom_right=Point(x=100, y=100), color=16711680)
55
+ ```
56
+
57
+ ### Working with Arrays
58
+
59
+ ```python
60
+ from typing import Literal
61
+
62
+ from cbridge import CStruct
63
+ from cbridge import types
64
+
65
+
66
+ class Data(CStruct):
67
+ id: types.int32
68
+ values: types.Array[types.int8, Literal[4]] # Array of 4 int8 values
69
+ name: types.char_ptr
70
+
71
+
72
+ # Create with array data
73
+ data = Data(id=1, values=[1, 2, 3, 4], name=b"test")
74
+ print(data.values) # [1, 2, 3, 4]
75
+ ```
76
+
77
+ ### C Function Binding
78
+
79
+ ```python
80
+ from cbridge import cfunc
81
+ from cbridge import types
82
+
83
+ @cfunc("c") # Bind to libc
84
+ def time(t: types.Pointer[types.ctime_t]) -> types.ctime_t: ...
85
+
86
+ # Call the C function
87
+ current_time = time(None)
88
+ print(current_time)
89
+ ```
90
+
91
+ ### Memory Operations
92
+
93
+ ```python
94
+ import array
95
+
96
+ from cbridge import CStruct
97
+ from cbridge import types
98
+
99
+ class Point(CStruct):
100
+ x: types.int32
101
+ y: types.int32
102
+
103
+
104
+ # Create from buffer
105
+ buffer = array.array("B", b"\x01\x00\x00\x00\x02\x00\x00\x00")
106
+ point = Point.from_buffer(buffer)
107
+ print(point) # Point(x=1, y=2)
108
+ ```
109
+
110
+ ## Advanced Usage
111
+
112
+ ### Structure Packing
113
+
114
+ ```python
115
+ import ctypes
116
+
117
+ from cbridge import CStruct
118
+ from cbridge import types
119
+
120
+
121
+ class DefaultPackData(CStruct): # 1-byte alignment
122
+ a: types.char
123
+ b: types.int32
124
+
125
+
126
+ class Pack1Data(CStruct, pack=1): # 1-byte alignment
127
+ a: types.char
128
+ b: types.int32
129
+
130
+
131
+ print(ctypes.sizeof(DefaultPackData)) # 8 bytes
132
+ print(ctypes.sizeof(Pack1Data)) # 5 bytes
133
+
134
+ ```
135
+
136
+ ### Default Values and Factories
137
+
138
+ ```python
139
+ from typing import Literal
140
+
141
+ from cbridge import CStruct
142
+ from cbridge import field
143
+ from cbridge import types
144
+
145
+
146
+ class Config(CStruct):
147
+ name: types.char_ptr
148
+ timeout: types.int32 = 30
149
+ flags: types.Array[types.int32, Literal[2]] = field(default_factory=lambda: [0, 1])
150
+
151
+
152
+ print(Config(name=b"test")) # Config(name=b'test', timeout=30, flags=[0, 1])
153
+ ```
154
+
155
+ ### Pointer Operations
156
+
157
+ > [!WARNING]
158
+ > Python 3.13 and above are currently not supported forward declarations
159
+
160
+ ```python
161
+ from cbridge import CStruct
162
+ from cbridge import types
163
+ from cbridge.types import pointer
164
+
165
+
166
+ class Node(CStruct):
167
+ data: types.int32
168
+ next: "types.Pointer[Node]"
169
+
170
+
171
+ # Create linked list
172
+ node1 = Node(data=1, next=None)
173
+ node2 = Node(data=2, next=pointer(node1))
174
+ node1.next = pointer(node2)
175
+
176
+ node = node1
177
+ data = []
178
+ for _ in range(8):
179
+ data.append(node.data)
180
+ node = node.next[0] # same as *node.next
181
+ assert data == [1, 2, 1, 2, 1, 2, 1, 2]
182
+ ```
@@ -0,0 +1,78 @@
1
+ [project]
2
+ name = "cbridge"
3
+ version = "0.1.0"
4
+ authors = [{ name = "ZhengYu, Xu", email = "zen-xu@outlook.com" }]
5
+ description = "Creating ctype structure like dataclass"
6
+ requires-python = ">=3.9"
7
+ readme = "README.md"
8
+ license = "MIT"
9
+ classifiers = [
10
+ "License :: OSI Approved :: MIT License",
11
+ "Programming Language :: Python",
12
+ "Programming Language :: Python :: 3",
13
+ "Programming Language :: Python :: 3 :: Only",
14
+ "Programming Language :: Python :: 3.9",
15
+ "Programming Language :: Python :: 3.10",
16
+ "Programming Language :: Python :: 3.11",
17
+ "Programming Language :: Python :: 3.12",
18
+ "Programming Language :: Python :: 3.13",
19
+ ]
20
+ dependencies = ["typing-extensions; python_version< '3.12'"]
21
+
22
+ [dependency-groups]
23
+ nox = ["nox", "nox-uv"]
24
+ test = ["pytest", "pytest-coverage"]
25
+
26
+ [project.urls]
27
+ homepage = "https://github.com/zen-xu/cbridge"
28
+ repository = "https://github.com/zen-xu/cbridge.git"
29
+ issues = "https://github.com/zen-xu/cbridge/issues"
30
+
31
+ [build-system]
32
+ requires = ["uv_build>=0.8,<0.9"]
33
+ build-backend = "uv_build"
34
+
35
+ [tool.ruff]
36
+ extend-exclude = ["docs/*"]
37
+ fix = true
38
+ line-length = 88
39
+ target-version = "py39"
40
+
41
+ [tool.ruff.lint]
42
+ extend-select = [
43
+ "B", # flake8-bugbear
44
+ "C4", # flake8-comprehensions
45
+ "ERA", # flake8-eradicate/eradicate
46
+ "I", # isort
47
+ "N", # pep8-naming
48
+ "PIE", # flake8-pie
49
+ "PGH", # pygrep
50
+ "RUF", # ruff checks
51
+ "SIM", # flake8-simplify
52
+ "TC", # flake8-type-checking
53
+ "TID", # flake8-tidy-imports
54
+ "UP", # pyupgrade
55
+ ]
56
+
57
+ [tool.ruff.lint.isort]
58
+ force-single-line = true
59
+ known-first-party = ["cbridge"]
60
+ lines-after-imports = 2
61
+ lines-between-types = 1
62
+
63
+ [tool.ruff.format]
64
+ docstring-code-format = true
65
+
66
+ [tool.mypy]
67
+ files = "src"
68
+ explicit_package_bases = true
69
+ namespace_packages = true
70
+ show_error_codes = true
71
+
72
+ [tool.coverage.run]
73
+ source = ["src/cbridge"]
74
+ branch = true
75
+ omit = ["src/cbridge/types.py"]
76
+
77
+ [tool.coverage.report]
78
+ exclude_lines = ["pragma: no cover", "if TYPE_CHECKING:"]
@@ -0,0 +1,12 @@
1
+ from __future__ import annotations
2
+
3
+ from .cbridge import CStruct
4
+ from .cbridge import field
5
+ from .cfunc import cfunc
6
+
7
+
8
+ __version__ = "0.1.0"
9
+ __authors__ = [
10
+ "ZhengYu, Xu <zen-xu@outlook.com>",
11
+ ]
12
+ __all__ = ["CStruct", "cfunc", "field"]
@@ -0,0 +1,112 @@
1
+ from __future__ import annotations
2
+
3
+ import ctypes
4
+ import dataclasses as ds
5
+ import sys
6
+
7
+ from functools import wraps
8
+ from typing import TYPE_CHECKING
9
+ from typing import Any
10
+ from typing import ClassVar
11
+ from typing import TypeVar
12
+ from typing import get_origin
13
+ from typing import get_type_hints
14
+
15
+
16
+ if sys.version_info >= (3, 12):
17
+ from typing import Self
18
+ from typing import dataclass_transform
19
+ else:
20
+ from typing_extensions import Self
21
+ from typing_extensions import dataclass_transform
22
+
23
+
24
+ _T = TypeVar("_T")
25
+
26
+ _CStructType: type = type(ctypes.Structure)
27
+
28
+
29
+ @dataclass_transform()
30
+ class CStructType(_CStructType):
31
+ def __new__(
32
+ meta_self, # type: ignore[misc]
33
+ name: str,
34
+ bases: tuple[type, ...],
35
+ attrs: dict[str, Any],
36
+ pack: int = 0,
37
+ **extra,
38
+ ):
39
+ if sys.version_info >= (3, 13):
40
+ attrs["_fields_"] = []
41
+ attrs["_pack_"] = pack
42
+ cls = super().__new__(meta_self, name, bases, attrs)
43
+ fields_map = {
44
+ f_name: f_type
45
+ for f_name, f_type in get_type_hints(
46
+ cls, localns={**locals(), name: cls}
47
+ ).items()
48
+ if get_origin(f_type) is not ClassVar
49
+ }
50
+ fields = list(fields_map.items())
51
+ if fields:
52
+ # update fields
53
+ if sys.version_info >= (3, 13):
54
+ cls._fields_[:] = fields
55
+ else:
56
+ cls._fields_ = fields
57
+
58
+ cls = ds.dataclass(cls)
59
+
60
+ @wraps(cls.__init__)
61
+ def wrapped_init(self, *args, **kwargs):
62
+ args = list(args)
63
+
64
+ for i, arg in enumerate(args):
65
+ field_name = fields[i][0]
66
+ kwargs[field_name] = arg
67
+
68
+ # fill default values
69
+ for field_name, _ in fields:
70
+ if field_name in kwargs:
71
+ continue
72
+
73
+ if field_option := attrs.get(field_name):
74
+ if isinstance(field_option, ds.Field):
75
+ if field_option.default is not ds.MISSING:
76
+ kwargs[field_name] = field_option.default
77
+ elif field_option.default_factory is not ds.MISSING:
78
+ kwargs[field_name] = field_option.default_factory()
79
+ else:
80
+ kwargs[field_name] = field_option
81
+
82
+ for arg_name, arg_value in kwargs.items():
83
+ field_type = fields_map[arg_name]
84
+ if issubclass(field_type, ctypes.Array):
85
+ kwargs[arg_name] = field_type(*arg_value)
86
+
87
+ return ctypes.Structure.__init__(self, **kwargs)
88
+
89
+ cls.__init__ = wrapped_init
90
+
91
+ return cls
92
+
93
+
94
+ field = ds.field
95
+
96
+ if TYPE_CHECKING:
97
+
98
+ @dataclass_transform(field_specifiers=(field,))
99
+ class CStruct(ctypes.Structure):
100
+ def __init_subclass__(cls, pack: int = 0) -> None: ...
101
+
102
+ @classmethod
103
+ def empty(cls) -> Self:
104
+ """Create an empty instance of the structure."""
105
+ ...
106
+
107
+ else:
108
+
109
+ class CStruct(ctypes.Structure, metaclass=CStructType):
110
+ @classmethod
111
+ def empty(cls) -> Self:
112
+ return cls()
@@ -0,0 +1,45 @@
1
+ from __future__ import annotations
2
+
3
+ import ctypes
4
+
5
+ from ctypes.util import find_library
6
+ from typing import Callable
7
+ from typing import TypeVar
8
+ from typing import get_type_hints
9
+
10
+
11
+ _F = TypeVar("_F", bound=Callable)
12
+
13
+
14
+ def cfunc(clib: str | ctypes.CDLL) -> Callable[[_F], _F]:
15
+ """
16
+ Decorator to bind a Python function signature to a C function from a shared library.
17
+
18
+ Args:
19
+ clib (str | ctypes.CDLL): The name of the C library (as a string) or a ctypes.CDLL instance.
20
+
21
+ Returns:
22
+ Callable[[_F], _F]: A decorator that replaces the Python function with the corresponding C function,
23
+ setting its argument and return types based on the Python type hints.
24
+
25
+ Examples:
26
+ >>> from cbridge import cfunc
27
+ >>> from cbridge import types
28
+ >>> from cbridge.types import pointer
29
+ >>> @cfunc("c")
30
+ ... def time(t: types.Pointer[types.ctime_t]) -> types.ctime_t: ...
31
+ >>> print(time(None))
32
+ >>> 1727433600
33
+ """
34
+ clib = ctypes.CDLL(find_library(clib)) if isinstance(clib, str) else clib
35
+
36
+ def wrapper(func: _F) -> _F:
37
+ hints = get_type_hints(func)
38
+ restype = hints.pop("return", None)
39
+ argtypes = list(hints.values())
40
+ cfunc = getattr(clib, func.__name__)
41
+ cfunc.restype = restype
42
+ cfunc.argtypes = tuple(argtypes)
43
+ return cfunc
44
+
45
+ return wrapper
File without changes
@@ -0,0 +1,134 @@
1
+ import ctypes
2
+
3
+ from collections.abc import Sequence
4
+ from typing import TYPE_CHECKING
5
+ from typing import Generic
6
+ from typing import TypeVar
7
+ from typing import overload
8
+
9
+
10
+ _T = TypeVar("_T")
11
+
12
+ if TYPE_CHECKING:
13
+ from _ctypes import _CData as CData
14
+ from typing import Any
15
+ from typing import Union
16
+
17
+ bool = Union[bool, CData]
18
+ byte = Union[bytes, CData]
19
+ char = Union[bytes, CData]
20
+ double = Union[float, CData]
21
+ float = Union[float, CData]
22
+ ubyte = Union[bytes, CData]
23
+ int = Union[int, CData]
24
+ int8 = Union[int, CData]
25
+ int16 = Union[int, CData]
26
+ int32 = Union[int, CData]
27
+ int64 = Union[int, CData]
28
+ long = Union[int, CData]
29
+ longdouble = Union[float, CData]
30
+ longlong = Union[float, CData]
31
+ short = Union[int, CData]
32
+ size_t = Union[int, CData]
33
+ ssize_t = Union[int, CData]
34
+ uint = Union[int, CData]
35
+ uint8 = Union[int, CData]
36
+ uint16 = Union[int, CData]
37
+ uint32 = Union[int, CData]
38
+ uint64 = Union[int, CData]
39
+ ulong = Union[int, CData]
40
+ ulonglong = Union[int, CData]
41
+ ushort = Union[int, CData]
42
+ wchar = Union[str, CData]
43
+ void_ptr = Union[ctypes.c_void_p, Any]
44
+
45
+ _Len = TypeVar("_Len")
46
+
47
+ class _Array(Generic[_T, _Len], ctypes.Array[_T]): ... # type: ignore[type-var]
48
+
49
+ Array = Union[_Array[_T, _Len], Sequence[_T]]
50
+
51
+ class _Pointer(ctypes._Pointer[_T]): # type: ignore[type-var]
52
+ @overload
53
+ def __getitem__(self, index: int) -> _T: ...
54
+ @overload
55
+ def __getitem__(self, index: slice) -> list[_T]: ...
56
+ def __getitem__(self, index: int | slice) -> _T | list[_T]: ...
57
+
58
+ Pointer = Union[_Pointer[_T], None]
59
+
60
+ char_ptr = Pointer[char] | bytes
61
+ wchar_ptr = Pointer[wchar] | str
62
+
63
+ def pointer(obj: _T) -> Pointer[_T]: ...
64
+ else:
65
+ CData = object
66
+ byte = ctypes.c_byte
67
+ bool = ctypes.c_bool
68
+ char = ctypes.c_char
69
+ double = ctypes.c_double
70
+ float = ctypes.c_float
71
+ ubyte = ctypes.c_ubyte
72
+ int = ctypes.c_int
73
+ int8 = ctypes.c_int8
74
+ int16 = ctypes.c_int16
75
+ int32 = ctypes.c_int32
76
+ int64 = ctypes.c_int64
77
+ long = ctypes.c_long
78
+ longdouble = ctypes.c_longdouble
79
+ longlong = ctypes.c_longlong
80
+ short = ctypes.c_short
81
+ size_t = ctypes.c_size_t
82
+ ssize_t = ctypes.c_ssize_t
83
+ uint = ctypes.c_uint
84
+ uint8 = ctypes.c_uint8
85
+ uint16 = ctypes.c_uint16
86
+ uint32 = ctypes.c_uint32
87
+ uint64 = ctypes.c_uint64
88
+ ulong = ctypes.c_ulong
89
+ ulonglong = ctypes.c_ulonglong
90
+ ushort = ctypes.c_ushort
91
+ wchar = ctypes.c_wchar
92
+ void_ptr = ctypes.c_void_p
93
+ char_ptr = ctypes.c_char_p
94
+ wchar_ptr = ctypes.c_wchar_p
95
+
96
+ import builtins
97
+
98
+ from typing import get_args
99
+
100
+ class Array:
101
+ def __class_getitem__(cls, types: tuple[type[CData], int]):
102
+ ctype, length = types
103
+ if not isinstance(length, builtins.int):
104
+ length = get_args(length)[0]
105
+
106
+ return type(f"Array_{ctype.__name__}_{length}", (ctype * length, cls), {})
107
+
108
+ def __repr__(self):
109
+ return str(list(self))
110
+
111
+ def __eq__(self, value: object, /) -> bool:
112
+ if not isinstance(value, Sequence):
113
+ return False
114
+ return list(self) == list(value)
115
+
116
+ class Pointer(ctypes._Pointer):
117
+ def __class_getitem__(cls, type):
118
+ cls = ctypes.POINTER(type)
119
+
120
+ def pointer_repr(self):
121
+ try:
122
+ _ = self.contents
123
+ except ValueError:
124
+ return "nullptr"
125
+ else:
126
+ return f"*{type.__name__}"
127
+
128
+ cls.__repr__ = pointer_repr
129
+
130
+ return cls
131
+
132
+ pointer = ctypes.pointer
133
+
134
+ ctime_t = ulong