Как подключить модуль из другого файла из того же проекта?


131

Следуя этому руководству, я создал проект Cargo.

src/main.rs

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

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

который я использую

cargo build && cargo run

и компилируется без ошибок. Теперь я пытаюсь разделить основной модуль на две части, но не могу понять, как включить модуль из другого файла.

Дерево моего проекта выглядит так

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

и содержимое файлов:

src/main.rs

use hello;

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

src/hello.rs

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

Когда я компилирую его, cargo buildя получаю

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

Я попытался последовать предложениям компилятора и изменил его main.rsна:

#![feature(globs)]

extern crate hello;

use hello::*;

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

Но это все равно мало помогает, теперь я понял:

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

Есть ли тривиальный пример того, как включить один модуль из текущего проекта в основной файл проекта?


1
возможный дубликат базового импорта Rust (включает)
Levans

Ответы:


239

Вам не нужен mod helloв вашем hello.rsфайле. Код в любом файле, кроме корневого ящика ( main.rsдля исполняемых файлов, lib.rsдля библиотек), автоматически помещается в пространство имен в модуле.

Чтобы включить код из hello.rsв ваш main.rs, используйте mod hello;. Он расширяется до кода, который находится внутри hello.rs(точно так же, как и раньше). Ваша файловая структура остается прежней, и ваш код необходимо немного изменить:

main.rs:

mod hello;

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

hello.rs:

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

1
Поздний вопрос, разве это не сработает, если я укажу его с использованием hello вместо mod hello ?!
Кристиан Шмитт

17
@ChristianSchmitt Нет, это разные вещи. useэто просто вещь пространства имен, пока modтянет файл. Вы могли бы использовать use, например, чтобы иметь возможность вызывать print_helloфункцию без префикса с пространством имен
Ренато Заннон

27

Если вы хотите иметь вложенные модули ...

Ржавчина 2018

Он никогда больше не требуется иметь файл mod.rs(хотя он по - прежнему поддерживается). Идиоматическая альтернатива - назвать файл именем модуля:

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

Ржавчина 2015

Вам нужно поместить mod.rsфайл в вашу папку с тем же именем, что и ваш модуль. Rust by Example объясняет это лучше.

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

5
Предположим , что я хотел бы использовать что - то из inaccessible.rsв nested.rs... как бы мне это сделать?
Хеман Ганди

Чтобы получить доступ к родительскому файлу .rs из файла, отличного от main.rs, используйте атрибут path. Итак, в верхней части nested.rs добавьте следующее: #[path = "inaccessible.rs"]и в следующей строке:mod inaccessible;
Gardener


2
@HemanGandhi добавить, mod inaccessible;чтобы my/mod.rsсделать его подмодулем my, а затем получить доступ к родственному модулю nested.rsпо относительному пути super::inaccessible::function(). вам не нужен pathатрибут здесь.
артины

10

Мне очень нравится ответ Гарденера. Я использовал это предложение для объявлений моих модулей. Кто-нибудь, пожалуйста, свяжитесь с нами, если возникнут технические проблемы.

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

Пришлось использовать этот «трюк» для реэкспорта fnс тем же именем, что и файл, в котором он был.#[path = "./add_offer.rs"] mod _add_offer; pub use self::_add_offer::add_offer;
Арек Бал

1
это должен быть принятый ответ imo
Homam Bahrani
Используя наш сайт, вы подтверждаете, что прочитали и поняли нашу Политику в отношении файлов cookie и Политику конфиденциальности.
Licensed under cc by-sa 3.0 with attribution required.