Closure C callback

⚓ Rust    📅 2026-02-07    👤 surdeus    👁️ 2      

surdeus

Info

This post is auto-generated from RSS feed The Rust Programming Language Forum - Latest topics. Source: Closure C callback

Hello,

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

Read full topic

🏷️ Rust_feed