私はepoll Linux APIのラッパーを作成しようとしています。 thisリポジトリをフォークしましたが、epoll
APIで使用されているunion
タイプは使用しません。私はRustのCユニオン機能を使用して、安全でないコードを使用する必要のない完全なラッパーを作成することにしました。組合に強制的に1つのタイプのように振る舞う方法はありますか?
このユニオンは私にいくつかの問題を引き起こします。
コンパイル時に使用された共用体の型を1つの型にロックするにはどうすればよいですか? epollの組合は区別できません。あなたはepoll fdによって1つの組合員しか使えません。まあ、それは安全ですが、それはできません。
ユーザーは、複合型のフィールドのptr
フィールドとして列挙型を使用できますが、これはRustのenum
を使用するため安全です。
「generic」または「macro」で検索しましたが、私の意志に合う方法は見つかりません。
fn main() {
let event = event!(ptr, Box::new(42));
let _ = event.ptr();
let _ = event.fd(); // fails to compile; we can only use ptr
}
マイフォークはhereを見つけることができます:
extern crate libc;
#[derive(Clone, Copy)]
pub union Data {
pub ptr: *mut libc::c_void,
pub fd: std::os::unix::io::RawFd,
pub u32: libc::uint32_t,
pub u64: libc::uint64_t,
}
#[repr(C)]
#[repr(packed)]
#[derive(Clone, Copy)]
pub struct Event {
pub data: Data,
}
impl Event {
fn new(data: Data) -> Event {
Event { data: data }
}
}
fn main() {
let event = Event::new(Data {
ptr: Box::into_raw(Box::new(42)) as *mut libc::c_void,
});
unsafe { Box::from_raw(event.data.ptr) };
}
私はそのような何かをしたいと思います。マクロ、ジェネリック、その他が適切な解決策であるかどうかわかりません。あなたは私のコード、特にthe integration testを見ることができます、安全でないコードがたくさんあります、私はユーザー側から安全でないコードを可能な限り削除したいと思います。現在は非常に醜いです。
私はそれは私がしたい正確に何だと思います。 – Stargateur
少し複雑です。なぜ、あなたは 'struct Ptr(Data)'と 'struct Fd(Data)'を持っていて、共通の振る舞いを特性に入れませんか?私はこれがどのように使われているのかは不明だし、何かが足りないかもしれない。 – trentcl
@trentcl複数の回答がありえない理由はありません:-) – Shepmaster