[libvirt] [rust PATCH v2 2/5] libvirt-rust: stream: add more functions in stream

Sahid Orentino Ferdjaoui sahid.ferdjaoui at canonical.com
Fri Jan 10 11:46:33 UTC 2020


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 at aosc.io>
> ---
>  src/stream.rs | 46 ++++++++++++++++++++++++++++++++++++++++++++--
>  1 file changed, 44 insertions(+), 2 deletions(-)

Reviewed-by: Sahid Orentino Ferdjaoui <sahid.ferdjaoui at canonical.com>

> 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





More information about the libvir-list mailing list