diff --git a/include/qemu/plug-proptypes.h b/include/qemu/plug-proptypes.h
index 2c7be0e..cf3e06e 100644
--- a/include/qemu/plug-proptypes.h
+++ b/include/qemu/plug-proptypes.h
@@ -3,8 +3,33 @@
 
 #include "plug.h"
 
-typedef bool (PlugPropertyGetterBool)(Plug *plug);
-typedef void (PlugPropertySetterBool)(Plug *plug, bool value);
+#define CONCAT_I(a, b) a ## b
+#define CONCAT(a, b) CONCAT_I(a, b)
+
+#define GEN_PROP(ctype, typename, ctypename)                   \
+typedef ctype (CONCAT(PlugPropertyGetter, typename))(Plug *plug, Error **errp);  \
+typedef void (CONCAT(PlugPropertySetter, typename))(Plug *plug, ctype value, Error **errp); \
+ \
+void CONCAT(plug_add_property_, ctypename)(Plug *plug, const char *name, \
+                                           CONCAT(PlugPropertyGetter, typename) *getter, \
+                                           CONCAT(PlugPropertySetter, typename) *setter, \
+                                           int flags)
+
+GEN_PROP(int8_t, Int8, int8);
+GEN_PROP(int16_t, Int16, int16);
+GEN_PROP(int32_t, Int32, int32);
+GEN_PROP(int64_t, Int64, int64);
+GEN_PROP(uint8_t, UInt8, uint8);
+GEN_PROP(uint16_t, UInt16, uint16);
+GEN_PROP(uint32_t, UInt32, uint32);
+GEN_PROP(uint64_t, UInt64, uint64);
+GEN_PROP(int64_t, Int, int);
+GEN_PROP(const char *, Str, str);
+
+#undef GEN_PROP
+
+typedef bool (PlugPropertyGetterBool)(Plug *plug, Error **errp);
+typedef void (PlugPropertySetterBool)(Plug *plug, bool value, Error **errp);
 
 void plug_add_property_bool(Plug *plug, const char *name,
                             PlugPropertyGetterBool *getter,
diff --git a/include/qemu/plug.h b/include/qemu/plug.h
index a7ca985..03b63a2 100644
--- a/include/qemu/plug.h
+++ b/include/qemu/plug.h
@@ -62,8 +62,8 @@ void plug_unlock_property(Plug *plug, const char *name);
 void plug_lock_all_properties(Plug *plug);
 void plug_unlock_all_properties(Plug *plug);
 
-void plug_set_realized(Plug *plug, bool realized);
-bool plug_get_realized(Plug *plug);
+void plug_set_realized(Plug *plug, bool realized, Error **errp);
+bool plug_get_realized(Plug *plug, Error **errp);
 
 void plug_realize_all(Plug *plug);
 void plug_unrealize_all(Plug *plug);
diff --git a/qom/plug-proptypes.c b/qom/plug-proptypes.c
index e9152a7..b25093f 100644
--- a/qom/plug-proptypes.c
+++ b/qom/plug-proptypes.c
@@ -8,13 +8,78 @@ typedef struct FunctionPointer
     void (*setter)(void);
 } FunctionPointer;
 
+#define STRIFY_I(a) # a
+#define STRIFY(a) STRIFY_I(a)
+
+static void plug_del_property__fp(Plug *plug, const char *name, void *opaque)
+{
+    FunctionPointer *fp = opaque;
+    qemu_free(fp);
+}
+
+#define GEN_PROP(ctype, typename, ctypename) \
+static void CONCAT(plug_get_property__, ctypename)(Plug *plug, const char *name, Visitor *v, void *opaque, Error **errp) \
+{ \
+    FunctionPointer *fp = opaque; \
+    CONCAT(PlugPropertyGetter, typename) *getter = (CONCAT(PlugPropertyGetter, typename) *)fp->getter; \
+    int64_t value; \
+ \
+    value = getter(plug, errp);                 \
+    visit_type_int(v, &value, name, errp); \
+} \
+ \
+static void CONCAT(plug_set_property__, ctypename)(Plug *plug, const char *name, Visitor *v, void *opaque, Error **errp)  \
+{ \
+    FunctionPointer *fp = opaque; \
+    CONCAT(PlugPropertySetter, typename) *setter = (CONCAT(PlugPropertySetter, typename) *)fp->setter; \
+    int64_t value = 0; \
+    Error *local_err = NULL; \
+ \
+    visit_type_int(v, &value, name, &local_err); \
+    if (local_err) { \
+        error_propagate(errp, local_err); \
+        return; \
+    } \
+ \
+    setter(plug, value, errp);                       \
+} \
+ \
+void CONCAT(plug_add_property_, ctypename)(Plug *plug, const char *name, \
+                                           CONCAT(PlugPropertyGetter, typename) *getter, \
+                                           CONCAT(PlugPropertySetter, typename) *setter, \
+                                           int flags) \
+{ \
+    FunctionPointer *fp = qemu_mallocz(sizeof(*fp)); \
+ \
+    fp->getter = (void (*)(void))getter; \
+    fp->setter = (void (*)(void))setter; \
+ \
+    plug_add_property_full(plug, name, \
+                           CONCAT(plug_get_property__, ctypename), \
+                           CONCAT(plug_set_property__, ctypename), \
+                           plug_del_property__fp, \
+                           fp, STRIFY(ctypename), flags); \
+}
+
+GEN_PROP(int8_t, Int8, int8);
+GEN_PROP(int16_t, Int16, int16);
+GEN_PROP(int32_t, Int32, int32);
+GEN_PROP(int64_t, Int64, int64);
+GEN_PROP(uint8_t, UInt8, uint8);
+GEN_PROP(uint16_t, UInt16, uint16);
+GEN_PROP(uint32_t, UInt32, uint32);
+GEN_PROP(uint64_t, UInt64, uint64);
+GEN_PROP(int64_t, Int, int);
+
+#undef GEN_PROP
+
 static void plug_get_property__bool(Plug *plug, const char *name, Visitor *v, void *opaque, Error **errp)
 {
     FunctionPointer *fp = opaque;
     PlugPropertyGetterBool *getter = (PlugPropertyGetterBool *)fp->getter;
     bool value;
 
-    value = getter(plug);
+    value = getter(plug, errp);
     visit_type_bool(v, &value, name, errp);
 }
 
