如果您有这样的目录结构:
src/main.rs
src/module1/blah.rs
src/module1/blah2.rs
src/utils/logging.rs
Run Code Online (Sandbox Code Playgroud)
你如何使用其他文件中的函数?
从Rust教程,听起来我应该能够做到这一点:
main.rs
mod utils { pub mod logging; }
mod module1 { pub mod blah; }
fn main() {
utils::logging::trace("Logging works");
module1::blah::doit();
}
Run Code Online (Sandbox Code Playgroud)
logging.rs
pub fn trace(msg: &str) {
println!(": {}\n", msg);
}
Run Code Online (Sandbox Code Playgroud)
blah.rs
mod blah2;
pub fn doit() {
blah2::doit();
}
Run Code Online (Sandbox Code Playgroud)
blah2.rs
mod utils { pub mod logging; }
pub fn doit() {
utils::logging::trace("Blah2 invoked");
}
Run Code Online (Sandbox Code Playgroud)
但是,这会产生错误:
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"
Run Code Online (Sandbox Code Playgroud)
看起来导入路径,即从导入main到module1/blah.rs工作,导入对等,即blah2从blah作品导入,但从父作用域导入不会.
如果我使用魔法#[path]指令,我可以使这项工作:
blah2.rs
#[path="../utils/logging.rs"]
mod logging;
pub fn doit() {
logging::trace("Blah2 invoked");
}
Run Code Online (Sandbox Code Playgroud)
我是否真的必须手动使用相对文件路径从父作用域级别导入内容?在Rust中有没有更好的方法呢?
在Python中,您from .blah import x用于本地范围,但是如果要访问可以使用的绝对路径from project.namespace.blah import x.
Dou*_*oug 28
我也要回答这个问题,对于那些发现这个问题并且(像我一样)完全被难以理解的答案搞糊涂的人.
归结为我觉得在教程中解释不好的两件事:
该mod blah;语法导入文件的编译器.您必须在要编译的所有文件上使用它.
除了共享库之外,还可以使用任何已定义的本地模块导入到当前作用域中use blah::blah;.
一个典型的例子是:
src/main.rs
src/one/one.rs
src/two/two.rs
Run Code Online (Sandbox Code Playgroud)
在这种情况下,你可以有代码one.rs的two.rs使用use:
use two::two; // <-- Imports two::two into the local scope as 'two::'
pub fn bar() {
println!("one");
two::foo();
}
Run Code Online (Sandbox Code Playgroud)
但是,main.rs必须是这样的:
use one::one::bar; // <-- Use one::one::bar
mod one { pub mod one; } // <-- Awkwardly import one.rs as a file to compile.
// Notice how we have to awkwardly import two/two.rs even though we don't
// actually use it in this file; if we don't, then the compiler will never
// load it, and one/one.rs will be unable to resolve two::two.
mod two { pub mod two; }
fn main() {
bar();
}
Run Code Online (Sandbox Code Playgroud)
请注意,您可以blah/mod.rs通过放置文件来使用该文件来稍微减轻尴尬one/mod.rs,因为mod x;尝试x.rs和x/mod.rs加载.
// one/mod.rs
pub mod one.rs
Run Code Online (Sandbox Code Playgroud)
您可以将main.rs顶部的笨拙文件导入减少到:
use one::one::bar;
mod one; // <-- Loads one/mod.rs, which loads one/one.rs.
mod two; // <-- This is still awkward since we don't two, but unavoidable.
fn main() {
bar();
}
Run Code Online (Sandbox Code Playgroud)
在Github上有一个示例项目.
值得注意的是,模块独立于代码块所包含的文件; 虽然看起来加载文件的唯一方法blah.rs是创建一个名为的模块,如果你出于某种原因需要blah,可以使用它#[path]来解决这个问题.不幸的是,它似乎不支持通配符,将多个文件中的函数聚合到顶级模块中相当繁琐.
huo*_*uon 25
我假设您要声明utils并utils::logging处于顶层,并希望从内部调用函数module1::blah::blah2.完成模块的声明mod,将其插入AST并定义其规范foo::bar::baz式路径,并与模块(远离声明)进行正常交互use.
// main.rs
mod utils {
pub mod logging { // could be placed in utils/logging.rs
pub fn trace(msg: &str) {
println!(": {}\n", msg);
}
}
}
mod module1 {
pub mod blah { // in module1/blah.rs
mod blah2 { // in module1/blah2.rs
// *** this line is the key, to bring utils into scope ***
use crate::utils;
pub fn doit() {
utils::logging::trace("Blah2 invoked");
}
}
pub fn doit() {
blah2::doit();
}
}
}
fn main() {
utils::logging::trace("Logging works");
module1::blah::doit();
}
Run Code Online (Sandbox Code Playgroud)
我做的唯一改变是use crate::utils;线路blah2.另请参阅本答案的后半部分,了解有关use utils工作原理的更多详细信息.The Rust Programming Language的相关部分也是一个合理的参考,特别是这两个小节:
另外,请注意我将其全部内联写入use ::utils,use直接放入内容,将其更改为foo/bar.rs可用的相关文件应该是相同的.
(顺便说一句,mod foo { mod bar { <contents> } }打印了两个新的线; mod foo { mod bar; }包括一个已经(在println(": {}\n", msg)为"线"),无论是println!或ln打印唯一的一个.)
要获得您想要的确切结构:
src
??? main.rs
??? module1
? ??? blah
? ? ??? blah2.rs
? ??? blah.rs
??? utils
??? logging.rs
Run Code Online (Sandbox Code Playgroud)
mod utils {
pub mod logging;
}
mod module1 {
pub mod blah;
}
fn main() {
utils::logging::trace("Logging works");
module1::blah::doit();
}
Run Code Online (Sandbox Code Playgroud)
pub fn trace(msg: &str) {
println!(": {}\n", msg);
}
Run Code Online (Sandbox Code Playgroud)
mod blah2;
pub fn doit() {
blah2::doit();
}
Run Code Online (Sandbox Code Playgroud)
我意识到这是一篇非常旧的帖子,可能没有使用 2018 年。但是,这仍然非常棘手,我想帮助那些正在寻找的人。
因为图片胜过一千个单词,所以我将其简化为代码分割。
然后,正如您可能猜到的那样,它们都有一个空的 pub fn some_function()。
现在让我们回过头来回答这个问题:我们将 blah1 和 blah2 添加到 mod_1 我们添加了一个 utils,其中包含另一个 mod 日志记录,它调用一些 fn。我们的 mod_1/mod.rs 现在包含:
pub mod blah.rs
pub mod blah2.rs
Run Code Online (Sandbox Code Playgroud)
我们创建了一个在 main 中使用的 utils/mod.rs,其中包含:
pub mod logging
Run Code Online (Sandbox Code Playgroud)
然后是一个名为logging/的目录,其中包含另一个mod.rs,我们可以将fns放入logging中以进行导入。
来源也在这里https://github.com/DavidWhit/Rust_Modules
另请参阅第 7 章中的库示例和 14.3,后者进一步扩展了 Rust Book 中工作空间的拆分。祝你好运!