mcpField
R
rust-ffi-safe-wrappers

rust-ffi-safe-wrappers

github.com/lvtd-llc开发161 次安装8 周前更新
代码仓库

关于 rust-ffi-safe-wrappers

面向 Rust 开发者的外部接口安全封装技能,将原始绑定限制在 unsafe 边界,并指导 Rust API 明确所有权、错误、清理和 panic 行为。

主要功能

  1. 01分离原始绑定与安全封装
  2. 02核对 ABI 和所有权约定
  3. 03定义兼容 C 的数据布局
  4. 04管理 C 字符串与句柄
  5. 05将外部错误转换为 Result
  6. 06明确 panic 与回调行为

适用场景

  1. 01审查 Rust 对 C 库的绑定
  2. 02为外部句柄封装清理逻辑
  3. 03检查字符串和缓冲区所有权
  4. 04审计 Rust 2024 FFI 声明

安装

复制下面的命令,在终端中运行。

$npx skills add https://github.com/lvtd-llc/skills --skill rust-ffi-safe-wrappers

安装后在 Claude Code 中输入/rust-ffi-safe-wrappers确认已加载。

附带文件agents/openai.yamlreferences/ffi-boundary-patterns.md

详细介绍

Rust FFI 安全封装

使用此技能将外部接口封装为 Rust API,明确所有权、生命周期、错误和清理方式。FFI 代码在原始边界处应为不安全代码,对普通 Rust 调用方则应安全。

核心工作流

  1. 将原始声明与安全封装分开。将原始 unsafe extern 绑定放在一个小型私有模块中。
  2. 根据外部头文件或文档核实 ABI、类型布局、调用约定、所有权、可空性、线程行为和错误约定。
  3. 对现代 Rust 使用 unsafe extern "C" 块,尤其是在 Rust 2024 版代码中。对安全性取决于条件的项,不添加限定或显式标记为 unsafe;仅当对所有 Rust 输入而言调用都安全时,才将单个 extern 项标记为 safe。
  4. 对跨越 ABI 边界的结构体和枚举使用 #[repr(C)]。不要通过 C 暴露仅适用于 Rust 的布局类型。
  5. 使用 CString 表示发送给 C 的、由 Rust 拥有的以 nul 结尾的字符串,使用 CStr 表示借用的 C 字符串。绝不要将任意 C 内存视为由 Rust 拥有。
  6. 将原始句柄封装为字段私有的 Rust 类型,并通过 Drop 使用匹配的外部释放函数进行清理。
  7. 防止 Rust panic 穿过 extern "C" 边界。捕获 panic,或仅在有意使用 "C-unwind" 时暴露允许展开的 ABI。

封装规则

添加或审查 FFI 绑定前,请阅读 references/ffi-boundary-patterns.md。

  • 优先使用 core::ffi 或 std::ffi 中的 C 类型,不要猜测整数大小。
  • 在封装边界将外部错误码转换为 Rust Result。
  • 如有用,可在内部将可空句柄表示为 Option<NonNull<T>>,但向调用方暴露安全的 Rust 类型。
  • 当编译器无法识别借用值与所有者之间的关系时,通过常规引用或 PhantomData 将借用值绑定到所有者的生命周期。
  • 如果外部库要求进程级初始化,请使用 OnceLock、LazyLock 或 Once,确保初始化和关闭操作可安全重复执行。
  • 对大型或频繁变动的 C 头文件使用 bindgen,将 Rust API 导出为 C 时使用 cbindgen,但仍须审查生成的不安全签名。

Rust 2024 语法检查

unsafe extern "C" {
    pub fn library_open(path: *const core::ffi::c_char) -> *mut RawHandle;
    pub fn library_close(handle: *mut RawHandle);
    // Mark an item `safe` only when calling it is valid for all Rust inputs:
    // pub safe fn library_version() -> core::ffi::c_int;
}

// SAFETY: This exported symbol name is unique for this library.
#[unsafe(no_mangle)]
pub extern "C" fn plugin_version() -> core::ffi::c_int {
    1
}

在 Rust 2024 版代码中,no_mangle、export_name 和 link_section 等不安全属性需要使用 unsafe(...) 形式。如果符号唯一性或链接器行为属于契约的一部分,请添加 SAFETY 注释。

审查清单

  • 原始绑定为私有,或与安全封装明确分开。
  • 每个指针参数都注明了可空性和所有权规则。
  • 每次内存分配都由同一方释放,或由明确匹配的释放函数释放。
  • 字符串和缓冲区保留了长度、编码和 nul 字节要求。
  • 明确规定了跨边界的 panic、回调和线程行为。

评论

支持 Markdown