Struct autocxx::CppPin

source ·
pub struct CppPin<T: ?Sized>(_);
Expand description

A newtype wrapper which causes the contained object to obey C++ reference semantics rather than Rust reference semantics. That is, multiple aliasing mutable C++ references may exist to the contents.

C++ references are permitted to alias one another, and commonly do. Rust references must alias according only to the narrow rules of the borrow checker.

If you need C++ to access your Rust object, first imprison it in one of these objects, then use Self::as_cpp_ref to obtain C++ references to it. If you need the object back for use in the Rust domain, use CppPin::extract, but be aware of the safety invariants that you - as a human - will need to guarantee.

Usage models

From fairly safe to fairly unsafe:

  • Configure a thing in Rust then give it to C++. Take your Rust object, set it up freely using Rust references, methods and data, then imprison it in a CppPin and keep it around while you work with it in C++. There is no possibility of aliasing UB in this usage model, but you still need to be careful of use-after-free bugs, just as if you were to create a reference to any data in C++. The Rust borrow checker will help you a little by ensuring that your CppRef objects don’t outlive the CppPin, but once those references pass into C++, it can’t help.
  • Pass a thing to C++, have it operate on it synchronously, then take it back. To do this, you’d imprison your Rust object in a CppPin, then pass mutable C++ references (using AsCppMutRef::as_cpp_mut_ref) into a C++ function. C++ would duly operate on the object, and thereafter you could reclaim the object with extract(). At this point, you (as a human) will need to give a guarantee that no references remain in the C++ domain. If your object was just locally used by a single C++ function, which has now returned, this type of local analysis may well be practical.
  • Share a thing between Rust and C++. This object can vend both C++ references and Rust references (via as_ref etc.) It may be possible for you to guarantee that C++ does not mutate the object while any Rust reference exists. If you choose this model, you’ll need to carefully track exactly what happens to references and pointers on both sides, and document your evidence for why you are sure this is safe. Failure here is bad: Rust makes all sorts of optimization decisions based upon its borrow checker guarantees, so mistakes can lead to undebuggable action-at-a-distance crashes.

See also

See also CppUniquePtrPin, which is equivalent for data which is in a cxx::UniquePtr.

Implementations§

source§

impl<T: ?Sized> CppPin<T>

source

pub fn new(item: T) -> Selfwhere T: Sized,

Imprison the Rust data within a CppPin. This eliminates any remaining Rust references (since we take the item by value) and this object subsequently only vends C++ style references, not Rust references, until or unless extract is called.

source

pub fn from_box(item: Box<T>) -> Self

Imprison the boxed Rust data within a CppPin. This eliminates any remaining Rust references (since we take the item by value) and this object subsequently only vends C++ style references, not Rust references, until or unless extract is called.

If the item is already in a Box, this is slightly more efficient than new because it will avoid moving/reallocating it.

source

pub fn from_pinned_box(item: Pin<Box<T>>) -> Self

Rust references (since we take the item by value) and this object subsequently only vends C++ style references, not Rust references, until or unless extract is called.

If the item is already in a Box, this is slightly more efficient than new because it will avoid moving/reallocating it.

source

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

Get an immutable pointer to the underlying object.

source

pub fn as_mut_ptr(&mut self) -> *mut T

Get a mutable pointer to the underlying object.

source

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

Get a normal Rust reference to the underlying object. This is unsafe.

Safety

You must guarantee that C++ will not mutate the object while the reference exists.

source

pub unsafe fn as_mut(&mut self) -> &mut T

Get a normal Rust mutable reference to the underlying object. This is unsafe.

Safety

You must guarantee that C++ will not mutate the object while the reference exists.

source

pub unsafe fn extract(self) -> Box<T>

Extract the object from within its prison, for re-use again within the domain of normal Rust references.

This returns a Box<T>: if you want the underlying T you can extract it using *.

Safety

Callers promise that no remaining C++ references exist either in the form of Rust CppRef/CppMutRef or any remaining pointers/ references within C++.

Trait Implementations§

source§

impl<T: ?Sized> AsCppMutRef<T> for CppPin<T>

source§

fn as_cpp_mut_ref(&mut self) -> CppMutRef<'_, T>

Returns a mutable reference which obeys C++ reference semantics
source§

impl<T: ?Sized> AsCppRef<T> for CppPin<T>

source§

fn as_cpp_ref(&self) -> CppRef<'_, T>

Returns a reference which obeys C++ reference semantics

Auto Trait Implementations§

§

impl<T: ?Sized> RefUnwindSafe for CppPin<T>where T: RefUnwindSafe,

§

impl<T: ?Sized> Send for CppPin<T>where T: Send,

§

impl<T: ?Sized> Sync for CppPin<T>where T: Sync,

§

impl<T: ?Sized> Unpin for CppPin<T>

§

impl<T: ?Sized> UnwindSafe for CppPin<T>where T: UnwindSafe,

Blanket Implementations§

source§

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

source§

fn type_id(&self) -> TypeId

Gets the TypeId of self. Read more
source§

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

source§

fn borrow(&self) -> &T

Immutably borrows from an owned value. Read more
source§

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

source§

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

Mutably borrows from an owned value. 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 Twhere 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, U> TryFrom<U> for Twhere U: Into<T>,

§

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 Twhere U: TryFrom<T>,

§

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.