2014-11-03 11 views
5

c-union 구조체 XEvent를 해결하는 데 문제가 있습니다.루스트 FFI에서 공용 구조체 해결

나는 Xlib과 X Record Extension in Rust로 실험 중이다. 나는 rust-bindgen으로 ffi 바인딩을 생성합니다. 모든 코드는 github alxkolm/rust-xlib-record에서 호스팅됩니다.

XEvent 구조에서 데이터를 추출하려고 할 때 문제가 발생했습니다 (src/main.rs:106).

 

let key_event: *mut xlib::XKeyEvent = event.xkey(); 
println!("KeyPress {}", (*key_event).keycode); // this always print 128 on any key 

내 프로그램은 키 이벤트를 듣고 keycode을 출력합니다. 그러나 내가 누르는 키에 항상 128입니다. C 노조 유형에서 녹 유형으로의 잘못된 변환이라고 생각합니다.

XEvent의 정의는 여기에서 시작합니다. src/xlib.rs:1143. 그것은 노동 조합입니다. 원본 C 정의 here.

GitHub의 코드는 cargo run 명령으로 실행할 수 있습니다. 오류없이 컴파일됩니다.

내가 뭘 잘못 했니?

+0

발생하는 오류를 정확하게 지정할 수 있습니까? 컴파일 타임 오류가 발생하면 컴파일러 오류 메시지가 유용합니다. 로드 시간 오류가 발생하면 ... 아니면 항상'128'을 얻고 다른 것을 기다리고있는 문제입니까? –

+0

키를 누를 때마다 키 코드는 항상 128입니다. 오류없이 완벽하게 편집 할 수 있습니다. 질문의 텍스트를 수정하십시오. – alxkolm

+1

이벤트 유형이 예상 한 것임을 확인 했습니까? 생성 된 Rust 코드는 맹목적으로 당신에게 복종한다 : 메모리를 해석하는'xkey '를 요구한다. 그러나 그것이 키 눌린 이벤트가 아니라 다른 것이면, 그것은 이해가되지 않을 것이다. –

답변

3

rustbindgen은 C에서와 같이 많은 안전성을 가지고 C union에 바인딩을 생성합니다. 그 결과, 전화로 :

event.xkey(); // gets the C union 'xkey' field 

xkey 현재 값을 포함하는 필드 아무 런타임 검사가 없습니다.

왜냐하면 C는 union (즉, 현재 사용중인 필드를 알고있는 union) 태그가 없기 때문에 개발자는이 정보 (*)를 인코딩하는 다양한 방법을 생각해 냈습니다.

  • 외부 공급자; 일반적 바로 여기 union

의 각 구조의 첫 번째 필드, 당신은 후자의 경우 int type;에있는 union

  • 전에 구조의 또 다른 분야는 노동 조합의 첫 번째 필드와 각 중첩 된 구조는 이것을 나타 내기 위해 int _type;으로 시작합니다.

    1. 이되는 실제 필드 유형의 값에서 올바른 재 해석

    에게 매핑을, 값에 따라 type()

  • 상담 전화 : 결과적으로는 두 단계 접근 방식이 필요 잘하면 C 라이브러리의 문서 일부가되어야한다.

    결과를 검색하는 것이 더 안전 할 낮은 레벨 union 주위의 래퍼를 제안합니다. 적어도 접근 자의 올바른 유형인지 확인할 수 있습니다. 전체 접근 방식은 모든 필드에 프록시를 래핑하고 패턴 일치를 허용하는 녹 (Rust) enum을 필요로합니다.

    (*) 실제로는 예를 들어 C99에서 floatint으로, union { float f; int i; }으로 재 해석 할 수 있습니다.