Skip to content

Commit 83af810

Browse files
committed
examples: don't expose C API
1 parent e524d41 commit 83af810

File tree

8 files changed

+99
-156
lines changed

8 files changed

+99
-156
lines changed

examples/virtual_methods/base_button/imp.rs

Lines changed: 17 additions & 29 deletions
Original file line numberDiff line numberDiff line change
@@ -1,26 +1,25 @@
11
use super::BaseButtonExt;
22
use gtk::{
33
gio,
4-
glib::{self, translate::from_glib_borrow, Error},
4+
glib::{self, Error},
55
prelude::*,
66
subclass::prelude::*,
77
};
88
use std::{future::Future, pin::Pin};
99

10-
pub type BaseButtonInstance = <BaseButton as super::ObjectSubclass>::Instance;
10+
pub type BaseButtonInstance = super::BaseButton;
1111
pub type PinnedFuture = Pin<Box<dyn Future<Output = Result<(), Error>> + 'static>>;
1212

1313
/// GObject glue code for our BaseButtonClass which holds the function pointers to our virtual functions.
1414
#[repr(C)]
1515
pub struct BaseButtonClass {
1616
pub parent_class: gtk::ffi::GtkButtonClass,
17-
pub sync_method:
18-
Option<unsafe extern "C" fn(*mut BaseButtonInstance, extra_text: *mut Option<String>)>,
19-
pub async_method: Option<unsafe extern "C" fn(*mut BaseButtonInstance) -> PinnedFuture>,
17+
pub sync_method: Option<unsafe fn(&BaseButtonInstance, extra_text: Option<String>)>,
18+
pub async_method: Option<unsafe fn(&BaseButtonInstance) -> PinnedFuture>,
2019
}
2120

2221
unsafe impl ClassStruct for BaseButtonClass {
23-
type Type = super::imp::BaseButton;
22+
type Type = BaseButton;
2423
}
2524

