Comment inclure un module d'un autre fichier du même projet?

130

En suivant ce guide, j'ai créé un projet Cargo.

src/main.rs

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

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

que je cours en utilisant

cargo build && cargo run

et il compile sans erreurs. Maintenant, j'essaie de diviser le module principal en deux mais je ne peux pas comprendre comment inclure un module d'un autre fichier.

Mon arborescence de projet ressemble à ceci

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

et le contenu des fichiers:

src/main.rs

use hello;

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

src/hello.rs

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

Quand je le compile avec cargo buildje reçois

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

J'ai essayé de suivre les suggestions du compilateur et j'ai modifié main.rspour:

#![feature(globs)]

extern crate hello;

use hello::*;

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

Mais cela n'aide toujours pas beaucoup, maintenant je comprends ceci:

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

Existe-t-il un exemple trivial de la façon d'inclure un module du projet actuel dans le fichier principal du projet?

ave
la source
1
duplication possible des importations de base
Levans

Réponses:

239

Vous n'avez pas besoin du mod hellodans votre hello.rsfichier. Le code dans n'importe quel fichier sauf la racine de la crate ( main.rspour les exécutables, lib.rspour les bibliothèques) est automatiquement mis en espace dans un module.

Pour inclure le code de hello.rsvotre main.rs, utilisez mod hello;. Il est étendu au code qui se trouve hello.rs(exactement comme vous l'aviez auparavant). Votre structure de fichiers continue de la même manière et votre code doit être légèrement modifié:

main.rs:

mod hello;

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

hello.rs:

pub fn print_hello() {
    println!("Hello, world!");
}
Renato Zannon
la source
1
Question tardive ne fonctionnerait-il pas aussi si je le spécifie avec use hello au lieu de mod hello?!
Christian Schmitt
16
@ChristianSchmitt Non, ce sont des choses différentes. useest juste une chose d'espace de noms, tandis qu'il modextrait le fichier. Vous utiliseriez use, par exemple, pour pouvoir appeler la print_hellofonction sans avoir à préfixer avec l'espace de noms
Renato Zannon
26

Si vous souhaitez avoir des modules imbriqués ...

Rouille 2018

Il n'est plus nécessaire d'avoir le fichier mod.rs(bien qu'il soit toujours pris en charge). L'alternative idiomatique est de nommer le fichier le nom du module:

$ 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()`");
}

Rouille 2015

Vous devez mettre un mod.rsfichier dans votre dossier du même nom que votre module. Rust by Example l' explique mieux.

$ 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()`");
}
amxa
la source
4
Supposons que je voulais utiliser quelque chose inaccessible.rsdans nested.rs... comment pourrais - je faire cela?
Heman Gandhi
Pour accéder à un fichier .rs frère à partir d'un fichier autre que main.rs, utilisez l'attribut path. Donc, en haut de nested.rs, ajoutez ce qui suit: #[path = "inaccessible.rs"]et sur la ligne suivante:mod inaccessible;
Gardener
@Gandhi See The path attribute
Gardener
2
@HemanGandhi ajoute mod inaccessible;à my/mod.rspour en faire un sous-module de my, puis accède au module frère à partir nested.rsd'un chemin relatif super::inaccessible::function(). vous n'avez pas besoin d' pathattribut ici.
artin
9

J'aime vraiment la réponse de Gardener. J'ai utilisé la suggestion pour mes déclarations de module. Quelqu'un s'il vous plaît intervenir s'il y a un problème technique avec cela.

./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();
}
Rodo
la source
J'ai dû utiliser cette «astuce» pour réexporter fnavec le même nom que le fichier dans #[path = "./add_offer.rs"] mod _add_offer; pub use self::_add_offer::add_offer;
lequel
cela devrait être la réponse acceptée imo
Homam Bahrani le