Rust与C在Linux系统中的互操作性
Rust与C在Linux系统中的互操作性通过**Foreign Function Interface(FFI)**实现,允许两者直接调用对方的函数、传递数据并复用现有代码。这种互操作性依赖于C ABI(Application Binary Interface)的兼容性,确保二进制层面的一致性。
Rust通过extern "C"
块声明C函数,并通过build.rs
或libc
库链接C代码,实现对其功能的调用。
extern "C"
标记外部函数,告知Rust编译器按C ABI调用(避免名称修饰)。例如,调用C的gethostname
函数需声明:extern "C" { fn gethostname(name: *mut c_char, len: usize) -> i32; }
。.a
文件)和动态库(.so
文件)。静态库通过build.rs
中的cc::Build
编译并链接(如println!("cargo:rustc-link-lib=static=mylib");
),动态库则通过#[link(name = "mylib")]
属性指定库名(如#[link(name = "hello")] extern "C" { fn say_hello(); }
)。std::os::raw
模块中的类型(如c_int
对应int
、c_char
对应char
)。字符串需用CString
转换(如let c_str = CString::new("hello").unwrap();
),避免空字符问题。hello.c
:void say_hello() { printf("Hello from C!\n"); }
),编译为动态库(gcc -shared -o libhello.so -fPIC hello.c
),在Rust中声明并调用(extern "C" { fn say_hello(); }
,unsafe { say_hello(); }
)。C通过extern
关键字声明Rust函数,Rust需用#[no_mangle]
防止名称修饰,并编译为C兼容的库(静态库.a
或动态库.so
),供C链接。
#[no_mangle]
标记导出函数(如#[no_mangle] pub extern "C" fn add(a: i32, b: i32) -> i32 { a + b }
),并配置Cargo.toml
的crate-type
为cdylib
(动态库)或staticlib
(静态库)。cargo build --release
生成库文件(如target/release/librust_to_c.so
),供C链接。extern int add(int a, int b);
),编译时链接Rust库(gcc -o main main.c -L./target/release -lrust_to_c
),运行时通过LD_LIBRARY_PATH
指定库路径(export LD_LIBRARY_PATH=./target/release:$LD_LIBRARY_PATH
)。Box::into_raw
转换(如let ptr = Box::into_raw(Box::new(42));
),在C中用Box::from_raw
释放(如unsafe { Box::from_raw(ptr); }
),避免内存泄漏。-1
表示失败),Rust需用Result
类型包装(如pub fn safe_c_function() -> Result<i32, &'static str>
),处理C的错误返回值。bindgen
工具自动生成Rust绑定(如从C头文件生成bindings.rs
),简化复杂C库的调用(如bindgen wrapper.h -o src/bindings.rs
)。