diff --git a/gi-gtk-hs.cabal b/gi-gtk-hs.cabal
--- a/gi-gtk-hs.cabal
+++ b/gi-gtk-hs.cabal
@@ -1,5 +1,5 @@
 name:                gi-gtk-hs
-version:             0.3.1.0
+version:             0.3.2.0
 synopsis:            A wrapper for gi-gtk, adding a few more idiomatic API parts on top
 description:         A wrapper for gi-gtk, adding a few more idiomatic API parts on top
 homepage:            https://github.com/haskell-gi/gi-gtk-hs
@@ -32,7 +32,7 @@
                        transformers >=0.3.0.0 && <0.6,
                        containers >=0.5.5.1 && <0.6,
                        text >=1.2 && <1.3,
-                       haskell-gi-base >=0.18 && <0.19,
+                       haskell-gi-base >=0.20 && <0.21,
                        gi-glib >=2.0.6 && <2.1,
                        gi-gobject >=2.0.6 && <2.1,
                        gi-gdk >=3.0.6 && <3.1,
diff --git a/src/Data/GI/Gtk/BuildFn.hs b/src/Data/GI/Gtk/BuildFn.hs
--- a/src/Data/GI/Gtk/BuildFn.hs
+++ b/src/Data/GI/Gtk/BuildFn.hs
@@ -53,7 +53,7 @@
 buildWithBuilder :: MonadIO m => BuildFn a -> Builder -> m a
 buildWithBuilder fn builder = liftIO $ runReaderT fn builder
 
-getObject :: GObject a => (ForeignPtr a -> a) -> T.Text -> BuildFn a
+getObject :: GObject a => (ManagedPtr a -> a) -> T.Text -> BuildFn a
 getObject ctor name = do
     builder <- ask
     Just obj <- nullToNothing $ builderGetObject builder name
diff --git a/src/Data/GI/Gtk/ComboBox.hs b/src/Data/GI/Gtk/ComboBox.hs
--- a/src/Data/GI/Gtk/ComboBox.hs
+++ b/src/Data/GI/Gtk/ComboBox.hs
@@ -111,12 +111,12 @@
 --
 objectSetAttribute :: (MonadIO m, GObject o) => o -> GQuark -> Maybe a -> m ()
 objectSetAttribute obj attr Nothing = liftIO $ do
-  let obj' = unsafeManagedPtrCastPtr obj
+  obj' <- unsafeManagedPtrCastPtr obj
   g_object_set_qdata obj' (fromIntegral attr) nullPtr
   touchManagedPtr obj
 objectSetAttribute obj attr (Just val) = liftIO $ do
   sPtr <- newStablePtr val
-  let obj' = unsafeManagedPtrCastPtr obj
+  obj' <- unsafeManagedPtrCastPtr obj
   g_object_set_qdata_full obj' attr (castStablePtrToPtr sPtr) destroyStablePtr
   touchManagedPtr obj
 
@@ -131,7 +131,7 @@
 --
 objectGetAttributeUnsafe :: (MonadIO m, GObject o) => o -> GQuark -> m (Maybe a)
 objectGetAttributeUnsafe obj attr = liftIO $ do
-  let obj' = unsafeManagedPtrCastPtr obj
+  obj' <- unsafeManagedPtrCastPtr obj
   sPtr <- g_object_get_qdata obj' attr
   touchManagedPtr obj
   if sPtr==nullPtr then return Nothing else
diff --git a/src/Data/GI/Gtk/ModelView/CellLayout.hs b/src/Data/GI/Gtk/ModelView/CellLayout.hs
--- a/src/Data/GI/Gtk/ModelView/CellLayout.hs
+++ b/src/Data/GI/Gtk/ModelView/CellLayout.hs
@@ -70,6 +70,7 @@
 import Data.GI.Gtk.ModelView.TreeModel
 import Data.GI.Gtk.ModelView.CustomStore (customStoreGetRow)
 import Data.GI.Base (get)
+import Data.GI.Base.BasicTypes (ManagedPtr(..))
 
 --------------------
 -- Methods
