推荐答案
在 Rust 中调用 C 代码可以通过使用 extern
关键字和 #[link]
属性来实现。以下是一个简单的示例:
-- -------------------- ---- ------- -- ------ ------ --- - -- --------------- ---- -- ---- - -- ------ - -- -- - -- ------ - --- ------ - --------------- ---------------- ---- -- ---- -------- - -
在这个示例中,extern "C"
块用于声明一个外部的 C 函数 c_function
,然后在 main
函数中通过 unsafe
块调用这个函数。
本题详细解读
1. 使用 extern
关键字
extern
关键字用于声明外部函数或变量。在 Rust 中,extern "C"
表示这些函数或变量遵循 C 语言的调用约定(ABI)。这使得 Rust 能够与 C 代码进行交互。
2. #[link]
属性
#[link]
属性用于指定链接的外部库。例如,如果你要链接一个名为 mylib
的 C 库,可以这样写:
#[link(name = "mylib")] extern "C" { fn c_function(arg: i32) -> i32; }
3. unsafe
块
由于调用外部 C 函数可能引入未定义行为或内存安全问题,Rust 要求这些调用必须在 unsafe
块中进行。unsafe
块告诉编译器你正在执行一些不安全的操作,并且你需要自己确保这些操作的安全性。
4. 编译和链接
在编译 Rust 代码时,你需要确保 C 代码已经被编译成库,并且 Rust 编译器能够找到这个库。通常,你可以使用 cargo
来管理编译和链接过程。例如,在 Cargo.toml
中添加以下内容:
[build-dependencies] cc = "1.0"
然后在 build.rs
中编译 C 代码:
extern crate cc; fn main() { cc::Build::new() .file("src/mylib.c") .compile("mylib"); }
5. 示例 C 代码
假设你有一个简单的 C 函数 c_function
,它接受一个整数参数并返回该参数加 1 的结果:
// mylib.c int c_function(int arg) { return arg + 1; }
6. 完整示例
将上述所有部分结合起来,完整的 Rust 项目结构如下:
myproject/ ├── Cargo.toml ├── build.rs ├── src/ │ ├── main.rs │ └── mylib.c
Cargo.toml
:
[package] name = "myproject" version = "0.1.0" edition = "2021" [build-dependencies] cc = "1.0"
build.rs
:
extern crate cc; fn main() { cc::Build::new() .file("src/mylib.c") .compile("mylib"); }
src/mylib.c
:
int c_function(int arg) { return arg + 1; }
src/main.rs
:
-- -------------------- ---- ------- ------ --- - -- --------------- ---- -- ---- - -- ------ - ------ - --- ------ - --------------- ---------------- ---- -- ---- -------- - -
通过这种方式,你可以在 Rust 中成功调用 C 代码。