Skip to content
This repository was archived by the owner on Jun 8, 2021. It is now read-only.

Commit cd7c8e0

Browse files
authored
Merge pull request #433 from sdroege/single-boxed-signals
Update for signals using the concrete closure type instead of double-…
2 parents e5346be + a44661b commit cd7c8e0

File tree

2 files changed

+16
-18
lines changed

2 files changed

+16
-18
lines changed

src/object.rs

Lines changed: 7 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -1010,22 +1010,22 @@ impl<T: ObjectType> ObjectExt for T {
10101010
unsafe fn connect_notify_unsafe<'a, P: Into<Option<&'a str>>, F: Fn(&Self, &::ParamSpec)>(&self, name: P, f: F) -> SignalHandlerId {
10111011
use std::mem::transmute;
10121012

1013-
unsafe extern "C" fn notify_trampoline<P>(this: *mut gobject_ffi::GObject, param_spec: *mut gobject_ffi::GParamSpec, f: glib_ffi::gpointer)
1013+
unsafe extern "C" fn notify_trampoline<P, F: Fn(&P, &::ParamSpec)>(this: *mut gobject_ffi::GObject, param_spec: *mut gobject_ffi::GParamSpec, f: glib_ffi::gpointer)
10141014
where P: ObjectType {
1015-
let f: &&(Fn(&P, &::ParamSpec) + 'static) = transmute(f);
1015+
let f: &F = transmute(f);
10161016
f(&Object::from_glib_borrow(this).unsafe_cast(), &from_glib_borrow(param_spec))
10171017
}
10181018

10191019
let name = name.into();
10201020
let signal_name = if let Some(name) = name {
1021-
format!("notify::{}", name)
1021+
format!("notify::{}\0", name)
10221022
} else {
1023-
"notify".into()
1023+
"notify\0".into()
10241024
};
10251025

1026-
let f: Box<Box<Fn(&Self, &::ParamSpec)>> = Box::new(Box::new(f));
1027-
::signal::connect(self.as_object_ref().to_glib_none().0, &signal_name,
1028-
transmute(notify_trampoline::<Self> as usize), Box::into_raw(f) as *mut _)
1026+
let f: Box<F> = Box::new(f);
1027+
::signal::connect_raw(self.as_object_ref().to_glib_none().0, signal_name.as_ptr() as *const _,
1028+
Some(mem::transmute(notify_trampoline::<Self, F> as usize)), Box::into_raw(f))
10291029
}
10301030

10311031
fn notify<'a, N: Into<&'a str>>(&self, property_name: N) {

src/signal.rs

Lines changed: 9 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -7,9 +7,10 @@
77
use libc::{c_char, c_void, c_ulong};
88

99
use gobject_ffi::{self, GCallback};
10-
use ffi::gboolean;
10+
use ffi::{gboolean, gpointer};
1111
use object::ObjectType;
1212
use translate::{from_glib, FromGlib, ToGlib, ToGlibPtr};
13+
use std::mem;
1314

1415
/// The id of a signal that is returned by `connect`.
1516
#[derive(Debug, Eq, PartialEq)]
@@ -48,15 +49,12 @@ impl ToGlib for Inhibit {
4849
}
4950
}
5051

51-
pub unsafe fn connect(receiver: *mut gobject_ffi::GObject, signal_name: &str, trampoline: GCallback,
52-
closure: *mut Box<Fn() + 'static>) -> SignalHandlerId {
53-
connect_raw(receiver, signal_name.to_glib_none().0, trampoline, closure)
54-
}
55-
56-
pub unsafe fn connect_raw(receiver: *mut gobject_ffi::GObject, signal_name: *const c_char, trampoline: GCallback,
57-
closure: *mut Box<Fn() + 'static>) -> SignalHandlerId {
52+
pub unsafe fn connect_raw<F>(receiver: *mut gobject_ffi::GObject, signal_name: *const c_char, trampoline: GCallback,
53+
closure: *mut F) -> SignalHandlerId {
54+
assert_eq!(mem::size_of::<*mut F>(), mem::size_of::<gpointer>());
55+
assert!(trampoline.is_some());
5856
let handle = gobject_ffi::g_signal_connect_data(receiver, signal_name,
59-
trampoline, closure as *mut _, Some(destroy_closure), 0);
57+
trampoline, closure as *mut _, Some(destroy_closure::<F>), 0);
6058
assert!(handle > 0);
6159
from_glib(handle)
6260
}
@@ -86,7 +84,7 @@ pub fn signal_stop_emission_by_name<T: ObjectType>(instance: &T, signal_name: &s
8684
}
8785
}
8886

89-
unsafe extern "C" fn destroy_closure(ptr: *mut c_void, _: *mut gobject_ffi::GClosure) {
87+
unsafe extern "C" fn destroy_closure<F>(ptr: *mut c_void, _: *mut gobject_ffi::GClosure) {
9088
// destroy
91-
Box::<Box<Fn()>>::from_raw(ptr as *mut _);
89+
Box::<F>::from_raw(ptr as *mut _);
9290
}

0 commit comments

Comments
 (0)