> ## Documentation Index
> Fetch the complete documentation index at: https://docs.arkffi.hmbill.cn/llms.txt
> Use this file to discover all available pages before exploring further.

# Struct

> 在 ArkTS 中定义和操作 C 结构体

`Struct` 定义 C 结构体的内存布局，支持序列化/反序列化，可与 `ffi.ptr` 配合传递给 C 函数。

## 示例

```typescript theme={null}
import { Struct, FFIType, ffi } from 'arkffi';

const Point = Struct({
  x: FFIType.int32,
  y: FFIType.int32,
});

const buf = Point.create({ x: 10, y: 20 });
const ptr = ffi.ptr(buf);

const read = Point.fromPtr(somePtr);
console.log(read.x, read.y);
```

## Struct()

```typescript theme={null}
function Struct(fields: Record<string, string | StructSchema>): StructSchema;
```

| 参数       | 类型                                       | 说明               |
| -------- | ---------------------------------------- | ---------------- |
| `fields` | `Record<string, string \| StructSchema>` | 字段名到类型编码的映射，支持嵌套 |

## StructSchema

### `size`

```typescript theme={null}
readonly size: number;
```

结构体总大小（字节），包含对齐填充。

### `create()`

```typescript theme={null}
create(obj: Record<string, number | bigint | ArrayBuffer>): ArrayBuffer;
```

将对象序列化为 `ArrayBuffer`。嵌套结构体字段传入其 `create()` 返回的 `ArrayBuffer`。

### `fromPtr()`

```typescript theme={null}
fromPtr(ptr: number, byteOffset?: number): Record<string, number>;
```

从原始指针读取结构体数据。**基本类型字段返回数值，嵌套结构体字段返回指针**（该子结构体在内存中的起始地址），需通过子结构体的 `fromPtr` 进一步读取。

### `get()` / `set()`

```typescript theme={null}
get(buf: ArrayBuffer, field: string): number;
set(buf: ArrayBuffer, field: string, value: number): void;
```

`get` 和 `set` 仅支持基本类型字段，嵌套结构体字段返回 `0` / 不操作。

## 嵌套结构体

字段值可以是另一个 `StructSchema`，递归计算布局。

```typescript theme={null}
// C: struct Inner { double x, y; };
// C: struct Outer { struct Inner pos; const char* name; };
const Inner = Struct({
  x: FFIType.double,
  y: FFIType.double,
});
const Outer = Struct({
  pos: Inner,            // 嵌套结构体
  name: FFIType.ptr,     // const char*
});

// 创建
let buf = Outer.create({
  pos: Inner.create({ x: 1.0, y: 2.0 }),
  name: 0x1234,
});

// 读取
let r = Outer.fromPtr(ptr);
// r.pos → 指向 Inner 数据的指针
let innerR = Inner.fromPtr(r.pos);
console.log(innerR.x, innerR.y); // 1.0, 2.0
```

## 与 `dlopen` 配合（HFA 结构体传参）

对于在寄存器中传递的小型 HFA 结构体，可直接将 `StructSchema` 用作 `dlopen` 的 `args` / `returns`：

```typescript theme={null}
// C: complex_t complex_add(complex_t a, complex_t b);
const Complex = Struct({ real: FFIType.double, imag: FFIType.double });
const lib = dlopen(LIB_NAME, {
  complex_add: { args: [Complex, Complex], returns: Complex },
});

let a = Complex.create({ real: 1, imag: 2 });
let b = Complex.create({ real: 3, imag: 4 });
let ptr: number = lib.symbols.complex_add(a, b);
let result = Complex.fromPtr(ptr); // { real: 4, imag: 6 }
```

结构体作为参数时自动展开为字段值传入寄存器；作为返回值时自动分配 buffer，返回 buffer 的指针。该指针在本次调用后有效，通过 `fromPtr` 同步读取。

## ARM64 对齐规则

| 类型编码      | C 类型                   | 大小 | 对齐 |
| --------- | ---------------------- | -- | -- |
| `c`       | `char` / `int8_t`      | 1  | 1  |
| `i`       | `int32_t` / `int`      | 4  | 4  |
| `l`       | `int64_t` / `uint64_t` | 8  | 8  |
| `d`       | `double`               | 8  | 8  |
| `f`       | `float`                | 4  | 4  |
| `b`       | `bool`                 | 1  | 1  |
| `s`       | `const char*`（指针）      | 8  | 8  |
| `p` / `k` | `void*` / 函数指针         | 8  | 8  |

嵌套结构体的对齐取其所有子字段对齐的最大值。

```typescript theme={null}
const Mixed = Struct({
  a: FFIType.int8_t,     // offset 0, size 1
  b: FFIType.int32,       // offset 4 (3 byte padding), size 4
  c: FFIType.int8_t,      // offset 8, size 1
});                        // total 12 bytes (3 byte final padding)

const buf = Mixed.create({ a: 1, b: 2, c: 3 });
```

## 与 C 函数配合

```typescript theme={null}
// C: void setPoint(struct Point* p, int x, int y)

const Point = Struct({ x: 'i', y: 'i' });
const lib = dlopen('lib.so', {
  setPoint: { args: [FFIType.ptr, FFIType.int32, FFIType.int32], returns: 'i' },
});

const buf = Point.create({ x: 0, y: 0 });
lib.symbols.setPoint(ffi.ptr(buf), 42, 99);

const result = Point.fromPtr(ffi.ptr(buf));
console.log(result.x, result.y);
```
