diff --git a/Data/GI/Base.hs b/Data/GI/Base.hs
--- a/Data/GI/Base.hs
+++ b/Data/GI/Base.hs
@@ -26,7 +26,7 @@
 import Data.GI.Base.Constructible (new)
 import Data.GI.Base.GError
 import Data.GI.Base.GHashTable
-import Data.GI.Base.GValue (GValue(..), IsGValue(..))
+import Data.GI.Base.GValue (GValue(..), fromGValue, toGValue, IsGValue(..))
 import Data.GI.Base.GVariant
 import Data.GI.Base.ManagedPtr
 import Data.GI.Base.Signals (on, after, SignalProxy(PropertyNotify, (:::)))
diff --git a/Data/GI/Base/Attributes.hs b/Data/GI/Base/Attributes.hs
--- a/Data/GI/Base/Attributes.hs
+++ b/Data/GI/Base/Attributes.hs
@@ -156,6 +156,7 @@
 import {-# SOURCE #-} Data.GI.Base.Signals (SignalInfo(..), SignalProxy, on)
 
 import Data.Proxy (Proxy(..))
+import Data.Kind (Type)
 
 import GHC.TypeLits
 import GHC.Exts (Constraint)
@@ -176,28 +177,28 @@
 #endif
 
 -- | Info describing an attribute.
-class AttrInfo (info :: *) where
+class AttrInfo (info :: Type) where
     -- | The operations that are allowed on the attribute.
     type AttrAllowedOps info :: [AttrOpTag]
 
     -- | Constraint on the type for which we are allowed to
     -- create\/set\/get the attribute.
-    type AttrBaseTypeConstraint info :: * -> Constraint
+    type AttrBaseTypeConstraint info :: Type -> Constraint
 
     -- | Type returned by `attrGet`.
     type AttrGetType info
 
     -- | Constraint on the value being set.
-    type AttrSetTypeConstraint info :: * -> Constraint
+    type AttrSetTypeConstraint info :: Type -> Constraint
     type AttrSetTypeConstraint info = (~) (AttrGetType info)
 
     -- | Constraint on the value being set, with allocation allowed
     -- (see ':&=' below).
-    type AttrTransferTypeConstraint info :: * -> Constraint
+    type AttrTransferTypeConstraint info :: Type -> Constraint
     type AttrTransferTypeConstraint info = (~) (AttrTransferType info)
 
     -- | Type resulting from the allocation.
-    type AttrTransferType info :: *
+    type AttrTransferType info :: Type
     type AttrTransferType info = AttrGetType info
 
     -- | Name of the attribute.
@@ -280,7 +281,7 @@
 
 -- | Look in the given list to see if the given `AttrOp` is a member,
 -- if not return an error type.
-type family AttrOpIsAllowed (tag :: AttrOpTag) (ops :: [AttrOpTag]) (label :: Symbol) (definingType :: *) (useType :: *) :: Constraint where
+type family AttrOpIsAllowed (tag :: AttrOpTag) (ops :: [AttrOpTag]) (label :: Symbol) (definingType :: Type) (useType :: Type) :: Constraint where
     AttrOpIsAllowed tag '[] label definingType useType =
         TypeError ('Text "Attribute ‘" ':<>: 'Text label ':<>:
                    'Text "’ for type " ':<>:
@@ -292,7 +293,7 @@
 
 -- | Whether a given `AttrOpTag` is allowed on an attribute, given the
 -- info type.
-type family AttrOpAllowed (tag :: AttrOpTag) (info :: *) (useType :: *) :: Constraint where
+type family AttrOpAllowed (tag :: AttrOpTag) (info :: Type) (useType :: Type) :: Constraint where
     AttrOpAllowed tag info useType =
         AttrOpIsAllowed tag (AttrAllowedOps info) (AttrLabel info) (AttrOrigin info) useType
 
diff --git a/Data/GI/Base/GParamSpec.hsc b/Data/GI/Base/GParamSpec.hsc
--- a/Data/GI/Base/GParamSpec.hsc
+++ b/Data/GI/Base/GParamSpec.hsc
@@ -147,16 +147,16 @@
 wrapGetSet :: forall o a. (GObject o, IsGValue a) =>
               (o -> IO a)       -- ^ Haskell side getter
            -> (o -> a -> IO ()) -- ^ Haskell side setter
-           -> (GValue -> a -> IO ()) -- ^ Setter for the `GValue`
+           -> (Ptr GValue -> a -> IO ()) -- ^ Setter for the `GValue`
            -> PropGetSetter o
 wrapGetSet getter setter gvalueSetter = PropGetSetter {
   propGetter = \objPtr destPtr -> do
       value <- objectFromPtr objPtr >>= getter
-      withTransient GValue destPtr $ \dest -> gvalueSetter dest value
+      gvalueSetter destPtr value
   , propSetter = \objPtr newGValuePtr ->
       withTransient GValue newGValuePtr $ \newGValue -> do
         obj <- objectFromPtr objPtr
-        value <- fromGValue newGValue
+        value <- GV.fromGValue newGValue
         setter obj value
   }
 
@@ -217,7 +217,7 @@
     setter' :: Ptr o -> (Ptr GValue) -> IO ()
     setter' objPtr gvPtr = withTransient GValue gvPtr $ \gv -> do
       obj <- objectFromPtr objPtr
-      val <- fromGValue gv >>= deRefStablePtr
+      val <- GV.fromGValue gv >>= deRefStablePtr
       setter obj val
 
 -- | Information on a property of type `CInt` to be registered. A
@@ -271,7 +271,7 @@
                                      defaultValue
                                      (maybe defaultFlags gflagsToWord flags)
         quark <- pspecQuark
-        gParamSpecSetQData pspecPtr quark (wrapGetSet getter setter GV.set_int)
+        gParamSpecSetQData pspecPtr quark (wrapGetSet getter setter gvalueSet_)
         wrapGParamSpecPtr pspecPtr
 
 -- | Information on a property of type `Text` to be registered. A
@@ -317,7 +317,7 @@
               g_param_spec_string cname cnick cblurb cdefault
                     (maybe defaultFlags gflagsToWord flags)
         quark <- pspecQuark
-        gParamSpecSetQData pspecPtr quark (wrapGetSet getter setter GV.set_string)
+        gParamSpecSetQData pspecPtr quark (wrapGetSet getter setter gvalueSet_)
         wrapGParamSpecPtr pspecPtr
 
 foreign import ccall g_param_spec_set_qdata_full ::
diff --git a/Data/GI/Base/GValue.hs b/Data/GI/Base/GValue.hs
--- a/Data/GI/Base/GValue.hs
+++ b/Data/GI/Base/GValue.hs
@@ -1,11 +1,17 @@
 {-# LANGUAGE FlexibleInstances #-}
 {-# LANGUAGE OverloadedStrings #-}
 {-# LANGUAGE DataKinds, TypeFamilies #-}
+{-# LANGUAGE ScopedTypeVariables #-}
+{-# LANGUAGE TypeApplications #-}
+{-# LANGUAGE AllowAmbiguousTypes #-}
+
 module Data.GI.Base.GValue
     (
     -- * Constructing GValues
       GValue(..)
     , IsGValue(..)
+    , toGValue
+    , fromGValue
     , GValueConstruct(..)
 
     , newGValue
@@ -23,34 +29,6 @@
     , mapGValueArrayWithLength
 
     -- * Setters and getters
-    , set_string
-    , get_string
-    , set_pointer
-    , get_pointer
-    , set_int
-    , get_int
-    , set_uint
-    , get_uint
-    , set_long
-    , get_long
-    , set_ulong
-    , get_ulong
-    , set_int32
-    , get_int32
-    , set_uint32
-    , get_uint32
-    , set_int64
-    , get_int64
-    , set_uint64
-    , get_uint64
-    , set_float
-    , get_float
-    , set_double
-    , get_double
-    , set_boolean
-    , get_boolean
-    , set_gtype
-    , get_gtype
     , set_object
     , get_object
     , set_boxed
@@ -64,6 +42,7 @@
     , set_stablePtr
     , get_stablePtr
     , take_stablePtr
+
     ) where
 
 import Data.Coerce (coerce)
@@ -134,10 +113,10 @@
 
 -- | A convenience function for building a new GValue and setting the
 -- initial value.
-buildGValue :: GType -> (GValue -> a -> IO ()) -> a -> IO GValue
+buildGValue :: GType -> (Ptr GValue -> a -> IO ()) -> a -> IO GValue
 buildGValue gtype setter val = do
   gv <- newGValue gtype
-  setter gv val
+  withManagedPtr gv $ \gvPtr -> setter gvPtr val
   return gv
 
 -- | Disown a `GValue`, i.e. do not unref the underlying object when
@@ -159,289 +138,258 @@
 unsetGValue :: Ptr GValue -> IO ()
 unsetGValue = g_value_unset
 
--- | A convenience class for marshaling back and forth between Haskell
--- values and `GValue`s.
+-- | Class for types that can be marshaled back and forth between
+-- Haskell values and `GValue`s. These are low-level methods, you
+-- might want to use `toGValue` and `fromGValue` instead for a higher
+-- level interface.
 class IsGValue a where
-    toGValue :: a -> IO GValue
-    fromGValue :: GValue -> IO a
+  gvalueGType_ :: IO GType     -- ^ `GType` for the `GValue`
+                               -- containing values of this type.
+  gvalueSet_   :: Ptr GValue -> a -> IO ()  -- ^ Set the `GValue` to
+                                            -- the given Haskell
+                                            -- value.
+  gvalueGet_   :: Ptr GValue -> IO a -- ^ Get the Haskel value inside
+                                     -- the `GValue`.
 
+-- | Create a `GValue` from the given Haskell value.
+toGValue :: forall a. IsGValue a => a -> IO GValue
+toGValue val = do
+  gvptr <- callocBytes cgvalueSize
+  GType gtype <- gvalueGType_ @a
+  _ <- g_value_init gvptr gtype
+  gvalueSet_ gvptr val
+  gv <- wrapBoxed GValue gvptr
+  return $! gv
+
+-- | Create a Haskell object out of the given `GValue`.
+fromGValue :: IsGValue a => GValue -> IO a
+fromGValue gv = withManagedPtr gv gvalueGet_
+
 instance IsGValue (Maybe String) where
-    toGValue = buildGValue gtypeString set_string . fmap pack
-    fromGValue v = (fmap unpack) <$> get_string v
+  gvalueGType_ = return gtypeString
+  gvalueSet_ gvPtr mstr = set_string gvPtr (pack <$> mstr)
+  gvalueGet_ v = (fmap unpack) <$> get_string v
 
 instance IsGValue (Maybe Text) where
-    toGValue = buildGValue gtypeString set_string
-    fromGValue = get_string
+  gvalueGType_ = return gtypeString
+  gvalueSet_ = set_string
+  gvalueGet_ = get_string
 
 instance IsGValue (Ptr a) where
-    toGValue = buildGValue gtypePointer set_pointer
-    fromGValue = get_pointer
+  gvalueGType_ = return gtypePointer
+  gvalueSet_ = set_pointer
+  gvalueGet_ = get_pointer
 
 instance IsGValue Int32 where
-    toGValue = buildGValue gtypeInt set_int32
-    fromGValue = get_int32
+  gvalueGType_ = return gtypeInt
+  gvalueSet_ = set_int32
+  gvalueGet_ = get_int32
 
 instance IsGValue Word32 where
-    toGValue = buildGValue gtypeUInt set_uint32
-    fromGValue = get_uint32
+  gvalueGType_ = return gtypeUInt
+  gvalueSet_ = set_uint32
+  gvalueGet_ = get_uint32
 
 instance IsGValue CInt where
-    toGValue = buildGValue gtypeInt set_int
-    fromGValue = get_int
+  gvalueGType_ = return gtypeInt
+  gvalueSet_ = set_int
+  gvalueGet_ = get_int
 
 instance IsGValue CUInt where
-    toGValue = buildGValue gtypeUInt set_uint
-    fromGValue = get_uint
+  gvalueGType_ = return gtypeUInt
+  gvalueSet_ = set_uint
+  gvalueGet_ = get_uint
 
 instance IsGValue CLong where
-    toGValue = buildGValue gtypeLong set_long
-    fromGValue = get_long
+  gvalueGType_ = return gtypeLong
+  gvalueSet_ = set_long
+  gvalueGet_ = get_long
 
 instance IsGValue CULong where
-    toGValue = buildGValue gtypeULong set_ulong
-    fromGValue = get_ulong
+  gvalueGType_ = return gtypeULong
+  gvalueSet_ = set_ulong
+  gvalueGet_ = get_ulong
 
 instance IsGValue Int64 where
-    toGValue = buildGValue gtypeInt64 set_int64
-    fromGValue = get_int64
+  gvalueGType_ = return gtypeInt64
+  gvalueSet_ = set_int64
+  gvalueGet_ = get_int64
 
 instance IsGValue Word64 where
-    toGValue = buildGValue gtypeUInt64 set_uint64
-    fromGValue = get_uint64
+  gvalueGType_ = return gtypeUInt64
+  gvalueSet_ = set_uint64
+  gvalueGet_ = get_uint64
 
 instance IsGValue Float where
-    toGValue = buildGValue gtypeFloat set_float
-    fromGValue = get_float
+  gvalueGType_ = return gtypeFloat
+  gvalueSet_ = set_float
+  gvalueGet_ = get_float
 
 instance IsGValue Double where
-    toGValue = buildGValue gtypeDouble set_double
-    fromGValue = get_double
+  gvalueGType_ = return gtypeDouble
+  gvalueSet_ = set_double
+  gvalueGet_ = get_double
 
 instance IsGValue Bool where
-    toGValue = buildGValue gtypeBoolean set_boolean
-    fromGValue = get_boolean
+  gvalueGType_ = return gtypeBoolean
+  gvalueSet_ = set_boolean
+  gvalueGet_ = get_boolean
 
 instance IsGValue GType where
-    toGValue = buildGValue gtypeGType set_gtype
-    fromGValue = get_gtype
+  gvalueGType_ = return gtypeGType
+  gvalueSet_ = set_gtype
+  gvalueGet_ = get_gtype
 
 instance IsGValue (StablePtr a) where
-    toGValue = buildGValue gtypeStablePtr set_stablePtr
-    fromGValue = get_stablePtr
+  gvalueGType_ = return gtypeStablePtr
+  gvalueSet_ = set_stablePtr
+  gvalueGet_ = get_stablePtr
 
 foreign import ccall "g_value_set_string" _set_string ::
     Ptr GValue -> CString -> IO ()
 foreign import ccall "g_value_get_string" _get_string ::
     Ptr GValue -> IO CString
 
-set_string :: GValue -> Maybe Text -> IO ()
-set_string gv maybeStr =
-    withManagedPtr gv $ \ptr -> do
-      cstr <- case maybeStr of
-                Just str -> textToCString str
-                Nothing -> return nullPtr
-      _set_string ptr cstr
-      freeMem cstr
+set_string :: Ptr GValue -> Maybe Text -> IO ()
+set_string ptr maybeStr = do
+  cstr <- case maybeStr of
+            Just str -> textToCString str
+            Nothing -> return nullPtr
+  _set_string ptr cstr
+  freeMem cstr
 
-get_string :: GValue -> IO (Maybe Text)
-get_string gv = withManagedPtr gv $ \gvptr -> do
-                  cstr <- _get_string gvptr
-                  if cstr /= nullPtr
-                  then Just <$> cstringToText cstr
-                  else return Nothing
+get_string :: Ptr GValue -> IO (Maybe Text)
+get_string gvptr = do
+  cstr <- _get_string gvptr
+  if cstr /= nullPtr
+    then Just <$> cstringToText cstr
+    else return Nothing
 
-foreign import ccall unsafe "g_value_set_pointer" _set_pointer ::
+foreign import ccall unsafe "g_value_set_pointer" set_pointer ::
     Ptr GValue -> Ptr a -> IO ()
-foreign import ccall unsafe "g_value_get_pointer" _get_pointer ::
+foreign import ccall unsafe "g_value_get_pointer" get_pointer ::
     Ptr GValue -> IO (Ptr b)
 
-set_pointer :: GValue -> Ptr a -> IO ()
-set_pointer gv ptr = withManagedPtr gv $ flip _set_pointer ptr
-
-get_pointer :: GValue -> IO (Ptr b)
-get_pointer gv = withManagedPtr gv _get_pointer
-
-foreign import ccall unsafe "g_value_set_int" _set_int ::
+foreign import ccall unsafe "g_value_set_int" set_int ::
     Ptr GValue -> CInt -> IO ()
-foreign import ccall unsafe "g_value_get_int" _get_int ::
+foreign import ccall unsafe "g_value_get_int" get_int ::
     Ptr GValue -> IO CInt
 
-set_int32 :: GValue -> Int32 -> IO ()
-set_int32 gv n = withManagedPtr gv $ flip _set_int (coerce n)
-
-get_int32 :: GValue -> IO Int32
-get_int32 gv = coerce <$> withManagedPtr gv _get_int
-
-set_int :: GValue -> CInt -> IO ()
-set_int gv n = withManagedPtr gv $ flip _set_int n
+set_int32 :: Ptr GValue -> Int32 -> IO ()
+set_int32 gv n = set_int gv (coerce n)
 
-get_int :: GValue -> IO CInt
-get_int gv = withManagedPtr gv _get_int
+get_int32 :: Ptr GValue -> IO Int32
+get_int32 gv = coerce <$> get_int gv
 
-foreign import ccall unsafe "g_value_set_uint" _set_uint ::
+foreign import ccall unsafe "g_value_set_uint" set_uint ::
     Ptr GValue -> CUInt -> IO ()
-foreign import ccall unsafe "g_value_get_uint" _get_uint ::
+foreign import ccall unsafe "g_value_get_uint" get_uint ::
     Ptr GValue -> IO CUInt
 
-set_uint32 :: GValue -> Word32 -> IO ()
-set_uint32 gv n = withManagedPtr gv $ flip _set_uint (coerce n)
-
-get_uint32 :: GValue -> IO Word32
-get_uint32 gv = coerce <$> withManagedPtr gv _get_uint
-
-set_uint :: GValue -> CUInt -> IO ()
-set_uint gv n = withManagedPtr gv $ flip _set_uint n
+set_uint32 :: Ptr GValue -> Word32 -> IO ()
+set_uint32 gv n = set_uint gv (coerce n)
 
-get_uint :: GValue -> IO CUInt
-get_uint gv = withManagedPtr gv _get_uint
+get_uint32 :: Ptr GValue -> IO Word32
+get_uint32 gv = coerce <$> get_uint gv
 
-foreign import ccall unsafe "g_value_set_long" _set_long ::
+foreign import ccall unsafe "g_value_set_long" set_long ::
     Ptr GValue -> CLong -> IO ()
-foreign import ccall unsafe "g_value_get_long" _get_long ::
+foreign import ccall unsafe "g_value_get_long" get_long ::
     Ptr GValue -> IO CLong
 
-set_long :: GValue -> CLong -> IO ()
-set_long gv n = withManagedPtr gv $ flip _set_long n
-
-get_long :: GValue -> IO CLong
-get_long gv = withManagedPtr gv _get_long
-
-foreign import ccall unsafe "g_value_set_ulong" _set_ulong ::
+foreign import ccall unsafe "g_value_set_ulong" set_ulong ::
     Ptr GValue -> CULong -> IO ()
-foreign import ccall unsafe "g_value_get_ulong" _get_ulong ::
+foreign import ccall unsafe "g_value_get_ulong" get_ulong ::
     Ptr GValue -> IO CULong
 
-set_ulong :: GValue -> CULong -> IO ()
-set_ulong gv n = withManagedPtr gv $ flip _set_ulong n
-
-get_ulong :: GValue -> IO CULong
-get_ulong gv = withManagedPtr gv _get_ulong
-
-foreign import ccall unsafe "g_value_set_int64" _set_int64 ::
+foreign import ccall unsafe "g_value_set_int64" set_int64 ::
     Ptr GValue -> Int64 -> IO ()
-foreign import ccall unsafe "g_value_get_int64" _get_int64 ::
+foreign import ccall unsafe "g_value_get_int64" get_int64 ::
     Ptr GValue -> IO Int64
 
-set_int64 :: GValue -> Int64 -> IO ()
-set_int64 gv n = withManagedPtr gv $ flip _set_int64 n
-
-get_int64 :: GValue -> IO Int64
-get_int64 gv = withManagedPtr gv _get_int64
-
-foreign import ccall unsafe "g_value_set_uint64" _set_uint64 ::
+foreign import ccall unsafe "g_value_set_uint64" set_uint64 ::
     Ptr GValue -> Word64 -> IO ()
-foreign import ccall unsafe "g_value_get_uint64" _get_uint64 ::
+foreign import ccall unsafe "g_value_get_uint64" get_uint64 ::
     Ptr GValue -> IO Word64
 
-set_uint64 :: GValue -> Word64 -> IO ()
-set_uint64 gv n = withManagedPtr gv $ flip _set_uint64 n
-
-get_uint64 :: GValue -> IO Word64
-get_uint64 gv = withManagedPtr gv _get_uint64
-
 foreign import ccall unsafe "g_value_set_float" _set_float ::
     Ptr GValue -> CFloat -> IO ()
 foreign import ccall unsafe "g_value_get_float" _get_float ::
     Ptr GValue -> IO CFloat
 
-set_float :: GValue -> Float -> IO ()
-set_float gv f = withManagedPtr gv $ flip _set_float (realToFrac f)
+set_float :: Ptr GValue -> Float -> IO ()
+set_float gv f = _set_float gv (realToFrac f)
 
-get_float :: GValue -> IO Float
-get_float gv = realToFrac <$> withManagedPtr gv _get_float
+get_float :: Ptr GValue -> IO Float
+get_float gv = realToFrac <$> _get_float gv
 
 foreign import ccall unsafe "g_value_set_double" _set_double ::
     Ptr GValue -> CDouble -> IO ()
 foreign import ccall unsafe "g_value_get_double" _get_double ::
     Ptr GValue -> IO CDouble
 
-set_double :: GValue -> Double -> IO ()
-set_double gv d = withManagedPtr gv $ flip _set_double (realToFrac d)
+set_double :: Ptr GValue -> Double -> IO ()
+set_double gv d = _set_double gv (realToFrac d)
 
-get_double :: GValue -> IO Double
-get_double gv = realToFrac <$> withManagedPtr gv _get_double
+get_double :: Ptr GValue -> IO Double
+get_double gv = realToFrac <$> _get_double gv
 
 foreign import ccall unsafe "g_value_set_boolean" _set_boolean ::
     Ptr GValue -> CInt -> IO ()
 foreign import ccall unsafe "g_value_get_boolean" _get_boolean ::
     Ptr GValue -> IO CInt
 
-set_boolean :: GValue -> Bool -> IO ()
-set_boolean gv b = withManagedPtr gv $ \ptr ->
-                   _set_boolean ptr (fromIntegral $ fromEnum b)
+set_boolean :: Ptr GValue -> Bool -> IO ()
+set_boolean gv b = _set_boolean gv (fromIntegral $ fromEnum b)
 
-get_boolean :: GValue -> IO Bool
-get_boolean gv = withManagedPtr gv $ \ptr -> (/= 0) <$> _get_boolean ptr
+get_boolean :: Ptr GValue -> IO Bool
+get_boolean gv = (/= 0) <$> _get_boolean gv
 
 foreign import ccall unsafe "g_value_set_gtype" _set_gtype ::
     Ptr GValue -> CGType -> IO ()
 foreign import ccall unsafe "g_value_get_gtype" _get_gtype ::
     Ptr GValue -> IO CGType
 
-set_gtype :: GValue -> GType -> IO ()
-set_gtype gv (GType g) = withManagedPtr gv $ \ptr -> _set_gtype ptr g
+set_gtype :: Ptr GValue -> GType -> IO ()
+set_gtype gv (GType g) = _set_gtype gv g
 
-get_gtype :: GValue -> IO GType
-get_gtype gv = GType <$> withManagedPtr gv _get_gtype
+get_gtype :: Ptr GValue -> IO GType
+get_gtype gv = GType <$> _get_gtype gv
 
 foreign import ccall "g_value_set_object" _set_object ::
     Ptr GValue -> Ptr a -> IO ()
 foreign import ccall "g_value_get_object" _get_object ::
     Ptr GValue -> IO (Ptr a)
 
-set_object :: GObject a => GValue -> Ptr a -> IO ()
-set_object gv o = withManagedPtr gv $ flip _set_object o
+set_object :: GObject a => Ptr GValue -> Ptr a -> IO ()
+set_object = _set_object
 
-get_object :: GObject b => GValue -> IO (Ptr b)
-get_object gv = withManagedPtr gv _get_object
+get_object :: GObject a => Ptr GValue -> IO (Ptr a)
+get_object = _get_object
 
-foreign import ccall "g_value_set_boxed" _set_boxed ::
+foreign import ccall "g_value_set_boxed" set_boxed ::
     Ptr GValue -> Ptr a -> IO ()
-foreign import ccall "g_value_get_boxed" _get_boxed ::
+foreign import ccall "g_value_get_boxed" get_boxed ::
     Ptr GValue -> IO (Ptr b)
 
-set_boxed :: GValue -> Ptr a -> IO ()
-set_boxed gv b = withManagedPtr gv $ flip _set_boxed b
-
-get_boxed :: GValue -> IO (Ptr b)
-get_boxed gv = withManagedPtr gv _get_boxed
-
-foreign import ccall "g_value_set_variant" _set_variant ::
+foreign import ccall "g_value_set_variant" set_variant ::
     Ptr GValue -> Ptr GVariant -> IO ()
-foreign import ccall "g_value_get_variant" _get_variant ::
+foreign import ccall "g_value_get_variant" get_variant ::
     Ptr GValue -> IO (Ptr GVariant)
 
-set_variant :: GValue -> Ptr GVariant -> IO ()
-set_variant gv v = withManagedPtr gv $ flip _set_variant v
-
-get_variant :: GValue -> IO (Ptr GVariant)
-get_variant gv = withManagedPtr gv _get_variant
-
-foreign import ccall unsafe "g_value_set_enum" _set_enum ::
+foreign import ccall unsafe "g_value_set_enum" set_enum ::
     Ptr GValue -> CUInt -> IO ()
-foreign import ccall unsafe "g_value_get_enum" _get_enum ::
+foreign import ccall unsafe "g_value_get_enum" get_enum ::
     Ptr GValue -> IO CUInt
 
-set_enum :: GValue -> CUInt -> IO ()
-set_enum gv e = withManagedPtr gv $ flip _set_enum e
-
-get_enum :: GValue -> IO CUInt
-get_enum gv = withManagedPtr gv _get_enum
-
-foreign import ccall unsafe "g_value_set_flags" _set_flags ::
+foreign import ccall unsafe "g_value_set_flags" set_flags ::
     Ptr GValue -> CUInt -> IO ()
-foreign import ccall unsafe "g_value_get_flags" _get_flags ::
+foreign import ccall unsafe "g_value_get_flags" get_flags ::
     Ptr GValue -> IO CUInt
 
-set_flags :: GValue -> CUInt -> IO ()
-set_flags gv f = withManagedPtr gv $ flip _set_flags f
-
-get_flags :: GValue -> IO CUInt
-get_flags gv = withManagedPtr gv _get_flags
-
 -- | Set the value of `GValue` containing a `StablePtr`
-set_stablePtr :: GValue -> StablePtr a -> IO ()
-set_stablePtr gv ptr = withManagedPtr gv $ flip _set_boxed (castStablePtrToPtr ptr)
+set_stablePtr :: Ptr GValue -> StablePtr a -> IO ()
+set_stablePtr gv ptr = set_boxed gv (castStablePtrToPtr ptr)
 
 foreign import ccall g_value_take_boxed :: Ptr GValue -> StablePtr a -> IO ()
 
@@ -450,8 +398,8 @@
 take_stablePtr = g_value_take_boxed
 
 -- | Get the value of a `GValue` containing a `StablePtr`
-get_stablePtr :: GValue -> IO (StablePtr a)
-get_stablePtr gv = castPtrToStablePtr <$> withManagedPtr gv _get_boxed
+get_stablePtr :: Ptr GValue -> IO (StablePtr a)
+get_stablePtr gv = castPtrToStablePtr <$> get_boxed gv
 
 foreign import ccall g_value_copy :: Ptr GValue -> Ptr GValue -> IO ()
 
diff --git a/Data/GI/Base/Overloading.hs b/Data/GI/Base/Overloading.hs
--- a/Data/GI/Base/Overloading.hs
+++ b/Data/GI/Base/Overloading.hs
@@ -1,7 +1,8 @@
 {-# LANGUAGE TypeOperators, KindSignatures, DataKinds, PolyKinds,
              TypeFamilies, UndecidableInstances, EmptyDataDecls,
              MultiParamTypeClasses, FlexibleInstances, ConstraintKinds,
-             AllowAmbiguousTypes, FlexibleContexts #-}
+             AllowAmbiguousTypes, FlexibleContexts, ScopedTypeVariables,
+             TypeApplications, OverloadedStrings #-}
 
 -- | Helpers for dealing with overladed properties, signals and
 -- methods.
@@ -29,28 +30,36 @@
     -- * Looking up methods in parent types
     , MethodResolutionFailed
     , UnsupportedMethodError
+    , OverloadedMethodInfo(..)
+    , OverloadedMethod(..)
+    , MethodProxy(..)
     , MethodInfo(..)
+    , resolveMethod
     ) where
 
 import Data.Coerce (coerce)
+import Data.Kind (Type)
 
 import GHC.Exts (Constraint)
 import GHC.TypeLits
 
 import Data.GI.Base.BasicTypes (ManagedPtrNewtype, ManagedPtr(..))
 
+import Data.Text (Text)
+import qualified Data.Text as T
+
 -- | Look in the given list of (symbol, tag) tuples for the tag
 -- corresponding to the given symbol. If not found raise the given
 -- type error.
-type family FindElement (m :: Symbol) (ms :: [(Symbol, *)])
-    (typeError :: ErrorMessage) :: * where
+type family FindElement (m :: Symbol) (ms :: [(Symbol, Type)])
+    (typeError :: ErrorMessage) :: Type where
     FindElement m '[] typeError = TypeError typeError
     FindElement m ('(m, o) ': ms) typeError = o
     FindElement m ('(m', o) ': ms) typeError = FindElement m ms typeError
 
 -- | Check whether a type appears in a list. We specialize the
 -- names/types a bit so the error messages are more informative.
-type family CheckForAncestorType t (a :: *) (as :: [*]) :: Constraint where
+type family CheckForAncestorType t (a :: Type) (as :: [Type]) :: Constraint where
   CheckForAncestorType t a '[] = TypeError ('Text "Required ancestor ‘"
                                             ':<>: 'ShowType a
                                             ':<>: 'Text "’ not found for type ‘"
@@ -60,19 +69,19 @@
 
 -- | Check that a type is in the list of `ParentTypes` of another
 -- type.
-type family IsDescendantOf (parent :: *) (descendant :: *) :: Constraint where
+type family IsDescendantOf (parent :: Type) (descendant :: Type) :: Constraint where
     -- Every object is defined to be a descendant of itself.
     IsDescendantOf d d = ()
     IsDescendantOf p d = CheckForAncestorType d p (ParentTypes d)
 
 -- | All the types that are ascendants of this type, including
 -- interfaces that the type implements.
-type family ParentTypes a :: [*]
+type family ParentTypes a :: [Type]
 
 -- | A constraint on a type, to be fulfilled whenever it has a type
 -- instance for `ParentTypes`. This leads to nicer errors, thanks to
 -- the overlappable instance below.
-class HasParentTypes (o :: *)
+class HasParentTypes (o :: Type)
 
 -- | Default instance, which will give rise to an error for types
 -- without an associated `ParentTypes` instance.
@@ -95,7 +104,7 @@
 -- of the attribute, and the second the type encoding the information
 -- of the attribute. This type will be an instance of
 -- `Data.GI.Base.Attributes.AttrInfo`.
-type family AttributeList a :: [(Symbol, *)]
+type family AttributeList a :: [(Symbol, Type)]
 
 -- | A constraint on a type, to be fulfilled whenever it has a type
 -- instance for `AttributeList`. This is here for nicer error
@@ -111,7 +120,7 @@
 
 -- | Return the type encoding the attribute information for a given
 -- type and attribute.
-type family ResolveAttribute (s :: Symbol) (o :: *) :: * where
+type family ResolveAttribute (s :: Symbol) (o :: Type) :: Type where
     ResolveAttribute s o = FindElement s (AttributeList o)
                            ('Text "Unknown attribute ‘" ':<>:
                             'Text s ':<>: 'Text "’ for object ‘" ':<>:
@@ -119,14 +128,14 @@
 
 -- | Whether a given type is in the given list. If found, return
 -- @success@, otherwise return @failure@.
-type family IsElem (e :: Symbol) (es :: [(Symbol, *)]) (success :: k)
+type family IsElem (e :: Symbol) (es :: [(Symbol, Type)]) (success :: k)
     (failure :: ErrorMessage) :: k where
     IsElem e '[] success failure = TypeError failure
     IsElem e ( '(e, t) ': es) success failure = success
     IsElem e ( '(other, t) ': es) s f = IsElem e es s f
 
 -- | A constraint imposing that the given object has the given attribute.
-type family HasAttribute (attr :: Symbol) (o :: *) :: Constraint where
+type family HasAttribute (attr :: Symbol) (o :: Type) :: Constraint where
     HasAttribute attr o = IsElem attr (AttributeList o)
                           (() :: Constraint) -- success
                           ('Text "Attribute ‘" ':<>: 'Text attr ':<>:
@@ -134,7 +143,7 @@
                            'ShowType o ':<>: 'Text "’.")
 
 -- | A constraint that enforces that the given type has a given attribute.
-class HasAttr (attr :: Symbol) (o :: *)
+class HasAttr (attr :: Symbol) (o :: Type)
 instance HasAttribute attr o => HasAttr attr o
 
 -- | The list of signals defined for a given type. Each element of the
@@ -142,11 +151,11 @@
 -- the signal, and the second the type encoding the information of the
 -- signal. This type will be an instance of
 -- `Data.GI.Base.Signals.SignalInfo`.
-type family SignalList a :: [(Symbol, *)]
+type family SignalList a :: [(Symbol, Type)]
 
 -- | Return the type encoding the signal information for a given
 -- type and signal.
-type family ResolveSignal (s :: Symbol) (o :: *) :: * where
+type family ResolveSignal (s :: Symbol) (o :: Type) :: Type where
     ResolveSignal s o = FindElement s (SignalList o)
                         ('Text "Unknown signal ‘" ':<>:
                          'Text s ':<>: 'Text "’ for object ‘" ':<>:
@@ -154,7 +163,7 @@
 
 -- | A constraint enforcing that the signal exists for the given
 -- object, or one of its ancestors.
-type family HasSignal (s :: Symbol) (o :: *) :: Constraint where
+type family HasSignal (s :: Symbol) (o :: Type) :: Constraint where
     HasSignal s o = IsElem s (SignalList o)
                     (() :: Constraint) -- success
                     ('Text "Signal ‘" ':<>: 'Text s ':<>:
@@ -163,7 +172,7 @@
 
 -- | A constraint that always fails with a type error, for
 -- documentation purposes.
-type family UnsupportedMethodError (s :: Symbol) (o :: *) :: * where
+type family UnsupportedMethodError (s :: Symbol) (o :: Type) :: Type where
   UnsupportedMethodError s o =
     TypeError ('Text "Unsupported method ‘" ':<>:
                'Text s ':<>: 'Text "’ for object ‘" ':<>:
@@ -171,7 +180,7 @@
 
 -- | Returned when the method is not found, hopefully making
 -- the resulting error messages somewhat clearer.
-type family MethodResolutionFailed (method :: Symbol) (o :: *) where
+type family MethodResolutionFailed (method :: Symbol) (o :: Type) where
     MethodResolutionFailed m o =
         TypeError ('Text "Unknown method ‘" ':<>:
                    'Text m ':<>: 'Text "’ for type ‘" ':<>:
@@ -179,5 +188,34 @@
 
 -- | Class for types containing the information about an overloaded
 -- method of type @o -> s@.
-class MethodInfo i o s where
-    overloadedMethod :: o -> s
+class OverloadedMethod i o s where
+  overloadedMethod :: o -> s -- ^ The actual method being invoked.
+
+-- | Information about the method that will be invoked, for debugging
+-- purposes.
+data MethodInfo = MethodInfo { overloadedMethodName    :: Text
+                             , overloadedMethodURL     :: Text
+                             }
+
+instance Show MethodInfo where
+  -- Format as a hyperlink on modern terminals (older
+  -- terminals should ignore the hyperlink part).
+  show info = T.unpack ("\ESC]8;;" <> overloadedMethodURL info
+                         <> "\ESC\\" <> overloadedMethodName info
+                         <> "\ESC]8;;\ESC\\")
+
+-- | This is for debugging purposes, see `resolveMethod` below.
+class OverloadedMethodInfo i o where
+  overloadedMethodInfo :: MethodInfo
+
+-- | A proxy for carrying the types `MethodInfoName` needs (this is used
+-- for `resolveMethod`, see below).
+data MethodProxy (info :: Type) (obj :: Type) = MethodProxy
+
+-- | Return the fully qualified method name that a given overloaded
+-- method call resolves to (mostly useful for debugging).
+--
+-- > resolveMethod #show widget
+resolveMethod :: forall info obj. (OverloadedMethodInfo info obj) =>
+                 MethodProxy info obj -> obj -> MethodInfo
+resolveMethod _p _o = overloadedMethodInfo @info @obj
diff --git a/Data/GI/Base/Properties.hsc b/Data/GI/Base/Properties.hsc
--- a/Data/GI/Base/Properties.hsc
+++ b/Data/GI/Base/Properties.hsc
@@ -1,7 +1,8 @@
 {-# LANGUAGE ScopedTypeVariables, TypeApplications #-}
 
 module Data.GI.Base.Properties
-    ( setObjectPropertyString
+    ( setObjectPropertyIsGValueInstance
+    , setObjectPropertyString
     , setObjectPropertyStringArray
     , setObjectPropertyPtr
     , setObjectPropertyInt
@@ -29,6 +30,7 @@
     , setObjectPropertyGError
     , setObjectPropertyGValue
 
+    , getObjectPropertyIsGValueInstance
     , getObjectPropertyString
     , getObjectPropertyStringArray
     , getObjectPropertyPtr
@@ -57,6 +59,7 @@
     , getObjectPropertyGError
     , getObjectPropertyGValue
 
+    , constructObjectPropertyIsGValueInstance
     , constructObjectPropertyString
     , constructObjectPropertyStringArray
     , constructObjectPropertyPtr
@@ -114,231 +117,225 @@
 foreign import ccall "g_object_set_property" g_object_set_property ::
     Ptr a -> CString -> Ptr GValue -> IO ()
 
-setObjectProperty :: GObject a => a -> String -> b ->
-                     (GValue -> b -> IO ()) -> GType -> IO ()
-setObjectProperty obj propName propValue setter (GType gtype) = do
-  gvalue <- buildGValue (GType gtype) setter propValue
+-- | Set a property on an object to the given `GValue`.
+gobjectSetProperty :: GObject a => a -> String -> GValue -> IO ()
+gobjectSetProperty obj propName gvalue =
   withManagedPtr obj $ \objPtr ->
       withCString propName $ \cPropName ->
           withManagedPtr gvalue $ \gvalueptr ->
               g_object_set_property objPtr cPropName gvalueptr
 
+-- | A convenience wrapper over `gobjectSetProperty` that does the
+-- wrapping of a value into a `GValue`.
+setObjectProperty :: GObject a => a -> String -> b ->
+                     (Ptr GValue -> b -> IO ()) -> GType -> IO ()
+setObjectProperty obj propName propValue setter (GType gtype) = do
+  gvalue <- buildGValue (GType gtype) setter propValue
+  gobjectSetProperty obj propName gvalue
+
 foreign import ccall "g_object_get_property" g_object_get_property ::
     Ptr a -> CString -> Ptr GValue -> IO ()
 
-getObjectProperty :: GObject a => a -> String ->
-                     (GValue -> IO b) -> GType -> IO b
-getObjectProperty obj propName getter gtype = do
+-- | Get the `GValue` for the given property.
+gobjectGetProperty :: GObject a => a -> String -> GType -> IO GValue
+gobjectGetProperty obj propName gtype = do
   gvalue <- newGValue gtype
   withManagedPtr obj $ \objPtr ->
       withCString propName $ \cPropName ->
           withManagedPtr gvalue $ \gvalueptr ->
               g_object_get_property objPtr cPropName gvalueptr
-  getter gvalue
+  return gvalue
 
-constructObjectProperty :: String -> b -> (GValue -> b -> IO ()) ->
+-- | A convenience wrapper over `gobjectGetProperty` that unwraps the
+-- `GValue` into a Haskell value.
+getObjectProperty :: GObject a => a -> String ->
+                     (Ptr GValue -> IO b) -> GType -> IO b
+getObjectProperty obj propName getter gtype = do
+  gv <- gobjectGetProperty obj propName gtype
+  withManagedPtr gv getter
+
+constructObjectProperty :: String -> b -> (Ptr GValue -> b -> IO ()) ->
                            GType -> IO (GValueConstruct o)
 constructObjectProperty propName propValue setter gtype = do
   gvalue <- buildGValue gtype setter propValue
   return (GValueConstruct propName gvalue)
 
+-- | Set a property for a type with a `IsGValue` instance.
+setObjectPropertyIsGValueInstance :: (GObject a, IsGValue b) =>
+                                     a -> String -> b -> IO ()
+setObjectPropertyIsGValueInstance obj propName maybeVal = do
+  gvalue <- toGValue maybeVal
+  gobjectSetProperty obj propName gvalue
+
+-- | Construct a property for a type with a `IsGValue` instance.
+constructObjectPropertyIsGValueInstance :: IsGValue b => String -> b -> IO (GValueConstruct o)
+constructObjectPropertyIsGValueInstance propName maybeVal = do
+  gvalue <- toGValue maybeVal
+  return (GValueConstruct propName gvalue)
+
+-- | Get a nullable property for a type with a `IsGValue` instance.
+getObjectPropertyIsGValueInstance :: forall a b. (GObject a, IsGValue b) =>
+                       a -> String -> IO b
+getObjectPropertyIsGValueInstance obj propName = do
+  gtype <- gvalueGType_ @b
+  gv <- gobjectGetProperty obj propName gtype
+  fromGValue gv
+
 setObjectPropertyString :: GObject a =>
                            a -> String -> Maybe Text -> IO ()
-setObjectPropertyString obj propName str =
-    setObjectProperty obj propName str set_string gtypeString
+setObjectPropertyString = setObjectPropertyIsGValueInstance
 
 constructObjectPropertyString :: String -> Maybe Text ->
                                  IO (GValueConstruct o)
-constructObjectPropertyString propName str =
-    constructObjectProperty propName str set_string gtypeString
+constructObjectPropertyString = constructObjectPropertyIsGValueInstance
 
 getObjectPropertyString :: GObject a =>
                            a -> String -> IO (Maybe Text)
-getObjectPropertyString obj propName =
-    getObjectProperty obj propName get_string gtypeString
+getObjectPropertyString = getObjectPropertyIsGValueInstance
 
 setObjectPropertyPtr :: GObject a =>
                         a -> String -> Ptr b -> IO ()
-setObjectPropertyPtr obj propName ptr =
-    setObjectProperty obj propName ptr set_pointer gtypePointer
+setObjectPropertyPtr = setObjectPropertyIsGValueInstance
 
 constructObjectPropertyPtr :: String -> Ptr b ->
                               IO (GValueConstruct o)
-constructObjectPropertyPtr propName ptr =
-    constructObjectProperty propName ptr set_pointer gtypePointer
+constructObjectPropertyPtr = constructObjectPropertyIsGValueInstance
 
 getObjectPropertyPtr :: GObject a =>
                         a -> String -> IO (Ptr b)
-getObjectPropertyPtr obj propName =
-    getObjectProperty obj propName get_pointer gtypePointer
+getObjectPropertyPtr = getObjectPropertyIsGValueInstance
 
 setObjectPropertyInt :: GObject a =>
                          a -> String -> CInt -> IO ()
-setObjectPropertyInt obj propName int =
-    setObjectProperty obj propName int set_int gtypeInt
+setObjectPropertyInt = setObjectPropertyIsGValueInstance
 
 constructObjectPropertyInt :: String -> CInt ->
                               IO (GValueConstruct o)
-constructObjectPropertyInt propName int =
-    constructObjectProperty propName int set_int gtypeInt
+constructObjectPropertyInt = constructObjectPropertyIsGValueInstance
 
 getObjectPropertyInt :: GObject a => a -> String -> IO CInt
-getObjectPropertyInt obj propName =
-    getObjectProperty obj propName get_int gtypeInt
+getObjectPropertyInt = getObjectPropertyIsGValueInstance
 
 setObjectPropertyUInt :: GObject a =>
                           a -> String -> CUInt -> IO ()
-setObjectPropertyUInt obj propName uint =
-    setObjectProperty obj propName uint set_uint gtypeUInt
+setObjectPropertyUInt = setObjectPropertyIsGValueInstance
 
 constructObjectPropertyUInt :: String -> CUInt ->
                                 IO (GValueConstruct o)
-constructObjectPropertyUInt propName uint =
-    constructObjectProperty propName uint set_uint gtypeUInt
+constructObjectPropertyUInt = constructObjectPropertyIsGValueInstance
 
 getObjectPropertyUInt :: GObject a => a -> String -> IO CUInt
-getObjectPropertyUInt obj propName =
-    getObjectProperty obj propName get_uint gtypeUInt
+getObjectPropertyUInt = getObjectPropertyIsGValueInstance
 
 setObjectPropertyLong :: GObject a =>
                          a -> String -> CLong -> IO ()
-setObjectPropertyLong obj propName int =
-    setObjectProperty obj propName int set_long gtypeLong
+setObjectPropertyLong = setObjectPropertyIsGValueInstance
 
 constructObjectPropertyLong :: String -> CLong ->
                                IO (GValueConstruct o)
-constructObjectPropertyLong propName int =
-    constructObjectProperty propName int set_long gtypeLong
+constructObjectPropertyLong = constructObjectPropertyIsGValueInstance
 
 getObjectPropertyLong :: GObject a => a -> String -> IO CLong
-getObjectPropertyLong obj propName =
-    getObjectProperty obj propName get_long gtypeLong
+getObjectPropertyLong = getObjectPropertyIsGValueInstance
 
 setObjectPropertyULong :: GObject a =>
                           a -> String -> CULong -> IO ()
-setObjectPropertyULong obj propName uint =
-    setObjectProperty obj propName uint set_ulong gtypeULong
+setObjectPropertyULong = setObjectPropertyIsGValueInstance
 
 constructObjectPropertyULong :: String -> CULong ->
                                 IO (GValueConstruct o)
-constructObjectPropertyULong propName uint =
-    constructObjectProperty propName uint set_ulong gtypeULong
+constructObjectPropertyULong = constructObjectPropertyIsGValueInstance
 
 getObjectPropertyULong :: GObject a => a -> String -> IO CULong
-getObjectPropertyULong obj propName =
-    getObjectProperty obj propName get_ulong gtypeULong
+getObjectPropertyULong = getObjectPropertyIsGValueInstance
 
 setObjectPropertyInt32 :: GObject a =>
                           a -> String -> Int32 -> IO ()
-setObjectPropertyInt32 obj propName int32 =
-    setObjectProperty obj propName int32 set_int32 gtypeInt
+setObjectPropertyInt32 = setObjectPropertyIsGValueInstance
 
 constructObjectPropertyInt32 :: String -> Int32 ->
                                 IO (GValueConstruct o)
-constructObjectPropertyInt32 propName int32 =
-    constructObjectProperty propName int32 set_int32 gtypeInt
+constructObjectPropertyInt32 = constructObjectPropertyIsGValueInstance
 
 getObjectPropertyInt32 :: GObject a => a -> String -> IO Int32
-getObjectPropertyInt32 obj propName =
-    getObjectProperty obj propName get_int32 gtypeInt
+getObjectPropertyInt32 = getObjectPropertyIsGValueInstance
 
 setObjectPropertyUInt32 :: GObject a =>
                           a -> String -> Word32 -> IO ()
-setObjectPropertyUInt32 obj propName uint32 =
-    setObjectProperty obj propName uint32 set_uint32 gtypeUInt
+setObjectPropertyUInt32 = setObjectPropertyIsGValueInstance
 
 constructObjectPropertyUInt32 :: String -> Word32 ->
                                  IO (GValueConstruct o)
-constructObjectPropertyUInt32 propName uint32 =
-    constructObjectProperty propName uint32 set_uint32 gtypeUInt
+constructObjectPropertyUInt32 = constructObjectPropertyIsGValueInstance
 
 getObjectPropertyUInt32 :: GObject a => a -> String -> IO Word32
-getObjectPropertyUInt32 obj propName =
-    getObjectProperty obj propName get_uint32 gtypeUInt
+getObjectPropertyUInt32 = getObjectPropertyIsGValueInstance
 
 setObjectPropertyInt64 :: GObject a =>
                           a -> String -> Int64 -> IO ()
-setObjectPropertyInt64 obj propName int64 =
-    setObjectProperty obj propName int64 set_int64 gtypeInt64
+setObjectPropertyInt64 = setObjectPropertyIsGValueInstance
 
 constructObjectPropertyInt64 :: String -> Int64 ->
                                 IO (GValueConstruct o)
-constructObjectPropertyInt64 propName int64 =
-    constructObjectProperty propName int64 set_int64 gtypeInt64
+constructObjectPropertyInt64 = constructObjectPropertyIsGValueInstance
 
 getObjectPropertyInt64 :: GObject a => a -> String -> IO Int64
-getObjectPropertyInt64 obj propName =
-    getObjectProperty obj propName get_int64 gtypeInt64
+getObjectPropertyInt64 = getObjectPropertyIsGValueInstance
 
 setObjectPropertyUInt64 :: GObject a =>
                           a -> String -> Word64 -> IO ()
-setObjectPropertyUInt64 obj propName uint64 =
-    setObjectProperty obj propName uint64 set_uint64 gtypeUInt64
+setObjectPropertyUInt64 = setObjectPropertyIsGValueInstance
 
 constructObjectPropertyUInt64 :: String -> Word64 ->
                                  IO (GValueConstruct o)
-constructObjectPropertyUInt64 propName uint64 =
-    constructObjectProperty propName uint64 set_uint64 gtypeUInt64
+constructObjectPropertyUInt64 = constructObjectPropertyIsGValueInstance
 
 getObjectPropertyUInt64 :: GObject a => a -> String -> IO Word64
-getObjectPropertyUInt64 obj propName =
-    getObjectProperty obj propName get_uint64 gtypeUInt64
+getObjectPropertyUInt64 = getObjectPropertyIsGValueInstance
 
 setObjectPropertyFloat :: GObject a =>
                            a -> String -> Float -> IO ()
-setObjectPropertyFloat obj propName float =
-    setObjectProperty obj propName float set_float gtypeFloat
+setObjectPropertyFloat = setObjectPropertyIsGValueInstance
 
 constructObjectPropertyFloat :: String -> Float ->
                                  IO (GValueConstruct o)
-constructObjectPropertyFloat propName float =
-    constructObjectProperty propName float set_float gtypeFloat
+constructObjectPropertyFloat = constructObjectPropertyIsGValueInstance
 
 getObjectPropertyFloat :: GObject a =>
                            a -> String -> IO Float
-getObjectPropertyFloat obj propName =
-    getObjectProperty obj propName get_float gtypeFloat
+getObjectPropertyFloat = getObjectPropertyIsGValueInstance
 
 setObjectPropertyDouble :: GObject a =>
                             a -> String -> Double -> IO ()
-setObjectPropertyDouble obj propName double =
-    setObjectProperty obj propName double set_double gtypeDouble
+setObjectPropertyDouble = setObjectPropertyIsGValueInstance
 
 constructObjectPropertyDouble :: String -> Double ->
                                   IO (GValueConstruct o)
-constructObjectPropertyDouble propName double =
-    constructObjectProperty propName double set_double gtypeDouble
+constructObjectPropertyDouble = constructObjectPropertyIsGValueInstance
 
 getObjectPropertyDouble :: GObject a =>
                             a -> String -> IO Double
-getObjectPropertyDouble obj propName =
-    getObjectProperty obj propName get_double gtypeDouble
+getObjectPropertyDouble = getObjectPropertyIsGValueInstance
 
 setObjectPropertyBool :: GObject a =>
                          a -> String -> Bool -> IO ()
-setObjectPropertyBool obj propName bool =
-    setObjectProperty obj propName bool set_boolean gtypeBoolean
+setObjectPropertyBool = setObjectPropertyIsGValueInstance
 
 constructObjectPropertyBool :: String -> Bool -> IO (GValueConstruct o)
-constructObjectPropertyBool propName bool =
-    constructObjectProperty propName bool set_boolean gtypeBoolean
+constructObjectPropertyBool = constructObjectPropertyIsGValueInstance
 
 getObjectPropertyBool :: GObject a => a -> String -> IO Bool
-getObjectPropertyBool obj propName =
-    getObjectProperty obj propName get_boolean gtypeBoolean
+getObjectPropertyBool = getObjectPropertyIsGValueInstance
 
 setObjectPropertyGType :: GObject a =>
                          a -> String -> GType -> IO ()
-setObjectPropertyGType obj propName gtype =
-    setObjectProperty obj propName gtype set_gtype gtypeGType
+setObjectPropertyGType = setObjectPropertyIsGValueInstance
 
 constructObjectPropertyGType :: String -> GType -> IO (GValueConstruct o)
-constructObjectPropertyGType propName bool =
-    constructObjectProperty propName bool set_gtype gtypeGType
+constructObjectPropertyGType = constructObjectPropertyIsGValueInstance
 
 getObjectPropertyGType :: GObject a => a -> String -> IO GType
-getObjectPropertyGType obj propName =
-    getObjectProperty obj propName get_gtype gtypeGType
+getObjectPropertyGType = getObjectPropertyIsGValueInstance
 
 setObjectPropertyObject :: forall a b. (GObject a, GObject b) =>
                            a -> String -> Maybe b -> IO ()
@@ -533,7 +530,7 @@
 getObjectPropertyPtrGList :: GObject a =>
                               a -> String -> IO [Ptr b]
 getObjectPropertyPtrGList obj propName =
-    getObjectProperty obj propName (get_pointer >=> unpackGList) gtypePointer
+  getObjectProperty obj propName (gvalueGet_ >=> unpackGList) gtypePointer
 
 setObjectPropertyHash :: GObject a => a -> String -> b -> IO ()
 setObjectPropertyHash =
@@ -549,16 +546,16 @@
 
 setObjectPropertyCallback :: GObject a => a -> String -> FunPtr b -> IO ()
 setObjectPropertyCallback obj propName funPtr =
-    setObjectProperty obj propName (castFunPtrToPtr funPtr) set_pointer gtypePointer
+    setObjectProperty obj propName (castFunPtrToPtr funPtr) gvalueSet_ gtypePointer
 
 constructObjectPropertyCallback :: String -> FunPtr b -> IO (GValueConstruct o)
 constructObjectPropertyCallback propName funPtr =
-  constructObjectProperty propName (castFunPtrToPtr funPtr) set_pointer gtypePointer
+  constructObjectProperty propName (castFunPtrToPtr funPtr) gvalueSet_ gtypePointer
 
 getObjectPropertyCallback :: GObject a => a -> String ->
                              (FunPtr b -> c) -> IO (Maybe c)
 getObjectPropertyCallback obj propName wrapper = do
-  ptr <- getObjectProperty obj propName get_pointer gtypePointer
+  ptr <- getObjectProperty obj propName gvalueGet_ gtypePointer
   if ptr /= nullPtr
     then return . Just . wrapper $ castPtrToFunPtr ptr
     else return Nothing
diff --git a/Data/GI/Base/Signals.hs b/Data/GI/Base/Signals.hs
--- a/Data/GI/Base/Signals.hs
+++ b/Data/GI/Base/Signals.hs
@@ -66,6 +66,7 @@
 #endif
 
 import GHC.TypeLits
+import Data.Kind (Type)
 
 import qualified Data.Text as T
 import Data.Text (Text)
@@ -83,7 +84,7 @@
 type SignalHandlerId = CULong
 
 -- | Support for overloaded signal connectors.
-data SignalProxy (object :: *) (info :: *) where
+data SignalProxy (object :: Type) (info :: Type) where
   -- | A basic signal name connector.
   SignalProxy :: SignalProxy o info
   -- | A signal connector annotated with a detail.
@@ -105,9 +106,9 @@
 #endif
 
 -- | Information about an overloaded signal.
-class SignalInfo (info :: *) where
+class SignalInfo (info :: Type) where
     -- | The type for the signal handler.
-    type HaskellCallbackType info :: *
+    type HaskellCallbackType info :: Type
     -- | Connect a Haskell function to a signal of the given
     -- `GObject`, specifying whether the handler will be called before
     -- or after the default handler.
@@ -218,7 +219,7 @@
 
 -- | Generate an informative type error whenever one tries to use a
 -- signal for which code generation has failed.
-type family SignalCodeGenError (signalName :: Symbol) :: * where
+type family SignalCodeGenError (signalName :: Symbol) :: Type where
   SignalCodeGenError signalName = TypeError
     ('Text "The signal ‘"
      ':<>: 'Text signalName
diff --git a/haskell-gi-base.cabal b/haskell-gi-base.cabal
--- a/haskell-gi-base.cabal
+++ b/haskell-gi-base.cabal
@@ -1,5 +1,5 @@
 name:                haskell-gi-base
-version:             0.24.5
+version:             0.25.0
 synopsis:            Foundation for libraries generated by haskell-gi
 description:         Foundation for libraries generated by haskell-gi
 homepage:            https://github.com/haskell-gi/haskell-gi
