13

This is how the C API looks

void mosquitto_connect_callback_set(struct mosquitto *mosq, void (*on_connect)(struct mosquitto *, void *, int));

rust-bindgen has generated this for me

pub fn mosquitto_connect_callback_set(
    mosq: *mut Struct_mosquitto,
    on_connect: ::std::option::Option<
        extern "C" fn(
            arg1: *mut Struct_mosquitto,
            arg2: *mut ::libc::c_void,
            arg3: ::libc::c_int,
        ) -> (),
    >,
)

How do I create a Rust callback function to pass to the on_connect parameter in the above Rust binding?

Shepmaster
  • 388,571
  • 95
  • 1,107
  • 1,366
tez
  • 4,990
  • 12
  • 47
  • 67

1 Answers1

13

The Rust Programming Language, first edition, has a section about FFI titled Callbacks from C code to Rust functions.

The example from there is

extern "C" fn callback(a: i32) {
    println!("I'm called from C with value {0}", a);
}

#[link(name = "extlib")]
extern "C" {
    fn register_callback(cb: extern "C" fn(i32)) -> i32;
    fn trigger_callback();
}

fn main() {
    unsafe {
        register_callback(callback);
        trigger_callback(); // Triggers the callback
    }
}

For your specific case, you already know the specific type of function you need:

extern "C" fn mycallback(
    arg1: *mut Struct_mosquitto,
    arg2: *mut ::libc::c_void,
    arg3: ::libc::c_int,
) -> () {
    println!("I'm in Rust!");
}

And then use it like

mosquitto_connect_callback_set(mosq, Some(mycallback));
Shepmaster
  • 388,571
  • 95
  • 1,107
  • 1,366
  • I'm not going to call rust function from C. In my rust code, I want to pass an argument to `on_connect` argument. – tez Jul 16 '15 at 20:28
  • @tez *"I'm not going to call rust function from C call"* — but you specifically asked *"How do I create a rust callback function?"*. That's what a callback is. Maybe you are just asking how to use the `mosquitto` API, not anything specific to Rust? – Shepmaster Jul 16 '15 at 20:31
  • Ok. That might have created some confusion. But, by callback function, I mean 'a function which is passed to other function as an argument' – tez Jul 16 '15 at 20:37
  • @tez that's *exactly* what both examples in the answer show. See the calls to `register_callback` and `mosquitto_connect_callback_set`. – Shepmaster Jul 16 '15 at 20:45
  • Sorry. My bad. I thought you were referring to 'how to call rust functions from C'. – tez Jul 16 '15 at 20:54
  • Hello @Shepmaster, a follow-up question: for `arg2` with type `*mut ::libc::c_void`, if I need to pass in a Rust struct as the argument here, how can I do this? Rust will raise the type mismatch error. Thanks! – xxks-kkk Sep 01 '18 at 18:09
  • I'm wondering what if I don't have a callback function to pass in. In C, I can pass in `NULL` but in Rust, do I need to create some fake function that does nothing? – xxks-kkk Sep 07 '18 at 02:14
  • @zack that would be `Option ...>` – Shepmaster Sep 10 '18 at 23:52
  • @tez , am also facing the same kind of issue. Here the link for your review https://stackoverflow.com/questions/72066899/rust-libloading-callback-function-to-receive-response-from-c-lib – Senthil Mg Apr 30 '22 at 09:54