cxx 1.0.61

Safe interop between Rust and C++
Documentation
{{#title extern "C++" — Rust ♡ C++}}
# extern "C++"

```rust,noplayground
#[cxx::bridge]
mod ffi {
    extern "C++" {
        include!("path/to/header.h");
        include!("path/to/another.h");

        ...
    }
}
```

The `extern "C++"` section of a CXX bridge declares C++ types and signatures to
be made available to Rust, and gives the paths of the header(s) which contain
the corresponding C++ declarations.

A bridge module may contain zero or more extern "C++" blocks.

## Opaque C++ types

Type defined in C++ that are made available to Rust, but only behind an
indirection.

```rust,noplayground
# #[cxx::bridge]
# mod ffi {
    extern "C++" {
        # include!("path/to/header.h");
        #
        type MyType;
        type MyOtherType;
    }
# }
```

For example in the ***[Tutorial](tutorial.md)*** we saw `BlobstoreClient`
implemented as an opaque C++ type. The blobstore client was created in C++ and
returned to Rust by way of a UniquePtr.

**Mutability:** Unlike extern Rust types and shared types, an extern C++ type is
not permitted to be passed by plain mutable reference `&mut MyType` across the
FFI bridge. For mutation support, the bridge is required to use `Pin<&mut
MyType>`. This is to safeguard against things like mem::swap-ing the contents of
two mutable references, given that Rust doesn't have information about the size
of the underlying object and couldn't invoke an appropriate C++ move constructor
anyway.

**Thread safety:** Be aware that CXX does not assume anything about the thread
safety of your extern C++ types. In other words the `MyType` etc bindings which
CXX produces for you in Rust *do not* come with `Send` and `Sync` impls. If you
are sure that your C++ type satisfies the requirements of `Send` and/or `Sync`
and need to leverage that fact from Rust, you must provide your own unsafe
marker trait impls.

```rust,noplayground
# #[cxx::bridge]
# mod ffi {
#     extern "C++" {
#         include!("path/to/header.h");
#
#         type MyType;
#     }
# }
#
/// The C++ implementation of MyType is thread safe.
unsafe impl Send for ffi::MyType {}
unsafe impl Sync for ffi::MyType {}
```

Take care in doing this because thread safety in C++ can be extremely tricky to
assess if you are coming from a Rust background. For example the
`BlobstoreClient` type in the tutorial is *not thread safe* despite doing only
completely innocuous things in its implementation. Concurrent calls to the `tag`
member function trigger a data race on the `blobs` map.

## Functions and member functions

This largely follows the same principles as ***[extern
"Rust"](extern-rust.md)*** functions and methods. In particular, any signature
with a `self` parameter is interpreted as a C++ non-static member function and
exposed to Rust as a method.

The programmer **does not** need to promise that the signatures they have typed
in are accurate; that would be unreasonable. CXX performs static assertions that
the signatures exactly correspond with what is declared in C++. Rather, the
programmer is only on the hook for things that C++'s static information is not
precise enough to capture, i.e. things that would only be represented at most by
comments in the C++ code unintelligible to a static assertion: namely whether
the C++ function is safe or unsafe to be called from Rust.

**Safety:** the extern "C++" block is responsible for deciding whether to expose
each signature inside as safe-to-call or unsafe-to-call. If an extern block
contains at least one safe-to-call signature, it must be written as an `unsafe
extern` block, which serves as an item level unsafe block to indicate that an
unchecked safety claim is being made about the contents of the block.

```rust,noplayground
#[cxx::bridge]
mod ffi {
    unsafe extern "C++" {
        # include!("path/to/header.h");
        #
        fn f();  // safe to call
    }

    extern "C++" {
        unsafe fn g();  // unsafe to call
    }
}
```

## Lifetimes

C++ types holding borrowed data may be described naturally in Rust by an extern
type with a generic lifetime parameter. For example in the case of the following
pair of types:

```cpp
// header.h

class Resource;

class TypeContainingBorrow {
  TypeContainingBorrow(const Resource &res) : res(res) {}
  const Resource &res;
};

std::shared_ptr<TypeContainingBorrow> create(const Resource &res);
```

we'd want to expose this to Rust as:

```rust,noplayground
#[cxx::bridge]
mod ffi {
    unsafe extern "C++" {
        # include!("path/to/header.h");
        #
        type Resource;
        type TypeContainingBorrow<'a>;

        fn create<'a>(res: &'a Resource) -> SharedPtr<TypeContainingBorrow<'a>>;

        // or with lifetime elision:
        fn create(res: &Resource) -> SharedPtr<TypeContainingBorrow>;
    }
}
```

## Reusing existing binding types

Extern C++ types support a syntax for declaring that a Rust binding of the
correct C++ type already exists outside of the current bridge module. This
avoids generating a fresh new binding which Rust's type system would consider
non-interchangeable with the first.

```rust,noplayground
#[cxx::bridge(namespace = "path::to")]
mod ffi {
    extern "C++" {
        type MyType = crate::existing::MyType;
    }

    extern "Rust" {
        fn f(x: &MyType) -> usize;
    }
}
```

In this case rather than producing a unique new Rust type `ffi::MyType` for the
Rust binding of C++'s `::path::to::MyType`, CXX will reuse the already existing
binding at `crate::existing::MyType` in expressing the signature of `f` and any
other uses of `MyType` within the bridge module.

CXX safely validates that `crate::existing::MyType` is in fact a binding for the
right C++ type `::path::to::MyType` by generating a static assertion based on
`crate::existing::MyType`'s implementation of [`ExternType`], which is a trait
automatically implemented by CXX for bindings that it generates but can also be
manually implemented as described below.

[`ExternType`]: https://docs.rs/cxx/*/cxx/trait.ExternType.html

`ExternType` serves the following two related use cases.

#### Safely unifying occurrences of an extern type across bridges

In the following snippet, two #\[cxx::bridge\] invocations in different files
(possibly different crates) both contain function signatures involving the same
C++ type `example::Demo`. If both were written just containing `type Demo;`,
then both macro expansions would produce their own separate Rust type called
`Demo` and thus the compiler wouldn't allow us to take the `Demo` returned by
`file1::ffi::create_demo` and pass it as the `Demo` argument accepted by
`file2::ffi::take_ref_demo`. Instead, one of the two `Demo`s has been defined as
an extern type alias of the other, making them the same type in Rust.

```rust,noplayground
// file1.rs
#[cxx::bridge(namespace = "example")]
pub mod ffi {
    unsafe extern "C++" {
        type Demo;

        fn create_demo() -> UniquePtr<Demo>;
    }
}
```

```rust,noplayground
// file2.rs
#[cxx::bridge(namespace = "example")]
pub mod ffi {
    unsafe extern "C++" {
        type Demo = crate::file1::ffi::Demo;

        fn take_ref_demo(demo: &Demo);
    }
}
```

#### Integrating with bindgen-generated or handwritten unsafe bindings

Handwritten `ExternType` impls make it possible to plug in a data structure
emitted by bindgen as the definition of a C++ type emitted by CXX.

By writing the unsafe `ExternType` impl, the programmer asserts that the C++
namespace and type name given in the type id refers to a C++ type that is
equivalent to Rust type that is the `Self` type of the impl.

```rust,noplayground
mod folly_sys;  // the bindgen-generated bindings

use cxx::{type_id, ExternType};

unsafe impl ExternType for folly_sys::StringPiece {
    type Id = type_id!("folly::StringPiece");
    type Kind = cxx::kind::Opaque;
}

#[cxx::bridge(namespace = "folly")]
pub mod ffi {
    unsafe extern "C++" {
        include!("rust_cxx_bindings.h");

        type StringPiece = crate::folly_sys::StringPiece;

        fn print_string_piece(s: &StringPiece);
    }
}

// Now if we construct a StringPiece or obtain one through one
// of the bindgen-generated signatures, we are able to pass it
// along to ffi::print_string_piece.
```

The `ExternType::Id` associated type encodes a type-level representation of the
type's C++ namespace and type name. It will always be defined using the
`type_id!` macro exposed in the cxx crate.

The `ExternType::Kind` associated type will always be either
[`cxx::kind::Opaque`] or [`cxx::kind::Trivial`] identifying whether a C++ type
is soundly relocatable by Rust's move semantics. A C++ type is only okay to hold
and pass around by value in Rust if its [move constructor is trivial] and it has
no destructor. In CXX, these are called Trivial extern C++ types, while types
with nontrivial move behavior or a destructor must be considered Opaque and
handled by Rust only behind an indirection, such as a reference or UniquePtr.

[`cxx::kind::Opaque`]: https://docs.rs/cxx/*/cxx/kind/enum.Opaque.html
[`cxx::kind::Trivial`]: https://docs.rs/cxx/*/cxx/kind/enum.Trivial.html
[move constructor is trivial]: https://en.cppreference.com/w/cpp/types/is_move_constructible

If you believe your C++ type reflected by the ExternType impl is indeed fine to
hold by value and move in Rust, you can specify:

```rust,noplayground
# unsafe impl cxx::ExternType for TypeName {
#     type Id = cxx::type_id!("name::space::of::TypeName");
    type Kind = cxx::kind::Trivial;
# }
```

which will enable you to pass it into C++ functions by value, return it by
value, and include it in `struct`s that you have declared to `cxx::bridge`. Your
claim about the triviality of the C++ type will be checked by a `static_assert`
in the generated C++ side of the binding.

## Explicit shim trait impls

This is a somewhat niche feature, but important when you need it.

CXX's support for C++'s std::unique\_ptr and std::vector is built on a set of
internal trait impls connecting the Rust API of UniquePtr and CxxVector to
underlying template instantiations performed by the C++ compiler.

When reusing a binding type across multiple bridge modules as described in the
previous section, you may find that your code needs some trait impls which CXX
hasn't decided to generate.

```rust,noplayground
#[cxx::bridge]
mod ffi1 {
    extern "C++" {
        include!("path/to/header.h");

        type A;
        type B;

        // Okay: CXX sees UniquePtr<B> using a type B defined within the same
        // bridge, and automatically emits the right template instantiations
        // corresponding to std::unique_ptr<B>.
        fn get_b() -> UniquePtr<B>;
    }
}

#[cxx::bridge]
mod ffi2 {
    extern "C++" {
        type A = crate::ffi1::A;

        // Rust trait error: CXX processing this module has no visibility into
        // whether template instantiations corresponding to std::unique_ptr<A>
        // have already been emitted by the upstream library, so it does not
        // emit them here. If the upstream library does not have any signatures
        // involving UniquePtr<A>, an explicit instantiation of the template
        // needs to be requested in one module or the other.
        fn get_a() -> UniquePtr<A>;
    }
}
```

You can request a specific template instantiation at a particular location in
the Rust crate hierarchy by writing `impl UniquePtr<A> {}` inside of the bridge
module which defines `A` but does not otherwise contain any use of
`UniquePtr<A>`.

```rust,noplayground
#[cxx::bridge]
mod ffi1 {
    extern "C++" {
        include!("path/to/header.h");

        type A;
        type B;

        fn get_b() -> UniquePtr<B>;
    }

    impl UniquePtr<A> {}  // explicit instantiation
}
```