This project is a tool for calling C++ from Rust in a heavily automated, but safe, fashion.
The intention is that it has all the fluent safety from cxx whilst generating interfaces automatically from existing C++ headers using a variant of bindgen. Think of autocxx as glue which plugs bindgen into cxx.
It's intended that eventually this exposes a single procedural macro, something like this:
cpp
class Bob {
public:
Bob(std::string name);
...
void do_a_thing();
}
```rust use autocxx::include_cxx;
include_cxx!( Header("base/bob.h"), Allow("Bob"), )
let a = ffi::base::Bob::makeunique("hello".into()); a.doa_thing(); ```
The existing cxx facilities are used to allow safe ownership of C++ types from Rust; specifically things like std::unique_ptr
and std::string
- so the Rust code should not typically require use of unsafe code, unlike with normal bindgen
bindings.
The macro and code generator will both need to know the include path to be passed to bindgen. At the moment, this is passed in via an
environment variable, AUTOCXX_INC
. See the demo/build.rs
file for details.
It is effectively a three-stage procedural macro, which:
bindgen
to generate some bindings (with all the usual unsafe
, #[repr(C)]
etc.)cxx::bridge
.cxx::bridge
to convert them to Rust code.The same code can be passed through tools that generate .cc and .h bindings too:
bindgen
to generate some bindings (with all the usual unsafe
, #[repr(C)]
etc.) - in exactly the same way as above.cxx::bridge
- in the same way as above.cxx
to generate .cc and .h filesThere is an example of this macro working within the demo
directory.
The project also contains test code which does this end-to-end, for all sorts of C++ types and constructs which we eventually would like to support. They nearly all fail :)
| Type | Status |
| ---- | ------ |
| Primitives (u8, etc.) | Works |
| Plain-old-data structs | Works |
| std::uniqueptr of POD | Works |
| std::uniqueptr of std::string | Works |
| std::uniqueptr of opaque types | - |
| Reference to POD | Works |
| Reference to std::string | Works |
| Classes | Works but produced warnings |
| Methods | Works |
| #defines | - |
| Constants | - |
| Enums | In progress; doesn't work yet |
| Structs containing UniquePtr | - |
| Structs containing strings | - |
| Constructors/makeunique | - |
| Destructors | Works via cxx UniquePtr
already |
This crate is not yet on crates.io.
At present, thirteen of the tests pass. The rest are ignored.
Because this uses bindgen
, and bindgen
may depend on the state of your system C++ headers, it is somewhat sensitive. The following known build problems exist:
bindgen
generates pub type __uint32_t = ::std::os::raw::c_uint;
which cxx
can't cope with. This is just a matter of munging bindgen
output more. This currently stops the demo building on my Linux box, and prevents all but one test passing.cargo
1.47 nightly: trybuild
is unable to pull in dependencies from git repositories because it's in offline mode. Running cargo update
first seems to solve this.This runs bindgen
within a procedural macro. There are limited opportunities to pass information into procedural macros, yet bindgen needs to know a lot about the build environment.
The plan is: * The Rust code itself will specify the include file(s) and allowlist by passing them into the macro. This is the sort of thing that developers within an existing C++ codebase would specify in C++ (give or take) so it makes sense for it to be specific in the Rust code. * However, all build settings (e.g. bindgen compiler configuration, include path etc.) will be passed into the macro by means of environment variables. The build environment should set these before building the code. (An alternative means will be provided to pass these into the C++ code generator tools.)
demo
- a demo exampleengine
- all the core code. Currently a Rust library, but we wouldn't want to support
these APIs for external users, so maybe it needs to be a directory of code symlinked
into all the other sub-crates. All the following three sub-crates are thin wrappers
for part of this engine. This also contains the test code.gen/build
- a library to be used from build.rs
scripts to generate .cc and .h
files from an include_cxx
section.gen/cmd
- a command-line tool which does the same. Except this isn't written yet.src
(outermost project)- the procedural macro include_cxx
as described above.The plan is (roughly) to work through the above list of features. Some are going to be very hard, e.g. strings embedded in structs, and it's not at all clear that a plan will present itself. Until we are much further, I don't advise using this for anything in production.
David Tolnay did much of the hard work here, by inventing the underlying cxx crate, and in fact nearly all of the parsing infrastructure on which this crate depends.
This is not an officially supported Google product.
Licensed under either of Apache License, Version 2.0 or MIT license at your option.