| # C++ bindings for Rust libraries | |
| Rust libraries can be used directly from C++. This page documents roughly what | |
| that entails, and additional subpages (available in the left-hand navigation) | |
| document specific aspects of the generated bindings. | |
| Tip: The code examples below are pulled straight from | |
| <https://github.com/google/crubit/tree/main/examples/rust/function/>. The other examples | |
| in <https://github.com/google/crubit/tree/main/examples/rust/> are also useful. If you | |
| prefer just copy-pasting something, start there. | |
| ## How to use Crubit {#introduction} | |
| Crubit allows you to call some Rust interfaces from C++. It supports | |
| [functions](functions.md) (including methods), [structs](structs.md), | |
| [traits](traits.md), and even [enums](enums.md) as "opaque" objects. Crubit does | |
| **not** support advanced features like generics or dynamic dispatch with `dyn`. | |
| The rest of this document goes over how to create a Rust library that can be | |
| called from C++, and how to actually use it from C++. The quick summary is: | |
| * All `rust_library` targets can receive C++ bindings. | |
| * To use the bindings for a target `//path/to:example_crate`, you must create | |
| a C++ rule exporting the bindings, using | |
| `cpp_api_from_rust(name="any_name_here", crate=":example_crate")`. | |
| * The header name is the Rust target's label with a `.h` appended: to include | |
| the header for the Rust library `//path/to:example_crate`, you use `#include | |
| "path/to/example_crate.h"`. | |
| * The namespace name is the Rust target name, e.g. `example_crate`. To change | |
| the namespace, use `cc_bindings_from_rust_library_config`, described below. | |
| * To see the generated C++ API, right click the `"path/to/example_crate.h"` | |
| include in Cider, and select "Go to Definition". | |
| NOTE: In some cases the generated file in Cider may be out of date. If it | |
| isn't refreshing, you can manually inspect the bindings using `bazel build | |
| //path/to:example_crate --config=crubit-genfiles`. See [Look at the | |
| generated bindings](#examine). | |
| ### Write a `rust_library` target {#rust_library} | |
| The first part of creating a library that can be used by Crubit is to write a | |
| `rust_library` target. For example: | |
| ```live-snippet | |
| cs/file:examples/rust/function/example.rs content:^[^/].* | |
| ``` | |
| In the BUILD file, in addition to defining the `rust_library`, you should also | |
| define the `cpp_api_from_rust` target (loaded via | |
| `load("//bazel:cpp_api_from_rust.bzl", "cpp_api_from_rust")`) | |
| to make it easier to use from C++: | |
| ```live-snippet | |
| cs/file:examples/rust/function/BUILD symbol:example_crate|example_crate_cc_api | |
| ``` | |
| Example: If your Rust library is named `//path/to:example_crate`, then the C++ | |
| header file is `"path/to/example_crate.h"`, and the C++ namespace is | |
| `example_crate` by default. | |
| ### Use a Rust library from C++ {#use} | |
| C++ build rules do not have a `rust_deps` parameter, so to depend on the C++ | |
| bindings for a target, they must depend on the `cpp_api_from_rust` rule. | |
| For example: | |
| ```live-snippet | |
| cs/file:examples/rust/function/BUILD symbol:main | |
| ``` | |
| ```live-snippet | |
| cs/file:examples/rust/function/main.cc content:^[^/\n].* | |
| ``` | |
| NOTE: Other than for declaring the dependency, all other information about the | |
| generated bindings comes from the actual `rust_library` rule. For example, the | |
| `#include` for the above is `#include | |
| "examples/rust/function/example_crate.h"`, **not** | |
| `example_crate_cc_api.h`. | |
| ### (Optional) Customize the generated C++ API {#cc_bindings_from_rust_library_config} | |
| #### Give it a better namespace {#namespace} | |
| The crate name might make a poor namespace. In addition, typically, multiple C++ | |
| headers and build targets share the same namespace. To customize the namespace | |
| name, use `cc_bindings_from_rust_library_config`: | |
| ```live-snippet | |
| cs/file:examples/rust/library_config/BUILD symbol:custom_namespace|example_crate | |
| ``` | |
| Now, instead of the crate name, the generated bindings will use the namespace | |
| name you provided: | |
| ```live-snippet | |
| cs/file:examples/rust/library_config/main.cc content:^[^/\n].* | |
| ``` | |
| ### Look at the generated bindings {#examine} | |
| The generated C++ API for a `rust_library` is a header named after the | |
| `rust_library` target, in the build output directory. | |
| #### When something is missing {#missing} | |
| If Crubit can't generate bindings for a Rust item, the build doesn't fail by | |
| default. Crubit leaves the item out of the generated header and writes a comment | |
| in its place explaining why: | |
| ```c++ | |
| // Error generating bindings for function `tuples_golden::param_option_in_tuple` | |
| // defined at | |
| // path/to/tuples.rs;l=370: | |
| // Error handling parameter #0 of type `(std::option::Option<i32>,)`: | |
| // crubit.rs/errors/bridge_compound_type: Tuples containing bridged type | |
| ``` | |
| The first error you see is usually in the C++ code that calls the missing item, | |
| which doesn't say why it's missing. Search the generated header for the item's | |
| name to find the reason. The reason often names a type rather than the function | |
| itself; fix or wrap that type, and the function gets bindings too. | |
| To make a missing item fail the build instead, annotate it with | |
| `#[crubit_annotate::must_bind]`. `crubit_annotate` is a procedural macro crate, | |
| so add `//support:crubit_annotate` to your `rust_library`'s | |
| `proc_macro_deps` (see [Attributes to fine-tune generated | |
| bindings](customizing.md)). | |
| ## Common Errors {#errors} | |
| ### Unsupported features | |
| Some features are either unsupported, or else only supported with experimental | |
| feature | |
| flags . | |
| In order to get bindings for a Rust interface, that interface must only use the | |
| subset of features currently supported. | |
| For a particularly notable example, references are supported as function | |
| parameters and return types, but only in a subset of cases that we can prove | |
| does not add aliasing UB to C++ callers. | |
| The way to work around this kind of problem, in all cases, is to wrap or hide | |
| the problematic interface behind an interface Crubit can handle: | |
| * Use raw pointers instead of references, if this use of references falls into | |
| a case Crubit does not support. | |
| * Hide unsupported types behind a wrapper type. For example, a `HashMap<K, V>` | |
| is not supported by Crubit, but `pub struct MyStruct(HashMap<i32, i32>);` | |
| is. |