# rust-cpp: C++ snippets written inline inside Rust functions

> The cpp crate is a build tool and a macro that lets you write C++ directly in the body of a Rust function, and a second macro that exposes C++ classes to Rust with the usual traits implemented for you. The README is unusually candid about where it sits against the cxx bridge: less type checking, but no boilerplate file to maintain.

**mystor/rust-cpp** — Embed C++ directly inside your rust code!

- Repository: https://github.com/mystor/rust-cpp
- Stars: 859 · Forks: 48
- Language: Rust
- License: Apache-2.0
- Published: 2026-10-20 · Updated: 2026-10-20 · Language: en
- Canonical page: https://hysenlabs.com/projects/mystor-rust-cpp

## C++ inside the function body, with types spelled out

The cpp crate is described as a build tool and macro that enables you to write C++ code inline in your Rust code, and the example in the README is compact enough to read in one go:

```rust
let name = std::ffi::CString::new("World").unwrap();
let name_ptr = name.as_ptr();
let r = unsafe {
    cpp!([name_ptr as "const char *"] -> u32 as "int32_t" {
        std::cout << "Hello, " << name_ptr << std::endl;
        return 42;
    })
};
assert_eq!(r, 42)
```

Several things are happening in that snippet, and each of them is a design decision.

The C++ lives inside the macro invocation, in a block that is otherwise ordinary C++. The Rust values that the C++ needs are passed in through a bracket list, and each one is given an explicit C++ type with the as syntax, so name_ptr is passed as a const char pointer. The return type is declared in the same way, as a Rust u32 that the C++ side produces as an int32_t.

That explicit typing is the price of the approach, and it is also the mechanism. A macro can rewrite the C++ text before it reaches the compiler, and the way to do that safely enough to be useful is to require the types to be written down, so the generated code knows what to convert. The result is an expression that behaves like a Rust call, returning 42 and satisfying the assertion, and the whole thing sits inside an unsafe block because the boundary is, in the end, an unsafe one.

The crate is published as cpp on docs.rs, and the README points at the module level documentation there for usage information and the in-depth write-up.

## cpp_class! gives C++ types the traits Rust expects

The second macro handles the other half of the problem, which is getting a C++ type to behave like a Rust value rather than a bare pointer.

```rust
cpp_class!{
    #[derive(PartialEq)]
    unsafe struct MyClass as "std::unique_ptr<MyClass>"
}
```

The macro declares a Rust type that stands in for a C++ class, giving the C++ type name as a string. The Rust side is marked unsafe, which is the honest signal that constructing and using it crosses the boundary, and the derive attribute is placed inside the macro so the generated type can carry Rust's own derives.

The README explains the point in one sentence: the crate helps expose some C++ class to Rust by automatically implementing traits such as Drop, Clone, if the C++ type can be copied, and others. That single line covers most of what makes a foreign type painful to use from Rust. Without it, a C++ object that owns a resource leaks or double-frees, and a C++ type that is copyable still does not satisfy Clone in the eyes of the compiler. Generating those implementations from the macro means the ownership semantics of the C++ type are expressed once, in the type name, and the rest follows.

The example uses std::unique_ptr, which is the C++ idiom for exclusive ownership, and mapping it to a Rust struct with a generated Drop is exactly the case where the automatic implementations matter most.

Combined with the inline macro, the two cover the two things people reach for an FFI crate to do: make a small call, and own an object across the boundary.

## The comparison with the cxx bridge is the useful part of the README

The README has a section titled as a difference from the cxx crate, and it is the most informative paragraph in the repository because it states a trade-off instead of a feature.

The distinction is about where the C++ lives. This crate lets you write C++ code inline within your Rust functions, whereas with the cxx crate you have to write a bit of boilerplate to have calls to functions declared in a different .cpp file.

The README then explains when that matters. Having C++ code inline might be helpful when trying to call a C++ library that you want to make plenty of small calls to. It can otherwise be fastidious to write and maintain the boilerplate for many small functions in different places. That is the real trade: a handful of large calls is a better fit for a bridge with a proper type system, while dozens of small calls scattered through Rust code is where the boilerplate starts to cost you.

There is a second dimension. The cxx crate offers useful types such as CxxString that can also be used with this crate, so the two can be used together, and the cxx bridge does more type checking, which can avoid some classes of errors, while this crate can only check for equal size and alignment.

That last sentence is the boundary to hold on to. Size and alignment equality is a memory layout guarantee, not a semantic one, so a mismatch of meaning between the two sides passes the check. The inline convenience is bought with a weaker type contract, and a project that is happy to rely on the cxx bridge has no reason to move.

For a project already using cxx, this crate is an addition rather than a replacement, useful for the small calls that would otherwise each need a companion file.

## A workspace of four crates and a test crate

The Cargo.toml at the root shows a workspace rather than a single crate, and the members are the interesting part.

The version is 0.5.11, the edition is 2021, the rust-version is 1.71, and the licence is MIT OR Apache-2.0, which is the standard dual licence for a Rust crate even though the repository listing records the Apache-2.0 side. The workspace resolver is version 2, and the members are cpp, cpp_build, cpp_common, cpp_macros and test.

