推荐答案
在 Rust 中,可以通过 extern
关键字和 #[no_mangle]
属性将 Rust 代码暴露给 C 语言调用。以下是一个简单的示例:
#[no_mangle] pub extern "C" fn add(a: i32, b: i32) -> i32 { a + b }
在这个示例中,#[no_mangle]
属性用于防止 Rust 编译器对函数名进行名称修饰(name mangling),确保 C 代码可以正确链接到这个函数。extern "C"
指定了函数的调用约定为 C 语言的调用约定。
本题详细解读
1. #[no_mangle]
属性
Rust 编译器默认会对函数名进行名称修饰(name mangling),以支持函数重载等特性。然而,C 语言不支持名称修饰,因此需要通过 #[no_mangle]
属性来禁止 Rust 编译器对函数名进行修饰。这样,C 代码就可以通过函数名直接调用 Rust 函数。
2. extern "C"
关键字
extern "C"
关键字用于指定函数的调用约定为 C 语言的调用约定。Rust 和 C 有不同的函数调用约定(calling convention),extern "C"
确保 Rust 函数使用与 C 语言相同的调用约定,从而使得 C 代码可以正确调用 Rust 函数。
3. 编译为静态库或动态库
为了将 Rust 代码暴露给 C 使用,通常需要将 Rust 代码编译为静态库(.a
文件)或动态库(.so
或 .dll
文件)。可以通过在 Cargo.toml
中配置 crate-type
来实现:
[lib] crate-type = ["cdylib"] # 或者 "staticlib"
cdylib
:生成动态库,适用于大多数跨语言调用场景。staticlib
:生成静态库,适用于需要将 Rust 代码静态链接到 C 项目中的场景。
4. C 代码调用 Rust 函数
在 C 代码中,可以通过声明外部函数来调用 Rust 函数。例如:
-- -------------------- ---- ------- -------- --------- -- -- ---- -- ------ --- ------- -- --- --- --- ------ - --- ------ - ------ --- --------------- ------ -------- -- --- ------- - ------ -- -
5. 编译和链接
在编译 C 代码时,需要链接 Rust 生成的库文件。例如,使用 gcc
编译 C 代码并链接 Rust 生成的动态库:
gcc -o my_program my_program.c -L. -lmy_rust_library
其中,-L.
指定库文件的搜索路径,-lmy_rust_library
指定要链接的库文件(libmy_rust_library.so
或 libmy_rust_library.a
)。
通过以上步骤,Rust 代码就可以成功暴露给 C 语言调用。