0
# Type System
1
2
C type introspection and manipulation operations. The type system provides complete information about C types, sizes, alignment, and structure layouts.
3
4
## Capabilities
5
6
### Type Information
7
8
Gets type information for C declarations and data objects.
9
10
```python { .api }
11
def typeof(self, cdecl):
12
"""
13
Get the C type of a declaration or data object.
14
15
Parameters:
16
- cdecl (str|CData): C type string or existing CData object
17
18
Returns:
19
CType object representing the C type
20
"""
21
```
22
23
**Usage Examples:**
24
25
```python
26
# Get type from string declaration
27
int_type = ffi.typeof("int")
28
ptr_type = ffi.typeof("int *")
29
array_type = ffi.typeof("int[10]")
30
31
# Get type from existing data
32
data = ffi.new("int *", 42)
33
data_type = ffi.typeof(data) # Returns pointer type
34
35
# Function types
36
ffi.cdef("int add(int a, int b);")
37
func_type = ffi.typeof("int(*)(int, int)")
38
39
# Structure types
40
ffi.cdef("struct point { int x, y; };")
41
struct_type = ffi.typeof("struct point")
42
```
43
44
### Size Information
45
46
Gets the size in bytes of C types or data objects.
47
48
```python { .api }
49
def sizeof(self, cdecl):
50
"""
51
Get size in bytes of C type or data object.
52
53
Parameters:
54
- cdecl (str|CData): C type string or CData object
55
56
Returns:
57
int: Size in bytes
58
"""
59
```
60
61
**Usage Examples:**
62
63
```python
64
# Basic type sizes
65
int_size = ffi.sizeof("int") # Usually 4
66
long_size = ffi.sizeof("long") # Platform dependent
67
ptr_size = ffi.sizeof("void *") # Usually 8 on 64-bit
68
69
# Array sizes
70
array_size = ffi.sizeof("int[10]") # 40 bytes (10 * 4)
71
72
# Structure sizes (including padding)
73
ffi.cdef("struct data { char a; int b; };")
74
struct_size = ffi.sizeof("struct data") # Usually 8 (due to alignment)
75
76
# Size of existing data
77
data = ffi.new("char[100]")
78
data_size = ffi.sizeof(data) # 100
79
```
80
81
### Alignment Information
82
83
Gets the natural alignment requirements for C types.
84
85
```python { .api }
86
def alignof(self, cdecl):
87
"""
88
Get natural alignment size in bytes of C type.
89
90
Parameters:
91
- cdecl (str|CType): C type string or CType object
92
93
Returns:
94
int: Alignment requirement in bytes
95
"""
96
```
97
98
**Usage Examples:**
99
100
```python
101
# Basic type alignments
102
char_align = ffi.alignof("char") # 1
103
int_align = ffi.alignof("int") # Usually 4
104
double_align = ffi.alignof("double") # Usually 8
105
ptr_align = ffi.alignof("void *") # Usually 8 on 64-bit
106
107
# Structure alignment
108
ffi.cdef("struct aligned { char a; double b; };")
109
struct_align = ffi.alignof("struct aligned") # Usually 8
110
```
111
112
### Field Offset Information
113
114
Gets the byte offset of fields within structures or arrays.
115
116
```python { .api }
117
def offsetof(self, cdecl, *fields_or_indexes):
118
"""
119
Get byte offset of field within structure or array element.
120
121
Parameters:
122
- cdecl (str): C type string for structure or array
123
- *fields_or_indexes: Field names or array indexes
124
125
Returns:
126
int: Byte offset from start of structure/array
127
"""
128
```
129
130
**Usage Examples:**
131
132
```python
133
# Structure field offsets
134
ffi.cdef("""
135
struct person {
136
char name[32];
137
int age;
138
double salary;
139
};
140
""")
141
142
name_offset = ffi.offsetof("struct person", "name") # 0
143
age_offset = ffi.offsetof("struct person", "age") # 32
144
salary_offset = ffi.offsetof("struct person", "salary") # 36 (or 40 with padding)
145
146
# Array element offsets
147
element_offset = ffi.offsetof("int[10]", 5) # 20 (5 * 4)
148
149
# Nested structure offsets
150
ffi.cdef("""
151
struct inner { int x, y; };
152
struct outer { char flag; struct inner data[3]; };
153
""")
154
155
nested_offset = ffi.offsetof("struct outer", "data", 1, "y")
156
```
157
158
### Type String Generation
159
160
Generates C type strings from type objects with optional formatting.
161
162
```python { .api }
163
def getctype(self, cdecl, replace_with=''):
164
"""
165
Get C type string representation.
166
167
Parameters:
168
- cdecl (str|CType): C type string or CType object
169
- replace_with (str): Text to insert/append (e.g., variable name)
170
171
Returns:
172
str: C type string representation
173
"""
174
```
175
176
**Usage Examples:**
177
178
```python
179
# Basic type strings
180
int_str = ffi.getctype("int") # "int"
181
ptr_str = ffi.getctype("int *") # "int *"
182
183
# With variable names
184
var_decl = ffi.getctype("int", "my_var") # "int my_var"
185
ptr_decl = ffi.getctype("int *", "my_ptr") # "int * my_ptr"
186
187
# Array declarations
188
array_decl = ffi.getctype("int", "[10]") # "int[10]"
189
190
# Function pointer declarations
191
func_decl = ffi.getctype("int(*)(int, int)", "add_func") # "int(*add_func)(int, int)"
192
```
193
194
### Type Enumeration
195
196
Lists all user-defined types known to the FFI instance.
197
198
```python { .api }
199
def list_types(self):
200
"""
201
Get all user-defined type names.
202
203
Returns:
204
tuple: (typedef_names, struct_names, union_names)
205
"""
206
```
207
208
**Usage Example:**
209
210
```python
211
ffi.cdef("""
212
typedef int my_int_t;
213
typedef char* string_t;
214
215
struct point { int x, y; };
216
struct rect { struct point top_left, bottom_right; };
217
218
union value { int i; float f; char c; };
219
""")
220
221
typedefs, structs, unions = ffi.list_types()
222
print("Typedefs:", typedefs) # ['my_int_t', 'string_t']
223
print("Structs:", structs) # ['point', 'rect']
224
print("Unions:", unions) # ['value']
225
```
226
227
## Type Introspection Patterns
228
229
### Runtime Type Checking
230
231
```python
232
def process_data(data):
233
data_type = ffi.typeof(data)
234
235
if data_type.kind == "pointer":
236
print(f"Pointer to {data_type.item}")
237
if data_type.item.cname == "int":
238
print("Integer pointer")
239
elif data_type.kind == "array":
240
print(f"Array of {data_type.item} with length {data_type.length}")
241
```
242
243
### Structure Layout Analysis
244
245
```python
246
def analyze_struct(struct_name):
247
struct_type = ffi.typeof(struct_name)
248
struct_size = ffi.sizeof(struct_type)
249
250
print(f"Structure: {struct_name}")
251
print(f"Total size: {struct_size} bytes")
252
253
# Analyze fields (requires accessing internal structure)
254
for field_name in struct_type.fields:
255
offset = ffi.offsetof(struct_name, field_name)
256
field_type = ffi.typeof(f"{struct_name}.{field_name}")
257
field_size = ffi.sizeof(field_type)
258
259
print(f" {field_name}: offset {offset}, size {field_size}")
260
```
261
262
### Memory Layout Calculation
263
264
```python
265
def calculate_padding(struct_name):
266
struct_size = ffi.sizeof(struct_name)
267
268
# Calculate sum of field sizes
269
field_total = 0
270
for field_name in ["field1", "field2", "field3"]: # Known fields
271
try:
272
field_size = ffi.sizeof(ffi.typeof(f"{struct_name}.{field_name}"))
273
field_total += field_size
274
except:
275
break
276
277
padding = struct_size - field_total
278
print(f"Total padding: {padding} bytes")
279
```
280
281
### Type Compatibility Checking
282
283
```python
284
def are_compatible(type1, type2):
285
"""Check if two types are assignment compatible"""
286
t1 = ffi.typeof(type1)
287
t2 = ffi.typeof(type2)
288
289
# Same type
290
if t1 == t2:
291
return True
292
293
# Pointer compatibility
294
if t1.kind == "pointer" and t2.kind == "pointer":
295
return t1.item == t2.item or t1.item.cname == "char" or t2.item.cname == "char"
296
297
# Integer type compatibility
298
if t1.kind == "primitive" and t2.kind == "primitive":
299
return t1.cname in ["int", "long", "short"] and t2.cname in ["int", "long", "short"]
300
301
return False
302
```
303
304
## Platform-Specific Considerations
305
306
### Size Variations
307
308
```python
309
# Check platform-specific sizes
310
import platform
311
312
print(f"Platform: {platform.machine()}")
313
print(f"Pointer size: {ffi.sizeof('void *')} bytes")
314
print(f"Long size: {ffi.sizeof('long')} bytes")
315
print(f"Size_t size: {ffi.sizeof('size_t')} bytes")
316
317
# Adjust algorithms based on sizes
318
if ffi.sizeof("void *") == 8:
319
print("64-bit platform")
320
else:
321
print("32-bit platform")
322
```
323
324
### Alignment Considerations
325
326
```python
327
def check_alignment(type_name):
328
size = ffi.sizeof(type_name)
329
alignment = ffi.alignof(type_name)
330
331
print(f"{type_name}: size={size}, alignment={alignment}")
332
333
if size % alignment != 0:
334
print(f"Warning: {type_name} size not aligned!")
335
```