Rust闭包作为C绑定的回调,在捕获的变量中接收垃圾值

时间:2015-12-13 04:06:45

标签: closures rust ffi

我正在为C绑定编写Rust包装器,以便它们看起来更生锈。一个这样的C函数就是:

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

我正在使用以下技术将Rust闭包作为用户数据传递给上面的绑定(回调中的void*),以便在调用C回调时调用Rust闭包。

//  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);

    }
}

但问题是用户数据是使用函数设置的,而不是直接将其传递给回调集函数

// Set our closure as user data
bindings::mosquitto_user_data_set(self.mosquitto, cb);

我认为传递给callback: F的{​​{1}}闭包可能会在调用实际C回调时被销毁。这可能是我在捕获变量时获取垃圾值的原因。

onconnect_callback

输出:

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

如何在不传递闭包作为参考的情况下解决此问题?

The full code

0 个答案:

没有答案