在 C 代碼中調用 Rust 代碼,需要我們將 Rust 源代碼打包為靜態庫文件。在 C 代碼編譯時,鏈接進去。
1、創建靜態庫
1.1、在命令行使用 cargo init --lib mylog
建立 lib 庫。添加以下代碼到 src/lib.rs 中:
1 #![crate_type = "staticlib"] 2 3 extern crate libc; 4 5 use libc::{c_int, c_char}; 6 use std::ffi::CStr; 7 8 #[repr(C)] 9 pub struct RustLogMessage { 10 id: c_int, 11 msg: *const c_char 12 } 13 14 #[no_mangle] 15 pub extern "C" fn rust_log(msg: RustLogMessage) { 16 let s = unsafe { CStr::from_ptr(msg.msg)}; 17 println!("id:{} message: {:?}", msg.id, s); 18 }
1.2、在 Cargo.toml 文件中添加以下代碼,生成靜態庫文件:
[package] name = "mylog" version = "0.1.0" edition = "2021" [lib] name = "rust_log" crate-type = ["staticlib"] path = "src/lib.rs" [dependencies] libc = "0.2"
1.3、編譯靜態庫,生成的靜態庫在src/target/release目錄下,具體編譯命令如下:
cargo build --release
2、使用cbindgen生成靜態庫頭文件
2.1 新建 cbindgen.toml
文件,添加:language = "C"
默認已經安裝了cbindgen。
2.2 cbindgen生成頭文件:
cbindgen --config cbindgen.toml --crate mylog --output rust_log.h
生成的文件內容如下:
#include <stdarg.h> #include <stdbool.h> #include <stdint.h> #include <stdlib.h> typedef struct RustLogMessage { int id; const char *msg; } RustLogMessage; void rust_log(struct RustLogMessage msg);
3、新建C語言代碼並編譯
3.1 新建C語言代碼, mymain.c:
#include <stdio.h> #include <stdlib.h> #include "rust_log.h" // include header file int main() { for (int i = 0; i < 10; i++) { RustLogMessage msg = { id : i, msg : "string in C language\n", }; rust_log(msg); } return 0; }
3.2 編譯:
gcc -o main mymain.c -I. -Lmylog/target/release -lrust_log -ldl -lpthread -Wl,-gc-section
3.3 運行程序,輸出如下:
id:0 message: "string in C language\n" id:1 message: "string in C language\n" id:2 message: "string in C language\n" id:3 message: "string in C language\n" id:4 message: "string in C language\n" id:5 message: "string in C language\n" id:6 message: "string in C language\n" id:7 message: "string in C language\n" id:8 message: "string in C language\n" id:9 message: "string in C language\n"