@@ -117,7 +117,7 @@ pub struct PL011Class {
_inner: [u8; 0],
}
-impl qemu_api::definitions::Class for PL011Class {
+impl qemu_api::definitions::ClassInitImpl for PL011Class {
const CLASS_INIT: Option<unsafe extern "C" fn(klass: *mut ObjectClass, data: *mut c_void)> =
Some(crate::device_class::pl011_class_init);
const CLASS_BASE_INIT: Option<
@@ -650,7 +650,7 @@ pub struct PL011LuminaryClass {
}
}
-impl qemu_api::definitions::Class for PL011LuminaryClass {
+impl qemu_api::definitions::ClassInitImpl for PL011LuminaryClass {
const CLASS_INIT: Option<unsafe extern "C" fn(klass: *mut ObjectClass, data: *mut c_void)> =
None;
const CLASS_BASE_INIT: Option<
@@ -20,8 +20,27 @@ pub trait ObjectImpl {
const INSTANCE_FINALIZE: Option<unsafe extern "C" fn(obj: *mut Object)> = None;
}
-pub trait Class {
+/// Trait used to fill in a class struct.
+///
+/// Each QOM class that has virtual methods describes them in a
+/// _class struct_. Class structs include a parent field corresponding
+/// to the vtable of the parent class, all the way up to [`ObjectClass`].
+/// Each QOM type has one such class struct.
+///
+/// The Rust implementation of methods will usually come from a trait
+/// like [`ObjectImpl`].
+pub trait ClassInitImpl {
+ /// Function that is called after all parent class initialization
+ /// has occurred. On entry, the virtual method pointers are set to
+ /// the default values coming from the parent classes; the function
+ /// can change them to override virtual methods of a parent class.
const CLASS_INIT: Option<unsafe extern "C" fn(klass: *mut ObjectClass, data: *mut c_void)>;
+
+ /// Called on descendent classes after all parent class initialization
+ /// has occurred, but before the class itself is initialized. This
+ /// is only useful if a class is not a leaf, and can be used to undo
+ /// the effects of copying the contents of the parent's class struct
+ /// to the descendants.
const CLASS_BASE_INIT: Option<
unsafe extern "C" fn(klass: *mut ObjectClass, data: *mut c_void),
>;
@@ -82,8 +101,8 @@ macro_rules! type_info {
instance_finalize: <$t as $crate::definitions::ObjectImpl>::INSTANCE_FINALIZE,
abstract_: <$t as $crate::definitions::ObjectImpl>::ABSTRACT,
class_size: ::core::mem::size_of::<<$t as $crate::definitions::ObjectImpl>::Class>(),
- class_init: <<$t as $crate::definitions::ObjectImpl>::Class as $crate::definitions::Class>::CLASS_INIT,
- class_base_init: <<$t as $crate::definitions::ObjectImpl>::Class as $crate::definitions::Class>::CLASS_BASE_INIT,
+ class_init: <<$t as $crate::definitions::ObjectImpl>::Class as $crate::definitions::ClassInitImpl>::CLASS_INIT,
+ class_base_init: <<$t as $crate::definitions::ObjectImpl>::Class as $crate::definitions::ClassInitImpl>::CLASS_BASE_INIT,
class_data: ::core::ptr::null_mut(),
interfaces: ::core::ptr::null_mut(),
};
@@ -7,7 +7,7 @@
use qemu_api::{
bindings::*,
c_str, declare_properties, define_property,
- definitions::{Class, ObjectImpl},
+ definitions::{ClassInitImpl, ObjectImpl},
device_class, device_class_init,
zeroable::Zeroable,
};
@@ -60,7 +60,7 @@ impl ObjectImpl for DummyState {
const PARENT_TYPE_NAME: Option<&'static CStr> = Some(device_class::TYPE_DEVICE);
}
- impl Class for DummyClass {
+ impl ClassInitImpl for DummyClass {
const CLASS_INIT: Option<unsafe extern "C" fn(klass: *mut ObjectClass, data: *mut c_void)> =
Some(dummy_class_init);
const CLASS_BASE_INIT: Option<
While at it, document it. Signed-off-by: Paolo Bonzini <pbonzini@redhat.com> --- rust/hw/char/pl011/src/device.rs | 4 ++-- rust/qemu-api/src/definitions.rs | 25 ++++++++++++++++++++++--- rust/qemu-api/tests/tests.rs | 4 ++-- 3 files changed, 26 insertions(+), 7 deletions(-)