[libvirt-rust PATCH v3 2/4] libvirt-rust: stream: add more functions in stream

Zixing Liu liushuyu at aosc.io
Thu Jan 30 03:24:12 UTC 2020


* 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(-)

diff --git a/src/stream.rs b/src/stream.rs
index 96e37cb..3a83b34 100644
--- a/src/stream.rs
+++ b/src/stream.rs
@@ -50,6 +50,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;
@@ -64,9 +70,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 {
@@ -79,6 +102,13 @@ impl Drop for Stream {
                 )
             }
         }
+        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)
+            }
+        }
     }
 }
 
@@ -94,7 +124,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 {
@@ -151,6 +181,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.25.0





More information about the libvir-list mailing list