推荐答案
在 Rust 中调用 C 代码可以通过使用 extern 关键字和 #[link] 属性来实现。以下是一个简单的示例:
// www.javascriptcn.com code example
// 声明外部函数
extern "C" {
fn c_function(arg: i32) -> i32;
}
fn main() {
// 调用 C 函数
unsafe {
let result = c_function(42);
println!("Result from C: {}", result);
}
}在这个示例中,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:
// www.javascriptcn.com code example
extern "C" {
fn c_function(arg: i32) -> i32;
}
fn main() {
unsafe {
let result = c_function(42);
println!("Result from C: {}", result);
}
}通过这种方式,你可以在 Rust 中成功调用 C 代码。