2016-07-13 1 views
2

구조체의 다른 필드에 액세스하려고 시도했습니다. libc입니다. stdio.h의 메모리 매핑에 따라 녹에* mut libc :: FILE 필드에 어떻게 액세스합니까?

FILE 구현 : libc의 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, 
    ... 
} 

그들은 mut * 변형에 와서,이 어떻게 든 필드에 액세스하는 방법입니다. 다음 코드는 error: attempted access of field _flags on 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 * 작업을 얻을 필요가있다.

답변

3

FILEopaque type으로 정의된다, 즉 :

pub enum FILE {} 

그래서 (심지어 원시 포인터를 역 참조)에 액세스 할 분야가 없습니다.


는 내가 직접, 심지어 C에서 당신은 당신이 원하는 것을 할 stdio.h에 함수를 찾으려고한다 FILE 구조의 필드에 액세스하는 것은 좋은 생각이 아니다라고 생각합니다. 당신이 MY_FILE에 대한 올바른 정의를 사용하지 않는 경우, 당신은 몇 가지를 얻을 것이다

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

참고 :


어쨌든, 한 가지 해결 방법은 FILE 자신 만의 정의를 작성하고 &mutfp에서 얻는 것입니다 쓰레기 데이터 또는 심지어 segfault.

+0

감사합니다. '& mut *'비트가 내 코드에서 빠진 부분이었습니다. 이것이하는 일에 대해 어떤 생각을 밝힐 수 있습니까? 나는 어둠 속에서 포인터와 참조에 관해서는 정말 어려운 Java/PHP/Python 세계에서 오는 것입니다 – hansaplast

+0

추가 질문 : 내 구조체 이제 "작동하지 않습니다":'_flags' 항상 0입니다. 그걸 고치는 방법에 대한 어떤 힌트? 여기에 OSX에서 stdio.h가 있습니다 : https://gist.github.com/philippkeller/3921705e7b5d0ef5d394501496d146fe 난 그냥 문제가 무엇인지 모르겠다. IMO는 _flags에 직접 액세스하고'_flags'를 사용하여 정확해야합니다. 다음의 것들은 잘못 될 수있다. (심지어는 제외된다) – hansaplast

+0

'fdopen'은 [원시 포인터] (https://doc.rust-lang.org/stable/std/primitive.pointer.html)를 반환한다. 원시 포인터로는 많은 일을 할 수 없기 때문에 mutable reference ('& mut')를 얻습니다. ('*'포인터를 역 참조하고,'FILE' 타입의 값을주고,'mut ' FILE' 값).나는'FILE' 구조의 필드에 직접 접근하는 것이 좋지 않다고 생각합니다. 어쩌면 파일을 버퍼링했는지 테스트 할 때 원하는 것을 설명하는 또 다른 질문을해야 할 것입니다. – malbarbo

0

포인터 자체에는 포인터가있는 구조체 속성이 없습니다.

즉, 이 아니라 fp._flags이 아닙니다 (fp*mut FILE이라고 가정).

또한 원시 포인터의 역 참조는 항상 안전하지 않은 작업이기 때문에 unsafe 블록으로 액세스를 래핑해야합니다. 이런 식으로 뭔가를 시도 :

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