* added virStreamEventAddCallback function * added new types: StreamEventCallback and FreeCallback * added new field: callback for storing event callback * drop: will drop the Box<callback> if any * added wrapper event_callback for easier callback authoring for the user (so that closures with Fn or FnMut references could be used) * added padding function event_free to just makes it compile (Rust should not need this, because Rust sticks to RAII) Signed-off-by: Zixing Liu <liushuyu@xxxxxxx> --- src/stream.rs | 46 ++++++++++++++++++++++++++++++++++++++++++++-- 1 file changed, 44 insertions(+), 2 deletions(-) diff --git a/src/stream.rs b/src/stream.rs index de272ab..1ffd186 100644 --- a/src/stream.rs +++ b/src/stream.rs @@ -47,6 +47,12 @@ extern "C" { fn virStreamFree(c: sys::virStreamPtr) -> libc::c_int; fn virStreamAbort(c: sys::virStreamPtr) -> libc::c_int; fn virStreamFinish(c: sys::virStreamPtr) -> libc::c_int; + fn virStreamEventAddCallback(c: sys::virStreamPtr, + event: libc::c_int, + callback: StreamEventCallback, + opaque: *const libc::c_void, + ff: FreeCallback) + -> libc::c_int; fn virStreamEventUpdateCallback(c: sys::virStreamPtr, events: libc::c_int) -> libc::c_int; fn virStreamEventRemoveCallback(c: sys::virStreamPtr) -> libc::c_int; @@ -61,9 +67,26 @@ pub const VIR_STREAM_EVENT_HANGUP: StreamEventType = (1 << 3); pub type StreamFlags = self::libc::c_uint; pub const VIR_STREAM_NONBLOCK: StreamFlags = (1 << 0); -#[derive(Debug)] +pub type StreamEventCallback = extern "C" fn(sys::virStreamPtr, libc::c_int, *const libc::c_void); +pub type FreeCallback = extern "C" fn(*mut libc::c_void); + +// wrapper for callbacks +extern "C" fn event_callback(c: sys::virStreamPtr, flags: libc::c_int, opaque: *const libc::c_void) { + let flags = flags as StreamFlags; + let shadow_self = unsafe { + &mut*(opaque as *mut Stream) + }; + if let Some(callback) = &mut shadow_self.callback { + callback(&Stream::from_ptr(c), flags); + } +} + +extern "C" fn event_free(_opaque: *mut libc::c_void) {} + +// #[derive(Debug)] pub struct Stream { ptr: Option<sys::virStreamPtr>, + callback: Option<Box<dyn FnMut(&Stream, StreamEventType)>>, } impl Drop for Stream { @@ -75,6 +98,13 @@ impl Drop for Stream { e.message) } } + if self.callback.is_some() { + if let Err(e) = self.event_remove_callback() { + panic!("Unable to remove event callback for Stream, code {}, message: {}", + e.code, + e.message) + } + } } } @@ -90,7 +120,7 @@ impl Stream { } pub fn from_ptr(ptr: sys::virStreamPtr) -> Stream { - Stream { ptr: Some(ptr) } + Stream { ptr: Some(ptr), callback: None } } pub fn as_ptr(&self) -> sys::virStreamPtr { @@ -147,6 +177,18 @@ impl Stream { usize::try_from(ret).map_err(|_| Error::new()) } + pub fn event_add_callback<F: 'static + FnMut(&Stream, StreamEventType)>(&mut self, events: StreamEventType, cb: F) -> Result<(), Error> { + let ret = unsafe { + let ptr = &*self as *const _ as *const _; + virStreamEventAddCallback(self.as_ptr(), events as libc::c_int, event_callback, ptr, event_free) + }; + if ret == -1 { + return Err(Error::new()); + } + self.callback = Some(Box::new(cb)); + return Ok(()); + } + pub fn event_update_callback(&self, events: StreamEventType) -> Result<(), Error> { let ret = unsafe { virStreamEventUpdateCallback(self.as_ptr(), events as libc::c_int) -- 2.24.0 -- libvir-list mailing list libvir-list@xxxxxxxxxx https://www.redhat.com/mailman/listinfo/libvir-list