@@ -31,7 +96,7 @@ static void plug_set_property__bool(Plug *plug, const char *name, Visitor *v, vo
         return;
     }
 
-    setter(plug, value);
+    setter(plug, value, errp);
 }
 
 void plug_add_property_bool(Plug *plug, const char *name,
@@ -50,3 +115,53 @@ void plug_add_property_bool(Plug *plug, const char *name,
                            plug_del_property__fp,
                            fp, "bool", flags);
 }
+
+/** str **/
+
+static void plug_get_property__str(Plug *plug, const char *name, Visitor *v, void *opaque, Error **errp)
+{
+    FunctionPointer *fp = opaque;
+    PlugPropertyGetterStr *getter = (PlugPropertyGetterStr *)fp->getter;
+    char *value;
+
+    value = (char *)getter(plug, errp);
+    if (value == NULL) {
+        value = (char *)"";
+    }
+    visit_type_str(v, &value, name, errp);
+}
+
+static void plug_set_property__str(Plug *plug, const char *name, Visitor *v, void *opaque, Error **errp)
+{
+    FunctionPointer *fp = opaque;
+    PlugPropertySetterStr *setter = (PlugPropertySetterStr *)fp->setter;
+    char *value = false;
+    Error *local_err = NULL;
+
+    visit_type_str(v, &value, name, &local_err);
+    if (local_err) {
+        error_propagate(errp, local_err);
+        return;
+    }
+
+    setter(plug, value, errp);
+
+    qemu_free(value);
+}
+
+void plug_add_property_str(Plug *plug, const char *name,
+                           PlugPropertyGetterStr *getter,
+                           PlugPropertySetterStr *setter,
+                           int flags)
+{
+    FunctionPointer *fp = qemu_mallocz(sizeof(*fp));
+
+    fp->getter = (void (*)(void))getter;
+    fp->setter = (void (*)(void))setter;
+
+    plug_add_property_full(plug, name,
+                           plug_get_property__str,
+                           plug_set_property__str,
+                           plug_del_property__fp,
+                           fp, "str", flags);
+}
diff --git a/qom/plug.c b/qom/plug.c
index a9d8154..7f21c6b 100644
--- a/qom/plug.c
+++ b/qom/plug.c
@@ -136,7 +136,7 @@ void plug_foreach_property(Plug *plug, PropertyEnumerator *enumfn, void *opaque)
     }
 }
 
-void plug_set_realized(Plug *plug, bool realized)
+void plug_set_realized(Plug *plug, bool realized, Error **errp)
 {
     PlugClass *class = PLUG_GET_CLASS(plug);
     bool old_value = plug->realized;
@@ -154,7 +154,7 @@ void plug_set_realized(Plug *plug, bool realized)
     }
 }
 
-bool plug_get_realized(Plug *plug)
+bool plug_get_realized(Plug *plug, Error **errp)
 {
     return plug->realized;
 }
@@ -180,7 +180,7 @@ static void plug_propagate_realized(Plug *plug, const char *name,
         child_name = plug_get_property_str(plug, name, NULL);
         child_plug = PLUG(type_find_by_id(child_name));
 
-        plug_set_realized(child_plug, plug_get_realized(plug));
+        plug_set_realized(child_plug, plug_get_realized(plug, NULL), NULL);
 
         qemu_free(child_name);
     }
@@ -329,7 +329,7 @@ void plug_realize_all(Plug *plug)
 {
     /* This doesn't loop infinitely because the callbacks are only called when
      * the state changes. */
-    plug_set_realized(plug, true);
+    plug_set_realized(plug, true, NULL);
     plug_lock_all_properties(plug);
     plug_foreach_property(plug, plug_propagate_realized, NULL);
 }
@@ -338,7 +338,7 @@ void plug_unrealize_all(Plug *plug)
 {
     /* This doesn't loop infinitely because the callbacks are only called when
      * the state changes. */
-    plug_set_realized(plug, false);
+    plug_set_realized(plug, false, NULL);
     plug_unlock_all_properties(plug);
     plug_foreach_property(plug, plug_propagate_realized, NULL);
 }
