qtbridge_runtime/
qmetainfo.rs

1// Copyright (C) 2025 The Qt Company Ltd.
2// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR LGPL-3.0-only
3
4use crate::{DynamicMetaObjectBuilder, DynamicMetaObjectData};
5use qtbridge_type_lib::QMetaObject;
6use std::any::TypeId;
7use std::cell::RefCell;
8use std::collections::HashMap;
9
10pub trait QMetaInfo : 'static {
11    fn class_name() -> &'static str {
12        ::std::any::type_name::<Self>()
13    }
14
15    fn register_meta(meta_obj: std::pin::Pin<&mut DynamicMetaObjectBuilder>); // Called once per type (per specific class name)
16
17    fn get_static_meta_object() -> &'static QMetaObject;
18
19    /// Return DynamicMetaObjectData containing information
20    /// about signals/slots/properties for given Rust object.
21    fn get_shared_dynamic_meta_object_data() -> &'static DynamicMetaObjectData;
22
23    /// Creates a new `DynamicMetaObjectData` object.
24    ///
25    /// Registers signals/slots/properties for the given Rust type.
26    ///
27    /// Returns a raw pointer to the heap-allocated object.
28    /// Ownership is not managed internally; the caller is responsible for it.
29    fn create_dynamic_meta_object_data_for_type() -> *const DynamicMetaObjectData {
30        let mut builder = crate::create_dynamic_meta_object_builder(
31            Self::class_name(),
32            Self::get_static_meta_object());
33        Self::register_meta(builder.pin_mut());
34        builder.pin_mut()
35            .take_dynamic_metaobject_data()
36    }
37
38}
39
40pub fn dynamic_meta_object_data_for_generic<T: QMetaInfo + ?Sized>() -> &'static DynamicMetaObjectData {
41    thread_local!(static DYNAMIC_META_MAP: RefCell<HashMap<TypeId, *const DynamicMetaObjectData>> =
42        RefCell::new(HashMap::new()));
43
44    let type_id = TypeId::of::<T>();
45    {
46        let meta_data_ptr = DYNAMIC_META_MAP.with_borrow(|dynamic_meta_builder_map| {
47            dynamic_meta_builder_map.get(&type_id)
48                .copied()
49                .unwrap_or_default()
50        });
51        if let Some(meta_data_ref) = unsafe { meta_data_ptr.as_ref() } {
52            return meta_data_ref;
53        }
54    }
55
56    let meta_data_ptr = T::create_dynamic_meta_object_data_for_type();
57    let meta_data_ref = unsafe { meta_data_ptr.as_ref() }.unwrap();
58    DYNAMIC_META_MAP.with_borrow_mut(|dynamic_meta_builder_map| {
59        dynamic_meta_builder_map.insert(type_id, meta_data_ptr);
60    });
61
62    meta_data_ref
63}