glib/gobject/
type_plugin.rs

1// Take a look at the license at the top of the repository in the LICENSE file.
2
3use crate::{gobject_ffi, prelude::*, translate::*, InterfaceInfo, TypeInfo, TypeValueTable};
4
5crate::wrapper! {
6    /// An interface that handles the lifecycle of dynamically loaded types.
7    ///
8    /// The GObject type system supports dynamic loading of types.
9    /// It goes as follows:
10    ///
11    /// 1. The type is initially introduced (usually upon loading the module
12    ///  the first time, or by your main application that knows what modules
13    ///  introduces what types), like this:
14    ///  **⚠️ The following code is in c ⚠️**
15    ///
16    /// ```c
17    ///    new_type_id = g_type_register_dynamic (parent_type_id,
18    ///                                           "TypeName",
19    ///                                           new_type_plugin,
20    ///                                           type_flags);
21    ///    ```
22    ///  where `new_type_plugin` is an implementation of the
23    ///  `GTypePlugin` interface.
24    ///
25    /// 2. The type's implementation is referenced, e.g. through
26    ///  [func[`Object`][crate::Object].ref] or through [func[`Object`][crate::Object]]
27    ///  (this is being called by [ctor[`Object`][crate::Object].new]) or through one of the above
28    ///  done on a type derived from `new_type_id`.
29    ///
30    /// 3. This causes the type system to load the type's implementation by calling
31    ///  [method[`Object`][crate::Object].use] and [method[`Object`][crate::Object].complete_type_info]
32    ///  on `new_type_plugin`.
33    ///
34    /// 4. At some point the type's implementation isn't required anymore, e.g. after
35    ///  [method[`Object`][crate::Object].unref] or [func[`Object`][crate::Object]]
36    ///  (called when the reference count of an instance drops to zero).
37    ///
38    /// 5. This causes the type system to throw away the information retrieved
39    ///  from [method[`Object`][crate::Object].complete_type_info] and then it calls
40    ///  [method[`Object`][crate::Object].unuse] on `new_type_plugin`.
41    ///
42    /// 6. Things may repeat from the second step.
43    ///
44    /// So basically, you need to implement a `GTypePlugin` type that
45    /// carries a use_count, once use_count goes from zero to one, you need
46    /// to load the implementation to successfully handle the upcoming
47    /// [method[`Object`][crate::Object].complete_type_info] call. Later, maybe after
48    /// succeeding use/unuse calls, once use_count drops to zero, you can
49    /// unload the implementation again. The type system makes sure to call
50    /// [method[`Object`][crate::Object].use] and [method[`Object`][crate::Object].complete_type_info]
51    /// again when the type is needed again.
52    ///
53    /// [class[`Object`][crate::Object]] is an implementation of `GTypePlugin` that
54    /// already implements most of this except for the actual module loading and
55    /// unloading. It even handles multiple registered types per module.
56    ///
57    /// # Implements
58    ///
59    /// [`TypePluginExt`][trait@crate::prelude::TypePluginExt]
60    #[doc(alias = "GTypePlugin")]
61    pub struct TypePlugin(Interface<gobject_ffi::GTypePlugin, gobject_ffi::GTypePluginClass>);
62
63    match fn {
64        type_ => || gobject_ffi::g_type_plugin_get_type(),
65    }
66}
67
68impl TypePlugin {
69    pub const NONE: Option<&'static TypePlugin> = None;
70}
71
72/// Trait containing all [`struct@TypePlugin`] methods.
73///
74/// # Implementors
75///
76/// [`TypeModule`][struct@crate::TypeModule], [`TypePlugin`][struct@crate::TypePlugin]
77pub trait TypePluginExt: IsA<TypePlugin> + 'static {
78    /// Calls the `complete_interface_info` function from the
79    /// `GTypePluginClass` of `self`. There should be no need to use this
80    /// function outside of the GObject type system itself.
81    /// ## `instance_type`
82    /// the `GType` of an instantiatable type to which the interface
83    ///  is added
84    /// ## `interface_type`
85    /// the `GType` of the interface whose info is completed
86    /// ## `info`
87    /// the [`InterfaceInfo`][crate::InterfaceInfo] to fill in
88    #[doc(alias = "g_type_plugin_complete_interface_info")]
89    fn complete_interface_info(
90        &self,
91        instance_type: crate::types::Type,
92        interface_type: crate::types::Type,
93    ) -> InterfaceInfo {
94        let info = InterfaceInfo::default();
95        unsafe {
96            gobject_ffi::g_type_plugin_complete_interface_info(
97                self.as_ref().to_glib_none().0,
98                instance_type.into_glib(),
99                interface_type.into_glib(),
100                info.as_ptr(),
101            );
102        }
103        info
104    }
105
106    /// Calls the `complete_type_info` function from the `GTypePluginClass` of `self`.
107    /// There should be no need to use this function outside of the GObject
108    /// type system itself.
109    /// ## `g_type`
110    /// the `GType` whose info is completed
111    /// ## `info`
112    /// the [`TypeInfo`][crate::TypeInfo] struct to fill in
113    /// ## `value_table`
114    /// the [`TypeValueTable`][crate::TypeValueTable] to fill in
115    #[doc(alias = "g_type_plugin_complete_type_info")]
116    fn complete_type_info(&self, g_type: crate::types::Type) -> (TypeInfo, TypeValueTable) {
117        let info = TypeInfo::default();
118        let value_table = TypeValueTable::default();
119        unsafe {
120            gobject_ffi::g_type_plugin_complete_type_info(
121                self.as_ref().to_glib_none().0,
122                g_type.into_glib(),
123                info.as_ptr(),
124                value_table.as_ptr(),
125            );
126        }
127        (info, value_table)
128    }
129
130    /// Calls the `unuse_plugin` function from the `GTypePluginClass` of
131    /// `self`. There should be no need to use this function outside of
132    /// the GObject type system itself.
133    #[doc(alias = "g_type_plugin_unuse")]
134    fn unuse(&self) {
135        unsafe {
136            gobject_ffi::g_type_plugin_unuse(self.as_ref().to_glib_none().0);
137        }
138    }
139
140    /// Calls the `use_plugin` function from the `GTypePluginClass` of
141    /// `self`. There should be no need to use this function outside of
142    /// the GObject type system itself.
143    #[doc(alias = "g_type_plugin_use")]
144    #[doc(alias = "use")]
145    fn use_(&self) {
146        unsafe {
147            gobject_ffi::g_type_plugin_use(self.as_ref().to_glib_none().0);
148        }
149    }
150}
151
152impl<O: IsA<TypePlugin>> TypePluginExt for O {}