如何使用一个以引用为回调的 Rust 异步函数?

14

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
1个回答

3

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

此外,你可以通过返回 `impl` 特质来避免使用 `Box`:
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


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