Rust中的跨模块函数调用

6

我想从另一个模块中调用某个模块的函数(为了代码因素、组织等方面)。以下是我的箱子结构:

➜  mod_test git:(master) ✗ tree
.
├── Cargo.lock
├── Cargo.toml
└── src
    ├── bin
    │   └── one.rs
    ├── lib
    │   └── two.rs
    └── main.rs

3 directories, 5 files

main函数中,我声明:

pub mod bin {
    pub mod one;
}
pub mod lib {
    pub mod two;
}

所有这些文件只包含一个简单的pub fn main() {println!("hello");}

此时一切正常。

现在,是否可能从bin / one.rs调用lib :: two :: main

bin / one.rs中添加的use crate :: lib :: two;use super :: lib :: two;use self :: super :: lib :: two;都不起作用。


  • 编辑:我在Linux 5.3.0-45-generic上安装了rustc 1.42.0(b8cedc004 2020-03-09),如果有必要。

  • 编辑2:每当使用super关键字时,我都会从rustc获得这个神秘的错误:

error[E0433]: failed to resolve: there are too many leading `super` keywords

我找不到任何关于这个问题的故障排除方法。

  • 编辑3:在src中添加一个lib.rs文件,声明lib模块结构,并在one.rs中编写use mod_test::lib::two;可以解决问题,但是:

    1)这违反了不在我的包中产生“愚蠢的模块声明文件”的想法。

    2)我必须在两个不同的地方(main.rslib.rs中)完全复制相同的信息。

    3)使用use mod_test::lib::two;是唯一有效的语法,使用cratesuper关键字仍然会导致晦涩的编译器错误。

1个回答

7

src/bin是Cargo中的一个特殊目录名。当你运行cargo build时,该目录中的文件将被编译为独立的二进制文件。编译为二进制文件后,它们不会成为在main.rslib.rs中定义的crate结构的一部分。

如果你只想在main.rs中使用bin::one作为模块,那么你已经做对了!你得到的错误消息来自于编译one.rs作为独立二进制文件,而不是从编译带有bin::one作为模块的main.rs文件。如果你运行cargo run --bin <name-of-project>,编译将成功,并且它将运行main.rs中的程序。

要告诉Cargo不要单独编译one.rs,我建议你将bin目录重命名。这不仅解决了技术问题,而且不太可能会让其他程序员阅读项目时感到困惑,因为他们期望bin包含二进制文件。可能有某种方法可以防止Cargo以这种方式特殊处理bin;但是,重命名它可能是最好的选择。

如果你确实想要将one.rs编译为使用two的单独可执行文件,则必须在与main.rs相同的目录中创建一个lib.rs文件。这也是Cargo的特殊文件,它定义了库crate的模块结构。

// lib.rs
pub mod lib { /* note: this lib is not related to lib.rs; just unfortunately named */
    pub mod two;
}

然后在one.rs中,写下 use <crate-name>::lib::two;

// bin/one.rs
use mod_test::lib::two;

crate::lib::two无法使用,因为bin目录中的文件被编译为独立的二进制文件而不是作为crate成员;因此,您必须通过其“外部”名称调用crate。

在src中添加lib.rs文件来声明lib模块结构,在one.rs中编写"use mod_test::lib::two;"可行,但是:

1)这违反了不在我的crate中产生“愚蠢的模块声明文件”的想法。

2)我必须在两个不同的地方(main.rs和lib.rs中)完全复制相同的信息。

main.rslib.rs两个不同的crate根目录。它们允许具有不同的结构。除非您要生成二进制文件和库文件,否则不需要两者都存在。如果要从任何二进制文件(包括main.rs)中使用库crate,那么只需使用use即可:

use mod_test;

参考资料


1
非常感谢!我想我困惑的是创建一个bin/和lib/会导致两个不同的crate roots。 - Warpig

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接