@@ -152,7 +153,7 @@
   cellLayoutSetCellDataFunc self cell . Just $ \_ (CellRenderer cellPtr') model' iter -> do
     iter <- convertIterFromParentToChildModel iter model' =<< toTreeModel model
     CellRenderer cellPtr <- toCellRenderer cell
-    if cellPtr /= cellPtr' then
+    if managedForeignPtr cellPtr /= managedForeignPtr cellPtr' then
       error ("cellLayoutSetAttributeFunc: attempt to set attributes of "++
              "a different CellRenderer.")
       else func iter
@@ -174,14 +175,14 @@
   -> IO TreeIter
 convertIterFromParentToChildModel iter parentModel@(TreeModel parentModelPtr) childModel =
   let (TreeModel modelPtr) = childModel in
-  if modelPtr==parentModelPtr
+  if managedForeignPtr modelPtr == managedForeignPtr parentModelPtr
     then return iter
     else
         castTo TreeModelFilter parentModel >>= \case
             Just tmFilter -> do
                 childIter <- treeModelFilterConvertIterToChildIter tmFilter iter
                 Just child@(TreeModel childPtr) <- getTreeModelFilterChildModel tmFilter
-                if childPtr == modelPtr
+                if managedForeignPtr childPtr == managedForeignPtr modelPtr
                     then return childIter
                     else convertIterFromParentToChildModel childIter child childModel
             Nothing -> do
@@ -189,7 +190,7 @@
                     Just tmSort -> do
                         childIter <- treeModelSortConvertIterToChildIter tmSort iter
                         child@(TreeModel childPtr) <- getTreeModelSortModel tmSort
-                        if childPtr == modelPtr
+                        if managedForeignPtr childPtr == managedForeignPtr modelPtr
                             then return childIter
                             else convertIterFromParentToChildModel childIter child childModel
                     Nothing -> do
@@ -198,8 +199,8 @@
                         ud2 <- getTreeIterUserData2 iter
                         ud3 <- getTreeIterUserData3 iter
                         error ("CellLayout: don't know how to convert iter "++show (stamp, ud1, ud2, ud3)++
-                               " from model "++show parentModelPtr++" to model "++
-                               show modelPtr++". Is it possible that you are setting the "++
+                               " from model "++show (managedForeignPtr parentModelPtr)++" to model "++
+                               show (managedForeignPtr modelPtr)++". Is it possible that you are setting the "++
                                "attributes of a CellRenderer using a different model than "++
                                "that which was set in the view?")
 
diff --git a/src/Data/GI/Gtk/ModelView/CustomStore.hs b/src/Data/GI/Gtk/ModelView/CustomStore.hs
--- a/src/Data/GI/Gtk/ModelView/CustomStore.hs
+++ b/src/Data/GI/Gtk/ModelView/CustomStore.hs
@@ -65,9 +65,11 @@
 import Foreign.Marshal (fromBool)
 import Foreign.Storable (peek, poke, peekByteOff)
 import System.IO.Unsafe (unsafePerformIO)
-import Data.GI.Base.BasicTypes (GObject(..), GType, CGType(..), gtypeToCGType, gtypeInt, gtypeBoolean, gtypeString, gtypeInvalid)
+import Data.GI.Base.BasicTypes
+       (ManagedPtr(..), GObject(..), GType, CGType(..), gtypeToCGType,
+        gtypeInt, gtypeBoolean, gtypeString, gtypeInvalid)
 import Data.GI.Base.BasicConversions (gflagsToWord, withTextCString)
-import Data.GI.Base.ManagedPtr (newObject, withManagedPtr)
+import Data.GI.Base.ManagedPtr (newPtr, newObject, withManagedPtr)
 import Data.GI.Base.GValue (GValue(..))
 import GI.GObject (Object)
 import GI.GdkPixbuf.Objects (Pixbuf(..))
@@ -104,7 +106,7 @@
 --   create an instance of a 'CustomStore' or use one of the pre-defined
 --   models 'Data.GI.Gtk.ModelView.ListStore.ListStore' or
 --   'Data.GI.Gtk.ModelView.TreeStore.TreeStore'.
-newtype CustomStore private row = CustomStore (ForeignPtr (CustomStore private row))
+newtype CustomStore private row = CustomStore (ManagedPtr (CustomStore private row))
 instance IsTreeModel (CustomStore private row)
 
 instance GObject (CustomStore private row) where
@@ -264,10 +266,10 @@
 -- | Return the private data stored in this 'CustomStore'. The private data
 --   is meant as a container for the data stored in this model.
 customStoreGetPrivate :: CustomStore private row -> private
-customStoreGetPrivate (CustomStore model) =
+customStoreGetPrivate model =
   unsafePerformIO $ -- this is safe because the priv member is set at
                     -- construction time and never modified after that
-  withForeignPtr model gtk2hs_store_get_priv >>= deRefStablePtr
+  withManagedPtr model gtk2hs_store_get_priv >>= deRefStablePtr
 
 foreign import ccall unsafe "Gtk2HsStore.h gtk2hs_store_get_priv"
   gtk2hs_store_get_priv :: Ptr (CustomStore private row) -> IO (StablePtr private)
@@ -280,8 +282,8 @@
 --   use a stale 'TreeIter', i.e., one that refers to an old model.
 --
 customStoreGetStamp :: MonadIO m => CustomStore private row -> m Int32
-customStoreGetStamp (CustomStore model) = liftIO $ fromIntegral <$>
-  withForeignPtr model gtk2hs_store_get_stamp
+customStoreGetStamp model = liftIO $ fromIntegral <$>
+  withManagedPtr model gtk2hs_store_get_stamp
 
 foreign import ccall unsafe "Gtk2HsStore.h gtk2hs_store_get_stamp"
   gtk2hs_store_get_stamp :: Ptr (CustomStore private row) -> IO CInt
@@ -289,8 +291,8 @@
 -- | Create a new stamp. See 'customStoreGetStamp'.
 --
 customStoreInvalidateIters :: MonadIO m => CustomStore private row -> m ()
-customStoreInvalidateIters (CustomStore model) = liftIO $
-  withForeignPtr model gtk2hs_store_increment_stamp
+customStoreInvalidateIters model = liftIO $
+  withManagedPtr model gtk2hs_store_increment_stamp
 
 foreign import ccall unsafe "Gtk2HsStore.h gtk2hs_store_increment_stamp"
   gtk2hs_store_increment_stamp :: Ptr (CustomStore private row) -> IO ()
@@ -340,9 +342,11 @@
 
 treeModelIfaceGetIter_static :: StablePtr (CustomStoreImplementation model row) -> Ptr TreeIter -> Ptr TreePath -> IO CInt
 treeModelIfaceGetIter_static storePtr iterPtr pathPtr = do
-  iterOut <- TreeIter <$> newForeignPtr_ iterPtr -- Take care not to use this outside of this function
+  isOwned <- newIORef False
+  ptr <- newForeignPtr_ iterPtr
+  let iterOut = TreeIter $ ManagedPtr ptr isOwned  -- Take care not to use this outside of this function
   store <- customStoreIface <$> deRefStablePtr storePtr
-  path <- treePathCopy . TreePath =<< newForeignPtr_ pathPtr
+  path <- newBoxed TreePath pathPtr
   treeModelIfaceGetIter store path >>= \case
     Nothing   -> return (fromBool False)
     Just iter -> do treeIterOverwrite iterOut iter
@@ -402,7 +406,9 @@
 
 treeModelIfaceIterNext_static :: StablePtr (CustomStoreImplementation model row) -> Ptr TreeIter -> IO CInt
 treeModelIfaceIterNext_static storePtr iterPtr = do
-  iterOut <- TreeIter <$> newForeignPtr_ iterPtr -- Take care not to use this outside of this function
+  isOwned <- newIORef False
+  ptr <- newForeignPtr_ iterPtr
+  let iterOut = TreeIter $ ManagedPtr ptr isOwned  -- Take care not to use this outside of this function
   store <- customStoreIface <$> deRefStablePtr storePtr
   iter <- newBoxed TreeIter iterPtr
   treeModelIfaceIterNext store iter >>= \case
@@ -416,7 +422,9 @@
 
 treeModelIfaceIterChildren_static :: StablePtr (CustomStoreImplementation model row) -> Ptr TreeIter -> Ptr TreeIter -> IO CInt
 treeModelIfaceIterChildren_static storePtr iterPtr parentIterPtr = do
-  iterOut <- TreeIter <$> newForeignPtr_ iterPtr -- Take care not to use this outside of this function
+  isOwned <- newIORef False
+  ptr <- newForeignPtr_ iterPtr
+  let iterOut = TreeIter $ ManagedPtr ptr isOwned  -- Take care not to use this outside of this function
   store <- customStoreIface <$> deRefStablePtr storePtr
   parentIter <- maybeNull (newBoxed TreeIter) parentIterPtr
   treeModelIfaceIterChildren store parentIter >>= \case
@@ -450,7 +458,9 @@
 
 treeModelIfaceIterNthChild_static :: StablePtr (CustomStoreImplementation model row) -> Ptr TreeIter -> Ptr TreeIter -> CInt -> IO CInt
 treeModelIfaceIterNthChild_static storePtr iterPtr parentIterPtr n = do
-  iterOut <- TreeIter <$> newForeignPtr_ iterPtr -- Take care not to use this outside of this function
+  isOwned <- newIORef False
+  ptr <- newForeignPtr_ iterPtr
+  let iterOut = TreeIter $ ManagedPtr ptr isOwned  -- Take care not to use this outside of this function
   store <- customStoreIface <$> deRefStablePtr storePtr
   parentIter <- maybeNull (newBoxed TreeIter) parentIterPtr
   treeModelIfaceIterNthChild store parentIter (fromIntegral n) >>= \case
@@ -464,7 +474,9 @@
 
 treeModelIfaceIterParent_static :: StablePtr (CustomStoreImplementation model row) -> Ptr TreeIter -> Ptr TreeIter -> IO CInt
 treeModelIfaceIterParent_static  storePtr iterPtr childIterPtr = do
-  iterOut <- TreeIter <$> newForeignPtr_ iterPtr -- Take care not to use this outside of this function
+  isOwned <- newIORef False
+  ptr <- newForeignPtr_ iterPtr
+  let iterOut = TreeIter $ ManagedPtr ptr isOwned  -- Take care not to use this outside of this function
   store <- customStoreIface <$> deRefStablePtr storePtr
   childIter <- newBoxed TreeIter childIterPtr
   iter <- treeModelIfaceIterParent store childIter
@@ -500,7 +512,7 @@
 customDragSourceRowDraggable_static mPtr storePtr pathPtr = do
   model <- newObject TreeModel mPtr
   store <- customTreeDragSourceIface <$> deRefStablePtr storePtr
-  path <- treePathCopy . TreePath =<< newForeignPtr_ pathPtr
+  path <- newBoxed TreePath pathPtr
   fromBool <$> customDragSourceRowDraggable store (unsafeTreeModelToGeneric model) path
 
 foreign export ccall "gtk2hs_store_row_draggable_impl"
@@ -510,8 +522,8 @@
 customDragSourceDragDataGet_static mPtr storePtr pathPtr selectionPtr = do
   model <- newObject TreeModel mPtr
   store <- customTreeDragSourceIface <$> deRefStablePtr storePtr
-  path <- treePathCopy . TreePath =<< newForeignPtr_ pathPtr
-  selection <- selectionDataCopy . SelectionData =<< newForeignPtr_ selectionPtr
+  path <- newBoxed TreePath pathPtr
+  selection <- newBoxed SelectionData selectionPtr
   fromBool <$> customDragSourceDragDataGet store (unsafeTreeModelToGeneric model) path selection
 
 foreign export ccall "gtk2hs_store_drag_data_get_impl"
@@ -521,7 +533,7 @@
 customDragSourceDragDataDelete_static mPtr storePtr pathPtr = do
   model <- newObject TreeModel mPtr
   store <- customTreeDragSourceIface <$> deRefStablePtr storePtr
-  path <- treePathCopy . TreePath =<< newForeignPtr_ pathPtr
+  path <- newBoxed TreePath pathPtr
   fromBool <$> customDragSourceDragDataDelete store (unsafeTreeModelToGeneric model) path
 
 foreign export ccall "gtk2hs_store_drag_data_delete_impl"
@@ -531,8 +543,8 @@
 customDragDestDragDataReceived_static mPtr storePtr pathPtr selectionPtr = do
   model <- newObject TreeModel mPtr
   store <- customTreeDragDestIface <$> deRefStablePtr storePtr
-  path <- treePathCopy . TreePath =<< newForeignPtr_ pathPtr
-  selection <- selectionDataCopy . SelectionData =<< newForeignPtr_ selectionPtr
+  path <- newBoxed TreePath pathPtr
+  selection <- newBoxed SelectionData selectionPtr
   fromBool <$> customDragDestDragDataReceived store (unsafeTreeModelToGeneric model) path selection
 
 foreign export ccall "gtk2hs_store_drag_data_received_impl"
@@ -542,8 +554,8 @@
 customDragDestRowDropPossible_static mPtr storePtr pathPtr selectionPtr = do
   model <- newObject TreeModel mPtr
   store <- customTreeDragDestIface <$> deRefStablePtr storePtr
-  path <- treePathCopy . TreePath =<< newForeignPtr_ pathPtr
-  selection <- selectionDataCopy . SelectionData =<< newForeignPtr_ selectionPtr
+  path <- newBoxed TreePath pathPtr
+  selection <- newBoxed SelectionData selectionPtr
   fromBool <$> customDragDestRowDropPossible store (unsafeTreeModelToGeneric model) path selection
 
 foreign export ccall "gtk2hs_store_row_drop_possible_impl"
diff --git a/src/Data/GI/Gtk/ModelView/ForestStore.hs b/src/Data/GI/Gtk/ModelView/ForestStore.hs
--- a/src/Data/GI/Gtk/ModelView/ForestStore.hs
+++ b/src/Data/GI/Gtk/ModelView/ForestStore.hs
@@ -73,7 +73,8 @@
 
 import Foreign.ForeignPtr (ForeignPtr)
 
-import Data.GI.Base.BasicTypes (GObject(..), GObject)
+import Data.GI.Base.BasicTypes
+       (ManagedPtr(..), GObject(..), GObject)
 import Data.GI.Base.ManagedPtr (withManagedPtr)
 
 import Data.GI.Gtk.ModelView.Types
@@ -125,7 +126,7 @@
 
 -- | A store for hierarchical data.
 --
-newtype ForestStore a = ForestStore (ForeignPtr (CustomStore (IORef (Store a)) a))
+newtype ForestStore a = ForestStore (ManagedPtr (CustomStore (IORef (Store a)) a))
 
 mkForestStore :: CustomStore (IORef (Store a)) a -> ForestStore a
 mkForestStore (CustomStore ptr) = ForestStore ptr
diff --git a/src/Data/GI/Gtk/ModelView/SeqStore.hs b/src/Data/GI/Gtk/ModelView/SeqStore.hs
--- a/src/Data/GI/Gtk/ModelView/SeqStore.hs
+++ b/src/Data/GI/Gtk/ModelView/SeqStore.hs
@@ -74,7 +74,8 @@
        (customStoreGetStamp, customStoreGetPrivate,
         TreeModelIface(..), customStoreNew, DragDestIface(..),
         DragSourceIface(..), CustomStore(..))
-import Data.GI.Base.BasicTypes (GObject(..), GObject)
+import Data.GI.Base.BasicTypes
+       (ManagedPtr(..), GObject(..), GObject)
 import Data.GI.Base.ManagedPtr (withManagedPtr)
 import GI.Gtk.Interfaces.TreeModel
        (treeModelRowDeleted, treeModelRowInserted,
@@ -100,7 +101,7 @@
     setTreeIterUserData3 i nullPtr
     return i
 
-newtype SeqStore a = SeqStore (ForeignPtr (CustomStore (IORef (Seq a)) a))
+newtype SeqStore a = SeqStore (ManagedPtr (CustomStore (IORef (Seq a)) a))
 
 mkSeqStore :: CustomStore (IORef (Seq a)) a -> SeqStore a
 mkSeqStore (CustomStore ptr) = SeqStore ptr
diff --git a/src/Data/GI/Gtk/ModelView/Types.hs b/src/Data/GI/Gtk/ModelView/Types.hs
--- a/src/Data/GI/Gtk/ModelView/Types.hs
+++ b/src/Data/GI/Gtk/ModelView/Types.hs
@@ -50,7 +50,6 @@
   treePathNewFromIndices',
   treePathGetIndices',
   withTreePath,
-  maybeWithTreePath,
   stringToTreePath,
 
   treeSelectionGetSelectedRows',
@@ -86,7 +85,9 @@
 import Foreign.Marshal.Utils (toBool)
 import System.IO.Unsafe (unsafePerformIO)
 import Foreign.Marshal.Utils (with)
-import Data.GI.Base.BasicTypes (ForeignPtrNewtype, UnexpectedNullPointerReturn, GObject(..))
+import Data.GI.Base.BasicTypes
+       (ManagedPtr(..), ManagedPtrNewtype, UnexpectedNullPointerReturn,
+        GObject(..))
 import Data.GI.Base.ManagedPtr (withManagedPtr)
 import Data.GI.Base.GValue (GValue)
 import GI.GObject.Objects.Object (Object(..))
@@ -104,13 +105,11 @@
 import Data.GI.Base.Attributes (AttrOp(..))
 import Unsafe.Coerce (unsafeCoerce)
 import Data.GI.Base (set, get)
-
-nullForeignPtr :: ForeignPtr a
-nullForeignPtr = unsafePerformIO $ newForeignPtr_ nullPtr
+import Data.IORef (newIORef)
 
-equalManagedPtr :: ForeignPtrNewtype a => a -> a -> Bool
+equalManagedPtr :: ManagedPtrNewtype a => a -> a -> Bool
 equalManagedPtr a b =
-    (coerce a :: ForeignPtr ()) == (coerce b :: ForeignPtr ())
+    managedForeignPtr (coerce a :: ManagedPtr ()) == managedForeignPtr (coerce b :: ManagedPtr ())
 
 newtype TypedTreeModel row = TypedTreeModel (ForeignPtr (TypedTreeModel row))
 
@@ -128,7 +127,7 @@
 
 instance IsTypedTreeModel TypedTreeModel
 
-newtype TypedTreeModelSort row = TypedTreeModelSort (ForeignPtr (TypedTreeModelSort row))
+newtype TypedTreeModelSort row = TypedTreeModelSort (ManagedPtr (TypedTreeModelSort row))
 
 instance IsTreeModelSort (TypedTreeModelSort row)
 instance IsTreeSortable (TypedTreeModelSort row)
@@ -176,8 +175,8 @@
 withTreePath :: MonadIO m => [Int32] -> (TreePath -> m a) -> m a
 withTreePath tp act = treePathNewFromIndices' tp >>= act
 
-maybeWithTreePath :: MonadIO m => Maybe [Int32] -> (TreePath -> m a) -> m a
-maybeWithTreePath mbTp act = maybe (act (TreePath nullForeignPtr)) (`withTreePath` act) mbTp
+--maybeWithTreePath :: MonadIO m => Maybe [Int32] -> (TreePath -> m a) -> m a
+--maybeWithTreePath mbTp act = maybe (act (TreePath nullManagedPtr)) (`withTreePath` act) mbTp
 
 treeSelectionGetSelectedRows' :: (MonadIO m, IsTreeSelection sel) => sel -> m [TreePath]
 treeSelectionGetSelectedRows' sel = treeSelectionCountSelectedRows sel >>= \case
