Skip to content

Commit 839fc12

Browse files
authored
Merge pull request #1384 from felinira/object-interface-struct
glib: Decouple ObjectInterface impl from interface class struct
2 parents 0899c1e + 60ffeec commit 839fc12

File tree

7 files changed

+108
-37
lines changed

7 files changed

+108
-37
lines changed

glib-macros/tests/object_subclass_dynamic.rs

Lines changed: 46 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -11,13 +11,21 @@ mod static_ {
1111
// impl for an object interface to register as a static type.
1212
#[derive(Clone, Copy)]
1313
#[repr(C)]
14-
pub struct MyStaticInterface {
14+
pub struct MyStaticInterfaceClass {
1515
parent: glib::gobject_ffi::GTypeInterface,
1616
}
1717

18+
unsafe impl InterfaceStruct for MyStaticInterfaceClass {
19+
type Type = MyStaticInterface;
20+
}
21+
22+
pub enum MyStaticInterface {}
23+
1824
#[glib::object_interface]
19-
unsafe impl ObjectInterface for MyStaticInterface {
25+
impl ObjectInterface for MyStaticInterface {
2026
const NAME: &'static str = "MyStaticInterface";
27+
28+
type Interface = MyStaticInterfaceClass;
2129
}
2230

2331
pub trait MyStaticInterfaceImpl: ObjectImpl + ObjectSubclass {}
@@ -69,15 +77,22 @@ mod module {
6977
// impl for a object interface to register as a dynamic type and that extends `MyStaticInterface`.
7078
#[derive(Clone, Copy)]
7179
#[repr(C)]
72-
pub struct MyModuleInterface {
80+
pub struct MyModuleInterfaceClass {
7381
parent: glib::gobject_ffi::GTypeInterface,
7482
}
7583

84+
unsafe impl InterfaceStruct for MyModuleInterfaceClass {
85+
type Type = MyModuleInterface;
86+
}
87+
88+
pub enum MyModuleInterface {}
89+
7690
#[glib::object_interface]
7791
#[object_interface_dynamic]
78-
unsafe impl ObjectInterface for MyModuleInterface {
92+
impl ObjectInterface for MyModuleInterface {
7993
const NAME: &'static str = "MyModuleInterface";
8094
type Prerequisites = (MyStaticInterface,);
95+
type Interface = MyModuleInterfaceClass;
8196
}
8297

8398
pub trait MyModuleInterfaceImpl: ObjectImpl + ObjectSubclass {}
@@ -106,15 +121,22 @@ mod module {
106121
// impl for an object interface to lazy register as a dynamic type and that extends `MyStaticInterface`.
107122
#[derive(Clone, Copy)]
108123
#[repr(C)]
109-
pub struct MyModuleInterfaceLazy {
124+
pub struct MyModuleInterfaceLazyClass {
110125
parent: glib::gobject_ffi::GTypeInterface,
111126
}
112127

128+
unsafe impl InterfaceStruct for MyModuleInterfaceLazyClass {
129+
type Type = MyModuleInterfaceLazy;
130+
}
131+
132+
pub enum MyModuleInterfaceLazy {}
133+
113134
#[glib::object_interface]
114135
#[object_interface_dynamic(lazy_registration = true)]
115-
unsafe impl ObjectInterface for MyModuleInterfaceLazy {
136+
impl ObjectInterface for MyModuleInterfaceLazy {
116137
const NAME: &'static str = "MyModuleInterfaceLazy";
117138
type Prerequisites = (MyStaticInterface,);
139+
type Interface = MyModuleInterfaceLazyClass;
118140
}
119141

120142
pub trait MyModuleInterfaceLazyImpl: ObjectImpl + ObjectSubclass {}
@@ -295,15 +317,22 @@ pub mod plugin {
295317
// impl for a object interface to register as a dynamic type and that extends `MyStaticInterface`.
296318
#[derive(Clone, Copy)]
297319
#[repr(C)]
298-
pub struct MyPluginInterface {
320+
pub struct MyPluginInterfaceClass {
299321
parent: glib::gobject_ffi::GTypeInterface,
300322
}
301323

324+
unsafe impl InterfaceStruct for MyPluginInterfaceClass {
325+
type Type = MyPluginInterface;
326+
}
327+
328+
pub enum MyPluginInterface {}
329+
302330
#[glib::object_interface]
303331
#[object_interface_dynamic(plugin_type = super::MyPlugin)]
304-
unsafe impl ObjectInterface for MyPluginInterface {
332+
impl ObjectInterface for MyPluginInterface {
305333
const NAME: &'static str = "MyPluginInterface";
306334
type Prerequisites = (MyStaticInterface,);
335+
type Interface = MyPluginInterfaceClass;
307336
}
308337

309338
pub trait MyPluginInterfaceImpl: ObjectImpl + ObjectSubclass {}
@@ -332,15 +361,22 @@ pub mod plugin {
332361
// impl for an object interface to lazy register as a dynamic type and that extends `MyStaticInterface`.
333362
#[derive(Clone, Copy)]
334363
#[repr(C)]
335-
pub struct MyPluginInterfaceLazy {
364+
pub struct MyPluginInterfaceLazyClass {
336365
parent: glib::gobject_ffi::GTypeInterface,
337366
}
338367

368+
unsafe impl InterfaceStruct for MyPluginInterfaceLazyClass {
369+
type Type = MyPluginInterfaceLazy;
370+
}
371+
372+
pub enum MyPluginInterfaceLazy {}
373+
339374
#[glib::object_interface]
340375
#[object_interface_dynamic(plugin_type = super::MyPlugin, lazy_registration = true)]
341-
unsafe impl ObjectInterface for MyPluginInterfaceLazy {
376+
impl ObjectInterface for MyPluginInterfaceLazy {
342377
const NAME: &'static str = "MyPluginInterfaceLazy";
343378
type Prerequisites = (MyStaticInterface,);
379+
type Interface = MyPluginInterfaceLazyClass;
344380
}
345381

346382
pub trait MyPluginInterfaceLazyImpl: ObjectImpl + ObjectSubclass {}

glib/src/object.rs

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1317,6 +1317,15 @@ macro_rules! glib_object_wrapper {
13171317
);
13181318
};
13191319

1320+
(@object_interface [$($attr:meta)*] $visibility:vis $name:ident $(<$($generic:ident $(: $bound:tt $(+ $bound2:tt)*)?),+>)?, $iface:ty,
1321+
@type_ $get_type_expr:expr, @requires [$($requires:tt)*]) => {
1322+
$crate::glib_object_wrapper!(
1323+
@interface [$($attr)*] $visibility $name $(<$($generic $(: $bound $(+ $bound2)*)?),+>)?, $iface, std::os::raw::c_void,
1324+
@ffi_class <$iface as $crate::subclass::interface::ObjectInterface>::Interface,
1325+
@type_ $get_type_expr, @requires [$($requires)*]
1326+
);
1327+
};
1328+
13201329
(@interface [$($attr:meta)*] $visibility:vis $name:ident $(<$($generic:ident $(: $bound:tt $(+ $bound2:tt)*)?),+>)?, $impl_type:ty, $ffi_name:ty, @ffi_class $ffi_class_name:ty,
13211330
@type_ $get_type_expr:expr, @requires [$($requires:tt)*]) => {
13221331
$crate::glib_object_wrapper!(

glib/src/subclass/interface.rs

Lines changed: 17 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,7 @@
22

33
use std::{marker, mem};
44

5-
use super::{InitializingType, Signal};
5+
use super::{types::InterfaceStruct, InitializingType, Signal};
66
use crate::{prelude::*, translate::*, Object, ParamSpec, Type, TypeFlags, TypeInfo};
77

88
// rustdoc-stripper-ignore-next
@@ -69,17 +69,15 @@ pub unsafe trait ObjectInterfaceType {
6969

7070
/// The central trait for defining a `GObject` interface.
7171
///
72-
/// Links together the type name, and the interface struct for type registration and allows hooking
73-
/// into various steps of the type registration and initialization.
74-
///
75-
/// This must only be implemented on `#[repr(C)]` structs and have `gobject_ffi::GTypeInterface` as
76-
/// the first field.
72+
/// Links together the type name, the empty instance and class structs for type
73+
/// registration and allows hooking into various steps of the type registration
74+
/// and initialization.
7775
///
7876
/// See [`register_interface`] for registering an implementation of this trait
7977
/// with the type system.
8078
///
8179
/// [`register_interface`]: fn.register_interface.html
82-
pub unsafe trait ObjectInterface: ObjectInterfaceType + Sized + 'static {
80+
pub trait ObjectInterface: ObjectInterfaceType + Sized + 'static {
8381
/// `GObject` type name.
8482
///
8583
/// This must be unique in the whole process.
@@ -91,6 +89,10 @@ pub unsafe trait ObjectInterface: ObjectInterfaceType + Sized + 'static {
9189
/// in case of interfaces.
9290
type Prerequisites: PrerequisiteList;
9391

92+
// rustdoc-stripper-ignore-next
93+
/// The C class struct.
94+
type Interface: InterfaceStruct<Type = Self>;
95+
9496
/// Additional type initialization.
9597
///
9698
/// This is called right after the type was registered and allows
@@ -107,7 +109,7 @@ pub unsafe trait ObjectInterface: ObjectInterfaceType + Sized + 'static {
107109
/// and for setting default implementations of interface functions.
108110
///
109111
/// Optional
110-
fn interface_init(&mut self) {}
112+
fn interface_init(_klass: &mut Self::Interface) {}
111113

112114
/// Properties installed for this interface.
113115
///
@@ -155,12 +157,12 @@ unsafe extern "C" fn interface_init<T: ObjectInterface>(
155157
klass: ffi::gpointer,
156158
_klass_data: ffi::gpointer,
157159
) {
158-
let iface = &mut *(klass as *mut T);
160+
let iface = &mut *(klass as *mut T::Interface);
159161

160162
let pspecs = <T as ObjectInterface>::properties();
161163
for pspec in pspecs {
162164
gobject_ffi::g_object_interface_install_property(
163-
iface as *mut T as *mut _,
165+
iface as *mut T::Interface as *mut _,
164166
pspec.to_glib_none().0,
165167
);
166168
}
@@ -171,10 +173,10 @@ unsafe extern "C" fn interface_init<T: ObjectInterface>(
171173
signal.register(type_);
172174
}
173175

174-
iface.interface_init();
176+
T::interface_init(iface);
175177
}
176178

177-
/// Register a `glib::Type` ID for `T`.
179+
/// Register a `glib::Type` ID for `T::Class`.
178180
///
179181
/// This must be called only once and will panic on a second call.
180182
///
@@ -195,7 +197,7 @@ pub fn register_interface<T: ObjectInterface>() -> Type {
195197
let type_ = gobject_ffi::g_type_register_static_simple(
196198
Type::INTERFACE.into_glib(),
197199
type_name.as_ptr(),
198-
mem::size_of::<T>() as u32,
200+
mem::size_of::<T::Interface>() as u32,
199201
Some(interface_init::<T>),
200202
0,
201203
None,
@@ -216,7 +218,7 @@ pub fn register_interface<T: ObjectInterface>() -> Type {
216218
}
217219
}
218220

219-
/// Registers a `glib::Type` ID for `T` as a dynamic type.
221+
/// Registers a `glib::Type` ID for `T::Class` as a dynamic type.
220222
///
221223
/// An object interface must be explicitly registered as a dynamic type when
222224
/// the system loads the implementation by calling [`TypePluginImpl::use_`] or
@@ -243,7 +245,7 @@ pub fn register_dynamic_interface<P: DynamicObjectRegisterExt, T: ObjectInterfac
243245
gobject_ffi::g_type_from_name(type_name.as_ptr()) != gobject_ffi::G_TYPE_INVALID;
244246

245247
let type_info = TypeInfo(gobject_ffi::GTypeInfo {
246-
class_size: mem::size_of::<T>() as u16,
248+
class_size: mem::size_of::<T::Interface>() as u16,
247249
class_init: Some(interface_init::<T>),
248250
..TypeInfo::default().0
249251
});

glib/src/subclass/mod.rs

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -450,9 +450,9 @@ pub mod prelude {
450450
type_module::{TypeModuleImpl, TypeModuleImplExt},
451451
type_plugin::{TypePluginImpl, TypePluginImplExt, TypePluginRegisterImpl},
452452
types::{
453-
ClassStruct, InstanceStruct, InstanceStructExt, IsImplementable, IsSubclassable,
454-
IsSubclassableExt, ObjectSubclass, ObjectSubclassExt, ObjectSubclassIsExt,
455-
ObjectSubclassType,
453+
ClassStruct, InstanceStruct, InstanceStructExt, InterfaceStruct, IsImplementable,
454+
IsSubclassable, IsSubclassableExt, ObjectSubclass, ObjectSubclassExt,
455+
ObjectSubclassIsExt, ObjectSubclassType,
456456
},
457457
};
458458
}

glib/src/subclass/object.rs

Lines changed: 9 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -460,9 +460,16 @@ mod test {
460460
parent: gobject_ffi::GTypeInterface,
461461
}
462462

463+
unsafe impl InterfaceStruct for DummyInterface {
464+
type Type = Dummy;
465+
}
466+
467+
pub enum Dummy {}
468+
463469
#[glib::object_interface]
464-
unsafe impl ObjectInterface for DummyInterface {
470+
impl ObjectInterface for Dummy {
465471
const NAME: &'static str = "Dummy";
472+
type Interface = DummyInterface;
466473
}
467474
}
468475

@@ -475,7 +482,7 @@ mod test {
475482
}
476483

477484
wrapper! {
478-
pub struct Dummy(ObjectInterface<imp::DummyInterface>);
485+
pub struct Dummy(ObjectInterface<imp::Dummy>);
479486
}
480487

481488
unsafe impl<T: ObjectSubclass> IsImplementable<T> for Dummy {}

glib/src/subclass/types.rs

Lines changed: 23 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -5,7 +5,7 @@
55
66
use std::{any::Any, collections::BTreeMap, marker, mem, ptr};
77

8-
use super::SignalId;
8+
use super::{interface::ObjectInterface, SignalId};
99
use crate::{
1010
object::{IsClass, IsInterface, ObjectSubclassIs, ParentClassIs},
1111
prelude::*,
@@ -280,11 +280,29 @@ impl<U: IsClass + ParentClassIs> IsSubclassableExt for U {
280280
}
281281

282282
// rustdoc-stripper-ignore-next
283-
/// Trait for implementable interfaces.
284-
pub unsafe trait IsImplementable<T: ObjectSubclass>: IsInterface
283+
/// Trait implemented by structs that implement a `GTypeInterface` C class struct.
284+
///
285+
/// This must only be implemented on `#[repr(C)]` structs and have an interface
286+
/// that inherits from `gobject_ffi::GTypeInterface` as the first field.
287+
pub unsafe trait InterfaceStruct: Sized + 'static
285288
where
286-
<Self as ObjectType>::GlibClassType: Copy,
289+
Self: Copy,
287290
{
291+
// rustdoc-stripper-ignore-next
292+
/// Corresponding object interface type for this class struct.
293+
type Type: ObjectInterface;
294+
295+
// rustdoc-stripper-ignore-next
296+
/// Set up default implementations for interface vfuncs.
297+
///
298+
/// This is automatically called during type initialization.
299+
#[inline]
300+
fn interface_init(&mut self) {}
301+
}
302+
303+
// rustdoc-stripper-ignore-next
304+
/// Trait for implementable interfaces.
305+
pub unsafe trait IsImplementable<T: ObjectSubclass>: IsInterface {
288306
// rustdoc-stripper-ignore-next
289307
/// Override the virtual methods of this interface for the given subclass and do other
290308
/// interface initialization.
@@ -631,7 +649,7 @@ pub trait ObjectSubclass: ObjectSubclassType + Sized + 'static {
631649
// rustdoc-stripper-ignore-next
632650
/// The C class struct.
633651
///
634-
/// See [`basic::ClassStruct`] for an basic instance struct that should be
652+
/// See [`basic::ClassStruct`] for an basic class struct that should be
635653
/// used in most cases.
636654
///
637655
/// [`basic::ClassStruct`]: ../basic/struct.ClassStruct.html

glib/src/wrapper.rs

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -436,8 +436,7 @@ macro_rules! wrapper {
436436
$visibility:vis struct $name:ident $(<$($generic:ident $(: $bound:tt $(+ $bound2:tt)*)?),+>)? (ObjectInterface<$iface_name:ty>) $(@requires $($requires:path),+)?;
437437
) => {
438438
$crate::glib_object_wrapper!(
439-
@interface [$($attr)*] $visibility $name $(<$($generic $(: $bound $(+ $bound2)*)?),+>)?, *mut std::os::raw::c_void, std::os::raw::c_void,
440-
@ffi_class $iface_name,
439+
@object_interface [$($attr)*] $visibility $name $(<$($generic $(: $bound $(+ $bound2)*)?),+>)?, $iface_name,
441440
@type_ $crate::translate::IntoGlib::into_glib(<$iface_name as $crate::subclass::interface::ObjectInterfaceType>::type_()),
442441
@requires [$( $($requires),+ )?]
443442
);

0 commit comments

Comments
 (0)