Hi guys. I am from a C/C++ background. I just found out that the linking model of rust is very different from that of C/C++. In C/C++, you can call a function implemented in another file very easily, just declare it, and insert the implementation file into the project, and you are done. But in rust, if you need to call a function not in the same file, you need to import it from another crate. Therefore my question is how can I call a function in another file but in the same crate? Suppose now that we have two files, main.rs and sub.rs
main.rs
fn main() {
sub();
}
sub.rs
fn sub() {
println!("Hello world");
}
I want to know how to modify the two files so that they can both successfully compile. And how can I use rustc to link the two files and obtain main.exe? Please do not tell me I can use cargo, because cargo also does it by calling rustc.
Thanks!
In main.rs, you need to declare sub.rs as a module:
mod sub;
Note also that sub() is currently private to its owning module (i.e. sub). You need to make it public if you want it callable outside the sub module: pub fn sub() {...}.
Once you have that, you can then do:
fn main() {
sub::sub();
}
Alternatively, you can import just the sub function itself:
mod sub;
use sub::sub;
fn main() {
sub();
}
As for rustc, you can run cargo with a verbose flag (e.g. cargo build -v ...) and then look at how it invokes rustc.
I have tried according to your suggestions. But they still won't compile. Error message below:
D:\Computer\test\hello>edit src\main.rs
D:\Computer\test\hello>cargo build
Compiling hello v0.1.0 (file:///D:/Computer/test/hello)
error[E0423]: expected function, found module sub::sub
--> src\main.rs:4:5
|
4 | sub::sub();
| ^^^^^^^^ not a function
help: possible better candidate is found in another module, you can import it in
to scope
|
1 | use sub::sub::sub;
|
error[E0603]: module sub is private
--> src\main.rs:4:5
|
4 | sub::sub();
| ^^^^^^^^
error: aborting due to 2 previous errors
error: Could not compile hello.
To learn more, run the command again with --verbose.
D:\Computer\test\hello>
Is what you had in the original post the entire contents of each of those files? If not, can you paste exactly what you have?
D:\Computer\test\hello>type src\main.rs
mod sub;
fn main() {
sub::sub();
}
D:\Computer\test\hello>type src\sub.rs
mod sub {
pub fn sub() {
println!("Hello, world!");
}
}
D:\Computer\test\hello>
In sub.rs, you don't need the mod sub there - the file is already a module called sub by virtue of the file name being sub.rs. What you have there creates two sub modules, one nested within the other.
They now successfully compile! Thank you! Even the command does the job:
rustc main.rs
But how about if the project is a library? Because in a library there is no single clear entry point and rustc does not know which is the main file of the library.
The default main file of a library crate is lib.rs, just like it is main.rs for a binary crate.
@senator, you probably want to go back to The Book and read the modules section, that should explain everything for you.