我想创建一个访问文件系统的多平台应用程序,虽然我可以使用std::fs个,但我发现特定于操作系统的机箱稍微简化了代码.所以,我用std::os::windows::fs编写了一些代码,它像预期的那样工作.

我现在的问题是,我想同时为Windows和Linux编写代码.为此,我创建了不同的函数,理论上将分别使用std::os::windowsstd::os::linux.然而,当我试图编译onLinux forLinux时,我遇到了一个错误,即std::os::windows不是一个可识别的 crate .

我的问题是,有没有办法让我在Linux上使用std::os::windows,反之亦然,或者只编译特定的代码块,这取决于使用Cargo的操作系统?

我知道这是一个有点愚蠢的问题,考虑到我可以为不同的操作系统编写单独的模块,但我确实想try 将所有内容包含在一个模块中.

我目前的代码大致如下:

pub fn run(os: &str, path: &str){
    let files = fs::read_dir(path).unwrap_or_else(|error: std::io::Error| {
        println!("Error: {error}");
        process::exit(1);
    });

    // The 'os' variable is obtained from std::env::consts::OS
    if os == "windows" {
        // Use std::os::windows in the following function
        printDir_win(files);
    } else if os == "linux" {
        // Use std::os::linux in the following function
        printDir_lin(files);
    } else {
        println!("{}OS not recognised: defaulting to std::fs methods{}","\x1b[31m","\x1b[0m");
        printDir(files);
    }
}

推荐答案

根据目标操作系统使用#[cfg(…) attribute进行条件编译.这样编译器就不会try 编译针对不同操作系统的代码:

pub fn run(path: &str){
    let files = fs::read_dir(path).unwrap_or_else(|error: std::io::Error| {
        println!("Error: {error}");
        process::exit(1);
    });

    // The 'os' variable is obtained from std::env::consts::OS
    #[cfg (target_os = "windows")]
    {
        // Use std::os::windows in the following function
        use std::os::windows::*;
        printDir_win(files);
    }
    #[cfg (target_os = "linux")]
    {
        // Use std::os::linux in the following function
        use std::os::linux;
        printDir_lin(files);
    }
    #[cfg (not (any (target_os = "windows", target_os = "linux")))]
    {
        println!("{}OS not recognised: defaulting to std::fs methods{}","\x1b[31m","\x1b[0m");
        printDir(files);
    }
}

请注意,从组织的Angular 来看,将特定于平台的代码分组到一个模块中是很好的做法,该模块抽象了通用API背后的差异:

#[cfg (target_os = "windows")]
mod platform {
    use std::os::windows::*;
    pub fn print_dir (files: std::fs::ReadDir) {
        unimplemented!()
    }
}
#[cfg (target_os = "linux")]
mod platform {
    use std::os::linux::*;
    pub fn print_dir (files: std::fs::ReadDir) {
        unimplemented!()
    }
}
#[cfg (not (any (target_os = "windows", target_os = "linux")))]
mod platform {
    pub fn print_dir (files: std::fs::ReadDir) {
        unimplemented!()
    }
}

然后,您的代码的其余部分不需要判断每个地方的操作系统来知道要调用哪个函数:

pub fn run(path: &str){
    let files = std::fs::read_dir(path).unwrap_or_else(|error: std::io::Error| {
        println!("Error: {error}");
        std::process::exit(1);
    });
    platform::print_dir (files);
}

Playground

Rust相关问答推荐

为什么是!为Rust中的RwLockReadGuard和RwLockWriteGuard实现的发送特征?

trait声明中的生命周期参数

如何访问Rust存储值的内存地址

具有对同一类型的另一个实例的可变引用的

如何在Bevy/Rapier3D中获得碰撞机的计算质量?

为潜在的下游实现使用泛型绑定而不是没有泛型绑定的trait

在Rust中,在实现特征`Display`时,如何获取调用方指定的格式?

不能在一个代码分支中具有不变的自身borrow ,而在另一个代码分支中具有可变的self borrow

这个不安全的 Rust 代码有什么问题,所以它可以在 Windows 上运行,但不能在 Ubuntu 上运行?

RUST 中的读写器锁定模式

为什么这个闭包没有实现Fn?

实现泛型的 Trait 方法中的文字

如何使返回 XMLError 的方法与 anyhow::Error 兼容?

在 Rust 中如何将值推送到枚举 struct 内的 vec?

预期的整数,找到 `&{integer}`

使用 serde_json 进一步处理字段

通用函数中的生命周期扣除和borrow (通用测试需要)

实现不消费的迭代器

如何重写这个通用参数?

基于名称是否存在的条件编译