pub struct CppPin<T: ?Sized>(/* private fields */);
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 yourCppRef
objects don’t outlive theCppPin
, 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 (usingAsCppMutRef::as_cpp_mut_ref
) into a C++ function. C++ would duly operate on the object, and thereafter you could reclaim the object withextract()
. 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>
impl<T: ?Sized> CppPin<T>
Sourcepub fn new(item: T) -> Selfwhere
T: Sized,
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.
Sourcepub fn from_box(item: Box<T>) -> Self
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.
Sourcepub fn from_pinned_box(item: Pin<Box<T>>) -> Self
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.
Sourcepub fn as_mut_ptr(&mut self) -> *mut T
pub fn as_mut_ptr(&mut self) -> *mut T
Get a mutable pointer to the underlying object.
Sourcepub unsafe fn as_ref(&self) -> &T
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.
Sourcepub unsafe fn as_mut(&mut self) -> &mut T
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.
Sourcepub unsafe fn extract(self) -> Box<T>
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++.