Skip to content
This repository has been archived by the owner on Mar 4, 2024. It is now read-only.

Commit

Permalink
subclass: Hook up instance_init()
Browse files Browse the repository at this point in the history
Add a new wrapper type, InitializingObject, to store the object pointer
during instance_init(). Binding crates are expected to define traits and implement
them for InitializingObject to expose safe methods. Notably, this is required
for gtk_widget_init_template().
  • Loading branch information
YaLTeR committed Dec 14, 2020
1 parent f316f40 commit 2b583fd
Show file tree
Hide file tree
Showing 2 changed files with 33 additions and 3 deletions.
3 changes: 2 additions & 1 deletion glib/src/subclass/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -281,5 +281,6 @@ pub use self::boxed::register_boxed_type;
pub use self::interface::register_interface;
pub use self::object::Property;
pub use self::types::{
register_type, InitializingType, SignalClassHandlerToken, SignalInvocationHint, TypeData,
register_type, InitializingObject, InitializingType, SignalClassHandlerToken,
SignalInvocationHint, TypeData,
};
33 changes: 31 additions & 2 deletions glib/src/subclass/types.rs
Original file line number Diff line number Diff line change
Expand Up @@ -4,9 +4,9 @@

//! Module that contains the basic infrastructure for subclassing `GObject`.
use crate::object::{ObjectSubclassIs, ObjectType};
use crate::object::{Cast, ObjectSubclassIs, ObjectType};
use crate::translate::*;
use crate::{Closure, SignalFlags, StaticType, Type, Value};
use crate::{Closure, Object, SignalFlags, StaticType, Type, Value};
use std::fmt;
use std::marker;
use std::mem;
Expand Down Expand Up @@ -369,6 +369,31 @@ pub trait ObjectSubclass: Sized + 'static {
fn with_class(_klass: &Self::Class) -> Self {
Self::new()
}

/// Performs additional instance initialization.
///
/// Called just after `with_class()`. At this point the initialization has not completed yet, so
/// only a limited set of operations is safe (see `InitializingObject`).
fn instance_init(_obj: InitializingObject<Self::Type>) {}
}

/// An object that is currently being initialized.
///
/// Binding crates should use traits for adding methods to this struct. Only methods explicitly safe
/// to call during `instance_init()` should be added.
pub struct InitializingObject<T: ObjectType>(T);

impl<T: ObjectType> InitializingObject<T> {
/// Returns a reference to the object.
///
/// # Safety
///
/// The returned object has not been completely initialized at this point. Use of the object
/// should be restricted to methods that are explicitly documented to be safe to call during
/// `instance_init()`.
pub unsafe fn as_ref(&self) -> &T {
&self.0
}
}

unsafe extern "C" fn class_init<T: ObjectSubclass>(klass: ffi::gpointer, _klass_data: ffi::gpointer)
Expand Down Expand Up @@ -425,6 +450,10 @@ unsafe extern "C" fn instance_init<T: ObjectSubclass>(
let imp = T::with_class(klass);

ptr::write(imp_storage, imp);

// Any additional instance initialization.
let obj = from_glib_none::<_, Object>(obj.cast());
T::instance_init(InitializingObject(obj.unsafe_cast()));
}

unsafe extern "C" fn finalize<T: ObjectSubclass>(obj: *mut gobject_ffi::GObject) {
Expand Down

0 comments on commit 2b583fd

Please sign in to comment.