qtbridge_runtime/
qmetatypeforqobject.rs1use std::rc::Rc;
5use std::cell::RefCell;
6use std::any::TypeId;
7use std::collections::HashMap;
8use qtbridge_type_lib::{QMetaTypeInterface, QMetaTypeFlag, QMetaObject, QObject};
9use crate::qproxies::QCppProxy;
10use crate::{QObjectHolder, QMetaInfo};
11use crate::qproxies::ConstructionMode;
12
13pub fn interface_for_generic<T: QObjectHolder + 'static>() -> &'static QMetaTypeInterface {
14 thread_local!(static IFACE_MAP: RefCell<HashMap<TypeId , *const QMetaTypeInterface>> = RefCell::new(HashMap::new ()));
15 let type_id = TypeId::of::<T>();
16 {
17 let iface_ptr = IFACE_MAP
18 .with_borrow(|iface_map| iface_map.get(&type_id).copied().unwrap_or_default());
19 if let Some(iface_ref) = unsafe { iface_ptr.as_ref() } {
20 return iface_ref;
21 }
22 }
23 let iface_ref = Box::leak(Box::new(init_interface_for::<T>()));
24 let iface_ptr = std::ptr::from_ref(iface_ref);
25 IFACE_MAP.with_borrow_mut(|iface_map| iface_map.insert(type_id, iface_ptr));
26 iface_ref
27}
28
29fn monomorphize_meta_object_fn<T: QObjectHolder>() -> extern "C" fn(*const QMetaTypeInterface) -> *mut QMetaObject {
30 extern "C" fn meta_object_fn<T: QObjectHolder>(_iface: *const QMetaTypeInterface) -> *mut QMetaObject {
31 let meta_obj_data =
32 <T as QMetaInfo>::get_shared_dynamic_meta_object_data();
33 meta_obj_data.get_meta_object()
34 }
35 meta_object_fn::<T>
36}
37
38fn monomorphize_default_ctor<T: QObjectHolder>() -> extern "C" fn(*const QMetaTypeInterface, *mut u8) {
39 extern "C" fn default_ctor<T: QObjectHolder>(_iface: *const QMetaTypeInterface, addr: *mut u8) {
40 let instance =
41 Rc::new(RefCell::new(<T as Default>::default()));
42 <T as QObjectHolder>::register_instance_in_map(instance, ConstructionMode::AtAddress(addr));
43 }
44 default_ctor::<T>
45}
46
47fn monomorphize_dtor<T: QObjectHolder>() -> extern "C" fn (*const QMetaTypeInterface, *mut u8) {
48 extern "C" fn dtor<T: QObjectHolder>(_iface: *const QMetaTypeInterface, obj: *mut u8) {
49 QObject::destruct(obj.cast());
50 }
51 dtor::<T>
52}
53
54pub fn init_interface_for<T: QObjectHolder + 'static>()-> QMetaTypeInterface {
55 let flags: u32 =
56 (QMetaTypeFlag::NeedsConstruction as u32)
57 | (QMetaTypeFlag::NeedsDestruction as u32)
58 | (QMetaTypeFlag::NeedsCopyConstruction as u32)
59 | (QMetaTypeFlag::NeedsMoveConstruction as u32)
60 | (QMetaTypeFlag::PointerToQObject as u32);
61
62 let class_name = std::ffi::CString::new(std::any::type_name::<T>())
63 .expect("CString::new failed")
64 .into_bytes_with_nul()
65 .leak();
66
67 QMetaTypeInterface::fill_fields(
68 <<T as QMetaInfo>::CppProxy as QCppProxy>::get_align(),
69 <<T as QMetaInfo>::CppProxy as QCppProxy>::get_size(),
70 flags,
71 class_name,
72 monomorphize_meta_object_fn::<T>() as usize,
73 monomorphize_default_ctor::<T>() as usize,
74 0,
75 monomorphize_dtor::<T>() as usize,
76 )
77}