Autocxx
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.
Intended eventual interface
It's intended that eventually this exposes a single procedural macro, something like this:
class Bob {
public:
Bob(std::string name);
...
void do_a_thing();
}
use autocxx::include_cxx;
include_cxx!(
Header("base/bob.h"),
Allow("Bob"),
)
let a = ffi::base::Bob::make_unique("hello".into());
a.do_a_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.
How it works
It is effectively a two-stage procedural macro, which:
- First, runs
bindgen
to generate some bindings suitable forcxx::bridge
- Second, runs
cxx::bridge
to convert them to Rust code.
The same code can be passed through tools that generate .cc and .h bindings too:
- First, runs
bindgen
to generate some bindings suitable forcxx::bridge
(in exactly the same way as above) - Second, runs the codegen code from
cxx
to generate .cc and .h files
Current state of affairs
There is an example of this macro working within the demo
directory. At the
moment, it will work with only the very simplest functions (ints and voids only)!
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 :)
Build environment
This crate is not yet on crates.io and currently depends on a hacked-up version of bindgen and a hacked-up version of cxx.
To try it out,
- Fetch the code using git.
cargo update
cargo test --all -- --test-threads=1
.
This will fetch a specific fork of bindgen (see the Cargo.toml for the repo and branch) and use that as the dependency. The same applies to cxx.
At present, many of the tests fail, and thus the test run fails overall. Individual tests can be run, and some pass.
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:
- It requires Rust nightly due to
#[proc_macro_span]
- Tests fail if they run in parallel, hence why you should use
cargo test --all -- --test-threads=1
. Looks perhaps likebindgen
has global state. - On Linux including any system header:
bindgen
generatespub type __uint32_t = ::std::os::raw::c_uint;
whichcxx
can't cope with. This is just a matter of mungingbindgen
more. This currently stops the demo building on my Linux box, and prevents all but one test passing. - On Linux using
cargo
1.47 nightly:trybuild
is unable to pull in dependencies from git repositories because it's in offline mode. Runningcargo update
first seems to solve this. - (Fixed, I think: On Linux: tests fail:
cc
can't link because it can't find__gxx_personality_v0
; resolved by adding another-lstdc++
argument at the end of therustc
linker line.)
Directory structure
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.macro
- the procedural macroinclude_cxx
as described above.gen/build
- a library to be used frombuild.rs
scripts to generate .cc and .h files from aninclude_cxx
section.gen/cmd
- a command-line tool which does the same. Except this isn't written yet.src
- currently, nothing.
Next steps
Plans:
- Upstream the
cxx
change if possible. - Fix a few of the annoying TODOs (the oddest one being in
demo/build.rs
) - Then, start working on the
bindgen
fork to add support for more C++ types and see how far we can get through the test suite.
License and usage notes
This is not an officially supported Google product.
Licensed under either of Apache License, Version 2.0 or MIT license at your option.