| # Rust bindings for C++ pointer types |
| |
| Crubit maps C++ pointers to the corresponding Rust pointer types. Both C++ |
| pointer types are supported: |
| |
| * [Object pointers](https://en.cppreference.com/w/cpp/language/pointer#Pointers_to_objects) |
| (pointers to non-functions, such as `int*`) |
| * [Function pointers](https://en.cppreference.com/w/cpp/language/pointer#Pointers_to_functions) |
| |
| ## Object pointers {#object} |
| |
| C++ object pointers (non-function pointers) map straight to Rust raw pointers: |
| |
| C++ | Rust |
| ---------- | ---------- |
| `const T*` | `*const T` |
| `T*` | `*mut T` |
| |
| ### Lifetime {#object_lifetime} |
| |
| There are multiple ways to specify pointer lifetime in C++, none of which are |
| supported yet. For example: |
| |
| * `[[clang::lifetimebound]]` |
| * [Lifetime attributes](https://discourse.llvm.org/t/rfc-lifetime-annotations-for-c/61377) |
| |
| Types containing a pointer lifetime are not usable from Rust. (This is blocked |
| on support for aliasing in Rust.) |
| |
| ### Nullability {#object_nullability} |
| |
| Non-nullable object pointers and references are not yet supported. |
| |
| ## Function pointers {#function} |
| |
| C++ function pointers map to Rust `extern "C" fn(...) -> ...` types: |
| |
| | C++ | Rust | |
| | ------------------------------------- | ------------------------------- | |
| | `std::type_identity_t<void(int32_t)> | `extern "C" fn(i32)` | |
| : &`[^type_identity] : : |
| | `std::type_identity_t<void(int32_t)> | `Option<extern "C" fn(i32)>` | |
| : *` : : |
| | `std::type_identity_t<void(int32_t)>` | Not supported [^function_types] | |
| |
| If the function definition would be `unsafe`, then so is the function pointer -- |
| for example, a C++ reference to `void(void*)` becomes a Rust `unsafe extern "C" |
| fn(_: *mut c_void)`. |
| |
| Not all function pointers receive bindings. If Rust cannot call the function |
| directly, due to a known or potential ABI mismatch between Rust and C++, then |
| the function pointer receives no bindings. |
| |
| In particular, function pointers currently cannot take structs by value. |
| |
| This restriction will be relaxed over time, as more and more parts of the ABI |
| are successfully translated to Rust. It can be worked around by taking or |
| returning such problematic types by pointer instead of by value. |
| |
| ### Lifetime {#function_lifetime} |
| |
| All function pointers are `'static`. |
| |
| There is no way to specify the lifetime of a function pointer in Rust, nor in |
| C++: both assume a `'static` lifetime. In scenarios where the lifetime may be |
| shorter than `'static` (e.g., JIT compilation, or dynamic loading and unloading |
| of shared libraries at runtime), the developer is responsible for managing the |
| lifetime of the function pointer. |
| |
| [^type_identity]: The examples use |
| [`std::type_identity_t` (C++20)](https://en.cppreference.com/w/cpp/types/type_identity) |
| to provide a more convenient syntax. Crubit doesn't actually |
| require using `std::type_identity_t` in the C++ APIs that it |
| generates bindings for. |
| [^function_types]: C++ has plain |
| [function types](https://en.cppreference.com/w/cpp/types/is_function): |
| the type pointed to by function pointers. There is no Rust |
| equivalent. However, since C++ functions implicitly coerce to |
| function pointers, this only comes up in template classes |
| like |
| [`std::function`](https://en.cppreference.com/w/cpp/utility/functional/function) |
| or |
| [`absl::AnyInvocable`](https://github.com/abseil/abseil-cpp/blob/master/absl/functional/any_invocable.h). |