Як включити модуль з іншого файлу того ж проекту?


130

Дотримуючись цього керівництва, я створив проект 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

Чи є тривіальний приклад того, як включити один модуль з поточного проекту в основний файл проекту?



Відповіді:


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
Пізнє запитання, чи не буде це також працювати, якщо я вкажу його за допомогою привіт замість мода привіт ?!
Крістіан Шмітт

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

25

Якщо ви хочете мати вкладені модулі ...

Іржа 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файл у свою папку з однойменною назвою вашого модуля. Іржа за прикладом пояснює це краще.

$ 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
Припустимо , що я хотів би використовувати що - то з inaccessible.rsв nested.rs... як би мені це зробити?
Геман Ганді

Для доступу до .rs-файлу .rs з іншого файлу, ніж main.rs, використовуйте атрибут path. Отже, у верхній частині вкладеного сайта введіть наступне: #[path = "inaccessible.rs"]і в наступному рядку:mod inaccessible;
Садівник

@Gandhi Дивіться атрибут шляху
Садівник

2
@HemanGandhi додати, mod inaccessible;щоб my/mod.rsзробити його підмодулем my, а потім отримати доступ до симметричного модуля з nested.rsвідносного шляху super::inaccessible::function(). вам не потрібен pathатрибут тут.
artin

9

Мені дуже подобається відповідь Садівника. Я використовую пропозицію для декларацій свого модуля. Хтось, будь ласка, подзвонить, якщо з цим є технічна проблема.

./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;
Арек Бал

це має бути прийнята відповідь imo
Homam Bahrani
Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.