【问题标题】:How do I access fields of a *mut libc::FILE?如何访问 *mut libc::FILE 的字段?
【发布时间】:2016-07-13 20:18:39
【问题描述】:

我正在尝试访问libcFILE 结构的不同字段。

根据stdio.h中的内存映射在Rust中实现FILE

#[repr(C)]
pub struct FILE {
    pub _p: libc::c_char,
    pub _r: libc::c_int,
    pub _w: libc::c_int,
    pub _flags: libc::c_short,
    pub _file: libc::c_short,
    ...
}

当在 libc 中使用 FILEs 时,它们出现在 mut * 变体中,这在某种程度上妨碍了访问字段。以下代码触发error: attempted access of field_flagson type '*mut FILE', but no field with that name was found

let stdout = libc::fdopen(libc::STDOUT_FILENO, &('w' as libc::c_char));
let is_unbuffered = (fp._flags & libc::_IONBF as i16) != 0

没有mut * 变体的FILE 类型的变量可以工作,但我需要让它与mut * 一起工作。

【问题讨论】:

    标签: rust libc


    【解决方案1】:

    FILE被定义为opaque type,即:

    pub enum FILE {}
    

    因此没有可访问的字段(甚至取消引用原始指针)。


    我认为直接访问FILE 结构的字段不是一个好主意,即使在C 中也是如此。你应该尝试在stdio.h 上找到一个函数来做你想做的事情。


    无论如何,一种解决方法是创建您自己的FILE 定义并从fp 获取&mut

    #[repr(C)]
    pub struct MY_FILE {
        pub _p: libc::c_char,
        pub _r: libc::c_int,
        pub _w: libc::c_int,
        pub _flags: libc::c_short,
        pub _file: libc::c_short,
        // ...
    }
    
    // ...
    
    unsafe {
        let fp = libc::fdopen(libc::STDOUT_FILENO, &('w' as libc::c_char));
        let fp = &mut *(fp as *mut MY_FILE);
        let is_unbuffered = (fp._flags & libc::_IONBF as i16) != 0;
    }
    

    请注意,如果您没有对MY_FILE 使用正确的定义,您会得到一些垃圾数据甚至是段错误。

    【讨论】:

    • 谢谢。 &mut * 位是我的代码中缺少的部分。你能解释一下这是做什么的吗?当涉及到指针和引用时,我仍然一无所知,真的很难来自 Java/PHP/Python 世界
    • 附加问题:我的结构现在“不起作用”:_flags 始终为 0。您对如何解决这个问题有任何提示吗?这是 OSX 上的 stdio.h:gist.github.com/philippkeller/3921705e7b5d0ef5d394501496d146fe 我只是不明白问题出在哪里,IMO 直接访问 _flags 所有成员和_flags 需要是正确的,以下可能是错误的(甚至被遗漏) )
    • fdopen 返回一个raw pointer。你不能用原始指针做很多事情,所以我们从它那里得到一个可变引用(&mut)(*取消引用指针,它给出了一个FILE类型的值,&mut得到一个对@的可变引用987654345@ 值)。我认为直接访问FILE结构的字段不是一个好主意,即使在C中也是如此。也许你应该问另一个问题来解释你想要做什么(测试文件是否被缓冲?)。
    • 感谢指针的解释。我正在慢慢掌握它。关于我的意图:这纯粹是教育性的,我正在尝试将 this C program 移植到 Rust(“Unix 环境高级编程”一书中的示例)
    • 这很有趣。在这种情况下,我建议您使用bindgen 来生成正确的FILE 定义。您可以在.h 文件上运行它并复制生成的FILE 定义。
    【解决方案2】:

    指针本身没有属性,它指向的结构有。

    这意味着您需要访问*fp._flags,而不是fp._flags(假设fp 的类型为*mut FILE)。

    此外,您可能需要将访问封装在 unsafe 块中,因为取消引用原始指针始终是不安全的操作。试试这样的:

    let flags = unsafe { (*fp)._flags };
    let is_unbuffered = (flags & libc::_IONBF as i16) != 0;
    

    【讨论】:

      猜你喜欢
      • 2015-07-06
      • 1970-01-01
      • 1970-01-01
      • 2021-02-23
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多