blob: 45fcc976c4add5b1039a6bb3bc43e802da283f60 [file] [view] [edit]
# Rust bindings for C++ functions
Rust code can call (non-member) functions defined in C++, provided that the
parameter and return types are supported by Crubit:
* If a parameter or return type is a [primitive type](../types/primitive.md),
then the bindings for the function use the corresponding Rust type.
* Similarly, if a parameter or return type is a
[pointer type](../types/pointer.md), then the bindings for the function use
the corresponding Rust pointer type.
* If a parameter or return type is a C++ reference type, then the bindings for
the function use a Rust reference (if the lifetime was either explicitly
specified or elided and inferred) or a Rust pointer (otherwise). See
[References and lifetimes](references_and_lifetimes.md).
* If the type is a user-defined type, such as a
[class type](classes_and_structs.md) or [enum](enums.md), then the bindings
for the function use the bindings for that type.
Additionally, code can call member functions defined in C++ if the parameter and
return types are supported by Crubit (see above). Non-static member functions
become Rust methods, and static member functions become associated functions.
## Examples
### Functions
Given the following C++ header:
```live-snippet
cs/file:examples/cpp/function/example.h function:add_two_integers
```
Crubit will generate the following bindings, with a safe public function that
calls into the corresponding FFI glue:
```live-snippet
cs/file:examples/cpp/function/example_generated.rs function:add_two_integers
```
Which can be used like this:
```live-snippet
cs/file:examples/cpp/function/main.rs function:main
```
### Methods
Given the following C++ header:
```live-snippet
cs/file:examples/cpp/method/example.h class:Bar
```
Crubit will generate the following bindings:
```live-snippet
cs/file:examples/cpp/method/example_generated.rs class:Bar
```
```live-snippet
cs/file:examples/cpp/method/example_generated.rs content:"(?m)impl Bar.*?(^$|^ \})"
```
Which can be used like this:
```live-snippet
cs/file:examples/cpp/method/main.rs function:main
```
The `this` parameter of a method becomes `&self` or `&mut self`. See
[References and lifetimes](references_and_lifetimes.md) for more details.
### `unsafe` functions {#unsafe}
#### Which C++ functions are marked `unsafe` in Rust? {#unsafe-inference}
By default, the Rust binding to a C++ function is marked as safe or `unsafe`
based on the types of its parameters. If a C++ function accepts only simple
types like integers, the resulting Rust binding will be marked as safe.
Functions which accept a raw pointer are automatically marked as `unsafe`.
This behavior can be overridden using the `CRUBIT_UNSAFE`,
`CRUBIT_UNSAFE_MARK_SAFE` and `CRUBIT_OVERRIDE_UNSAFE(is_unsafe)` macros.
For example, given the following C++ header:
```live-snippet
cs/file:examples/cpp/unsafe_attributes/example.h content:^([^/#\n])[^\n]*
```
Crubit will generate the following bindings:
```live-snippet
cs/file:examples/cpp/unsafe_attributes/example_generated.rs content:^([^/\n])([^!\n]|$)[^\n]*
```
Which can be used like this:
```live-snippet
cs/file:examples/cpp/unsafe_attributes/main.rs function:main
```
#### Correct usage of `unsafe` {#using-unsafe}
Functions marked **`unsafe`** cannot be called outside of an `unsafe` block. In
order to avoid undefined behavior when using `unsafe`, callers must:
* Ensure that the pointer being passed to C++ is a valid C++ pointer. In
particular, it must not be dangling (e.g. `Nonnull::dangling()`).
* Ensure that the safety conditions documented in C++ are upheld. For example,
if the C++ function accepts a reference or non-null pointer, then do not
pass in `0 as *const _`.
#### Soundness
Note that many "safe" C++ functions may still trigger undefined behavior if used
incorrectly. Regardless of whether a C++ function is marked as `unsafe`, calls
into C++ will only be memory-safe if the caller verifies that all function
preconditions are met.
### Function Visibility: `pub(crate)` {#pub-crate}
By default, bindings for C++ functions and methods are generated with `pub`
visibility in Rust.
You can restrict the visibility of a function or method to the generated crate
using `CRUBIT_PUB_CRATE` from `"support/annotations.h"`:
```cpp
#include "support/annotations.h"
CRUBIT_PUB_CRATE void HelperFunction();
class MyClass {
public:
CRUBIT_PUB_CRATE void InternalMethod();
};
```
This is especially useful when providing handwritten Rust APIs via the `srcs`
attribute of `rust_api_from_cpp` (see
[Best Practices](best_practices.md#limiting-cpp-function-visibility-to-srcs)).
The custom Rust code in `srcs` can call the `pub(crate)` functions or methods,
while keeping them hidden from downstream crates.
`CRUBIT_PUB_CRATE` is only valid on functions and methods; applying it to types
will produce an error.
## Function Attributes
Most function attributes are not supported. For example, functions marked
`[[noreturn]]` don't get bindings. `[[nodiscard]]` is supported and becomes
`#[must_use]`.