Skip to content

Commit 45a3e7b

Browse files
committed
Introduce MappingConfig and mapping filters
Add a MappingConfig dataclass and wire language/type mapping through the generator and templates. Key changes: - config.py: introduce MappingConfig, parse mapping from YAML (_parse_mapping) and use it in BindgenConfig. - generator.py: accept MappingConfig, register new Jinja filters (map_type, map_type_name, format_type, is_pointer_type, is_array_type, is_void_type, get_inner_type, get_element_type) and implement _map_ir_type/map_type logic to map IR types to target language types (pointers, arrays, references, primitives, named types, function pointers, passthrough/default handling). - context.py: update build_context signature to accept MappingConfig typing. - templates: update example partials to use map_type filter and adjust context notes; rename bindings.j2 -> example.j2. - example/config.yaml: expand mapping example with many common type mappings and pointer shortcuts. - README: document the mapping config, available filters, and usage examples. These changes centralize type-mapping behavior, expose mapping options to templates, and provide richer mapping utilities for generators and templates.
1 parent ebc55b7 commit 45a3e7b

File tree

11 files changed

+665
-35
lines changed

11 files changed

+665
-35
lines changed

tools/bindgen/README.md

Lines changed: 152 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -238,15 +238,133 @@ tools/bindgen/
238238

239239
**语言映射配置(示例)**
240240

241-
语言相关配置统一写在 `config.yaml``mapping` 字段中:
241+
语言相关配置统一写在 `config.yaml``mapping` 字段中,包括类型映射
242242

243243
```yaml
244244
mapping:
245245
language: example
246-
conventions:
246+
247+
# 类型映射配置
248+
types:
249+
void: void
250+
bool: bool
251+
int: int
252+
float: double
253+
"void*": "Pointer<Void>"
254+
"const char*": "Pointer<Utf8>"
255+
256+
pointer_format: "Pointer<{inner}>"
257+
void_pointer_type: "Pointer<Void>"
258+
const_char_pointer_type: "Pointer<Utf8>"
259+
260+
# 自定义选项(模板可访问)
261+
options:
247262
enum_as_int: true
248-
naming:
249-
function: camel
263+
naming_function: camel
264+
```
265+
266+
**类型映射配置**
267+
268+
类型映射配置直接写在 `mapping` 字段中,用于将 C/C++ 类型映射到目标语言类型。支持以下配置项:
269+
270+
```yaml
271+
mapping:
272+
language: dart
273+
274+
# 直接类型名映射: C 类型名 -> 目标语言类型
275+
types:
276+
# 基本类型
277+
void: void
278+
bool: bool
279+
int: int
280+
float: double
281+
double: double
282+
283+
# 固定宽度整数
284+
int8_t: int
285+
int16_t: int
286+
int32_t: int
287+
int64_t: int
288+
uint8_t: int
289+
uint16_t: int
290+
uint32_t: int
291+
uint64_t: int
292+
size_t: int
293+
294+
# 指针类型快捷映射
295+
"void*": "Pointer<Void>"
296+
"char*": "Pointer<Utf8>"
297+
"const char*": "Pointer<Utf8>"
298+
299+
# 函数指针
300+
function_pointer: "Pointer<NativeFunction>"
301+
302+
# 指针类型格式,使用 {inner} 作为占位符
303+
# 例如 Dart FFI: "Pointer<{inner}>"
304+
pointer_format: "Pointer<{inner}>"
305+
306+
# const 指针类型格式
307+
const_pointer_format: "Pointer<{inner}>"
308+
309+
# 数组类型格式,使用 {element} 和 {length} 作为占位符
310+
array_format: "Array<{element}>"
311+
312+
# 引用类型格式
313+
reference_format: "{inner}"
314+
315+
# 未找到映射时的默认类型(可选)
316+
# default_type: dynamic
317+
318+
# 未找到映射时是否保留原始类型名
319+
passthrough_unknown: true
320+
321+
# 映射后类型名的前缀/后缀(可选)
322+
# type_prefix: ""
323+
# type_suffix: ""
324+
325+
# void* 的特殊映射(常用作不透明句柄)
326+
void_pointer_type: "Pointer<Void>"
327+
328+
# const char* 的特殊映射(常用作字符串)
329+
const_char_pointer_type: "Pointer<Utf8>"
330+
```
331+
332+
**类型映射过滤器**
333+
334+
在模板中可使用以下过滤器处理类型映射:
335+
336+
| 过滤器 | 说明 | 示例 |
337+
|--------|------|------|
338+
| `map_type` | 将 IRType 映射为目标语言类型字符串 | `{{ param.type \| map_type }}` |
339+
| `map_type_name` | 简单类型名查找映射 | `{{ "int" \| map_type_name }}` |
340+
| `format_type` | 自定义格式的类型映射 | `{{ type \| format_type(pointer_fmt="*{inner}") }}` |
341+
| `is_pointer_type` | 检查是否为指针类型 | `{% if type \| is_pointer_type %}` |
342+
| `is_array_type` | 检查是否为数组类型 | `{% if type \| is_array_type %}` |
343+
| `is_void_type` | 检查是否为 void 类型 | `{% if type \| is_void_type %}` |
344+
| `get_inner_type` | 获取指针/引用的内部类型 | `{{ type \| get_inner_type \| map_type }}` |
345+
| `get_element_type` | 获取数组的元素类型 | `{{ type \| get_element_type \| map_type }}` |
346+
347+
**模板中使用类型映射示例**
348+
349+
```jinja2
350+
{# 函数参数和返回值类型映射 #}
351+
fn {{ item.name }}(
352+
{%- for param in item.params %}
353+
{{ param.name }}: {{ param.type | map_type }}{% if not loop.last %},{% endif %}
354+
{%- endfor %}
355+
) -> {{ item.return_type | map_type }};
356+
357+
{# 结构体字段类型映射 #}
358+
struct {{ item.name }} {
359+
{%- for field in item.fields %}
360+
{{ field.name }}: {{ field.type | map_type }};
361+
{%- endfor %}
362+
}
363+
364+
{# 条件处理指针类型 #}
365+
{% if param.type | is_pointer_type %}
366+
// This is a pointer parameter
367+
{% endif %}
250368
```
251369

