Pointer types

C++ defines two categories of pointer types, while Rust adds a third. They are:

  • Pointers to some (non-function) object, without lifetime information. C++ calls these object pointers, while Rust calls them raw pointers.
  • Function pointers (C++, Rust).
  • Finally, Rust references: non-aliasing pointers with lifetime information.

With the exception of Rust references, which are only permitted in limited circumstances, pointer types are fully supported as long as the type they point to is supported. For example, const int32_t* maps bidirectionally to *const i32, and void (*)(int32_t) maps bidirectionally to fn(i32).

Object pointers

An "object pointer" is the C++ terminology for any pointer that is not a function pointer. Rust would call these "raw pointers". These are mapped to each other bidirectionally:

C++Rust
const T**const T
T**mut T

C++ pointers with lifetime

C++ allows attaching lifetime annotations to arbitrary types, including pointers. There are two competing annotations for this, neither of which are supported in Rust bindings yet:

Function pointers

C++ function pointers map to Rust extern "C" fn(...) -> ... function pointers, and vice versa:

C++Rust
void(&)(int32_t)>extern "C" fn(i32)
void(*)(int32_t)Option<extern "C" fn(i32)>
std::type_identity_t<void(int32_t)>Not supported 1

If the corresponding C++ function definition would be unsafe in Rust (per the rules for C++ function declarations), 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 the function cannot be called directly, due to a known or potential ABI mismatch between Rust and C++, then the function pointer receives no bindings. In particular, function pointers cannot take layout-compatible types by value. You can work around this by taking or returning such problematic types by pointer instead of by value.

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.

1

C++ has plain function types: 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 or absl::AnyInvocable. Or, in this case, type_identity_t.

Rust references

Rust references, unlike C++ references, cannot mutably alias. This introduces a new form of Undefined Behavior (UB) that many C++ programmers may not be accustomed to. For now, C++ pointers and references do not map to Rust references. Instead, they map to Rust raw pointers. Vice versa, Rust references are an unsupported type which do not map to any C++ type at all.

The one exception to this rule are function parameters. In some limited circumstances, Rust functions may accept references, and the corresponding C++ interface will accept C++ references. This is documented in /rust/functions.