I'm writing Rust wrappers for C bindings so that they look more Rusty. One such C function is this:
void mosquitto_connect_callback_set(
struct mosquitto * mosq,
void (*on_connect)(struct mosquitto *, void *, int)
)
I'm using the below technique to pass a Rust closure as the user data to above binding (void*
in the callback) so that the Rust closure will be called when the C callback is invoked.
// Registered callback is called when the broker sends a CONNACK message in response
// to a connection. Will be called even incase of failure. All your sub/pub stuff
// should ideally be done in this callback when connection is successful
pub fn onconnect_callback<F>(&self, callback: F)
where F: Fn(i32)
{
// Convert the rust closure into void* to be used as user_data. This will
// be passed to callback automatically by the library
let cb = &callback as *const _ as *mut libc::c_void;
unsafe {
// Set our closure as user data
bindings::mosquitto_user_data_set(self.mosquitto, cb);
// Register callback
bindings::mosquitto_connect_callback_set(self.mosquitto, Some(onconnect_wrapper::<F>));
}
// Registered callback. user data is our closure
unsafe extern "C" fn onconnect_wrapper<F>(mqtt: *mut bindings::Struct_mosquitto,
closure: *mut libc::c_void,
val: libc::c_int)
where F: Fn(i32)
{
let closure = closure as *mut F;
println!("rc = {:?}", val as i32);
(*closure)(val as i32);
}
}
But the problem is that user data is set using a function instead of directly passing it to the callback set function
// Set our closure as user data
bindings::mosquitto_user_data_set(self.mosquitto, cb);
I think the callback: F
closure passed to onconnect_callback
might get destroyed by the time the actual C callback is invoked. This might be the reason I'm getting garbage values when capturing a variable.
let i = 100;
client.onconnect_callback(|a: i32|{
println!("i = {:?}", i);
println!("@@@ On connect callback {}@@@", a)
});
match client.connect("localhost"){
Ok(_) => println!("Connection successful --> {:?}", client),
Err(n) => panic!("Connection error = {:?}", n)
}
OUTPUT:
i = 734146560
@@@ On connect callback 0@@@
How do I fix this without passing closure as reference?