Rust FFI 调用指南及示例

“最近在学习Rust的FFI功能,想请教几个问题:1) 如何在Rust中安全地调用C函数?2) 能否提供一个简单的示例展示Rust和C之间的数据类型转换?3) 在跨语言调用时需要注意哪些内存管理的问题?4) 有没有推荐的最佳实践来避免常见的FFI错误?”

2 回复

Rust FFI 调用指南:

  1. 使用 extern "C" 声明外部函数
  2. #[no_mangle] 确保函数名不被编译器修改
  3. 通过 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++)交互。以下是关键步骤和示例:

基本步骤

  1. 使用extern块声明外部函数
  2. 添加#[link]属性指定库
  3. 处理数据类型转换(如C字符串)
  4. 编译时链接库(通过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库

  1. C代码(lib.c)
#include <stdint.h>
int32_t add(int32_t a, int32_t b) { return a + b; }
  1. 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

注意事项

  1. 安全边界:FFI操作需包裹在unsafe块中
  2. 内存管理:注意所有权(如使用std::ffi::CString传递字符串)
  3. 错误处理:检查C函数的返回值和错误码

进阶工具

  • bindgen:自动生成C头文件的Rust绑定
  • cbindgen:生成Rust代码的C头文件

通过合理使用FFI,Rust可无缝集成现有C/C++生态。

回到顶部