diff --git a/src/blob.rs b/src/blob.rs index 4361366..06457d6 100644 --- a/src/blob.rs +++ b/src/blob.rs @@ -50,7 +50,6 @@ //! ``` use std::io; use std::cmp::min; -use std::mem; use std::ptr; use super::ffi; @@ -155,7 +154,7 @@ impl<'conn> io::Read for Blob<'conn> { return Ok(0); } let rc = - unsafe { ffi::sqlite3_blob_read(self.blob, mem::transmute(buf.as_ptr()), n, self.pos) }; + unsafe { ffi::sqlite3_blob_read(self.blob, buf.as_ptr() as *mut _, n, self.pos) }; self.conn .decode_result(rc) .map(|_| { @@ -184,7 +183,7 @@ impl<'conn> io::Write for Blob<'conn> { return Ok(0); } let rc = unsafe { - ffi::sqlite3_blob_write(self.blob, mem::transmute(buf.as_ptr()), n, self.pos) + ffi::sqlite3_blob_write(self.blob, buf.as_ptr() as *mut _, n, self.pos) }; self.conn .decode_result(rc) diff --git a/src/hooks.rs b/src/hooks.rs index 42f88b6..0f3b359 100644 --- a/src/hooks.rs +++ b/src/hooks.rs @@ -130,7 +130,8 @@ impl InnerConnection { use std::ffi::CStr; use std::str; - let boxed_hook: &mut Box = mem::transmute(p_arg); + let boxed_hook: *mut F = mem::transmute(p_arg); + assert!(!boxed_hook.is_null(), "Internal error - null function pointer"); let action = Action::from(action_code); let db_name = { @@ -142,15 +143,15 @@ impl InnerConnection { str::from_utf8_unchecked(c_slice) }; - boxed_hook(action, db_name, tbl_name, row_id); + (*boxed_hook)(action, db_name, tbl_name, row_id); } let previous_hook = { - let boxed_hook: Box> = Box::new(Box::new(hook)); + let boxed_hook: *mut F = Box::into_raw(Box::new(hook)); unsafe { ffi::sqlite3_update_hook(self.db(), Some(call_boxed_closure::), - Box::into_raw(boxed_hook) as *mut _) + boxed_hook as *mut _) } }; free_boxed_update_hook(previous_hook); @@ -164,14 +165,9 @@ impl InnerConnection { } fn free_boxed_update_hook(hook: *mut c_void) { - /* - http://stackoverflow.com/questions/32270030/how-do-i-convert-a-rust-closure-to-a-c-style-callback - Double indirection (i.e. Box>) is necessary - because Box ..> is a trait object and therefore a fat pointer, - incompatible with *mut c_void because of different size. - */ if !hook.is_null() { - let _: Box> = unsafe { Box::from_raw(hook as *mut _) }; + // TODO make sure that size_of::<*mut F>() is always equal to size_of::<*mut c_void>() + let _: Box<*mut c_void> = unsafe { Box::from_raw(hook as *mut _) }; } } diff --git a/src/lib.rs b/src/lib.rs index a55cd9b..949271a 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -781,6 +781,9 @@ impl InnerConnection { } fn close(&mut self) -> Result<()> { + if self.db.is_null() { + return Ok(()); + } self.remove_hooks(); unsafe { let r = ffi::sqlite3_close(self.db());