Skip to content

互操作设计

目标

Qlang 要想在真实工程里落地,必须天然支持和已有原生生态协作。这里的关键不是“能不能链接”,而是:

  • 调用规则是否稳定
  • 边界上的所有权是否明确
  • 构建系统是否好用
  • 调试和诊断是否能跟上

总策略

结论一:C ABI 是互操作底座

无论目标是 C、C++ 还是 Rust,第一层稳定互操作都围绕 C ABI 展开。原因:

  • ABI 稳定、平台可控
  • LLVM 生成对象文件与链接流程成熟
  • 能作为其他语言接入 Qlang 的最小公共层

结论二:C++ 必须分阶段推进

直接完整支持 C++ ABI、模板、异常、名称修饰和对象模型,复杂度极高。正确策略不是一开始宣称“全面互通”,而是:

  1. P0:通过 C shim 接入 C++ 库
  2. P1:支持常见类、命名空间、静态函数、简单方法绑定生成
  3. P2:再评估异常、模板实例和更多 ABI 细节

结论三:Rust 先走稳定边界,再谈更深整合

Rust 互操作优先方案:

  • 使用 extern "C" 暴露稳定接口
  • 使用 bindgen / cbindgen 风格工具生成桥接层
  • 通过 repr(C) 和显式生命周期转换包装复杂类型

后续如果需要更深整合,再研究读取 Rust 元数据或更直接的符号协作。

语言层设计

建议提供清晰的 FFI 语法:

rust
extern "c" {
    fn strlen(ptr: *const U8) -> USize;
}

extern "c" pub fn q_add(left: I32, right: I32) -> I32;

边界规则:

  • FFI 声明必须显式 ABI
  • 原始指针、裸句柄、未验证布局放入 unsafe
  • 可自动生成安全包装层

构建系统设计

ql 统一 CLI 应支持:

  • 编译本地 C 文件
  • 调用系统编译器或 clang
  • 链接静态库和动态库
  • 生成头文件和桥接代码
  • 为 Rust/C++ 示例工程创建模板

调试与诊断

互操作体验不仅是“编译通过”,还包括:

  • FFI 边界的布局检查
  • ABI 不匹配报错
  • 符号缺失诊断
  • unsafe 调用点的追踪
  • 与 lldb / gdb 的调试信息配合

推荐顺序

  1. 先把 C FFI 做成一等能力
  2. 用 C ABI 打通 Rust 互操作
  3. 用 shim 稳定支持 C++ 库接入
  4. 最后再扩展更直接的 C++ 能力

如果顺序反过来,项目极大概率会陷入“演示很酷、工程不可用”的状态。

Qlang research repository