blob: 472f40cf21f4045b0fb545e932bc5685acc1af30 [file] [view] [edit]
# C++ bindings for Rust traits
Crubit allows C++ callers to invoke Rust trait implementations. For each `trait
SomeTrait`, Crubit generates a matching C++ `struct SomeTrait`. To call a trait
method `SomeTrait::some_fn` implemented by `SomeType`, C++ callers can use
`SomeTrait::impl<SomeType>::some_fn(args...)`.
## Example
Given the following Rust crate:
```live-snippet
cs/file:examples/rust/trait/example.rs
```
You can call the trait from C++ using the following code:
```live-snippet
cs/file:examples/rust/trait/main.cc function:main
```
Each trait has an associated `impl` member which is generic upon the `Self` type
of the trait implementation, and which provides all of the associated types,
consts, and functions.
## Checking if a trait is implemented
C++ users can check if a trait implementation is available using `rs::where_v<T,
SomeTrait>`. This is useful when writing templated C++ functions, as it can be
used with `requires` (or `enable_if`) to specify that a particular trait is
implemented by a type parameter. For example:
```live-snippet
cs/file:examples/rust/trait/main.cc function:add_with_2
```
## Limitations
Some trait implementations will not receive bindings:
* Trait implementations with generic parameters (e.g. `impl<T> ...`) will not
receive bindings.
* For example, an implementation `impl<U> TwoArgs<i32, U> for MyStruct`
will not receive bindings because the `impl` has a type parameter (`U`).
* This also means that blanket impls (e.g. `impl<T> Trait for T`) are not
supported.
* Traits with `const` parameters (e.g. `trait T<const V: usize>`) do not yet
receive bindings.
* Trait methods will not receive bindings if their parameter or return types
are not yet supported by Crubit.
## How does it work?
Under the hood, Crubit will generate three bindings from the example Rust crate.
A template specialization for `impl MyTrait for MyStruct`:
```live-snippet
cs/file:examples/rust/trait/example_generated.h class:impl
```
Our generated `rs::impl` specialization is an implementation detail of binding
generation. It holds the actual thunks that call into rust to implement our
trait, but they should be accessed through our template struct `MyTrait`:
```live-snippet
cs/file:examples/rust/trait/example_generated.h class:MyTrait
```
Each struct generated for a Rust trait has the `impl` member that provides
access to the generated `rs::impl`. This is the preferred way to reference the
generated `rs::impl`.
Finally, a struct for `MyStruct`:
```live-snippet
cs/file:examples/rust/trait/example_generated.h class:MyStruct
```
Our struct is generated normally and exists purely so we have something to
implement our trait for.