The decomposition follows the mechanics of the project. cpp is the crate users depend on, cpp_macros holds the procedural macro implementations that rewrite the inline C++ and expand the class declaration, cpp_build is the build-time component, cpp_common is the shared code, and test is a workspace member rather than a directory of loose tests, which usually means it is built and tested on its own as a crate.

The presence of a build component is the part that matters in practice. Inline C++ in a Rust function is not something rustc can compile on its own, so the crate has to arrange for the C++ snippet to reach a C++ compiler and the result to come back as an object file that the Rust code links against. That is a build-system job, and it is why the crate is described as a build tool as well as a macro, and why the Cargo.toml declares rust-version 1.71 rather than something older.

The repository carries the usual supporting files, a CHANGELOG.md, a rustfmt.toml, a .mailmap, and two shell scripts, bump_version.sh and publish_crates.sh, which are the release automation for a workspace where the version number has to move in several places at once.

The crate is published on docs.rs under the name cpp, and the README is explicit that the module level documentation there is where to look for usage information and the deeper explanation.

## The last push was on 2026-04-07, and that matters for a dependency

The maintenance picture is the thing to weigh before you take this as a dependency.

The last push to the repository was on 2026-04-07, which is more than six months ago, so this is not a project with a recent commit trail. There are no GitHub releases either, so the version history is the changelog and the crates.io releases rather than a tag list.

The version in the manifest is 0.5.11, and it is still below 1.0, which in Rust carries a specific meaning: the API is not considered stable, and the semver contract does not promise you anything across a minor version. For a crate whose whole purpose is a macro that rewrites source code, that matters more than it would for an ordinary library, because the macro's output is part of your build and a change in how it generates code can change what compiles.

None of this means the project is bad or unusable. The dual licence is permissive, the workspace is small and legible, the README is honest about the limitations, and the design decision it makes is defensible: the cxx bridge is the better answer for a large typed boundary, and this crate is the better answer for a wide scatter of small calls.

It does mean the risk sits with you. If you adopt it, pin an exact version, read the changelog between the version you pinned and the current one, and be ready to vendor the crate rather than track the branch. The build scripts, the changelog and the small workspace all make that easier than they would be in a larger project.

And because the macro sits inside an unsafe block that generates real C++ and links it into your binary, the same caution applies as to any foreign function interface code: the compiler will not check the semantics across the boundary, only the layout.

## Conclusion

Adopt rust-cpp when you are calling into a C++ library from Rust and the calls are small and numerous, since the inline form removes the separate .cpp file and the boilerplate that comes with it, and when you want the C++ types to carry Rust traits such as Drop and Clone. Do not adopt it when the boundary is large and typed, because the README says the cxx bridge does more type checking while this crate can only check for equal size and alignment, which is a weaker guarantee. Before you commit, read the crate documentation on docs.rs for the macro's rules, check the CHANGELOG for the version you pin, and confirm you are comfortable with the unsafe boundary, since the macro expands into an unsafe block.

## FAQ

### What does the rust-cpp crate do?

It is a build tool and macro that lets you write C++ code inline inside Rust functions, and it also provides a macro that exposes C++ classes to Rust by automatically implementing traits such as Drop and Clone. The crate is published as cpp on docs.rs and the workspace version is 0.5.11.

### How does rust-cpp compare with the cxx crate?

This crate writes C++ inline within Rust functions, while cxx needs boilerplate for functions declared in a separate .cpp file. The README says cxx does more type checking, which can avoid some classes of errors, while this crate can only check for equal size and alignment, and the two can be used together.

### How do I expose a C++ class to Rust with rust-cpp?

With the cpp_class macro, where you declare an unsafe Rust struct and give the C++ type name as a string, for example a struct aliased to std::unique_ptr<MyClass>. The macro automatically implements traits such as Drop, and Clone when the C++ type can be copied, and you can add Rust derives inside the macro.

### What are the requirements for building the rust-cpp crate?

The workspace declares edition 2021 and a minimum supported Rust version of 1.71, and it is a workspace of four crates plus a test crate, with a dedicated build crate, because inline C++ has to reach a C++ compiler and be linked into the Rust build.

### Is the rust-cpp crate still maintained?

The last push to the repository was on 2026-04-07, so there has been no recent commit activity, and the repository publishes no GitHub releases. The project version is 0.5.11, still below 1.0, so pin an exact version and read the changelog before upgrading.

## Sources

- [Issues](https://github.com/mystor/rust-cpp/issues)
- [License: Apache-2.0](https://github.com/mystor/rust-cpp/blob/master/LICENSE)
- [mystor/rust-cpp on GitHub](https://github.com/mystor/rust-cpp)
- [README](https://github.com/mystor/rust-cpp/blob/master/README.md)

---

Hysen Labs editorial analysis, written from the project's own repository and release notes. Cite the canonical page: https://hysenlabs.com/projects/mystor-rust-cpp
