Closure C callback
⚓ Rust 📅 2026-02-07 👤 surdeus 👁️ 2Hello,
I am desperately trying to set the callback of the glib g_dbus_connection_signal_subscribe function. I tried several codes, but I always get a crash.
I wrote the following code:
let property_change_callback = |property_name: &str| { ... }
proxy.on_property_change(property_change_callback);
let g_main_loop = unsafe { glib_sys::gio::g_main_loop_new(std::ptr::null_mut(), 1) };
unsafe { glib_sys::gio::g_main_loop_run(g_main_loop) };
Here is the on_property_change function definition:
pub fn on_property_change<C>(&mut self, callback: C)
where
C: Fn(&str, &DBusValue) + 'static,
{
const MEMBER_NAME: &str = "PropertiesChanged";
let connection = unsafe { glib_sys::gio::g_dbus_proxy_get_connection(self.handle) };
let sender = std::ptr::null_mut::<glib_sys::gio::gchar>();
let member =
unsafe { std::ffi::CStr::from_ptr(MEMBER_NAME.as_ptr().cast::<std::ffi::c_char>()) };
let interface_name = std::ptr::null_mut::<std::ffi::c_char>();
let callback_box = Box::new(callback);
self.callback_list.push(callback_box);
let callback = self.callback_list.last_mut().unwrap() as *mut Box<dyn Fn(&str, &DBusValue)>;
let object_path = std::ffi::CString::new(self.object_path.as_str()).unwrap();
let flags = glib_sys::gio::GDBusSignalFlags_G_DBUS_SIGNAL_FLAGS_NONE;
let arg0 = std::ptr::null::<std::ffi::c_char>();
unsafe {
glib_sys::gio::g_dbus_connection_signal_subscribe(
connection,
sender,
interface_name,
member.as_ptr(),
object_path.as_ptr(),
arg0,
flags,
Some(Self::on_property_changed),
callback.cast::<std::ffi::c_void>(),
None,
);
}
self.callback_list is of type Vec<Box<dyn Fn(&str, &DBusValue) + 'static>>
The Self::on_property_change function definition is:
extern "C" fn on_property_changed(
_connection: *mut glib_sys::gio::GDBusConnection,
_sender_name: *const glib_sys::gio::gchar,
_object_path: *const glib_sys::gio::gchar,
_interface_name: *const glib_sys::gio::gchar,
_signal_name: *const glib_sys::gio::gchar,
parameters: *mut glib_sys::gio::GVariant,
user_data: glib_sys::gio::gpointer,
) {
let callback = unsafe { &mut *user_data.cast::<Box<fn(&str, &DBusValue)>>() };
let dbus_value = DBusValue::from_gvariant_raw_ptr(parameters);
if let Some(dbus_value) = dbus_value
&& let Ok(dbus_struct) = TryInto::<DBusStruct>::try_into(dbus_value)
&& let Ok(dbus_array) =
TryInto::<DBusArray>::try_into(dbus_struct.iter().nth(1).unwrap())
{
for property_changed in dbus_array.iter() {
if let Ok(property_changed) = TryInto::<DBusDictEntry>::try_into(property_changed)
&& let Ok((property_name, property_value)) =
TryInto::<(String, DBusValue)>::try_into(property_changed.clone())
{
callback(&property_name, &property_value);
}
}
}
}
I always get a crash at callback(&property_name, &property_value);. For the current code I get:
Signal: SIGSEGV (signal SIGSEGV: address not mapped to object (fault address: 0x1))
Signal: SIGSEGV (signal SIGSEGV: address not mapped to object (fault address: 0x1))
The callback can be called multiple times.
Thank you very much for any help.
5 posts - 2 participants
🏷️ Rust_feed