Come includere un modulo da un altro file dello stesso progetto?


130

Seguendo questa guida ho creato un progetto Cargo.

src/main.rs

fn main() {
    hello::print_hello();
}

mod hello {
    pub fn print_hello() {
        println!("Hello, world!");
    }
}

che corro usando

cargo build && cargo run

e si compila senza errori. Ora sto cercando di dividere il modulo principale in due ma non riesco a capire come includere un modulo da un altro file.

Il mio albero del progetto è simile a questo

├── src
    ├── hello.rs
    └── main.rs

e il contenuto dei file:

src/main.rs

use hello;

fn main() {
    hello::print_hello();
}

src/hello.rs

mod hello {
    pub fn print_hello() {
        println!("Hello, world!");
    }
}

Quando lo compilo con cargo buildottengo

error[E0432]: unresolved import `hello`
 --> src/main.rs:1:5
  |
1 | use hello;
  |     ^^^^^ no `hello` external crate

Ho provato a seguire i suggerimenti del compilatore e modificato main.rsin:

#![feature(globs)]

extern crate hello;

use hello::*;

fn main() {
    hello::print_hello();
}

Ma questo ancora non aiuta molto, ora ho capito:

error[E0463]: can't find crate for `hello`
 --> src/main.rs:3:1
  |
3 | extern crate hello;
  | ^^^^^^^^^^^^^^^^^^^ can't find crate

C'è un banale esempio di come includere un modulo dal progetto corrente nel file principale del progetto?


1
possibile duplicato delle importazioni di base Rust (include)
Levans

Risposte:


239

Non hai bisogno di mod hellonel tuo hello.rsfile. Il codice in qualsiasi file tranne la radice di crate ( main.rsper gli eseguibili, lib.rsper le librerie) viene automaticamente posizionato in un modulo.

Per includere il codice da hello.rsnel tuo main.rs, usa mod hello;. Viene espanso al codice che si trova in hello.rs(esattamente come avevi prima). La struttura del file continua la stessa e il codice deve essere leggermente modificato:

main.rs:

mod hello;

fn main() {
    hello::print_hello();
}

hello.rs:

pub fn print_hello() {
    println!("Hello, world!");
}

1
Late Question non funzionerebbe anche se lo specifichi con use hello anziché mod hello?
Christian Schmitt,

16
@ChristianSchmitt No, sono cose diverse. useè solo una cosa dello spazio dei nomi, mentre modtira nel file. Si utilizzerebbe use, ad esempio, per poter chiamare la print_hellofunzione senza dover
aggiungere il

25

Se desideri avere moduli nidificati ...

Ruggine 2018

Non è più necessario disporre del file mod.rs(sebbene sia ancora supportato). L'alternativa idiomatica è dare al file il nome del modulo:

$ tree src
src
├── main.rs
├── my
│   ├── inaccessible.rs
│   └── nested.rs
└── my.rs

main.rs

mod my;

fn main() {
    my::function();
}

my.rs

pub mod nested; // if you need to include other modules

pub fn function() {
    println!("called `my::function()`");
}

Ruggine 2015

Devi inserire un mod.rsfile nella tua cartella con lo stesso nome del tuo modulo. Rust by Example lo spiega meglio.

$ tree src
src
├── main.rs
└── my
    ├── inaccessible.rs
    ├── mod.rs
    └── nested.rs

main.rs

mod my;

fn main() {
    my::function();
}

mod.rs

pub mod nested; // if you need to include other modules

pub fn function() {
    println!("called `my::function()`");
}

4
Supponiamo che volessi usare qualcosa di inaccessible.rsin nested.rs... come potrei farlo?
Heman Gandhi

Per accedere a un file .rs di pari livello da un file diverso da main.rs, utilizzare l'attributo path. Quindi, all'inizio di nested.rs, aggiungi quanto segue: #[path = "inaccessible.rs"]e sulla riga successiva:mod inaccessible;
Gardener


2
@HemanGandhi aggiungi mod inaccessible;a my/mod.rsper renderlo sottomodulo di my, quindi accedi al modulo di pari livello da nested.rsper percorso relativo super::inaccessible::function(). non hai bisogno di pathattributi qui.
artin

9

Mi piace molto la risposta di Gardener. Sto usando il suggerimento per le mie dichiarazioni di modulo. Qualcuno, per favore, intervenga se c'è un problema tecnico con questo.

./src
├── main.rs
├── other_utils
│   └── other_thing.rs
└── utils
    └── thing.rs

main.rs

#[path = "utils/thing.rs"] mod thing;
#[path = "other_utils/other_thing.rs"] mod other_thing;

fn main() {
  thing::foo();
  other_thing::bar();
}

utils / thing.rs

pub fn foo() {
  println!("foo");
}

other_utils / other_thing.rs

#[path = "../utils/thing.rs"] mod thing;

pub fn bar() {
  println!("bar");
  thing::foo();
}

Ho dovuto usare questo "trucco" per riesportare fncon lo stesso nome del file in cui si trovava.#[path = "./add_offer.rs"] mod _add_offer; pub use self::_add_offer::add_offer;
Arek Bal

questa dovrebbe essere la risposta accettata imo
Homam Bahrani il
Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.