我有4个文件:
main.rs
mod bar;
fn main() {
let v = vec![1, 2, 3];
println!("Hello, world!");
}
Run Code Online (Sandbox Code Playgroud)
lib.rs
pub mod foo;
pub mod bar;
Run Code Online (Sandbox Code Playgroud)
foo.rs
pub fn say_foo() {
}
Run Code Online (Sandbox Code Playgroud)
bar.rs
use crate::foo;
fn bar() {
foo::say_foo();
}
Run Code Online (Sandbox Code Playgroud)
运行时cargo run出现错误消息:
mod bar;
fn main() {
let v = vec![1, 2, 3];
println!("Hello, world!");
}
Run Code Online (Sandbox Code Playgroud)
有人可以向我解释如何解决此问题吗?更广泛地说:当存在a main.rs和a 时,模块查找如何工作lib.rs?我觉得很混乱
编辑:添加mod foo以main.rs解决此问题。但是我不明白这一点,给我的印象lib.rs是,这个地方“暴露”了我所有的模块?为什么也必须在其中声明模块main.rs?
我的Cargo.toml:
pub mod foo;
pub mod bar;
Run Code Online (Sandbox Code Playgroud)
L.Y*_*Sim 24
简而言之,Rust 官方书是这样说的:
如果一个包包含
src/main.rsandsrc/lib.rs,它有两个包:一个库和一个二进制文件,两者都与包同名。
此外,Rust 参考文献说:
crate解析相对于当前 crate 的路径
因此,您的项目中实际上有两个 crate,crate限定符解析到哪个 crate取决于您调用它的位置。
现在在你的代码示例中,如果你想要编译你必须 mod bar;从src/main.rs. 否则,您将声明它bar是两个板条箱中的模块。
在你删除它之后,然后因为src/lib.rs你有:
pub mod foo;
pub mod bar;
Run Code Online (Sandbox Code Playgroud)
bar现在将是src/lib.rs's crate 中的一个模块,因此cratein 中的限定符bar.rs将引用src/lib.rs's hello-worldcrate,这就是您想要的。
还有一件事,如果您想访问src/lib.rsfrom中公开的项目src/main.rs,您必须按照@zrzka 所说的去做,即命名两者src/lib.rs和src/main.rs共享的 crate 的名称。例如,在您名为 的项目中hello-world:
use hello_world::foo;
fn main() {
foo::say_foo();
}
Run Code Online (Sandbox Code Playgroud)
是如何将foo声明的模块导入src/lib.rs到src/main.rs.
然而,导入行为似乎并没有以其他方式工作。即,如果您在 中声明了一些公共模块src/main.rs,src/lib.rs即使您指定了 crate 的名称,也无法将其导入到crate 中。我找不到描述此行为的文档,但通过在 Rust 1.37.0 中对其进行测试,情况似乎确实如此。
Let's start from the beginning. Look at the Package Layout chapter in The Cargo Book. As you can see, your package can contain lot of stuff:
Not all of the possibilities are listed here, just the binary / library combinations.
This is an example of a package with single binary. Entry point is the main function in the src/main.rs.
Cargo.toml:
[package]
name = "hallo"
version = "0.1.0"
edition = "2018"
Run Code Online (Sandbox Code Playgroud)
src/main.rs:
[package]
name = "hallo"
version = "0.1.0"
edition = "2018"
Run Code Online (Sandbox Code Playgroud)
fn main() {
println!("Hallo, Rust here!")
}
Run Code Online (Sandbox Code Playgroud)
This is an example of a package with a library. Libraries don't have entry points, you can't run them. They're used for functionality sharing.
Cargo.toml:
[package]
name = "hallo"
version = "0.1.0"
edition = "2018"
Run Code Online (Sandbox Code Playgroud)
src/lib.rs:
$ cargo run
Hallo, Rust here!
Run Code Online (Sandbox Code Playgroud)
[package]
name = "hallo"
version = "0.1.0"
edition = "2018"
Run Code Online (Sandbox Code Playgroud)
Do you see anything in the Cargo.toml file about a binary or a library? No. The reason is that I've followed the Package Layout and the cargo knows where to look for things.
This is an example of a package with a binary and a library.
Cargo.toml:
[package]
name = "hallo"
version = "0.1.0"
edition = "2018"
Run Code Online (Sandbox Code Playgroud)
src/lib.rs:
pub fn foo() {
println!("Hallo, Rust library here!")
}
Run Code Online (Sandbox Code Playgroud)
src/main.rs:
$ cargo run
error: a bin target must be available for `cargo run`
Run Code Online (Sandbox Code Playgroud)
Same question, do you see anything in the Cargo.toml file about a binary or a library? No.
This package contains two things:
src/main.rs, entry point src/main.rs::main),src/lib.rs, shared code).A library can be referenced from the binary via use hallo::... where the hallo is this package name (Cargo.toml -> [package] -> name).
Cargo.toml:
[package]
name = "hallo"
version = "0.1.0"
edition = "2018"
Run Code Online (Sandbox Code Playgroud)
src/lib.rs:
[package]
name = "hallo"
version = "0.1.0"
edition = "2018"
Run Code Online (Sandbox Code Playgroud)
src/foo.rs:
pub const GREETING: &'static str = "Hallo, Rust library here!";
Run Code Online (Sandbox Code Playgroud)
src/bar.rs:
use hallo::GREETING;
fn main() {
println!("{}", GREETING);
}
Run Code Online (Sandbox Code Playgroud)
crate refers to src/lib.rs, because we're in the context of our library here.
Treat it as a standalone unit and refer to it via use hallo::...; from the outside world.
src/main.rs:
[package]
name = "hallo"
version = "0.1.0"
edition = "2018"
Run Code Online (Sandbox Code Playgroud)
Here we're just using our library.
Same code, but lib.rs was renamed to utils.rs and (foo|bar).rs files were moved to the src/utils/ folder.
src/utils.rs:
pub mod bar;
pub mod foo;
Run Code Online (Sandbox Code Playgroud)
src/utils/foo.rs:
pub fn say_foo() {
println!("Foo");
}
Run Code Online (Sandbox Code Playgroud)
src/utils/bar.rs:
use crate::foo;
pub fn bar() {
foo::say_foo();
}
Run Code Online (Sandbox Code Playgroud)
We can use crate here as well, but because we're in the context of our binary, the path differs.
src/main.rs:
use hallo::bar::bar;
fn main() {
bar();
}
Run Code Online (Sandbox Code Playgroud)
Here we just declared another module (utils) and we're using it.
Cargo.toml content:
[package]
name = "hallo"
version = "0.1.0"
edition = "2018"
Run Code Online (Sandbox Code Playgroud)
If there's a src/main.rs file, you're basically saying this:
[package]
name = "hallo"
version = "0.1.0"
edition = "2018"
[[bin]]
name = "hallo"
src = "src/main.rs"
Run Code Online (Sandbox Code Playgroud)
If there's a src/lib.rs file, you're basically saying this:
[package]
name = "hallo"
version = "0.1.0"
edition = "2018"
[lib]
name = "hallo"
path = "src/lib.rs"
Run Code Online (Sandbox Code Playgroud)
If there're both of them, you're basically saying this:
[package]
name = "hallo"
version = "0.1.0"
edition = "2018"
[[bin]]
name = "hallo"
path = "src/main.rs"
[lib]
name = "hallo"
path = "src/lib.rs"
Run Code Online (Sandbox Code Playgroud)
在lib.rs和main.rs文件是你的包两个独立的入口点。
当您使用cargo run(或构建二进制文件并显式运行它)时,要使用的入口点是main.rs,crate关键字是指二进制文件箱。它甚至没有要知道,有一些是在lib.rs:二进制将把库,因为这将任何其他外部包装箱,而且必须进口,通过extern crate hello_world或例如,use hello_world::foo。
但是,当您导入库时,入口点是lib.rs,而crate是library crate。在这种情况下,是的,您添加的所有内容都lib.rs暴露在整个 crate 中。
在这种情况下,通常的工作流程是使二进制文件类似于库周围的薄包装 - 在某些极端情况下,它main.rs只会包含类似的内容
use library;
fn main() {
library::main();
}
Run Code Online (Sandbox Code Playgroud)
整个逻辑(以及所有项目结构)都进入了库箱。原因之一正是您遇到的情况:可能会混淆是否在包中的每个板条箱中导入此具体模块。
| 归档时间: |
|
| 查看次数: |
551 次 |
| 最近记录: |