252370
**通用生成器伪代码**
@@ -268,7 +386,7 @@ render_to_files(templates, context, out_dir)
268386
- `functions`: 函数列表(已过滤并扁平化)
269387
- `classes`: C++ 类/struct 列表(public methods)
270388
- `constants`: 常量列表(扁平化)
271-
- `mapping`: 语言映射配置(types/conventions/naming
389+
- `mapping`: 语言映射配置(MappingConfig 对象,包含 language、types、pointer_format 等
272390

273391
**按文件模板渲染规则**
274392

@@ -378,6 +496,35 @@ PYTHONPATH=../.. python3 -m bindgen \
378496
- **C++ 语义**:默认 `extern "C"` 入口
379497
- **跨平台 ABI**:需在生成器中区分平台(Windows/Linux/macOS)
380498

499+
## 内置过滤器
500+
501+
### 命名转换过滤器
502+
503+
| 过滤器 | 说明 | 示例 |
504+
|--------|------|------|
505+
| `snake_case` | 转换为 snake_case | `{{ "MyClass" \| snake_case }}``my_class` |
506+
| `camel_case` | 转换为 camelCase | `{{ "my_function" \| camel_case }}``myFunction` |
507+
| `pascal_case` | 转换为 PascalCase | `{{ "my_class" \| pascal_case }}``MyClass` |
508+
| `screaming_snake_case` | 转换为 SCREAMING_SNAKE_CASE | `{{ "myConst" \| screaming_snake_case }}``MY_CONST` |
509+
| `kebab_case` | 转换为 kebab-case | `{{ "MyClass" \| kebab_case }}``my-class` |
510+
| `strip_prefix` | 移除前缀 | `{{ "na_init" \| strip_prefix("na_") }}``init` |
511+
| `strip_suffix` | 移除后缀 | `{{ "WindowHandle" \| strip_suffix("Handle") }}``Window` |
512+
| `add_prefix` | 添加前缀 | `{{ "Window" \| add_prefix("NA") }}``NAWindow` |
513+
| `add_suffix` | 添加后缀 | `{{ "Window" \| add_suffix("Impl") }}``WindowImpl` |
514+
515+
### 类型映射过滤器
516+
517+
| 过滤器 | 说明 | 示例 |
518+
|--------|------|------|
519+
| `map_type` | IRType 映射为目标类型 | `{{ param.type \| map_type }}` |
520+
| `map_type_name` | 类型名直接映射 | `{{ "int32_t" \| map_type_name }}` |
521+
| `format_type` | 自定义格式映射 | `{{ type \| format_type(pointer_fmt="*{inner}") }}` |
522+
| `is_pointer_type` | 是否指针类型 | `{% if type \| is_pointer_type %}` |
523+
| `is_array_type` | 是否数组类型 | `{% if type \| is_array_type %}` |
524+
| `is_void_type` | 是否 void 类型 | `{% if type \| is_void_type %}` |
525+
| `get_inner_type` | 获取指针内部类型 | `{{ type \| get_inner_type }}` |
526+
| `get_element_type` | 获取数组元素类型 | `{{ type \| get_element_type }}` |
527+
381528
## 下一步
382529

383530
- 补充更多模板示例

tools/bindgen/codegen/context.py

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,11 +1,12 @@
11
from __future__ import annotations
22

3-
from typing import Dict
3+
from typing import Any, Dict
44

5+
from ..config import MappingConfig
56
from ..ir.model import IRModule
67

78

8-
def build_context(module: IRModule, mapping: Dict) -> Dict:
9+
def build_context(module: IRModule, mapping: MappingConfig) -> Dict[str, Any]:
910
files = module.files
1011
sorted_paths = sorted(files.keys())
1112
types = []

0 commit comments

Comments
 (0)