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 {}