qtbridge_runtime/
qmetatypeforqobject.rs

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