跳转至

绑定生成器 (bindgen)

Link 提供内置的 link bindgen 工具,可以从 .link 源文件的 export "<lang>" { ... } 块自动生成目标语言的绑定代码,免去手写胶水层的工作。

基本用法

link bindgen --lang <lang> <input.link> [-o <output>] [--module <name>]
参数 说明
--lang / -l 目标语言: c / python / typescript
<input.link> Link 源文件路径
-o / --output 输出文件路径(默认: stdout)
--module 模块名(默认: 输入文件名 stem)

支持的目标语言

语言 --lang 取值 输出扩展名 输出形式
C / C++ c / header / h .h C 头文件(含 include guard 与 extern "C")
Python python / py / pyi .pyi Python 类型存根
TypeScript typescript / ts / dts .d.ts TypeScript 声明文件

示例:一次定义,三处导出

examples/link_sdk.link:

export "C" {
    fn link_init() -> bool;
    fn link_create_room(max_players: u8) -> u32;
    fn link_join_room(room_id: u32, player_name: str) -> bool;
    fn link_shutdown();
}

export "python" module "link_game" {
    fn start_server(port: u16) -> bool;
    async fn fetch_state(room_id: u32) -> str;
    fn events(room_id: u32) -> stream<i32>;
}

export "typescript" module "link-game-sdk" {
    fn createRoom(maxPlayers: u8) -> u32;
    async fn fetchState(roomId: u32) -> str;
}

生成 C 头文件

link bindgen --lang c examples/link_sdk.link --module link_sdk -o examples/link_sdk.h

输出 examples/link_sdk.h:

#ifndef LINK_LINK_SDK_H
#define LINK_LINK_SDK_H

#include <stdint.h>
#include <stddef.h>
#include <stdbool.h>

#ifdef __cplusplus
extern "C" {
#endif

bool link_init(void);

uint32_t link_create_room(uint8_t max_players);

bool link_join_room(uint32_t room_id, const char* player_name);

void link_shutdown(void);

#ifdef __cplusplus
}  // extern "C"
#endif

#endif  // LINK_LINK_SDK_H

生成 Python 存根

link bindgen --lang python examples/link_sdk.link -o examples/link_sdk.pyi

输出 examples/link_sdk.pyi:

"""
link_sdk  —— Auto-generated by `link bindgen --lang python`
DO NOT EDIT MANUALLY.
Source module: link_game
"""

from typing import AsyncIterable

def start_server(port: int) -> bool: ...
async def fetch_state(room_id: int) -> str: ...
def events(room_id: int) -> AsyncIterable[int]: ...

生成 TypeScript 声明

link bindgen --lang typescript examples/link_sdk.link -o examples/link_sdk.d.ts

输出 examples/link_sdk.d.ts:

/**
 * link_sdk  —— Auto-generated by `link bindgen --lang typescript`
 * DO NOT EDIT MANUALLY.
 * Source module: link-game-sdk
 */

declare module "link_sdk" {
    export function createRoom(maxPlayers: number): number;
    export function fetchState(roomId: number): Promise<string>;
}

类型映射

bindgen 按下表将 Link 类型映射到目标语言:

Link 类型 C / C++ Python TypeScript
bool bool bool boolean
i8 / i16 / i32 / i64 int8_t / int16_t / int32_t / int64_t int number
u8 / u16 / u32 / u64 uint8_t / ... / uint64_t int number
usize size_t int number
f32 / f64 float / double float number
str const char* str string
void / () void None void
T* T* int(指针地址) number
stream<T> /* stream<T> */ void*(注解) AsyncIterable[T] AsyncIterable<T>
命名类型 Foo Foo Foo Foo

async 函数处理

async fn 在不同目标语言中的处理方式:

  • C: 注释标记 // async fn ...,签名保持同步形式(C 本身没有 async 概念)
  • Python: 生成 async def
  • TypeScript: 返回类型包装为 Promise<T>

多 export 块合并

如果源文件中包含多个相同语言的 export 块,bindgen 会自动合并所有声明一起生成:

export "C" {
    fn first() -> bool;
}

export "C" {
    fn second(x: i32) -> i32;
}

会合并为一个头文件,包含 firstsecond 两个声明。

语言过滤

bindgen 只生成匹配 --lang 的 export 块,其他语言的块会被忽略:

export "C" { fn c_fn() -> bool; }
export "python" { fn py_fn() -> bool; }
export "typescript" { fn ts_fn() -> bool; }
link bindgen --lang c triple.link   # 只含 c_fn
link bindgen --lang python triple.link  # 只含 py_fn

标识符净化

如果 Link 中的标识符与目标语言的关键字冲突,bindgen 会自动加下划线后缀:

Link 标识符 Python 输出 TypeScript 输出
class class_ class_
import import_ import_
function function function_
return return_ return_

错误处理

如果源文件中没有匹配语言的 export 块,bindgen 会报错:

$ link bindgen --lang rust my.link
Error: No `export "C" { ... }` block found in source

(目前 rust 还未作为 --lang 支持,可选项为 c / python / typescript)

当前限制

  • 不支持生成 struct / enum 的目标语言定义(只生成函数声明)
  • 不支持生成 Python class / TypeScript interface(export 块目前只解析函数签名)
  • 不支持从 C 头文件反向生成 Link extern 声明(规划中)
  • 不支持泛型实例化绑定

下一步