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;
11use crate::qobjectholder::CppProxyOf;
12use crate::registry::Owner;
13
14fn monomorphize_meta_object_fn<T: QObjectHolder>() -> extern "C" fn(*const QMetaTypeInterface) -> *mut QMetaObject {
15 extern "C" fn meta_object_fn<T: QObjectHolder>(_iface: *const QMetaTypeInterface) -> *mut QMetaObject {
16 let meta_obj_data =
17 <T as QObjectHolder>::get_shared_dynamic_meta_object_data();
18 meta_obj_data.get_meta_object()
19 }
20 meta_object_fn::<T>
21}
22
23fn monomorphize_default_ctor<T: QObjectHolder + Default>() -> extern "C" fn(*const QMetaTypeInterface, *mut u8) {
24 extern "C" fn default_ctor<T: QObjectHolder + Default>(_iface: *const QMetaTypeInterface, addr: *mut u8) {
25 let instance =
26 Rc::new(RefCell::new(<T as Default>::default()));
27 <T as QObjectHolder>::register_instance(instance, Owner::Engine, Some(addr));
28 }
29 default_ctor::<T>
30}
31
32fn monomorphize_dtor<T: QObjectHolder>() -> extern "C" fn (*const QMetaTypeInterface, *mut u8) {
33 extern "C" fn dtor<T: QObjectHolder>(_iface: *const QMetaTypeInterface, obj: *mut u8) {
34 QObject::destruct(obj.cast());
35 }
36 dtor::<T>
37}
38
39pub fn init_interface_for<T: QObjectHolder + Default>()-> QMetaTypeInterface {
41 let flags: u32 =
42 (QMetaTypeFlag::NeedsConstruction as u32)
43 | (QMetaTypeFlag::NeedsDestruction as u32)
44 | (QMetaTypeFlag::NeedsCopyConstruction as u32)
45 | (QMetaTypeFlag::NeedsMoveConstruction as u32)
46 | (QMetaTypeFlag::PointerToQObject as u32);
47
48 let class_name = std::ffi::CString::new(std::any::type_name::<T>())
49 .expect("CString::new failed")
50 .into_bytes_with_nul()
51 .leak();
52
53 QMetaTypeInterface::fill_fields(
54 <CppProxyOf<T> as QCppProxy>::get_align(),
55 <CppProxyOf<T> as QCppProxy>::get_size(),
56 flags,
57 class_name,
58 monomorphize_meta_object_fn::<T>() as usize,
59 monomorphize_default_ctor::<T>() as usize,
60 0,
61 monomorphize_dtor::<T>() as usize,
62 )
63}
64
65pub fn init_ptr_interface_for<T: QObjectHolder>() -> QMetaTypeInterface {
68 let flags: u32 =
69 (QMetaTypeFlag::IsPointer as u32)
70 | (QMetaTypeFlag::PointerToQObject as u32)
71 | (QMetaTypeFlag::RelocatableType as u32);
72
73 let name = std::ffi::CString::new(format!("{}*", std::any::type_name::<T>()))
74 .expect("CString::new failed")
75 .into_bytes_with_nul()
76 .leak();
77
78 QMetaTypeInterface::fill_fields(
79 std::mem::align_of::<*mut QObject>(),
80 std::mem::size_of::<*mut QObject>(),
81 flags,
82 name,
83 monomorphize_meta_object_fn::<T>() as usize,
84 0,
85 0,
86 0,
87 )
88}
89
90pub fn interface_for_generic<T: QObjectHolder + Default>() -> &'static QMetaTypeInterface {
93 thread_local!(static IFACE_MAP: RefCell<HashMap<TypeId , *const QMetaTypeInterface>> = RefCell::new(HashMap::new ()));
94 let type_id = TypeId::of::<T>();
95 {
96 let iface_ptr = IFACE_MAP
97 .with_borrow(|iface_map| iface_map.get(&type_id).copied().unwrap_or_default());
98 if let Some(iface_ref) = unsafe { iface_ptr.as_ref() } {
99 return iface_ref;
100 }
101 }
102 let iface_ref = Box::leak(Box::new(init_interface_for::<T>()));
103 let iface_ptr = std::ptr::from_ref(iface_ref);
104 IFACE_MAP.with_borrow_mut(|iface_map| iface_map.insert(type_id, iface_ptr));
105 iface_ref
106}
107
108pub fn ptr_interface_for_generic<T: QObjectHolder>() -> &'static QMetaTypeInterface {
111 thread_local!(static PTR_IFACE_MAP: RefCell<HashMap<TypeId, *const QMetaTypeInterface>> = RefCell::new(HashMap::new()));
112 let type_id = TypeId::of::<T>();
113 {
114 let iface_ptr = PTR_IFACE_MAP
115 .with_borrow(|iface_map| iface_map.get(&type_id).copied().unwrap_or_default());
116 if let Some(iface_ref) = unsafe { iface_ptr.as_ref() } {
117 return iface_ref;
118 }
119 }
120 let iface_ref = Box::leak(Box::new(init_ptr_interface_for::<T>()));
121 let iface_ptr = std::ptr::from_ref(iface_ref);
122 PTR_IFACE_MAP.with_borrow_mut(|iface_map| iface_map.insert(type_id, iface_ptr));
123 iface_ref
124}