来自 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,
}
所以,这是我的疑惑:
什么是OFlag: c_int
?
c_int
is an type alias of i32. pub type c_int = i32;
为什么它的字段没有任何类型注释?
我的猜测是 OFlag
是 c_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 的文档。
我刚遇到这个奇怪的结构体定义,它在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,
}
所以,这是我的疑惑:
什么是
OFlag: c_int
?c_int
is an type alias of i32.pub type c_int = i32;
为什么它的字段没有任何类型注释?
我的猜测是 OFlag
是 c_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 的文档。