87 lines
1.8 KiB
Markdown
87 lines
1.8 KiB
Markdown
{{#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,hidelines
|
|
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));
|
|
});
|
|
}
|
|
```
|