2625
impl std::ops::Deref for BaseButtonClass {
@@ -38,42 +37,31 @@ impl std::ops::DerefMut for BaseButtonClass {
3837
}
3938

4039
#[derive(Debug, Default)]
41-
pub struct BaseButton {}
40+
pub struct BaseButton;
4241

4342
// Virtual method default implementation trampolines
44-
unsafe extern "C" fn sync_method_default_trampoline(
45-
this: *mut BaseButtonInstance,
46-
extra_text: *mut Option<String>,
47-
) {
48-
let imp = (*this).impl_();
49-
imp.sync_method(&from_glib_borrow(this), Box::from_raw(extra_text))
43+
unsafe fn sync_method_default_trampoline(this: &BaseButtonInstance, extra_text: Option<String>) {
44+
BaseButton::from_instance(this).sync_method(this, extra_text)
5045
}
5146

52-
unsafe extern "C" fn async_method_default_trampoline(
53-
this: *mut BaseButtonInstance,
54-
) -> PinnedFuture {
55-
let imp = (*this).impl_();
56-
imp.async_method(&from_glib_borrow(this))
47+
unsafe fn async_method_default_trampoline(this: &BaseButtonInstance) -> PinnedFuture {
48+
BaseButton::from_instance(this).async_method(this)
5749
}
5850

59-
pub unsafe extern "C" fn base_button_sync_method(
60-
this: *mut BaseButtonInstance,
61-
extra_text: *mut Option<String>,
62-
) {
63-
let klass = glib::subclass::types::InstanceStruct::class(&*this);
64-
51+
pub unsafe fn base_button_sync_method(this: &BaseButtonInstance, extra_text: Option<String>) {
52+
let klass = &*(this.class() as *const _ as *const BaseButtonClass);
6553
(klass.sync_method.unwrap())(this, extra_text)
6654
}
6755

68-
pub unsafe extern "C" fn base_button_async_method(this: *mut BaseButtonInstance) -> PinnedFuture {
69-
let klass = glib::subclass::types::InstanceStruct::class(&*this);
56+
pub unsafe fn base_button_async_method(this: &BaseButtonInstance) -> PinnedFuture {
57+
let klass = &*(this.class() as *const _ as *const BaseButtonClass);
7058
klass.async_method.unwrap()(this)
7159
}
7260

7361
/// Default implementations of our sync_method and async_method.
7462
impl BaseButton {
75-
fn sync_method(&self, obj: &super::BaseButton, extra_text: Box<Option<String>>) {
76-
if let Some(text) = *extra_text {
63+
fn sync_method(&self, obj: &super::BaseButton, extra_text: Option<String>) {
64+
if let Some(text) = extra_text {
7765
obj.set_label(&format!("BaseButton sync: {}", text));
7866
} else {
7967
obj.set_label("BaseButton sync");
@@ -107,7 +95,7 @@ impl ObjectSubclass for BaseButton {
10795
impl ObjectImpl for BaseButton {
10896
fn constructed(&self, obj: &Self::Type) {
10997
// For demo purposes, call the sync_method during construction to set the button label
110-
obj.sync_method(Box::new(Some(String::from("Sync extra text"))));
98+
obj.sync_method(Some(String::from("Sync extra text")));
11199
}
112100
}
113101

examples/virtual_methods/base_button/mod.rs

Lines changed: 41 additions & 29 deletions
Original file line numberDiff line numberDiff line change
@@ -2,56 +2,72 @@
22
mod imp;
33

44
pub use self::imp::PinnedFuture;
5-
use gtk::glib::{
6-
self,
5+
use gtk::{
6+
glib::{self, subclass::prelude::*},
7+
prelude::*,
78
subclass::prelude::*,
8-
translate::{from_glib_borrow, ToGlibPtr},
99
};
10-
use gtk::{prelude::*, subclass::prelude::*};
1110

1211
glib::wrapper! {
1312
pub struct BaseButton(ObjectSubclass<imp::BaseButton>)
1413
@extends gtk::Widget, gtk::Button;
1514
}
1615

16+
impl BaseButton {
17+
pub fn new() -> Self {
18+
glib::Object::new(&[]).expect("Failed to create BaseButton")
19+
}
20+
}
21+
22+
impl Default for BaseButton {
23+
fn default() -> Self {
24+
Self::new()
25+
}
26+
}
27+
1728
/// Public trait that implements our functions for everything that derives from BaseButton
1829
pub trait BaseButtonExt {
19-
fn sync_method(&self, extra_text: Box<Option<String>>);
30+
fn sync_method(&self, extra_text: Option<String>);
2031
fn async_method(&self) -> PinnedFuture;
2132
}
2233

2334
/// We call into imp::BaseButton_$method_name for each function. These will retrieve the
2435
/// correct class (the base class for the BaseButton or the derived class for DerivedButton)
2536
/// and call the correct implementation of the function.
2637
impl<O: IsA<BaseButton>> BaseButtonExt for O {
27-
fn sync_method(&self, extra_text: Box<Option<String>>) {
28-
unsafe {
29-
imp::base_button_sync_method(self.as_ref().to_glib_none().0, Box::into_raw(extra_text))
30-
}
38+
fn sync_method(&self, extra_text: Option<String>) {
39+
unsafe { imp::base_button_sync_method(self.upcast_ref::<BaseButton>(), extra_text) }
3140
}
3241

3342
fn async_method(&self) -> PinnedFuture {
34-
unsafe { imp::base_button_async_method(self.as_ref().to_glib_none().0) }
43+
unsafe { imp::base_button_async_method(self.upcast_ref::<BaseButton>()) }
3544
}
3645
}
3746

3847
/// The BaseButtonImpl that each derived private struct has to implement. See derived_button/imp.rs for how
3948
/// to override functions.
4049
pub trait BaseButtonImpl: ButtonImpl + ObjectImpl + 'static {
41-
fn sync_method(&self, obj: &BaseButton, extra_text: Box<Option<String>>) {
50+
fn sync_method(&self, obj: &BaseButton, extra_text: Option<String>) {
4251
self.parent_sync_method(obj, extra_text)
4352
}
4453

4554
fn async_method(&self, obj: &BaseButton) -> PinnedFuture {
4655
self.parent_async_method(obj)
4756
}
57+
}
4858

49-
fn parent_sync_method(&self, obj: &BaseButton, extra_text: Box<Option<String>>) {
59+
pub trait BaseButtonImplExt: ObjectSubclass {
60+
fn parent_sync_method(&self, obj: &BaseButton, extra_text: Option<String>);
61+
fn parent_async_method(&self, obj: &BaseButton) -> PinnedFuture;
62+
}
63+
64+
impl<T: BaseButtonImpl> BaseButtonImplExt for T {
65+
fn parent_sync_method(&self, obj: &BaseButton, extra_text: Option<String>) {
5066
unsafe {
5167
let data = Self::type_data();
5268
let parent_class = data.as_ref().parent_class() as *mut imp::BaseButtonClass;
5369
if let Some(ref f) = (*parent_class).sync_method {
54-
f(obj.to_glib_none().0, Box::into_raw(extra_text))
70+
f(obj, extra_text)
5571
} else {
5672
unimplemented!()
5773
}
@@ -63,7 +79,7 @@ pub trait BaseButtonImpl: ButtonImpl + ObjectImpl + 'static {
6379
let data = Self::type_data();
6480
let parent_class = data.as_ref().parent_class() as *mut imp::BaseButtonClass;
6581
if let Some(ref f) = (*parent_class).async_method {
66-
f(obj.to_glib_none().0)
82+
f(obj)
6783
} else {
6884
unimplemented!()
6985
}
@@ -74,7 +90,7 @@ pub trait BaseButtonImpl: ButtonImpl + ObjectImpl + 'static {
7490
/// Make the BaseButton subclassable
7591
unsafe impl<T: BaseButtonImpl> IsSubclassable<T> for BaseButton {
7692
fn class_init(class: &mut glib::Class<Self>) {
77-
<gtk::Widget as IsSubclassable<T>>::class_init(class);
93+
<gtk::Button as IsSubclassable<T>>::class_init(class.upcast_ref_mut());
7894

7995
let klass = class.as_mut();
8096
klass.sync_method = Some(sync_method_trampoline::<T>);
@@ -86,25 +102,21 @@ unsafe impl<T: BaseButtonImpl> IsSubclassable<T> for BaseButton {
86102
}
87103
}
88104

89-
// Virtual method default implementation trampolines
90-
unsafe extern "C" fn sync_method_trampoline<T: ObjectSubclass>(
91-
this: *mut imp::BaseButtonInstance,
92-
extra_text: *mut Option<String>,
93-
) where
94-
T: BaseButtonImpl,
105+
// Virtual method implementation trampolines
106+
unsafe fn sync_method_trampoline<T>(this: &BaseButton, extra_text: Option<String>)
107+
where
108+
T: ObjectSubclass + BaseButtonImpl,
95109
{
96-
let instance = &*(this as *const T::Instance);
110+
let instance = &*(this as *const _ as *const T::Instance);
97111
let imp = instance.impl_();
98-
imp.sync_method(&from_glib_borrow(this), Box::from_raw(extra_text))
112+
imp.sync_method(this, extra_text)
99113
}
100114

101-
unsafe extern "C" fn async_method_trampoline<T: ObjectSubclass>(
102-
this: *mut imp::BaseButtonInstance,
103-
) -> PinnedFuture
115+
unsafe fn async_method_trampoline<T>(this: &BaseButton) -> PinnedFuture
104116
where
105-
T: BaseButtonImpl,
117+
T: ObjectSubclass + BaseButtonImpl,
106118
{
107-
let instance = &*(this as *const T::Instance);
119+
let instance = &*(this as *const _ as *const T::Instance);
108120
let imp = instance.impl_();
109-
imp.async_method(&from_glib_borrow(this))
121+
imp.async_method(this)
110122
}

examples/virtual_methods/derived_button/imp.rs

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -17,8 +17,8 @@ impl ButtonImpl for DerivedButton {}
1717

1818
/// Implement the base trait and override the functions
1919
impl BaseButtonImpl for DerivedButton {
20-
fn sync_method(&self, obj: &BaseButton, extra_text: Box<Option<String>>) {
21-
if let Some(text) = *extra_text {
20+
fn sync_method(&self, obj: &BaseButton, extra_text: Option<String>) {
21+
if let Some(text) = extra_text {
2222
obj.set_label(&format!("DerivedButton sync {}", text));
2323
} else {
2424
obj.set_label("DerivedButton sync");

examples/virtual_methods/derived_button/mod.rs

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -6,3 +6,15 @@ glib::wrapper! {
66
pub struct DerivedButton(ObjectSubclass<imp::DerivedButton>)
77
@extends gtk::Widget, gtk::Button, crate::base_button::BaseButton;
88
}
9+
10+
impl DerivedButton {
11+
pub fn new() -> Self {
12+
glib::Object::new(&[]).expect("Failed to create DerivedButton")
13+
}
14+
}
15+
16+
impl Default for DerivedButton {
17+
fn default() -> Self {
18+
Self::new()
19+
}
20+
}

examples/virtual_methods/main.rs

Lines changed: 27 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1,9 +1,11 @@
11
mod base_button;
22
mod derived_button;
3-
mod virtual_methods_window;
43

5-
use crate::virtual_methods_window::VirtualMethodsAppWindow;
6-
use gtk::prelude::*;
4+
use crate::base_button::BaseButtonExt;
5+
use gtk::{
6+
glib::{self, clone},
7+
prelude::*,
8+
};
79

810
fn main() {
911
let application = gtk::Application::new(
@@ -12,7 +14,28 @@ fn main() {
1214
);
1315

1416
application.connect_activate(|app| {
15-
let win = VirtualMethodsAppWindow::new(app);
17+
let win = gtk::ApplicationWindow::new(app);
18+
let boxed = gtk::Box::new(gtk::Orientation::Horizontal, 6);
19+
let base_button = base_button::BaseButton::new();
20+
let derived_button = derived_button::DerivedButton::new();
21+
22+
base_button.connect_clicked(|b| {
23+
let ctx = glib::MainContext::default();
24+
let b = b.clone();
25+
ctx.spawn_local(clone!(@weak b => async move {
26+
b.async_method().await.unwrap();
27+
}));
28+
});
29+
derived_button.connect_clicked(|b| {
30+
let ctx = glib::MainContext::default();
31+
ctx.spawn_local(clone!(@weak b => async move {
32+
b.async_method().await.unwrap();
33+
}));
34+
});
35+
36+
boxed.append(&base_button);
37+
boxed.append(&derived_button);
38+
win.set_child(Some(&boxed));
1639
win.show();
1740
});
1841

examples/virtual_methods/virtual_methods_window/imp.rs

Lines changed: 0 additions & 55 deletions
This file was deleted.

examples/virtual_methods/virtual_methods_window/mod.rs

Lines changed: 0 additions & 14 deletions
This file was deleted.

0 commit comments

Comments
 (0)