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
72mod sealed {
73    pub trait Sealed {}
74    impl<T: super::IsA<super::TypePlugin>> Sealed for T {}
75}
76
77/// Trait containing all [`struct@TypePlugin`] methods.
78///
79/// # Implementors
80///
81/// [`TypeModule`][struct@crate::TypeModule], [`TypePlugin`][struct@crate::TypePlugin]
82pub trait TypePluginExt: IsA<TypePlugin> + sealed::Sealed + 'static {
83    /// Calls the `complete_interface_info` function from the
84    /// `GTypePluginClass` of `self`. There should be no need to use this
85    /// function outside of the GObject type system itself.
86    /// ## `instance_type`
87    /// the `GType` of an instantiatable type to which the interface
88    ///  is added
89    /// ## `interface_type`
90    /// the `GType` of the interface whose info is completed
91    /// ## `info`
92    /// the [`InterfaceInfo`][crate::InterfaceInfo] to fill in
93    #[doc(alias = "g_type_plugin_complete_interface_info")]
94    fn complete_interface_info(
95        &self,
96        instance_type: crate::types::Type,
97        interface_type: crate::types::Type,
98    ) -> InterfaceInfo {
99        let info = InterfaceInfo::default();
100        unsafe {
101            gobject_ffi::g_type_plugin_complete_interface_info(
102                self.as_ref().to_glib_none().0,
103                instance_type.into_glib(),
104                interface_type.into_glib(),
105                info.as_ptr(),
106            );
107        }
108        info
109    }
110
111    /// Calls the `complete_type_info` function from the `GTypePluginClass` of `self`.
112    /// There should be no need to use this function outside of the GObject
113    /// type system itself.
114    /// ## `g_type`
115    /// the `GType` whose info is completed
116    /// ## `info`
117    /// the [`TypeInfo`][crate::TypeInfo] struct to fill in
118    /// ## `value_table`
119    /// the [`TypeValueTable`][crate::TypeValueTable] to fill in
120    #[doc(alias = "g_type_plugin_complete_type_info")]
121    fn complete_type_info(&self, g_type: crate::types::Type) -> (TypeInfo, TypeValueTable) {
122        let info = TypeInfo::default();
123        let value_table = TypeValueTable::default();
124        unsafe {
125            gobject_ffi::g_type_plugin_complete_type_info(
126                self.as_ref().to_glib_none().0,
127                g_type.into_glib(),
128                info.as_ptr(),
129                value_table.as_ptr(),
130            );
131        }
132        (info, value_table)
133    }
134
135    /// Calls the `unuse_plugin` function from the `GTypePluginClass` of
136    /// `self`. There should be no need to use this function outside of
137    /// the GObject type system itself.
138    #[doc(alias = "g_type_plugin_unuse")]
139    fn unuse(&self) {
140        unsafe {
141            gobject_ffi::g_type_plugin_unuse(self.as_ref().to_glib_none().0);
142        }
143    }
144
145    /// Calls the `use_plugin` function from the `GTypePluginClass` of
146    /// `self`. There should be no need to use this function outside of
147    /// the GObject type system itself.
148    #[doc(alias = "g_type_plugin_use")]
149    #[doc(alias = "use")]
150    fn use_(&self) {
151        unsafe {
152            gobject_ffi::g_type_plugin_use(self.as_ref().to_glib_none().0);
153        }
154    }
155}
156
157impl<O: IsA<TypePlugin>> TypePluginExt for O {}