来自 crate nix 的奇怪结构定义

Strange struct definition from crate nix

我刚遇到这个奇怪的结构体定义,它在fcntl.rs from the crate nix.

pub struct OFlag: c_int {
    /// Mask for the access mode of the file.
    O_ACCMODE; 

    // other fields are omitted.
}

在我看来,一个正常的结构应该是这样的:

struct Person{
    name: String,
    age: u8,
}

所以,这是我的疑惑:

  1. 什么是OFlag: c_int

    c_int is an type alias of i32. pub type c_int = i32;

  2. 为什么它的字段没有任何类型注释?

我的猜测是 OFlagc_int 类型,字段类似于 enum 的字段。(符合开放系统调用函数签名 int open(const char *pathname, int flags, mode_t mode) ) 但这只是我的猜测,将不胜感激引用 rust 官方文档的解释。

如果您查看该文件,您可以看到宏 libc_bitflags! 中的代码。宏的定义是here. There you can see that the macro ::bitflags::bitflags! is called and that libc_bitflags almost redirects the full input to bitflags. You can read more about that crate here.

现在回答您的问题:

  • OFlag 将在宏扩展之后是一个具有单个属性的结构,其类型为 c_int:
pub struct OFlag {
    bits: c_int,
}
  • 这些字段不需要类型,因为它们将不再存在于扩展代码中(在宏 运行 之后)。这些位属于“结构类型”,因此在您的情况下 c_int。这些字段将被转换为关联的常量:
impl OFlag {
    pub const O_ACCMODE = Self { bits: libc::O_ACCMODE };
}

您可以在 playground (Tools -> Expand macros)

中创建示例的扩展

您引用的代码本身不是有效的 Rust 代码。它是传递给 nix 板条箱的内部宏的代码,称为 libc_bitflags!()。该宏将引用的代码作为输入并将其转换为有效的 Rust 代码。

libc_bitflags!() 宏是一个 simple wrapper around the bitflags!() macro from the bitflags crate。包装器简化了位标志结构的创建,这些结构从 libc 板条箱中定义的常量中获取所有值。例如这个调用

libc_bitflags!{
    pub struct ProtFlags: libc::c_int {
        PROT_NONE;
        PROT_READ;
        PROT_WRITE;
        PROT_EXEC;
    }
}

扩展到

bitflags!{
    pub struct ProtFlags: libc::c_int {
        const PROT_NONE = libc::PROT_NONE;
        const PROT_READ = libc::PROT_READ;
        const PROT_WRITE = libc::PROT_WRITE;
        const PROT_EXEC = libc::PROT_EXEC;
    }
}

又会被 bitflags!() 宏扩展为 Rust 代码。 libc::c_int 类型用作结果结构的 bits 字段的类型。里面的常量将成为结果结构的关联常量。有关详细信息,请参阅 bitflags crate 的文档。