On 18/08/2026 12:10, Marc-André Lureau wrote:

Signed-off-by: Marc-AndrĂ© Lureau <[email protected]>
---
  include/qom/object.h | 64 +++++++++++++++++++++++++++++++++++++
  qom/object.c         | 89 +++++++++++++++++++++++++++++++++++++++++++++++++---
  2 files changed, 148 insertions(+), 5 deletions(-)

diff --git a/include/qom/object.h b/include/qom/object.h
index 9684db935d23..a03f4bf8f7cf 100644
--- a/include/qom/object.h
+++ b/include/qom/object.h
@@ -1990,6 +1990,70 @@ ObjectProperty 
*object_class_property_add_enum(ObjectClass *klass,
                                      int (*get)(Object *, Error **),
                                      void (*set)(Object *, int, Error **));
+/**
+ * struct QapiEnumProp - Descriptor for a QOM property backed by a QAPI enum 
type
+ *
+ * Binds a QOM object property to a QAPI enum, providing automatic
+ * string<->int conversion through QAPI visitors and optional
+ * default-value initialization during object instance init.
+ *
+ * Use the QAPI_ENUM_PROP() macro to construct instances inline.
+ *
+ * @name: property name exposed on the QOM object
+ * @description: human-readable description (shown in ``-device help``, etc.)
+ * @default_value: initial enum value applied via @set during instance init,
+ *                 or -1 (the QAPI_ENUM_PROP default) to skip initialization
+ * @qapi_type: pointer to the generated QAPITypeInfo for the enum
+ *             (provides the string<->int lookup table)
+ * @get: getter that returns the current enum value as int, or -1 on error
+ * @set: setter that receives the enum value as int; %NULL for read-only props
+ */
+typedef struct QapiEnumProp {
+    const char *name;
+    const char *description;
+    const int default_value;
+    const QAPITypeInfo *qapi_type;
+    int (*get)(Object *, Error **);
+    void (*set)(Object *, int, Error **);
+} QapiEnumProp;
+
+#define QAPI_ENUM_PROP(...) ({                                           \
+    static const QapiEnumProp _prop = {                                  \
+        .default_value = -1, __VA_ARGS__                                 \
+    };                                                                   \
+    &_prop; })
+
+/**
+ * object_property_add_qapi_enum:
+ * @obj: the object to add a property to
+ * @prop: property descriptor
+ *
+ * Add an enum property with QAPI type association.
+ *
+ * Use the QAPI_ENUM_PROP() macro to construct the property descriptor
+ * inline. If .default_value is not set, the property is not initialized
+ * (default_value is -1). Otherwise, the setter is called with
+ * default_value during object instance init.
+ *
+ * Example::
+ *
+ *   object_class_property_add_qapi_enum(oc, QAPI_ENUM_PROP(
+ *       .name = "policy",
+ *       .description = "Set the NUMA policy",
+ *       .default_value = HOST_MEM_POLICY_DEFAULT,
+ *       .qapi_type = &HostMemPolicy_type_info,
+ *       .get = my_get_policy,
+ *       .set = my_set_policy,
+ *   ));
+ *
+ * Returns: The newly added property on success, or %NULL on failure.
+ */
+ObjectProperty *
+object_property_add_qapi_enum(Object *obj, const QapiEnumProp *prop);

Same comment here about duplicating the doc comments for object_class_property_add_qapi_enum() below.

+ObjectProperty *
+object_class_property_add_qapi_enum(ObjectClass *klass, const QapiEnumProp 
*prop);
+
  /**
   * object_property_add_qapi:
   * @obj: the object to add a property to
diff --git a/qom/object.c b/qom/object.c
index 1bfb6b933339..f5568b9f9790 100644
--- a/qom/object.c
+++ b/qom/object.c
@@ -1206,7 +1206,7 @@ static void object_class_foreach_tramp(gpointer key, 
gpointer value,
          return;
      }
- if (data->implements_type &&
+    if (data->implements_type &&
          !object_class_dynamic_cast(k, data->implements_type)) {
          return;
      }
@@ -1772,7 +1772,6 @@ int object_property_get_enum(Object *obj, const char 
*name,
      char *str;
      int ret;
      ObjectProperty *prop = object_property_find_err(obj, name, errp);
-    EnumProperty *enumprop;
if (prop == NULL) {
          return -1;
@@ -1785,14 +1784,17 @@ int object_property_get_enum(Object *obj, const char 
*name,
          return -1;
      }
- enumprop = prop->opaque;
-
      str = object_property_get_str(obj, name, errp);
      if (!str) {
          return -1;
      }
- ret = qapi_enum_parse(enumprop->lookup, str, -1, errp);
+    if (prop->qapi_type) {
+        ret = qapi_enum_parse(prop->qapi_type->lookup, str, -1, errp);
+    } else {
+        EnumProperty *enumprop = prop->opaque;
+        ret = qapi_enum_parse(enumprop->lookup, str, -1, errp);
+    }
      g_free(str);
return ret;
@@ -2595,6 +2597,83 @@ object_class_property_add_enum(ObjectClass *klass, const 
char *name,
                                       prop);
  }
+static void get_qapi_enum(Object *obj, Visitor *v, const char *name,
+                          void *opaque, Error **errp)
+{
+    const QapiEnumProp *prop = opaque;
+    int value;
+    Error *err = NULL;
+
+    value = prop->get(obj, &err);
+    if (err) {
+        error_propagate(errp, err);
+        return;
+    }
+
+    visit_type_enum(v, name, &value, prop->qapi_type->lookup, errp);
+}
+
+static void set_qapi_enum(Object *obj, Visitor *v, const char *name,
+                          void *opaque, Error **errp)
+{
+    const QapiEnumProp *prop = opaque;
+    int value;
+
+    if (!visit_type_enum(v, name, &value, prop->qapi_type->lookup, errp)) {
+        return;
+    }
+    prop->set(obj, value, errp);
+}
+
+static void init_qapi_enum(Object *obj, ObjectProperty *prop)
+{
+    const QapiEnumProp *e = prop->opaque;
+
+    if (e->set && e->default_value >= 0) {
+        e->set(obj, e->default_value, &error_abort);
+    }
+}
+
+ObjectProperty *
+object_property_add_qapi_enum(Object *obj, const QapiEnumProp *e)
+{
+    ObjectProperty *prop;
+
+    assert(e && e->qapi_type && e->qapi_type->lookup);
+
+    prop = object_property_add_qapi(obj, e->name, e->qapi_type,
+                                    e->get ? get_qapi_enum : NULL,
+                                    e->set ? set_qapi_enum : NULL,
+                                    NULL,
+                                    (void *)e);
+    prop->description = g_strdup(e->description);
+    if (e->default_value >= 0) {
+        prop->init = init_qapi_enum;
+    }
+
+    return prop;
+}
+
+ObjectProperty *
+object_class_property_add_qapi_enum(ObjectClass *klass, const QapiEnumProp *e)
+{
+    ObjectProperty *prop;
+
+    assert(e && e->qapi_type && e->qapi_type->lookup);
+
+    prop = object_class_property_add_qapi(klass, e->name, e->qapi_type,
+                                          e->get ? get_qapi_enum : NULL,
+                                          e->set ? set_qapi_enum : NULL,
+                                          NULL,
+                                          (void *)e);
+    prop->description = g_strdup(e->description);
+    if (e->default_value >= 0) {
+        prop->init = init_qapi_enum;
+    }
+
+    return prop;
+}
+
  ObjectProperty *
  object_property_add_qapi(Object *obj, const char *name,
                           const QAPITypeInfo *qapi_type,



ATB,

Mark.


Reply via email to