如果目录结构如下所示:
src/main.rs
src/module1/blah.rs
src/module1/blah2.rs
src/utils/logging.rs
如何使用其他文件中的函数?
从Rust教程中,听起来我应该能够做到这一点:
主文件.rs
mod utils { pub mod logging; }
mod module1 { pub mod blah; }
fn main() {
utils::logging::trace("Logging works");
module1::blah::doit();
}
日志记录.rs
pub fn trace(msg: &str) {
println!(": {}\n", msg);
}
废话
mod blah2;
pub fn doit() {
blah2::doit();
}
blah2.rs
mod utils { pub mod logging; }
pub fn doit() {
utils::logging::trace("Blah2 invoked");
}
但是,这会产生一个错误:
error[E0583]: file not found for module `logging`
--> src/main.rs:1:21
|
1 | mod utils { pub mod logging; }
| ^^^^^^^
|
= help: name the file either logging.rs or logging/mod.rs inside the directory "src/utils"
看起来,沿着路径向下导入(即从main
到module1/blah.rs
)是有效的,导入对等体(即从blah
到blah2
)是有效的,但从父作用域导入则无效。
如果我使用神奇的#[path]
指令,就可以实现以下功能:
blah2.rs
#[path="../utils/logging.rs"]
mod logging;
pub fn doit() {
logging::trace("Blah2 invoked");
}
我真的必须手动使用相对文件路径从父作用域级别导入一些东西吗?在Rust中没有更好的方法来做到这一点吗?
在Python中,我们使用from .blah import x
作为局部作用域,但是如果你想访问一个绝对路径,你可以使用from project.namespace.blah import x
。
5条答案
按热度按时间l7mqbcuq1#
我也要回答这个问题,对于任何其他人谁发现这一点,是(像我一样)完全困惑的难以理解的答案。
它归结为两件事,我觉得在教程中解释得很差:
mod blah;
语法为编译器导入一个文件。你**必须在所有你想编译的文件上使用这个语法。use blah::blah;
将定义的任何本地模块导入到当前作用域中。一个典型的例子是:
在这种情况下,可以使用
use
将two.rs
中的代码放入one.rs
中:但是,
main.rs
必须类似于:请注意,您可以使用
blah/mod.rs
文件来稍微减轻这种尴尬,方法是放置类似one/mod.rs
的文件,因为mod x;
尝试将x.rs
和x/mod.rs
作为加载。您可以将www.example.com顶部笨拙的文件导入减少main.rs到:
在Github上有一个这样做的示例项目。
值得注意的是,模块独立于包含代码块的文件;虽然加载
blah.rs
文件的唯一方法是创建一个名为blah
的模块,但是如果出于某种原因需要,可以使用#[path]
来解决这个问题。不幸的是,它似乎不支持通配符,将多个文件中的函数聚合到一个顶级模块中是相当乏味的。irtuqstp2#
我假设您希望在顶层声明
utils
和utils::logging
,并且只希望在module1::blah::blah2
中从它们调用函数。模块的声明是用mod
完成的,mod
将其插入AST并定义其规范的foo::bar::baz
样式路径,与模块的正常交互(远离声明)是用use
完成的。我做的唯一更改是
blah2
中的use crate::utils;
行(在Rust 2015中,您还可以使用use utils
或use ::utils
)。有关use
如何工作的更多详细信息,请参见此答案的后半部分。relevant section of The Rust Programming Language也是一个合理的参考,特别是以下两个小节:另外,请注意,我将其全部内联编写,将
foo/bar.rs
的内容直接放置在mod foo { mod bar { <contents> } }
中,将其更改为mod foo { mod bar; }
,相关文件应该是相同的。(By
println(": {}\n", msg)
打印两个新行;println!
已经包含一个(ln
是“行”),print!(": {}\n", msg)
或println!(": {}", msg)
只打印一个。)要得到您想要的确切结构并不符合惯例,您必须对blah2.rs的位置做一个更改:
main.rs
实用程序/logging.rs
第1单元/blah.rs
module 1/blah/blah2.rs(唯一需要更改的文件)
bvhaajcl3#
我知道这是一个很老的职位,可能没有使用2018年。但是,这仍然是真的很棘手,我想帮助那些正在寻找。
因为图片胜过千言万语,所以我简化了代码分割。
然后,正如您可能猜到的,它们都有一个空的pub fn some_function()。
我们可以通过对主
的更改来进一步扩展这一点
nested_mod x1c4d 1x的其他更改
现在让我们回过头来回答这个问题:我们在mod_1中添加了blah 1和blah 2。我们添加了一个utils,其中包含另一个mod日志,调用了一些fn。我们的mod_1/mod.rs现在包含:
我们创建了一个utils/mod.rs,在main中使用,包含:
然后是一个名为logging/的目录和另一个mod.rs,我们可以在其中将fns放入logging以进行导入。
源代码也在此处https://github.com/DavidWhit/Rust_Modules
另外,请查看第7章中的库示例,以及Rust Book中进一步扩展了工作空间拆分的14.3。祝你好运!
vq8itlhq4#
这里的答案对我来说并不清楚,所以我将把我的两分钱给未来的 rust 虫。
您需要做的就是通过
src/main.rs
在src/main.rs
中声明所有文件(当然还有fn main)。通过
pub
公开所有你需要在外部使用的东西(复制粘贴原始的src/utils/logging.rs
),然后通过crate::
简单地声明use
的模块。将
crate::
看作~/
,其中~
是cargo项目的src
文件夹,还有一个关键字super::
可以从当前目录访问(如./
)。为了得到一个更清晰的答案,我稍微打乱了一些函数。
3yhwsihp5#
如果你创建了一个名为
mod.rs
的文件,rustc
在导入模块时会查看它,我建议你创建一个文件src/utils/mod.rs
,并使其内容如下所示:然后,在
main.rs
中添加如下语句:然后用
或者你可以
基本上,在
mod.rs
文件中声明模块,在源文件中声明use
。