使用cargo new创建项目时,有项目类型的选项:

  • —bin:编译为可执行文件
  • —lib:编译为库文件

默认的,是—lib。事实上,Rust能创建的库的种类有下面几种:

  • rlib:Rust库,这是cargo new默认的种类,只能被Rust调用;
  • dylib:Rust规范的动态链接库,windows上编译成.dll,linux上编译成.so,也只能被Rust调用;
  • cdylib:满足C语言规范的动态链接库,windows上编译成.dll,linux上编译成.so,可以被其他语言调用
  • staticlib:静态库,windows上编译成.lib,linux上编译成.a,可以被其他语言调用

只是被Rust调用的话,默认的rlib是最好的选择,如果想用其他的种类,无法直接使用cargo指定,只能手动修改Cargo.toml。

  1. [lib]
  2. crate-type = ["rlib", "dylib", "cdylib", "staticlib"]

cargo允许同时设置多种类型,同一套代码,同时编译为多种类型。

创建numrust库

可以使用cargo创建项目:

  1. cargo new numrust

也可以使用Clion为我们创建,两者创建的文件是相同的:

使用Rust创建库,并在exe中调用 - 图1

在库中创建mod

Rust使用mod关键字创建命名空间,自动生成的代码中,已经包含了一个mod tests:

  1. #[cfg(test)]
  2. mod tests {
  3. #[test]
  4. fn it_works() {
  5. assert_eq!(2 + 2, 4);
  6. }
  7. }

mod默认为私有,也就是说,这个tests并不会被库导出,它是为我们测试而准备的。我们可以创建自己的mod:

  1. pub mod numrust { // 创建公有的mod
  2. pub fn hello() { // 创建公有的函数
  3. println!("hello numrust")
  4. }
  5. }

要想在tests中调用,需要了解mod的路径规则。Rust使用“::”来分隔命名空间,使用crate、self、super三个关键字来表示路径的起点:

  • crate:类似于根目录
  • self:指当前mod,类似于“.”
  • super:指当前mod的父mod,类似于“..”

numrust与tests是同级的,所以在tests中调用numrust有两种方式:

  1. crate::numrust::hello();
  2. super::numrust::hello();

除此之外,还可以使用use引用mod。在Python中,人们都习惯这样引入numpy:

  1. import numpy as np

这在Rust中同样可以:

  1. #[cfg(test)]
  2. mod tests {
  3. use super::numrust as nr;
  4. #[test]
  5. fn it_works() {
  6. nr::hello();
  7. assert_eq!(2 + 2, 4);
  8. }
  9. }

要调试我们的库,可以直接使用命令:

  1. > cargo test
  2. Finished test [unoptimized + debuginfo] target(s) in 0.01s
  3. Running unittests (target\debug\deps\numrust-0bda5bdf4b187237.exe)
  4. running 1 test
  5. test tests::it_works ... ok
  6. test result: ok. 1 passed; 0 failed; 0 ignored; 0 measured; 0 filtered out; finished in 0.00s

也可以在Clion中运行:

使用Rust创建库,并在exe中调用 - 图2

在exe中调用库

下面再创建一个可执行的项目,来调用刚刚的库。

  1. cargo new --bin numrustexe

可使用Clion创建:

使用Rust创建库,并在exe中调用 - 图3

然后修改Cargo.toml,指定库项目Cargo.toml所在的目录:

  1. [dependencies]
  2. numrust = { path = "../numrust" }

然后修改main.rs:

  1. extern crate numrust; // 导入外部crate
  2. use numrust::numrust as nr; // 引用numrust,第一个为库名,第二个为库中mod的名称
  3. fn main() {
  4. nr::hello();
  5. }

到此,就可以运行了:

  1. > cargo run
  2. Compiling numrustexe v0.1.0 (C:\Users\zhangmh\Desktop\MarkDown\numrust\code\numrustexe)
  3. Finished dev [unoptimized + debuginfo] target(s) in 0.78s
  4. Running `target\debug\numrustexe.exe`
  5. hello numrust

当numrust库被修改时,cargo会先编译numrust,然后再编译numrustexe,保证每次运行都是最新的结果。