diff --git a/src/bitmap.rs b/src/bitmap.rs
index f658b85..c07fa07 100644
--- a/src/bitmap.rs
+++ b/src/bitmap.rs
@@ -1,18 +1,8 @@
 use servicepoint::{DataRef, Grid};
-use std::sync::{Arc, RwLock};
+use std::sync::{Arc};
+use crate::macros::wrap_uniffi_object;
 
-#[derive(uniffi::Object)]
-pub struct Bitmap {
-    pub(crate) actual: RwLock<servicepoint::Bitmap>,
-}
-
-impl Bitmap {
-    fn internal_new(actual: servicepoint::Bitmap) -> Arc<Self> {
-        Arc::new(Self {
-            actual: RwLock::new(actual),
-        })
-    }
-}
+wrap_uniffi_object!(Bitmap);
 
 #[uniffi::export]
 impl Bitmap {
diff --git a/src/bitvec.rs b/src/bitvec.rs
index 778b7bc..e9356fd 100644
--- a/src/bitvec.rs
+++ b/src/bitvec.rs
@@ -1,17 +1,7 @@
-use std::sync::{Arc, RwLock};
+use std::sync::{Arc};
+use crate::macros::wrap_uniffi_object;
 
-#[derive(uniffi::Object)]
-pub struct BitVec {
-    pub(crate) actual: RwLock<servicepoint::DisplayBitVec>,
-}
-
-impl BitVec {
-    fn internal_new(actual: servicepoint::DisplayBitVec) -> Arc<Self> {
-        Arc::new(Self {
-            actual: RwLock::new(actual),
-        })
-    }
-}
+wrap_uniffi_object!(DisplayBitVec, BitVec);
 
 #[uniffi::export]
 impl BitVec {
diff --git a/src/brightness_grid.rs b/src/brightness_grid.rs
index ba84cb4..ca64ebf 100644
--- a/src/brightness_grid.rs
+++ b/src/brightness_grid.rs
@@ -1,18 +1,8 @@
 use servicepoint::{Brightness, DataRef, Grid};
-use std::sync::{Arc, RwLock};
+use std::sync::{Arc};
+use crate::macros::wrap_uniffi_object;
 
-#[derive(uniffi::Object)]
-pub struct BrightnessGrid {
-    pub(crate) actual: RwLock<servicepoint::BrightnessGrid>,
-}
-
-impl BrightnessGrid {
-    fn internal_new(actual: servicepoint::BrightnessGrid) -> Arc<Self> {
-        Arc::new(Self {
-            actual: RwLock::new(actual),
-        })
-    }
-}
+wrap_uniffi_object!(BrightnessGrid);
 
 #[uniffi::export]
 impl BrightnessGrid {
diff --git a/src/char_grid.rs b/src/char_grid.rs
index e5d59a8..8bf70ac 100644
--- a/src/char_grid.rs
+++ b/src/char_grid.rs
@@ -1,12 +1,10 @@
 use crate::cp437_grid::Cp437Grid;
 use servicepoint::{Grid, SetValueSeriesError};
 use std::convert::Into;
-use std::sync::{Arc, RwLock};
+use std::sync::{Arc};
+use crate::macros::wrap_uniffi_object;
 
-#[derive(uniffi::Object)]
-pub struct CharGrid {
-    pub(crate) actual: RwLock<servicepoint::CharGrid>,
-}
+wrap_uniffi_object!(CharGrid);
 
 #[derive(uniffi::Error, thiserror::Error, Debug)]
 pub enum CharGridError {
@@ -133,12 +131,6 @@ impl CharGrid {
 }
 
 impl CharGrid {
-    pub(crate) fn internal_new(actual: servicepoint::CharGrid) -> Arc<Self> {
-        Arc::new(Self {
-            actual: RwLock::new(actual),
-        })
-    }
-
     fn str_to_char(value: String) -> Result<char, CharGridError> {
         if value.len() != 1 {
             return Err(CharGridError::StringNotOneChar { value });
diff --git a/src/command.rs b/src/command.rs
index 710aeab..5939761 100644
--- a/src/command.rs
+++ b/src/command.rs
@@ -1,4 +1,3 @@
-use crate::bitmap::Bitmap;
 use crate::bitvec::BitVec;
 use crate::brightness_grid::BrightnessGrid;
 use crate::char_grid::CharGrid;
@@ -7,17 +6,10 @@ use crate::cp437_grid::Cp437Grid;
 use crate::errors::ServicePointError;
 use servicepoint::{BitVecCommand, BrightnessGridCommand, CharGridCommand, ClearCommand, Cp437GridCommand, FadeOutCommand, GlobalBrightnessCommand, HardResetCommand, Origin};
 use std::sync::Arc;
+use crate::bitmap::Bitmap;
+use crate::macros::wrap_uniffi_object;
 
-#[derive(uniffi::Object)]
-pub struct Command {
-    pub(crate) actual: servicepoint::TypedCommand,
-}
-
-impl Command {
-    fn internal_new(actual: servicepoint::TypedCommand) -> Arc<Command> {
-        Arc::new(Command { actual })
-    }
-}
+wrap_uniffi_object!(TypedCommand, Command);
 
 #[uniffi::export]
 impl Command {
@@ -126,11 +118,11 @@ impl Command {
 
     #[uniffi::constructor]
     pub fn clone(other: &Arc<Self>) -> Arc<Self> {
-        Self::internal_new(other.actual.clone())
+        Self::internal_new(other.actual.read().unwrap().clone())
     }
 
     pub fn equals(&self, other: &Command) -> bool {
-        self.actual == other.actual
+        *self.actual.read().unwrap() == *other.actual.read().unwrap()
     }
 }
 
diff --git a/src/connection.rs b/src/connection.rs
index 9b0baea..32c9b8a 100644
--- a/src/connection.rs
+++ b/src/connection.rs
@@ -25,7 +25,7 @@ impl Connection {
     }
 
     pub fn send(&self, command: Arc<Command>) -> Result<(), ServicePointError> {
-        self.actual.send_command(command.actual.clone()).ok_or_else(|| {
+        self.actual.send_command(command.actual.read().unwrap().clone()).ok_or_else(|| {
             ServicePointError::IoError {
                 error: "send failed".to_string(),
             }
diff --git a/src/cp437_grid.rs b/src/cp437_grid.rs
index 89f9420..7ca1e62 100644
--- a/src/cp437_grid.rs
+++ b/src/cp437_grid.rs
@@ -1,19 +1,9 @@
 use crate::char_grid::CharGrid;
 use servicepoint::{DataRef, Grid};
-use std::sync::{Arc, RwLock};
+use std::sync::{Arc};
+use crate::macros::wrap_uniffi_object;
 
-#[derive(uniffi::Object)]
-pub struct Cp437Grid {
-    pub(crate) actual: RwLock<servicepoint::Cp437Grid>,
-}
-
-impl Cp437Grid {
-    pub(crate) fn internal_new(actual: servicepoint::Cp437Grid) -> Arc<Self> {
-        Arc::new(Self {
-            actual: RwLock::new(actual),
-        })
-    }
-}
+wrap_uniffi_object!(Cp437Grid);
 
 #[uniffi::export]
 impl Cp437Grid {
diff --git a/src/lib.rs b/src/lib.rs
index 2ecad45..b981f9d 100644
--- a/src/lib.rs
+++ b/src/lib.rs
@@ -10,3 +10,4 @@ mod connection;
 mod constants;
 mod cp437_grid;
 mod errors;
+mod macros;
diff --git a/src/macros.rs b/src/macros.rs
new file mode 100644
index 0000000..8f46c1c
--- /dev/null
+++ b/src/macros.rs
@@ -0,0 +1,22 @@
+
+macro_rules! wrap_uniffi_object {
+     ($orig_t:ident, $new_t:ident) => {
+        #[derive(uniffi::Object)]
+        pub struct $new_t {
+            pub(crate) actual: std::sync::RwLock<servicepoint::$orig_t>,
+        }
+
+        impl $new_t {
+            pub(crate) fn internal_new(actual: servicepoint::$orig_t) -> Arc<Self> {
+                Arc::new(Self {
+                    actual: std::sync::RwLock::new(actual),
+                })
+            }
+        }
+     };
+    ($t:ident) => {
+        wrap_uniffi_object!($t, $t);
+    };
+}
+
+pub(crate) use wrap_uniffi_object;
\ No newline at end of file