Files
TransPyC/wiki/05-classes.md
2026-06-16 16:09:42 +08:00

191 lines
3.6 KiB
Markdown
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
# 05 - 类与数据布局
Viper 中的 `class` 有两种用途:定义**数据布局**(结构体/联合体/枚举,本章内容),以及定义**面向对象的对象类型**(见 [06-oop.md](06-oop.md))。
## 结构体定义
普通 `class` 定义编译为 LLVM 结构体类型:
```python
class point:
x: t.CInt
y: t.CInt
```
在 C 中:
```c
struct point {
int x;
int y;
};
```
在 LLVM IR 中:
```llvm
%"<SHA1>.point" = type { i32, i32 }
```
### 带属性的结构体
```python
@c.Attribute(t.attr.packed)
class idt_entry:
base_low: t.CUInt16T
selector: t.CUInt16T
ist_attr: t.CUInt8T
type_attr: t.CUInt8T
base_middle: t.CUInt16T
base_high: t.CUInt32T
reserved1: t.CUInt32T
```
### 结构体数组
```python
idt: list[idt_entry, 256] = []
```
### 结构体指针成员
```python
class node:
value: t.CInt
next: node | t.CPtr # 指向自身的指针(有向图链表)
```
### 结构体实例化与初始化
```python
entry: idt_entry = idt_entry()
```
或带构造函数:
```python
mousepoint = Point(x=1, y=2)
```
乱序传参或带参传参对于结构体的初始化同样有效:
```python
entry: idt_entry = idt_entry(selector=0x08, base_low=0x0000)
```
也可以给结构体成员指定默认值:
```python
class config:
width: t.CInt = 640
height: t.CInt = 480
depth: t.CInt = 32
```
使用 `c.Addr` 获取实例指针:
```python
obj_ptr: MyClass | t.CPtr = c.Addr(MyClass(arg1, arg2))
```
### 匿名结构体成员(❌)
> WARNING: **警告:** 由于 Viper 在声明结构体,枚举等处不需要关键字,因此 `t.Anonymouse` 是不需要使用的。此关键字不再维护,强行使用可能导致未定义行为。
继承 `t.Anonymous` 的类作为匿名成员嵌入:
```python
class header(t.Anonymous):
magic: t.CUInt32T
version: t.CUInt32T
class packet:
header # 匿名嵌入,可直接访问 packet.magic
length: t.CUInt32T
```
### 字节序标记
> WARNING: **警告:** 此关键字是实验性的。未经充分测试,不当使用可能导致未定义行为。
使用 `t.BigEndian``t.LittleEndian` 标记成员的字节序:
```python
class network_packet:
length: t.CUInt16T | t.BigEndian # 大端序存储
type: t.CUInt8T # 默认小端序
```
## 联合体
继承 `t.CUnion` 定义联合体:
```python
class value(t.CUnion):
ival: t.CInt
fval: t.CFloat
pval: t.CVoid | t.CPtr
```
等价 C 代码:
```c
union value {
int ival;
float fval;
void* pval;
};
```
## 枚举
继承 `t.CEnum` 定义枚举:
```python
class color(t.CEnum):
RED: t.CEnum = 0
GREEN: t.CEnum = 1
BLUE: t.CEnum = 2
```
等价 C 代码:
```c
enum color {
RED = 0,
GREEN = 1,
BLUE = 2
};
```
枚举成员可直接使用名称:
```python
c: t.CInt = color.RED
```
## Typedef
使用 `t.CTypedef` 创建类型别名:
```python
irq_handler_t: t.CTypedef | t.Callable[[], t.CInt] # typedef int (*irq_handler_t)();
```
或通过注解赋值:
```python
MyStruct: t.CTypedef = original_struct # typedef struct original_struct MyStruct;
```
更推荐通过后者的形式,前者编译器不一定能够识别到注解是对 `t.CTypedef` 的,还是后面的注解的,而且容易触发未定义行为。
## 位域
使用 `t.Bit(n)` 定义位域成员:
```python
class flags:
a: t.CUInt32T | t.Bit[1]
b: t.CUInt32T | t.Bit[3]
c: t.CUInt32T | t.Bit[4]
```
注意:如果存入超出位域宽度的值,会被截断。例如 `a` 为 1 位,存入 2二进制 `10`)会被截断为 0。