On Tue, Dec 24, 2019 at 12:12:52AM -0700, Zixing Liu wrote: > * 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(-) Reviewed-by: Sahid Orentino Ferdjaoui <sahid.ferdjaoui@xxxxxxxxxxxxx> > 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)] This line can be removed. > 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.1 -- libvir-list mailing list libvir-list@xxxxxxxxxx https://www.redhat.com/mailman/listinfo/libvir-list