Skip to main content

CppRef

Struct CppRef 

Source
pub struct CppRef<T: ?Sized>(/* private fields */);
Expand description

A C++ const reference. These are different from Rust’s &T in that these may exist even while the object is mutated elsewhere. See also CppMutRef for the mutable equivalent.

The key rule is: we never dereference these in Rust. Therefore, any UB here cannot manifest within Rust, but only across in C++, and therefore they are equivalently safe to using C++ references in pure-C++ codebases.

Important: you might be wondering why you’ve never encountered this type. These exist in autocxx-generated bindings only if the unsafe_references_wrapped safety policy is given. This may become the default in future.

§Usage

These types of references are pretty useless in Rust. You can’t do field access. But, you can pass them back into C++! And specifically, you can call methods on them (i.e. use this type as a this). So the common case here is when C++ gives you a reference to some type, then you want to call methods on that reference.

§Calling methods

As noted, one of the main reasons for this type is to call methods. Currently, that depends on unstable Rust features. If you can’t call methods on one of these references, check you’re using nightly and add #![feature(arbitrary_self_types)] to your crate.

§Lifetimes

A CppRef is not associated with any Rust lifetime. Normally, for ergonomics, you actually may want a lifetime associated. CppLtRef gives you this.

§Field access

Field access would be achieved by adding C++ get and/or set methods. It’s possible that a future version of autocxx could generate such getters and setters automatically, but they would need to be unsafe because there is no guarantee that the referent of a CppRef is actually what it’s supposed to be, or alive. CppRefs may flow from C++ to Rust via arbitrary means, and with sufficient uses of get and set it would even be possible to create a use-after-free in pure Rust code (for instance, store a CppPin in a struct field, get a CppRef to its referent, then use a setter to reset that field of the struct.)

§Nullness

Creation of a null C++ reference is undefined behavior (because such a reference can only be created by dereferencing a null pointer.) However, in practice, they exist, and we need to be compatible with pre-existing C++ APIs even if they do naughty things like this. Therefore this CppRef type does allow null values. This is a bit unfortunate because it means Option<CppRef<T>> occupies more space than CppRef<T>.

§Dynamic dispatch

You might wonder if you can do this:

let CppRef<dyn Trait> = ...; // obtain some CppRef<concrete type>

Dynamic dispatch works so long as you’re using nightly (we require another unstable feature, dispatch_from_dyn). But we need somewhere to store the trait object, and CppRef isn’t it – a CppRef can only store a simple pointer to something else. So, you need to store the trait object in a Box or similar:

trait SomeTrait {
   fn some_method(self: CppRef<Self>)
}
impl SomeTrait for ffi::Concrete {
  fn some_method(self: CppRef<Self>) {}
}
let obj: Pin<Box<dyn SomeTrait>> = ffi::Concrete::new().within_box();
let obj = CppPin::from_pinned_box(obj);
farm_area.as_cpp_ref().some_method();

§Implementation notes

Internally, this is represented as a raw pointer in Rust. See the note above about Nullness for why we don’t use core::ptr::NonNull.

Implementations§

Source§

impl<T: ?Sized> CppRef<T>

Source

pub fn as_ptr(&self) -> *const T

Retrieve the underlying C++ pointer.

Source

pub unsafe fn as_ref(&self) -> &T

Get a regular Rust reference out of this C++ reference.

§Safety

Callers must guarantee that the referent is not modified by any other C++ or Rust code while the returned reference exists. Callers must also guarantee that no mutable Rust reference is created to the referent while the returned reference exists.

Callers must also be sure that the C++ reference is properly aligned, not null, pointing to valid data, etc.

Source

pub fn from_ptr(ptr: *const T) -> Self

Create a C++ reference from a raw pointer.

Source

pub fn const_cast(&self) -> CppMutRef<T>

Create a mutable version of this reference, roughly equivalent to C++ const_cast.

The opposite is to use AsCppRef::as_cpp_ref on a CppMutRef to obtain a CppRef.

§Safety

Because we never dereference a CppRef in Rust, this cannot create undefined behavior within Rust and is therefore not unsafe. It is however generally unwise, just as it is in C++. Use sparingly.

Trait Implementations§

Source§

impl<T: ?Sized> Clone for CppRef<T>

Source§

fn clone(&self) -> Self

Returns a duplicate of the value. Read more
1.0.0 (const: unstable) · Source§

fn clone_from(&mut self, source: &Self)

Performs copy-assignment from source. Read more
Source§

impl<T: ?Sized> Copy for CppRef<T>

Source§

impl<T> From<CppMutRef<T>> for CppRef<T>

Source§

fn from(mutable: CppMutRef<T>) -> Self

Converts to this type from the input type.

Auto Trait Implementations§

§

impl<T> !Send for CppRef<T>

§

impl<T> !Sync for CppRef<T>

§

impl<T> Freeze for CppRef<T>
where T: ?Sized,

§

impl<T> RefUnwindSafe for CppRef<T>
where T: RefUnwindSafe + ?Sized,

§

impl<T> Unpin for CppRef<T>
where T: ?Sized,

§

impl<T> UnsafeUnpin for CppRef<T>
where T: ?Sized,

§

impl<T> UnwindSafe for CppRef<T>
where T: RefUnwindSafe + ?Sized,

Blanket Implementations§

Source§

impl<T> Any for T
where T: 'static + ?Sized,

Source§

fn type_id(&self) -> TypeId

Gets the TypeId of self. Read more
Source§

impl<T> Borrow<T> for T
where T: ?Sized,

Source§

fn borrow(&self) -> &T

Immutably borrows from an owned value. Read more
Source§

impl<T> BorrowMut<T> for T
where T: ?Sized,

Source§

fn borrow_mut(&mut self) -> &mut T

Mutably borrows from an owned value. Read more
Source§

impl<T> CloneToUninit for T
where T: Clone,

Source§

unsafe fn clone_to_uninit(&self, dest: *mut u8)

🔬This is a nightly-only experimental API. (clone_to_uninit)
Performs copy-assignment from self to dest. Read more
Source§

impl<T> From<T> for T

Source§

fn from(t: T) -> T

Returns the argument unchanged.

Source§

impl<T, U> Into<U> for T
where U: From<T>,

Source§

fn into(self) -> U

Calls U::from(self).

That is, this conversion is whatever the implementation of From<T> for U chooses to do.

Source§

impl<T> ToOwned for T
where T: Clone,

Source§

type Owned = T

The resulting type after obtaining ownership.
Source§

fn to_owned(&self) -> T

Creates owned data from borrowed data, usually by cloning. Read more
Source§

fn clone_into(&self, target: &mut T)

Uses borrowed data to replace owned data, usually by cloning. Read more
Source§

impl<T, U> TryFrom<U> for T
where U: Into<T>,

Source§

type Error = Infallible

The type returned in the event of a conversion error.
Source§

fn try_from(value: U) -> Result<T, <T as TryFrom<U>>::Error>

Performs the conversion.
Source§

impl<T, U> TryInto<U> for T
where U: TryFrom<T>,

Source§

type Error = <U as TryFrom<T>>::Error

The type returned in the event of a conversion error.
Source§

fn try_into(self) -> Result<U, <U as TryFrom<T>>::Error>

Performs the conversion.