How to call a function in another file but the same crate?

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!

3 Likes

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.

6 Likes

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?

1 Like

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.

2 Likes

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.

2 Likes

@senator, you probably want to go back to The Book and read the modules section, that should explain everything for you.

2 Likes