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?


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!");
}

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

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


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

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
En utilisant notre site, vous reconnaissez avoir lu et compris notre politique liée aux cookies et notre politique de confidentialité.
Licensed under cc by-sa 3.0 with attribution required.