本文将分别介绍在Windows和MacOS的环境下,在C中调用Rust的库函数的方法和步骤。
Windows
默认你已经安装了Visual Studio 2019 community并勾选了C/C++开发以及Windows 10 SDK的部分
首先我们要在命令行中使用cl.exe
,即MVSC中的C/C++编译器,具体可看这篇文章
关于Rust的部分
初始化一个新的库
> cd Desktop
> cargo new --lib bridge_c
在Cargo.toml
中添加
[lib]
crate-type = ["cdylib"]
这样,编译后生成的动态链接库xxx.dll可供C调用。
重新编辑bridge_c/src/lib.rs
#[no_mangle]
pub extern "C" fn bridge_c() {
println!("A hello from Rust :)");
}
使用cbindgen
生成对应的头文件,将bridge.h
拖放到桌面上备用
> cbindgen bridge_c/src/lib.rs -l c > "bridge.h"
上述步骤都完成后,开始编译该库
> cargo build --release
把bridge_c/target/release
目录下的bridge_c.dll.lib
和bridge_c.dll
拖放到桌面上备用。
关于C的部分
在Desktop
目录下新建一个文件夹hello
,把桌面上的bridge.h
,bridge_c.dll.lib
和bridge_c.dll
拖到hello
目录下。
在hello
目录下新建一个main.c
文件,写上:
#include "bridge.h"
int main(int argc, char const *argv[])
{
bridge_c();
return 0;
}
接下来开始编译main.c
> cd hello
> cl.exe /Iheaders/ bridge_c.dll.lib main.c
运行main.exe
> main.exe
A hello from Rust :)
如果报错中出现"undefined_symbols"
的字样,多半是配置cl.exe
时环境变量设置的不对,届时请仔细阅读前述提到的那篇文章。
MacOS
默认你已经安装了Xcode的最新版,并且执行过
xcode-select --install
在mac上的交互与上述有些细小的差别。
关于Rust的部分
$ cd Desktop
$ cargo new --lib bridge_c
这次我们使用静态库,即在Cargo.toml
中添加
[lib]
crate-type = ["lib", "staticlib"]
我们也可以添加依赖,例如
[dependencies]
ferris-says = "0.1"
bridge_c/src/lib.rs
改为
use std::io::{stdout, BufWriter};
#[no_mangle]
pub extern "C" fn hello_devworld() {
let phrase = b"Hello, /dev/world/2019!";
let stdout = stdout();
let mut writer = BufWriter::new(stdout.lock());
ferris_says::say(phrase, 30, &mut writer).unwrap();
}
cbindgen
生成头文件:
cbindgen bridge_c/src/lib.rs -l c > "bridge.h"
编译库:
$ cargo build --release
把target/release
目录下的libbridge_c.a
和bridge.h
拖到桌面上备用
除此之外,我们还需要一个信息,即在编译C时需要哪些本地库
$ cargo rustc -- --print native-static-libs
Compiling ...
note: Link against the following native artifacts when linking against this static library. The order and any duplication can be significant on some platforms.
note: native-static-libs: -lSystem -lresolv -lc -lm
Finished dev [unoptimized + debuginfo] target(s) in 9.95s
注意note: native-static-libs:
后的几个选项,一会儿要用。
关于C的部分
$ mkdir hello
把libbridge_c.a
和bridge.h
拖到hello
文件夹中,新建main.c
$ touch main.c
编辑main.c的内容为:
#include "bridge.h"
int main() {
hello_devworld();
return 0;
}
编译main.c
$ cc main.c libbridge_c.a -lSystem -lresolv -lc -lm -o main
运行main
$ ./main
----------------------------------
| Hello, /dev/world/2019! |
----------------------------------
\
\
_~^~^~_
\) / o o \ (/
'_ - _'
/ '-----' \
成功啦~
参考链接: