名称: 端口C模块技能 描述: 将C模块移植到Rust的指南 禁用模型调用: true
端口模块技能
将C模块移植到Rust的指南。
参数
要移植的模块名称应作为参数提供(例如,/port-module triemap)。
要移植的模块:$ARGUMENTS
用法
在开始将C模块移植到Rust时使用此技能。
说明
1. 分析C代码
首先,理解您要移植的C模块(在src/中查找$ARGUMENTS.c和$ARGUMENTS.h):
- 阅读
src/中的.c和.h文件 - 识别头文件暴露的内容:
- 代码库的其他部分是否可以访问此模块定义的数据结构的内部字段?
- 类型总是按值传递还是按引用传递?混合方式?
- 相应的Rust类型是否可以通过FFI边界传递?
- 理解数据结构及其生命周期
- 识别此模块从其他模块导入的类型和函数:
- 确定这些类型是在Rust还是C中实现
- 如果这些类型在Rust中实现,识别相关的Rust crate
- 如果这些类型在C中实现,理解是否应首先将它们移植到Rust,或者是否更倾向于通过FFI从Rust调用C实现
- 注意任何全局状态或Redis模块交互
- 识别
tests/下与此模块相关的测试
2. 定义移植计划
创建一个$ARGUMENTS_plan.md文件来概述移植模块的步骤和决策。
确定在此阶段是否应修改C代码以简化移植过程。
例如:
- 引入getter和setter以避免暴露此模块定义的数据结构的内部字段。
- 将模块拆分为更小、更易管理的部分。
3. 创建Rust Crate
cd src/redisearch_rs
cargo new $ARGUMENTS --lib
4. 实现纯Rust逻辑
- 创建符合惯用法的Rust代码
- 添加全面测试
- 确保所有C/C++测试都有等效的Rust测试
- 使用文档注释记录公共API
- 对于性能敏感的代码,使用
criterion创建微基准测试 - 在适当的地方使用
proptest进行基于属性的测试 - 测试代码应像生产代码一样精心编写
5. 比较Rust API与C API
- 对照头文件中的C API,审查新Rust模块的公共API
- 确保差异可以通过添加适当的包装器或适配器来桥接
- 如果发现差异无法通过重新设计来桥接,请返回步骤1
6. 创建FFI包装器
创建一个FFI crate以将新的Rust模块暴露给C代码库:
cd src/redisearch_rs/c_entrypoint
cargo new ${ARGUMENTS}_ffi --lib
FFI crate应:
- 暴露
#[unsafe(no_mangle)] pub extern "C" fn函数 - 处理空指针和错误情况
- 安全地在C和Rust类型之间转换
- 用
// SAFETY:注释记录所有不安全块
7. 连接C代码
- 删除C头文件及其实现
- 更新C代码库的其余部分,在原来使用旧C头文件的地方导入新的Rust头文件
Rust FFI crate的C头文件是自动生成的。在导入时无需使用其完整路径,
只需使用其名称(例如,对于${ARGUMENTS}_ffi,使用#include $ARGUMENTS.h;)
8. 测试集成
./build.sh RUN_UNIT_TESTS # C/C++单元测试
./build.sh RUN_PYTEST # 集成测试
示例:良好移植的模块
参见src/redisearch_rs/trie_rs/以获取高质量示例:
- 纯Rust实现,附有全面文档
- 广泛的测试覆盖
- 在
c_entrypoint/trie_ffi/中清晰的FFI边界