Rust FFI 调用指南及示例
“最近在学习Rust的FFI功能,想请教几个问题:1) 如何在Rust中安全地调用C函数?2) 能否提供一个简单的示例展示Rust和C之间的数据类型转换?3) 在跨语言调用时需要注意哪些内存管理的问题?4) 有没有推荐的最佳实践来避免常见的FFI错误?”
2 回复
Rust FFI 调用指南:
- 使用
extern "C"声明外部函数 - 用
#[no_mangle]确保函数名不被编译器修改 - 通过
libc库处理 C 类型(如c_int)
示例(调用 C 的 abs 函数):
extern "C" {
fn abs(num: c_int) -> c_int;
}
fn main() {
unsafe {
println!("abs(-5) = {}", abs(-5));
}
}
注意:FFI 需用 unsafe 块,确保内存安全。
Rust FFI(Foreign Function Interface)允许Rust与其他语言(如C/C++)交互。以下是关键步骤和示例:
基本步骤
- 使用
extern块声明外部函数 - 添加
#[link]属性指定库 - 处理数据类型转换(如C字符串)
- 编译时链接库(通过build.rs或编译器标志)
示例:调用C标准库函数
// 声明外部函数
#[link(name = "c")]
extern "C" {
fn strlen(s: *const i8) -> usize;
}
fn main() {
let c_str = b"Hello\0"; // 模拟C字符串(以null结尾)
unsafe {
let len = strlen(c_str.as_ptr());
println!("String length: {}", len); // 输出 5
}
}
调用自定义C库
- C代码(lib.c):
#include <stdint.h>
int32_t add(int32_t a, int32_t b) { return a + b; }
- Rust调用:
#[link(name = "mylib")]
extern "C" {
fn add(a: i32, b: i32) -> i32;
}
fn main() {
unsafe {
println!("Sum: {}", add(3, 5)); // 输出 8
}
}
编译命令
# 编译C为共享库
gcc -shared -o libmylib.so lib.c
# 编译Rust并链接
RUSTFLAGS='-L .' cargo build
注意事项
- 安全边界:FFI操作需包裹在
unsafe块中 - 内存管理:注意所有权(如使用
std::ffi::CString传递字符串) - 错误处理:检查C函数的返回值和错误码
进阶工具
- bindgen:自动生成C头文件的Rust绑定
- cbindgen:生成Rust代码的C头文件
通过合理使用FFI,Rust可无缝集成现有C/C++生态。

