จะรวมโมดูลจากไฟล์อื่นจากโครงการเดียวกันได้อย่างไร?


131

การทำตามคำแนะนำนี้ฉันได้สร้างโครงการขนส่งสินค้า

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

มีตัวอย่างเล็กน้อยในการรวมโมดูลหนึ่งจากโครงการปัจจุบันลงในไฟล์หลักของโครงการหรือไม่?



เกี่ยวข้องกับstackoverflow.com/questions/22596920/…
Kelvin

คำตอบ:


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 สวัสดี?!
Christian Schmitt

17
@ChristianSchmitt ไม่มันคนละอย่าง useเป็นเพียงเนมสเปซในขณะที่modดึงไฟล์ useตัวอย่างเช่นคุณจะใช้เพื่อให้สามารถเรียกใช้print_helloฟังก์ชันได้โดยไม่ต้องขึ้นต้นด้วยเนมสเปซ
Renato Zannon

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ไฟล์ไว้ในโฟลเดอร์ชื่อเดียวกับโมดูลของคุณ สนิมตามตัวอย่างอธิบายได้ดีกว่า

$ 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... ฉันจะทำอย่างไร
Heman Gandhi

ในการเข้าถึงไฟล์. rs พี่น้องจากไฟล์อื่นที่ไม่ใช่ main.rs ให้ใช้แอตทริบิวต์ path ดังนั้นที่ด้านบนสุดของ nested.rs ให้เพิ่มสิ่งต่อไปนี้: #[path = "inaccessible.rs"]และในบรรทัดถัดไป:mod inaccessible;
Gardener


2
@HemanGandhi เพิ่มmod inaccessible;เพื่อmy/mod.rsที่จะทำให้มัน submodule ของmyโมดูลพี่น้องเข้าถึงจากนั้นโดยทางญาติnested.rs super::inaccessible::function()คุณไม่ต้องการpathแอตทริบิวต์ที่นี่
artin

10

ฉันชอบคำตอบของ Gardener มาก ฉันใช้คำแนะนำสำหรับการประกาศโมดูลของฉัน ใครบางคนโปรดแจ้งเตือนหากมีปัญหาทางเทคนิคนี้

./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;
Arek Bal

1
นี่ควรเป็นคำตอบที่ยอมรับ imo
Homam Bahrani
โดยการใช้ไซต์ของเรา หมายความว่าคุณได้อ่านและทำความเข้าใจนโยบายคุกกี้และนโยบายความเป็นส่วนตัวของเราแล้ว
Licensed under cc by-sa 3.0 with attribution required.