How do I access fields of a *mut libc::FILE?

夙愿已清 提交于 2019-12-11 04:06:57

问题


I'm trying to access the different fields of the FILE struct of libc.

FILE implementation in Rust according to the memory mapping in stdio.h:

#[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,
    ...
}

when working with FILEs in libc they come in the mut * variant, and this somehow is in the way to access the fields. The following code triggers 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

A variable of type FILE without the mut * variant works but I need to get it working with mut *.


回答1:


FILE is defined as an opaque type, that is:

pub enum FILE {}

So there is no field to access (even dereferencing the raw pointer).


I think it is not a good idea to access the fields of FILE structure directly, even in C. You should try to find a function on stdio.h that do what you want.


Anyway, one workaround is to create your own definition of FILE and get a &mut from fp:

#[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;
}

Note that if you do not use the correct definition for MY_FILE, you will get some garbage data or even a segfault.




回答2:


The pointer itself doesn't have attributes, the struct it points to does.

So what this means is that you need to access *fp._flags, not fp._flags (assuming fp is of type *mut FILE).

In addition, you'll probably need to wrap the access in an unsafe block, as dereferencing a raw pointer is always an unsafe operation. Try something like this:

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


来源:https://stackoverflow.com/questions/38360996/how-do-i-access-fields-of-a-mut-libcfile

标签
易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!