Como incluir um módulo de outro arquivo do mesmo projeto?

130

Seguindo este guia , criei um projeto Cargo.

src/main.rs

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

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

que corro usando

cargo build && cargo run

e compila sem erros. Agora estou tentando dividir o módulo principal em dois, mas não consigo descobrir como incluir um módulo de outro arquivo.

Minha árvore de projeto se parece com isto

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

e o conteúdo dos arquivos:

src/main.rs

use hello;

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

src/hello.rs

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

Quando eu compilo com cargo buildeu obtenho

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

Tentei seguir as sugestões do compilador e modifiquei main.rspara:

#![feature(globs)]

extern crate hello;

use hello::*;

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

Mas isso ainda não ajuda muito, agora eu entendo:

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

Existe um exemplo trivial de como incluir um módulo do projeto atual no arquivo principal do projeto?

ave
fonte
1
possível duplicata de importações básicas
Levans

Respostas:

239

Você não precisa do mod helloem seu hello.rsarquivo. O código em qualquer arquivo, exceto a raiz da caixa ( main.rspara executáveis, lib.rspara bibliotecas), recebe um namespace automaticamente em um módulo.

Para incluir o código de hello.rsem seu main.rs, use mod hello;. Ele é expandido para o código que está hello.rs(exatamente como você fazia antes). Sua estrutura de arquivo continua a mesma e seu código precisa ser ligeiramente alterado:

main.rs:

mod hello;

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

hello.rs:

pub fn print_hello() {
    println!("Hello, world!");
}
Renato Zannon
fonte
1
Late Question também não funcionaria se eu especificasse usando hello em vez de mod hello ?!
Christian Schmitt
16
@ChristianSchmitt Não, são coisas diferentes. useé apenas uma coisa de namespace, enquanto modpuxa o arquivo. Você usaria use, por exemplo, para poder chamar a print_hellofunção sem ter que prefixar com o namespace
Renato Zannon
25

Se você deseja ter módulos aninhados ...

Ferrugem 2018

Não é mais necessário ter o arquivo mod.rs(embora ainda seja compatível). A alternativa idiomática é nomear o arquivo com o nome do módulo:

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

Rust 2015

Você precisa colocar um mod.rsarquivo dentro de sua pasta com o mesmo nome de seu módulo. Rust by Example explica melhor.

$ 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
fonte
4
Suponha que eu queria usar algo inaccessible.rsem nested.rs... como eu faria isso?
Heman Gandhi
Para acessar um arquivo irmão .rs a partir de um arquivo diferente de main.rs, use o atributo path. Portanto, na parte superior de nested.rs, adicione o seguinte: #[path = "inaccessible.rs"]e na próxima linha:mod inaccessible;
Gardener
@Gandhi Ver o atributo path
Gardener
2
@HemanGandhi adicione mod inaccessible;a my/mod.rspara torná-lo submódulo de e my, a seguir, acesse o módulo irmão nested.rspelo caminho relativo super::inaccessible::function(). você não precisa de pathatributo aqui.
arte em
9

Eu realmente gosto da resposta de Gardener. Tenho usado a sugestão para minhas declarações de módulo. Alguém, por favor, entre em contato se houver um problema técnico com isso.

./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
fonte
Tive que usar este 'truque' para reexportar fncom o mesmo nome do arquivo em que estava.#[path = "./add_offer.rs"] mod _add_offer; pub use self::_add_offer::add_offer;
Arek Bal
esta deve ser a resposta aceita em
Homam Bahrani