FFI(Foreign Function Interface)让Rust能够调用C语言库,也让C能调用Rust。这是Rust与现有生态系统集成的关键桥梁。
// 声明外部函数
extern "C" {
fn abs(input: i32) -> i32;
fn strlen(s: *const i8) -> usize;
}
fn main() {
// 调用C标准库函数
let x = -42;
unsafe {
println!("|{}| = {}", x, abs(x));
}
// C字符串处理
let c_str = b"Hello, FFI!\0";
unsafe {
println!("长度: {}", strlen(c_str.as_ptr() as *const i8));
}
// 从C字符串创建Rust字符串
use std::ffi::{CStr, CString};
let c_string = CString::new("Hello from C").unwrap();
unsafe {
let rust_str = CStr::from_ptr(c_string.as_ptr());
println!("Rust读取: {}", rust_str.to_str().unwrap());
}
// Rust字符串转C字符串
let rust_string = String::from("Hello from Rust");
let c_string = CString::new(rust_string).unwrap();
unsafe {
println!("C可读: {}", CStr::from_ptr(c_string.as_ptr()).to_str().unwrap());
}
}
✅ 验证通过
// 让C调用的Rust函数
#[no_mangle]
pub extern "C" fn rust_add(a: i32, b: i32) -> i32 {
a + b
}
#[no_mangle]
pub extern "C" fn rust_greet(name: *const i8) -> i32 {
use std::ffi::CStr;
unsafe {
if name.is_null() { return -1; }
let c_str = CStr::from_ptr(name);
match c_str.to_str() {
Ok(s) => { println!("你好, {}!", s); 0 }
Err(_) => -2,
}
}
}
fn main() {
// 模拟C调用Rust
let sum = rust_add(3, 5);
println!("3 + 5 = {}", sum);
use std::ffi::CString;
let name = CString::new("World").unwrap();
let result = rust_greet(name.as_ptr());
println!("返回码: {}", result);
}
✅ 验证通过
use std::ffi::{CStr, CString};
use std::os::raw::c_char;
// Rust实现的数学函数,导出给C
#[no_mangle]
pub extern "C" fn math_factorial(n: u32) -> u64 {
(1..=n as u64).product()
}
#[no_mangle]
pub extern "C" fn math_fibonacci(n: u32) -> u64 {
let mut a = 0u64;
let mut b = 1u64;
for _ in 0..n {
let temp = a + b;
a = b;
b = temp;
}
a
}
#[no_mangle]
pub extern "C" fn math_is_prime(n: u64) -> bool {
if n < 2 { return false; }
if n < 4 { return true; }
if n % 2 == 0 || n % 3 == 0 { return false; }
let mut i = 5u64;
while i * i <= n {
if n % i == 0 || n % (i + 2) == 0 { return false; }
i += 6;
}
true
}
// 接收C字符串,返回C字符串
#[no_mangle]
pub extern "C" fn math_describe(n: u32) -> *mut c_char {
let desc = format!(
"{}: 阶乘={}, 斐波那契={}, 素数={}",
n, math_factorial(n), math_fibonacci(n), math_is_prime(n as u64)
);
CString::new(desc).unwrap().into_raw()
}
fn main() {
for n in [5, 7, 10] {
let desc = unsafe { CStr::from_ptr(math_describe(n)) };
println!("{}", desc.to_str().unwrap());
}
}
✅ 验证通过
添加libc依赖,调用getpid()和time()函数。
实现C的qsort回调:Rust实现比较函数,通过FFI传给C的qsort。
use std::ffi::{CStr, CString};
use std::os::raw::c_char;
mod safe_ffi {
use std::ffi::{CStr, CString};
use std::os::raw::c_char;
pub fn receive_c_string(ptr: *const c_char) -> Option {
if ptr.is_null() { return None; }
unsafe { CStr::from_ptr(ptr).to_str().ok().map(|s| s.to_string()) }
}
pub fn return_c_string(s: String) -> *mut c_char {
CString::new(s).unwrap().into_raw()
}
pub fn free_c_string(ptr: *mut c_char) {
if !ptr.is_null() { unsafe { let _ = CString::from_raw(ptr); } }
}
}
type Callback = extern "C" fn(i32) -> i32;
fn apply_callback(value: i32, cb: Callback) -> i32 { cb(value) }
extern "C" fn double(x: i32) -> i32 { x * 2 }
fn main() {
let c_str = CString::new("Hello FFI").unwrap();
let rust_str = safe_ffi::receive_c_string(c_str.as_ptr());
println!("收到: {:?}", rust_str);
println!("回调: double(5) = {}", apply_callback(5, double));
}
✅ 验证通过
// 何时使用FFI:
// 1. 使用已有的C/C++库(OpenSSL, SQLite, zlib等)
// 2. 性能关键路径需要底层优化
// 3. 与嵌入式系统交互
// 4. 系统调用封装
//
// Rust→C→Rust 数据流:
// Rust String → CString → *const c_char → C函数 → *mut c_char → CStr → &str
//
// 重要注意事项:
// 1. C没有所有权概念,需手动管理内存
// 2. C没有空指针检查,Rust侧必须处理
// 3. C字符串以\0结尾,Rust字符串不一定
// 4. C的int大小不确定,用c_int/c_uint
fn main() {
// 常见FFI crate
println!("常用FFI crate:");
println!(" libc - C标准库绑定");
println!(" bindgen - 自动生成C头文件绑定");
println!(" cbindgen - 从Rust生成C头文件");
println!(" cxx - 安全的C++互操作");
println!(" pyo3 - Python绑定");
println!(" neon - Node.js绑定");
println!(" uniFFI - 跨语言绑定生成器");
println!("
使用bindgen流程:");
println!(" 1. 编写wrapper.h包含C头文件");
println!(" 2. bindgen wrapper.h -o bindings.rs");
println!(" 3. 在Rust代码中使用生成的绑定");
println!("
使用cbindgen导出:");
println!(" 1. 编写Rust库,标注#[no_mangle]");
println!(" 2. cbindgen --crate mylib -o mylib.h");
println!(" 3. C代码include头文件调用");
}
use std::ffi::{CStr, CString};
use std::os::raw::c_char;
#[no_mangle]
pub extern "C" fn math_gcd(a: i64, b: i64) -> i64 {
let mut a = a.abs();
let mut b = b.abs();
while b != 0 { let t = b; b = a % b; a = t; }
a
}
#[no_mangle]
pub extern "C" fn math_lcm(a: i64, b: i64) -> i64 {
if a == 0 || b == 0 { return 0; }
(a.abs() / math_gcd(a, b)) * b.abs()
}
#[no_mangle]
pub extern "C" fn math_extended_gcd(a: i64, b: i64) -> MathResult {
let (old_r, r) = (a, b);
let (mut old_s, mut s) = (1i64, 0i64);
let (mut old_t, mut t) = (0i64, 1i64);
let (mut old_r, mut r) = (old_r, r);
while r != 0 {
let q = old_r / r;
(old_r, r) = (r, old_r - q * r);
(old_s, s) = (s, old_s - q * s);
(old_t, t) = (t, old_t - q * t);
}
MathResult { gcd: old_r, x: old_s, y: old_t }
}
#[repr(C)]
pub struct MathResult { gcd: i64, x: i64, y: i64 }
fn main() {
println!("GCD(48, 18) = {}", math_gcd(48, 18));
println!("LCM(12, 18) = {}", math_lcm(12, 18));
let r = math_extended_gcd(35, 15);
println!("ext_gcd(35,15): gcd={}, x={}, y={}", r.gcd, r.x, r.y);
println!("验证: 35*{} + 15*{} = {}", r.x, r.y, 35*r.x + 15*r.y);
}
✅ 验证通过
use std::ffi::{CStr, CString};
use std::os::raw::c_char;
// 模式1: Rust调用C
// extern "C" { fn c_function(arg: i32) -> i32; }
// 模式2: C调用Rust
// #[no_mangle] pub extern "C" fn rust_function() -> i32 { 42 }
// 模式3: 回调函数
// type Callback = extern "C" fn(i32) -> i32;
// extern "C" { fn register_callback(cb: Callback); }
// 模式4: 结构体传递
#[repr(C)]
struct PointC { x: f64, y: f64 }
fn main() {
let p = PointC { x: 3.0, y: 4.0 };
println!("C兼容点: ({}, {})", p.x, p.y);
// 字符串转换备忘
let rust_s = "Hello";
let c_s = CString::new(rust_s).unwrap();
let back_to_rust = unsafe { CStr::from_ptr(c_s.as_ptr()).to_str().unwrap() };
println!("往返: {} → C → {}", rust_s, back_to_rust);
println!("
常用FFI工具:");
println!(" bindgen - 自动生成C绑定");
println!(" cbindgen - 生成C头文件");
println!(" cxx - 安全C++互操作");
println!(" cc - 构建C代码");
}
// PyO3概念演示(不依赖pyo3)
use std::ffi::{CStr, CString};
use std::os::raw::c_char;
// 模拟Python调用Rust的接口
#[no_mangle]
pub extern "C" fn py_calculate_fibonacci(n: u32) -> u64 {
let mut a = 0u64; let mut b = 1u64;
for _ in 0..n { let t = a + b; a = b; b = t; }
a
}
#[no_mangle]
pub extern "C" fn py_is_prime(n: u64) -> bool {
if n < 2 { return false; }
if n < 4 { return true; }
if n % 2 == 0 || n % 3 == 0 { return false; }
let mut i = 5u64;
while i * i <= n { if n % i == 0 || n % (i+2) == 0 { return false; } i += 6; }
true
}
#[no_mangle]
pub extern "C" fn py_format_result(n: u64, result: u64) -> *mut c_char {
CString::new(format!("fib({})={}", n, result)).unwrap().into_raw()
}
fn main() {
// 模拟Python调用
let n = 30u32;
let result = py_calculate_fibonacci(n);
println!("fib({}) = {}", n, result);
// 素数检查
println!("17是素数: {}", py_is_prime(17));
println!("100是素数: {}", py_is_prime(100));
// 格式化结果
let c_str = py_format_result(30, result);
unsafe {
let s = CStr::from_ptr(c_str);
println!("格式化: {}", s.to_str().unwrap());
let _ = CString::from_raw(c_str); // 释放
}
println!("
PyO3使用流程:");
println!(" 1. pip install maturin");
println!(" 2. maturin init");
println!(" 3. 编写Rust代码(#[pyfunction])");
println!(" 4. maturin develop");
println!(" 5. Python: import mylib");
}
✅ 验证通过
Rust的设计哲学贯穿始终:安全、并发、高性能。每个特性都是这三个目标的具体体现。本课所学内容是构建真实Rust应用的基石,务必在实践中反复练习巩固。
记住:Rust的学习曲线虽陡,但一旦掌握,你将获得前所未有的编程信心——编译器就是你的最佳队友。
use std::ffi::{CStr, CString};
use std::os::raw::{c_char, c_int, c_double};
// 类型对应表:
// Rust C
// i32 int (c_int)
// i64 long long (c_longlong)
// f64 double (c_double)
// *mut T T*
// *const T const T*
// bool _Bool
// () void
// 字符串转换流程:
// Rust String → CString → *const c_char → C函数
// C函数 → *const c_char → CStr → &str → String
// 内存所有权规则:
// 1. Rust分配的内存,Rust释放
// 2. C分配的内存,C释放
// 3. 跨边界传递时明确所有权
fn main() {
// C类型大小
println!("C类型大小:");
println!(" c_int: {}字节", std::mem::size_of::());
println!(" c_double: {}字节", std::mem::size_of::());
println!(" *const c_char: {}字节", std::mem::size_of::<*const c_char>());
// 字符串转换示例
let rust_str = "Hello from Rust";
let c_string = CString::new(rust_str).unwrap();
let c_ptr = c_string.as_ptr();
unsafe {
let back = CStr::from_ptr(c_ptr);
println!("往返: {}", back.to_str().unwrap());
}
// 常用FFI crate
println!("
推荐FFI工具:");
println!(" bindgen: 自动生成C绑定");
println!(" cbindgen: 生成C头文件");
println!(" cxx: 安全C++绑定");
println!(" pyo3: Python绑定");
println!(" neon: Node.js绑定");
println!(" jni: Java绑定");
}