{"id":13648568,"url":"https://github.com/pcwalton/cxx-async","last_synced_at":"2025-05-15T15:03:32.832Z","repository":{"id":41401072,"uuid":"409809776","full_name":"pcwalton/cxx-async","owner":"pcwalton","description":"Simple interoperability between C++ coroutines and asynchronous Rust","archived":false,"fork":false,"pushed_at":"2024-11-19T16:34:04.000Z","size":230,"stargazers_count":245,"open_issues_count":7,"forks_count":14,"subscribers_count":8,"default_branch":"main","last_synced_at":"2025-03-31T20:05:36.405Z","etag":null,"topics":[],"latest_commit_sha":null,"homepage":"","language":"Rust","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"apache-2.0","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/pcwalton.png","metadata":{"files":{"readme":"README.md","changelog":null,"contributing":null,"funding":null,"license":"LICENSE-APACHE","code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null,"governance":null,"roadmap":null,"authors":null,"dei":null,"publiccode":null,"codemeta":null}},"created_at":"2021-09-24T02:43:57.000Z","updated_at":"2025-03-31T13:03:53.000Z","dependencies_parsed_at":"2024-11-09T18:00:38.821Z","dependency_job_id":"20245a20-6180-4ef9-94bf-162c95bc4bd8","html_url":"https://github.com/pcwalton/cxx-async","commit_stats":{"total_commits":129,"total_committers":3,"mean_commits":43.0,"dds":"0.023255813953488413","last_synced_commit":"043150a4a7c23a810845dd52e0439df1301491dd"},"previous_names":[],"tags_count":1,"template":false,"template_full_name":null,"repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/pcwalton%2Fcxx-async","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/pcwalton%2Fcxx-async/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/pcwalton%2Fcxx-async/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/pcwalton%2Fcxx-async/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/pcwalton","download_url":"https://codeload.github.com/pcwalton/cxx-async/tar.gz/refs/heads/main","host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":247730068,"owners_count":20986404,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2022-07-04T15:15:14.044Z","host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":[],"created_at":"2024-08-02T01:04:21.431Z","updated_at":"2025-04-07T21:08:50.169Z","avatar_url":"https://github.com/pcwalton.png","language":"Rust","funding_links":[],"categories":["Rust"],"sub_categories":[],"readme":"# `cxx-async`\n\n## Overview\n\n`cxx-async` is a Rust crate that extends the [`cxx`](http://cxx.rs/) library to provide\ninteroperability between asynchronous Rust code using `async`/`await` and [C++20 coroutines] using\n`co_await`. If your C++ code is asynchronous, `cxx-async` can provide a more convenient, and\npotentially more efficient, alternative to callbacks. You can freely convert between C++ coroutines\nand Rust futures and/or streams and await one from the other.\n\nIt's important to emphasize what `cxx-async` isn't: it isn't a C++ binding to Tokio or any other\nRust I/O library. Nor is it a Rust binding to `boost::asio` or similar. Such bindings could in\nprinciple be layered on top of `cxx-async` if desired, but this crate doesn't provide them out of\nthe box. (Note that this is a tricky problem even in theory, since Rust async I/O code is generally\ntightly coupled to a single library such as Tokio, in much the same way C++ async I/O code tends to\nbe tightly coupled to libraries like `boost::asio`.) If you're writing server code, you can still\nuse `cxx-async`, but you will need to ensure that both the Rust and C++ sides run separate I/O\nexecutors.\n\n`cxx-async` aims for compatibility with popular C++ coroutine support libraries. Right now, both\nthe lightweight [`cppcoro`](https://github.com/lewissbaker/cppcoro) and the more comprehensive\n[Folly](https://github.com/facebook/folly/) are supported. Pull requests are welcome to support\nothers.\n\n## Quick tutorial\n\nTo use `cxx-async`, first start by adding `cxx` to your project. Then add the following to your\n`Cargo.toml`:\n\n```toml\n[dependencies]\ncxx-async = \"0.1\"\n```\n\nNow, inside your `#[cxx::bridge]` module, declare a future type and some methods like so:\n\n```rust\n#[cxx::bridge]\nmod ffi {\n    // Declare type aliases for each of the future types you wish to use here. Then declare\n    // async C++ methods that you wish Rust to call. Make sure they return one of the future\n    // types you declared.\n    unsafe extern \"C++\" {\n        type RustFutureString = crate::RustFutureString;\n\n        fn hello_from_cpp() -\u003e RustFutureString;\n    }\n\n    // Async Rust methods that you wish C++ to call go here. Again, make sure they return one of the\n    // boxed future types you declared above.\n    extern \"Rust\" {\n        fn hello_from_rust() -\u003e Box\u003cRustFutureString\u003e;\n    }\n}\n```\n\nAfter the `#[cxx::bridge]` block, define the future types using the `#[cxx_async::bridge]`\nattribute:\n\n```rust\n// The inner type is the Rust type that this future yields.\n#[cxx_async::bridge]\nunsafe impl Future for RustFutureString {\n    type Output = String;\n}\n```\n\nNow, in your C++ file, make sure to `#include` the right headers:\n\n```cpp\n#include \"rust/cxx.h\"\n#include \"rust/cxx_async.h\"\n#include \"rust/cxx_async_cppcoro.h\"  // Or cxx_async_folly.h, as appropriate.\n```\n\nAnd add a call to the `CXXASYNC_DEFINE_FUTURE` macro to define the C++ side of the future:\n\n```cpp\n// The first argument is the C++ type that the future yields, and the second argument is the\n// fully-qualified name of the future, with `::` namespace separators replaced with commas. (For\n// instance, if your future is named `mycompany::myproject::RustFutureString`, you might write\n// `CXXASYNC_DEFINE_FUTURE(rust::String, mycompany, myproject, RustFutureString);`. The first\n// argument is the C++ type that `cxx` maps your Rust type to: in this case, `String` maps to\n// `rust::String`, so we supply `rust::String` here.\n//\n// This macro must be invoked at the top level, not in a namespace.\nCXXASYNC_DEFINE_FUTURE(rust::String, RustFutureString);\n```\n\nYou're all set! Now you can define asynchronous C++ code that Rust can call:\n\n```cpp\nRustFutureString hello_from_cpp() {\n    co_return std::string(\"Hello world!\");\n}\n```\n\nOn the Rust side:\n\n```rust\nasync fn call_cpp() -\u003e String {\n    // This returns a Result (with the error variant populated if C++ threw an exception), so you\n    // need to unwrap it:\n    ffi::hello_from_cpp().await.unwrap()\n}\n```\n\nAnd likewise, define some asynchronous Rust code that C++ can call:\n\n```rust\nuse cxx_async::CxxAsyncResult;\nfn hello_from_rust() -\u003e RustFutureString {\n    // You can instead use `fallible` if your async block returns a Result.\n    RustFutureString::infallible(async { \"Hello world!\".to_owned() })\n}\n```\n\nOver on the C++ side:\n\n```cpp\ncppcoro::task\u003crust::String\u003e call_rust() {\n    co_return hello_from_rust();\n}\n```\n\nThat's it! You should now be able to freely await futures on either side. An analogous procedure can\nbe followed to wrap C++ coroutines that yield values with `co_yield` in Rust streams.\n\n## Installation notes\n\nYou will need a C++ compiler that implements the coroutines TS, which generally coincides with\nsupport for C++20. Some C++ compilers (e.g. Apple clang 13.0.0) that implement the coroutines TS\ncrash when compiling Folly. It's also recommended to use `libc++` instead of `libstdc++`, as the\nformer has more complete support for coroutines.\n\n### Folly installation\n\nUsage of `cxx-async` with Folly requires that Folly have been built with coroutine support. Many\ndistributions of Folly (e.g.  the one in Homebrew) don't have coroutine support enabled; a common\nsymptom of this is a linker error mentioning a missing symbol\n`folly::resumeCoroutineWithNewAsyncStackRoot`.\n\nTo build Folly with coroutine support on macOS, try:\n\n```sh\n$ git clone https://github.com/facebook/folly.git\n$ cd folly\n$ ./build.sh --install-dir=/usr/local --extra-cmake-defines \\\n    '{\"CXX_STD\": \"c++20\", \"CMAKE_CXX_FLAGS\": \"-fcoroutines-ts\"}'\n```\n\nNote that, depending on how your permissions are set up, you might get an error like `Permission denied: '/usr/local/.built-by-getdeps'`; this is harmless.\n\n## Code of conduct\n\n`cxx-async` follows the same Code of Conduct as Rust itself. Reports can be made to the crate\nauthors.\n\n## License\n\nLicensed under either of Apache License, Version 2.0 or MIT license at your option.\n\nUnless you explicitly state otherwise, any contribution intentionally submitted for inclusion in\nthis project by you, as defined in the Apache-2.0 license, shall be dual licensed as above, without\nany additional terms or conditions.\n\n[C++20 coroutines]: https://en.cppreference.com/w/cpp/language/coroutines\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fpcwalton%2Fcxx-async","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fpcwalton%2Fcxx-async","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fpcwalton%2Fcxx-async/lists"}