如何使用将引用作为回调的Rust异步fn?


10

async fn返回实现的匿名类型Future,因此,如果我们要将其用作回调,则需要将返回值转换为trait对象。

我试图编写一个函数来执行此操作,但是我遇到了一些终身问题。

async fn将返回所有参数的生存期,因此回调的签名也需要。如何将生存期添加到回调的返回值?

use futures::future::{Future, FutureExt, LocalBoxFuture};

type Context = ();
type AsyncCb = Box<dyn for<'r> FnOnce(&'r Context) -> LocalBoxFuture<'r, ()>>;

fn normalize_async_cb<Fut: Future<Output = ()>>(f: for<'r> fn(&'r Context) -> Fut) -> AsyncCb
//                                                    how to add 'r for Fut?  ^^^
{
    let cb = move |ctx: &Context| f(ctx).boxed_local();
    Box::new(cb)
}

为什么输入到normalize_async_cb函数指针?
Coder-256

另外,“回叫”是什么意思?您能否提供一个示例,说明在哪里需要这种类型的回调?
Coder-256

Answers:


1

Rust不支持更高种类的多态性,因此您需要在AsyncCb类型中添加一个生命周期参数:

use futures::future::{Future, FutureExt, LocalBoxFuture};

type Context = ();
type AsyncCb<'r> = Box<dyn FnOnce(&'r Context) -> LocalBoxFuture<'r, ()> + 'r>;

fn normalize_async_cb<'r, Fut: Future<Output = ()> + 'r>(f: fn(&'r Context) -> Fut) -> AsyncCb {
    let cb = move |ctx: &'r Context| f(ctx).boxed_local();
    Box::new(cb)
}

另外,您可以Box通过返回impltrait 来避免使用a :

fn normalize_async_cb<'r, Fut: Future<Output = ()> + 'r>(
    f: fn(&'r Context) -> Fut,
) -> impl FnOnce(&'r Context) -> LocalBoxFuture<'r, ()> {
    let cb = move |ctx: &'r Context| f(ctx).boxed_local();
    cb
}

(然后,呼叫者可以根据需要使用该Box::new(normalize_async_cb(…))类型AsyncCb。)

By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.