diff --git a/include/qom/object.h b/include/qom/object.h index 73d72619b8..4c0645817a 100644 --- a/include/qom/object.h +++ b/include/qom/object.h @@ -2324,6 +2324,23 @@ object_class_property_add_alias(ObjectClass *klass, const char *name, const char *target_type, const char *target_name); +/** + * object_property_set_alias: + * @obj: the object upon which to set the alias property + * @name: the name of the alias property + * @target_obj: the object to forward property access to + * + * Set an alias property on an object to point to @target_obj. This is only + * required for class properties, and will assert at runtime if used on an + * object property. + * + * This function ensures that @target_obj stays alive as long as @obj exists + * by taking a reference if @target_obj is not a child object or an alias on + * the same object. + */ +void object_property_set_alias(Object *obj, const char *name, + Object *target_obj); + /** * object_property_add_const_link: * @obj: the object to add a property to diff --git a/qom/object.c b/qom/object.c index e4e8dc6886..96498f3d00 100644 --- a/qom/object.c +++ b/qom/object.c @@ -3126,6 +3126,18 @@ static void property_release_alias(Object *obj, const char *name, void *opaque) if (!(prop->flags & OBJ_PROP_ALIAS_CLASS)) { g_free(prop->target_name); g_free(prop); + } else { + Object **target_obj = object_alias_get_targetp(obj, prop); + + if (*target_obj) { + ObjectProperty *target_prop = object_property_find_err(*target_obj, + prop->target_name, + &error_abort); + if (*target_obj != obj && + !object_property_is_child(target_prop)) { + object_unref(*target_obj); + } + } } } @@ -3212,6 +3224,35 @@ object_class_property_add_alias(ObjectClass *klass, const char *name, return op; } +void object_property_set_alias(Object *obj, const char *name, + Object *target_obj) +{ + AliasProperty *prop; + ObjectProperty *op, *target_prop; + Object **target_objp; + + op = object_property_find_err(obj, name, &error_abort); + prop = op->opaque; + assert(prop->flags & OBJ_PROP_ALIAS_CLASS); + + target_objp = object_alias_get_targetp(obj, prop); + if (*target_objp) { + target_prop = object_property_find_err(*target_objp, prop->target_name, + &error_abort); + if (*target_objp != obj && !object_property_is_child(target_prop)) { + object_unref(*target_objp); + } + } + *target_objp = target_obj; + if (*target_objp) { + target_prop = object_property_find_err(*target_objp, prop->target_name, + &error_abort); + if (*target_objp != obj && !object_property_is_child(target_prop)) { + object_ref(*target_objp); + } + } +} + void object_property_set_description(Object *obj, const char *name, const char *description) {