mirror of
https://github.com/Motorhead1991/qemu.git
synced 2025-08-30 21:42:06 -06:00
rust: qom: allow initializing interface vtables
Unlike regular classes, interface vtables can only be obtained via object_class_dynamic_cast. Provide a wrapper that allows accessing the vtable and pass it to a ClassInitImpl implementation, for example ClassInitImpl<ResettableClass>. Reviewed-by: Zhao Liu <zhao1.liu@intel.com> Signed-off-by: Paolo Bonzini <pbonzini@redhat.com>
This commit is contained in:
parent
201ef001dd
commit
688c674158
2 changed files with 44 additions and 2 deletions
|
@ -9,6 +9,7 @@ pub use crate::cell::BqlRefCell;
|
||||||
|
|
||||||
pub use crate::qdev::DeviceMethods;
|
pub use crate::qdev::DeviceMethods;
|
||||||
|
|
||||||
|
pub use crate::qom::InterfaceType;
|
||||||
pub use crate::qom::IsA;
|
pub use crate::qom::IsA;
|
||||||
pub use crate::qom::Object;
|
pub use crate::qom::Object;
|
||||||
pub use crate::qom::ObjectCast;
|
pub use crate::qom::ObjectCast;
|
||||||
|
|
|
@ -66,8 +66,8 @@ pub use bindings::{Object, ObjectClass};
|
||||||
|
|
||||||
use crate::{
|
use crate::{
|
||||||
bindings::{
|
bindings::{
|
||||||
self, object_dynamic_cast, object_get_class, object_get_typename, object_new, object_ref,
|
self, object_class_dynamic_cast, object_dynamic_cast, object_get_class,
|
||||||
object_unref, TypeInfo,
|
object_get_typename, object_new, object_ref, object_unref, TypeInfo,
|
||||||
},
|
},
|
||||||
cell::bql_locked,
|
cell::bql_locked,
|
||||||
};
|
};
|
||||||
|
@ -263,6 +263,47 @@ pub unsafe trait ObjectType: Sized {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// Trait exposed by all structs corresponding to QOM interfaces.
|
||||||
|
/// Unlike `ObjectType`, it is implemented on the class type (which provides
|
||||||
|
/// the vtable for the interfaces).
|
||||||
|
///
|
||||||
|
/// # Safety
|
||||||
|
///
|
||||||
|
/// `TYPE` must match the contents of the `TypeInfo` as found in the C code;
|
||||||
|
/// right now, interfaces can only be declared in C.
|
||||||
|
pub unsafe trait InterfaceType: Sized {
|
||||||
|
/// The name of the type, which can be passed to
|
||||||
|
/// `object_class_dynamic_cast()` to obtain the pointer to the vtable
|
||||||
|
/// for this interface.
|
||||||
|
const TYPE_NAME: &'static CStr;
|
||||||
|
|
||||||
|
/// Initialize the vtable for the interface; the generic argument `T` is the
|
||||||
|
/// type being initialized, while the generic argument `U` is the type that
|
||||||
|
/// lists the interface in its `TypeInfo`.
|
||||||
|
///
|
||||||
|
/// # Panics
|
||||||
|
///
|
||||||
|
/// Panic if the incoming argument if `T` does not implement the interface.
|
||||||
|
fn interface_init<
|
||||||
|
T: ObjectType + ClassInitImpl<Self> + ClassInitImpl<U::Class>,
|
||||||
|
U: ObjectType,
|
||||||
|
>(
|
||||||
|
klass: &mut U::Class,
|
||||||
|
) {
|
||||||
|
unsafe {
|
||||||
|
// SAFETY: upcasting to ObjectClass is always valid, and the
|
||||||
|
// return type is either NULL or the argument itself
|
||||||
|
let result: *mut Self = object_class_dynamic_cast(
|
||||||
|
(klass as *mut U::Class).cast(),
|
||||||
|
Self::TYPE_NAME.as_ptr(),
|
||||||
|
)
|
||||||
|
.cast();
|
||||||
|
|
||||||
|
<T as ClassInitImpl<Self>>::class_init(result.as_mut().unwrap())
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
/// This trait provides safe casting operations for QOM objects to raw pointers,
|
/// This trait provides safe casting operations for QOM objects to raw pointers,
|
||||||
/// to be used for example for FFI. The trait can be applied to any kind of
|
/// to be used for example for FFI. The trait can be applied to any kind of
|
||||||
/// reference or smart pointers, and enforces correctness through the [`IsA`]
|
/// reference or smart pointers, and enforces correctness through the [`IsA`]
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue