{{#title Async functions — Rust ♡ C++}}
# Async functions
Direct FFI of async functions is absolutely in scope for CXX (on C++20 and up)
but is not implemented yet in the current release. We are aiming for an
implementation that is as easy as:
```rust,noplayground
#[cxx::bridge]
mod ffi {
unsafe extern "C++" {
async fn doThing(arg: Arg) -> Ret;
}
}
```
```cpp
rust::Future<Ret> doThing(Arg arg) {
auto v1 = co_await f();
auto v2 = co_await g(arg);
co_return v1 + v2;
}
```
## Workaround
For now the recommended approach is to handle the return codepath over a oneshot
channel (such as [`futures::channel::oneshot`]) represented in an opaque Rust
type on the FFI.
[`futures::channel::oneshot`]: https://docs.rs/futures/0.3.8/futures/channel/oneshot/index.html
```rust,noplayground
// bridge.rs
use futures::channel::oneshot;
#[cxx::bridge]
mod ffi {
extern "Rust" {
type DoThingContext;
}
unsafe extern "C++" {
include!("path/to/bridge_shim.h");
fn shim_doThing(
arg: Arg,
done: fn(Box<DoThingContext>, ret: Ret),
ctx: Box<DoThingContext>,
);
}
}
struct DoThingContext(oneshot::Sender<Ret>);
pub async fn do_thing(arg: Arg) -> Ret {
let (tx, rx) = oneshot::channel();
let context = Box::new(DoThingContext(tx));
ffi::shim_doThing(
arg,
|context, ret| { let _ = context.0.send(ret); },
context,
);
rx.await.unwrap()
}
```
```cpp
// bridge_shim.cc
#include "path/to/bridge.rs.h"
#include "rust/cxx.h"
void shim_doThing(
Arg arg,
rust::Fn<void(rust::Box<DoThingContext> ctx, Ret ret)> done,
rust::Box<DoThingContext> ctx) noexcept {
doThing(arg)
.then([done, ctx(std::move(ctx))](auto &&res) mutable {
(*done)(std::move(ctx), std::move(res));
});
}
```