如何创建一个Rust回调函数以传递给FFI函数?

13

这就是C API的样子

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

rust-bindgen已经为我生成了这个

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,
        ) -> (),
    >,
)

我该如何创建一个Rust回调函数,以便将其传递给上述Rust绑定中的on_connect参数?

1个回答

13

Rust 编程语言第一版有一章关于 FFI,名为 "从 C 代码回调 Rust 函数"

其中的示例代码如下:

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
    }
}

针对您的具体情况,您已经知道您需要的具体函数类型:

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

然后像这样使用它

mosquitto_connect_callback_set(mosq, Some(mycallback));

好的。这可能会造成一些混淆。但是,通过回调函数,我指的是“作为参数传递给其他函数的函数”。 - tez
你好,@Shepmaster,有一个跟进的问题:对于类型为*mut ::libc::c_voidarg2,如果我需要在此处传递 Rust 结构体作为参数,该怎么做呢? Rust 会引发类型不匹配错误。谢谢! - xxks-kkk
我在想如果我没有回调函数要传入怎么办。在C语言中,我可以传入NULL,但在Rust中,我需要创建一个什么都不做的虚假函数吗? - xxks-kkk
@zack 那将是 Option<fn(...) -> ...> - Shepmaster
@tez,我也遇到了同样的问题。这是你审查的链接https://stackoverflow.com/questions/72066899/rust-libloading-callback-function-to-receive-response-from-c-lib - Senthil Mg
显示剩余4条评论

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接