| # 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 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). Currently, member functions |
| are translated as non-method 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 |
| ``` |
| |
| ### 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 snippet:0,6 "impl Bar" |
| ``` |
| |
| ### `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]* |
| ``` |
| |
| #### 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 Attributes |
| |
| Function attributes are **not currently supported**. Functions marked |
| `[[noreturn]]`, `[[nodiscard]]`, etc. do not have bindings. |