Attribute Macro glib_macros::object_subclass

source ·
#[object_subclass]
Expand description

Macro for boilerplate of ObjectSubclass implementations.

This adds implementations for the type_data() and type_() methods, which should probably never be defined differently.

It provides default values for the Instance, Class, and Interfaces type parameters. If these are present, the macro will use the provided value instead of the default.

Usually the defaults for Instance and Class will work. Interfaces is necessary for types that implement interfaces.

type Instance = glib::subclass::basic::InstanceStruct<Self>;
type Class = glib::subclass::basic::ClassStruct<Self>;
type Interfaces = ();

If no new() or with_class() method is provide, the macro adds a new() implementation calling Default::default(). So the type needs to implement Default, or this should be overridden.

fn new() -> Self {
    Default::default()
}

An object subclass can be registered as a dynamic type by setting the macro helper attribute object_class_dynamic:

#[derive(Default)]
pub struct MyType;

#[glib::object_subclass]
#[object_subclass_dynamic]
impl ObjectSubclass for MyType { ... }

As a dynamic type, an object subclass must be explicitly registered when the system loads the implementation (see TypePlugin and TypeModule. Therefore, whereas an object subclass can be registered only once as a static type, it can be registered several times as a dynamic type.

An object subclass registered as a dynamic type is never unregistered. The system calls TypePluginExt::unuse to unload the implementation. If the TypePlugin subclass is a TypeModule, the object subclass registered as a dynamic type is marked as unloaded and must be registered again when the module is reloaded.

The macro helper attribute object_class_dynamic provides two behaviors when registering an object subclass as a dynamic type:

  • lazy registration: by default an object subclass is registered as a dynamic type when the system loads the implementation (e.g. when the module is loaded). Optionally setting lazy_registration to true postpones registration on the first use (when static_type() is called for the first time):
#[derive(Default)]
pub struct MyType;

#[glib::object_subclass]
#[object_subclass_dynamic(lazy_registration = true)]
impl ObjectSubclass for MyType { ... }
  • registration within TypeModule subclass or within TypePlugin subclass: an object subclass is usually registered as a dynamic type within a TypeModule subclass:
#[derive(Default)]
pub struct MyModuleType;

#[glib::object_subclass]
#[object_subclass_dynamic]
impl ObjectSubclass for MyModuleType { ... }
...
#[derive(Default)]
pub struct MyModule;
...
impl TypeModuleImpl for MyModule {
    fn load(&self) -> bool {
        // registers object subclasses as dynamic types.
        let my_module = self.obj();
        let type_module: &glib::TypeModule = my_module.upcast_ref();
        MyModuleType::on_implementation_load(type_module)
    }
    ...
}

Optionally setting plugin_type allows to register an object subclass as a dynamic type within a TypePlugin subclass that is not a TypeModule:

#[derive(Default)]
pub struct MyPluginType;

#[glib::object_subclass]
#[object_subclass_dynamic(plugin_type = MyPlugin)]
impl ObjectSubclass for MyPluginType { ... }
...
#[derive(Default)]
pub struct MyPlugin;
...
impl TypePluginImpl for MyPlugin {
    fn use_plugin(&self) {
        // register object subclasses as dynamic types.
        let my_plugin = self.obj();
        MyPluginType::on_implementation_load(my_plugin.as_ref());
    }
    ...
}