Add a class_post_init() handler to be called by parents *after* child class_init() handler is called. This is necessary to have parent class check children properly set some values or mandatory handlers.
Signed-off-by: Philippe Mathieu-Daudé <phi...@linaro.org> --- include/qom/object.h | 7 +++++-- qom/object.c | 10 ++++++++++ rust/qemu-api/src/qom.rs | 6 ++++++ 3 files changed, 21 insertions(+), 2 deletions(-) diff --git a/include/qom/object.h b/include/qom/object.h index 3776267e903..d1e437a81be 100644 --- a/include/qom/object.h +++ b/include/qom/object.h @@ -465,8 +465,10 @@ struct Object * has occurred to allow a class to set its default virtual method pointers. * This is also the function to use to override virtual methods from a parent * class. - * @class_data: Data to pass to the @class_init, - * @class_base_init. This can be useful when building dynamic + * @class_post_init: This function is called to finish initialization of + * a class, after all @class_init functions were called. + * @class_data: Data to pass to the @class_base_init, @class_init, and + * @class_post_init. This can be useful when building dynamic * classes. * @interfaces: The list of interfaces associated with this type. This * should point to a static array that's terminated with a zero filled @@ -488,6 +490,7 @@ struct TypeInfo void (*class_base_init)(ObjectClass *klass, void *data); void (*class_init)(ObjectClass *klass, void *data); + void (*class_post_init)(ObjectClass *klass, void *data); void *class_data; InterfaceInfo *interfaces; diff --git a/qom/object.c b/qom/object.c index 1a686dff5a0..694009f0c94 100644 --- a/qom/object.c +++ b/qom/object.c @@ -56,6 +56,7 @@ struct TypeImpl void (*class_base_init)(ObjectClass *klass, void *data); void (*class_init)(ObjectClass *klass, void *data); + void (*class_post_init)(ObjectClass *klass, void *data); void *class_data; @@ -121,6 +122,7 @@ static TypeImpl *type_new(const TypeInfo *info) ti->class_base_init = info->class_base_init; ti->class_init = info->class_init; + ti->class_post_init = info->class_post_init; ti->class_data = info->class_data; ti->instance_init = info->instance_init; @@ -416,6 +418,14 @@ static void type_initialize(TypeImpl *ti) if (ti->class_init) { ti->class_init(ti->class, ti->class_data); } + + parent = type_get_parent(ti); + while (parent) { + if (parent->class_post_init) { + parent->class_post_init(ti->class, ti->class_data); + } + parent = type_get_parent(parent); + } } static void object_init_with_type(Object *obj, TypeImpl *ti) diff --git a/rust/qemu-api/src/qom.rs b/rust/qemu-api/src/qom.rs index 6033228e338..d95e90153a9 100644 --- a/rust/qemu-api/src/qom.rs +++ b/rust/qemu-api/src/qom.rs @@ -470,6 +470,11 @@ pub trait ObjectImpl: ObjectType + ClassInitImpl<Self::Class> { unsafe extern "C" fn(klass: *mut ObjectClass, data: *mut c_void), > = None; + /// Called to finish initialization of a class. + const CLASS_POST_INIT: Option< + unsafe extern "C" fn(klass: *mut ObjectClass, data: *mut c_void), + > = None; + const TYPE_INFO: TypeInfo = TypeInfo { name: Self::TYPE_NAME.as_ptr(), parent: Self::ParentType::TYPE_NAME.as_ptr(), @@ -488,6 +493,7 @@ pub trait ObjectImpl: ObjectType + ClassInitImpl<Self::Class> { class_size: core::mem::size_of::<Self::Class>(), class_base_init: Self::CLASS_BASE_INIT, class_init: Some(rust_class_init::<Self>), + class_post_init: Self::CLASS_POST_INIT, class_data: core::ptr::null_mut(), interfaces: core::ptr::null_mut(), }; -- 2.47.1