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