Wie füge ich ein Modul aus einer anderen Datei aus demselben Projekt hinzu?

128

Durch Befolgen dieser Anleitung habe ich ein Frachtprojekt erstellt.

src/main.rs

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

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

was ich benutze mit

cargo build && cargo run

und es kompiliert ohne Fehler. Jetzt versuche ich, das Hauptmodul in zwei Teile zu teilen, kann aber nicht herausfinden, wie ein Modul aus einer anderen Datei eingefügt werden kann.

Mein Projektbaum sieht so aus

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

und den Inhalt der Dateien:

src/main.rs

use hello;

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

src/hello.rs

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

Wenn ich es mit kompiliere cargo buildbekomme ich

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

Ich habe versucht, den Vorschlägen des Compilers zu folgen und habe Folgendes geändert main.rs:

#![feature(globs)]

extern crate hello;

use hello::*;

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

Aber das hilft immer noch nicht viel, jetzt verstehe ich Folgendes:

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

Gibt es ein triviales Beispiel dafür, wie ein Modul aus dem aktuellen Projekt in die Hauptdatei des Projekts aufgenommen wird?

ave
quelle
1
Mögliches Duplikat der Grundimporte
Levans

Antworten:

234

Sie brauchen das nicht mod helloin Ihrer hello.rsDatei. Code in einer beliebigen Datei außer dem Kistenstamm ( main.rsfür ausführbare Dateien, lib.rsfür Bibliotheken) wird automatisch in einem Modul mit einem Namespace versehen.

Verwenden hello.rsSie main.rs, um den Code von in Ihren einzuschließen mod hello;. Es wird auf den Code erweitert, der sich befindet hello.rs(genau wie zuvor). Ihre Dateistruktur bleibt unverändert, und Ihr Code muss geringfügig geändert werden:

main.rs::

mod hello;

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

hello.rs::

pub fn print_hello() {
    println!("Hello, world!");
}
Renato Zannon
quelle
1
Späte Frage, würde es nicht auch funktionieren, wenn ich es mit "Hallo" anstelle von "Mod Hallo" spezifiziere?!
Christian Schmitt
16
@ChristianSchmitt Nein, das sind verschiedene Dinge. useist nur eine Namespace-Sache, während modin der Datei zieht. Sie würden usezum Beispiel verwenden, um die print_helloFunktion aufrufen zu können, ohne den Namespace
voranstellen zu müssen
25

Wenn Sie verschachtelte Module haben möchten ...

Rost 2018

Es ist nicht mehr erforderlich , um die Datei zu haben mod.rs(obwohl es immer noch unterstützt wird). Die idiomatische Alternative besteht darin, der Datei den Namen des Moduls zu geben:

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

Rost 2015

Sie müssen eine mod.rsDatei in Ihrem Ordner mit demselben Namen wie Ihr Modul ablegen. Rust by Example erklärt es besser.

$ 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
quelle
4
Angenommen, ich wollte etwas von inaccessible.rsin verwenden nested.rs... wie würde ich das tun?
Heman Gandhi
Verwenden Sie das Pfadattribut, um von einer anderen Datei als main.rs auf eine Geschwister-.rs-Datei zuzugreifen. Fügen Sie also oben in nested.rs Folgendes hinzu: #[path = "inaccessible.rs"]und in der nächsten Zeile:mod inaccessible;
Gardener
@ Gandhi Siehe Das
Gärtner
2
@HemanGandhi add mod inaccessible;to my/mod.rs, um es zum Submodul zu machen, und greift mydann nested.rsüber das relative Pfad auf das Geschwistermodul zu super::inaccessible::function(). Sie brauchen pathhier kein Attribut.
Artin
8

Ich mag die Antwort von Gardener sehr. Ich habe den Vorschlag für meine Moduldeklarationen verwendet. Jemand meldet sich bitte, wenn es ein technisches Problem gibt.

./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
quelle
Musste diesen 'Trick' verwenden, um fnmit demselben Namen wie die Datei, in der er sich befand , erneut zu exportieren .#[path = "./add_offer.rs"] mod _add_offer; pub use self::_add_offer::add_offer;
Arek Bal
Dies sollte die akzeptierte Antwort sein. imo
Homam Bahrani