Skip to content

Commit

Permalink
Add UniquePtr::to_shared and SharedPtr::from_unmanaged
Browse files Browse the repository at this point in the history
  • Loading branch information
russelltg committed Jan 25, 2022
1 parent e41be2f commit c2967b7
Show file tree
Hide file tree
Showing 5 changed files with 63 additions and 1 deletion.
9 changes: 9 additions & 0 deletions macro/src/expand.rs
Original file line number Diff line number Diff line change
Expand Up @@ -1470,6 +1470,7 @@ fn expand_shared_ptr(
let prefix = format!("cxxbridge1$shared_ptr${}$", resolve.name.to_symbol());
let link_null = format!("{}null", prefix);
let link_uninit = format!("{}uninit", prefix);
let link_from_unmanaged = format!("{}from_unmanaged", prefix);
let link_clone = format!("{}clone", prefix);
let link_get = format!("{}get", prefix);
let link_drop = format!("{}drop", prefix);
Expand Down Expand Up @@ -1512,6 +1513,14 @@ fn expand_shared_ptr(
}
#new_method
#[doc(hidden)]
unsafe fn __from_unmanaged(value: *mut Self, new: *mut ::cxx::core::ffi::c_void) {
extern "C" {
#[link_name = #link_from_unmanaged]
fn __from_unmanaged(new: *const ::cxx::core::ffi::c_void, value: *mut ::cxx::core::ffi::c_void);
}
__from_unmanaged(new, value as *mut ::cxx::core::ffi::c_void);
}
#[doc(hidden)]
unsafe fn __clone(this: *const ::cxx::core::ffi::c_void, new: *mut ::cxx::core::ffi::c_void) {
extern "C" {
#[link_name = #link_clone]
Expand Down
4 changes: 4 additions & 0 deletions src/cxx.cc
Original file line number Diff line number Diff line change
Expand Up @@ -666,6 +666,10 @@ static_assert(sizeof(std::string) <= kMaxExpectedWordsInString * sizeof(void *),
std::shared_ptr<CXX_TYPE> *ptr) noexcept { \
new (ptr) std::shared_ptr<CXX_TYPE>(); \
} \
void cxxbridge1$std$shared_ptr$##RUST_TYPE##$from_unmanaged( \
std::shared_ptr<CXX_TYPE> *ptr, void* data) noexcept { \
new (ptr) std::shared_ptr<CXX_TYPE>(static_cast<CXX_TYPE*>(data)); \
} \
CXX_TYPE *cxxbridge1$std$shared_ptr$##RUST_TYPE##$uninit( \
std::shared_ptr<CXX_TYPE> *ptr) noexcept { \
CXX_TYPE *uninit = \
Expand Down
30 changes: 30 additions & 0 deletions src/shared_ptr.rs
Original file line number Diff line number Diff line change
Expand Up @@ -48,6 +48,24 @@ where
}
}

/// Create a shared pointer from an already-allocated object
/// Corresponds to constructor (3) of [std::shared\_ptr](https://en.cppreference.com/w/cpp/memory/shared_ptr/shared_ptr)
///
/// The SharedPtr gains ownership of the pointer and will call std::default_delete on it when the refcount goes to zero.
/// The data will not be moved, so any pointers to this data elsewhere in the program continue to be valid
///
/// # Safety
///
/// Value must either be null or point to a valid instance of T
pub unsafe fn from_unmanaged(value: *mut T) -> Self {
let mut shared_ptr = MaybeUninit::<SharedPtr<T>>::uninit();
let new = shared_ptr.as_mut_ptr().cast();
unsafe {
T::__from_unmanaged(value, new);
shared_ptr.assume_init()
}
}

/// Checks whether the SharedPtr does not own an object.
///
/// This is the opposite of [std::shared_ptr\<T\>::operator bool](https://en.cppreference.com/w/cpp/memory/shared_ptr/operator_bool).
Expand Down Expand Up @@ -194,6 +212,8 @@ pub unsafe trait SharedPtrTarget {
unreachable!()
}
#[doc(hidden)]
unsafe fn __from_unmanaged(value: *mut Self, new: *mut c_void);
#[doc(hidden)]
unsafe fn __clone(this: *const c_void, new: *mut c_void);
#[doc(hidden)]
unsafe fn __get(this: *const c_void) -> *const Self;
Expand Down Expand Up @@ -229,6 +249,16 @@ macro_rules! impl_shared_ptr_target {
unsafe { __uninit(new).cast::<$ty>().write(value) }
}
#[doc(hidden)]
unsafe fn __from_unmanaged(value: *mut Self, new: *mut c_void) {
extern "C" {
attr! {
#[link_name = concat!("cxxbridge1$std$shared_ptr$", $segment, "$from_unmanaged")]
fn __from_unmanaged(new: *mut c_void, value: *mut c_void);
}
}
unsafe { __from_unmanaged(new, value as *mut c_void) }
}
#[doc(hidden)]
unsafe fn __clone(this: *const c_void, new: *mut c_void) {
extern "C" {
attr! {
Expand Down
13 changes: 12 additions & 1 deletion src/unique_ptr.rs
Original file line number Diff line number Diff line change
@@ -1,8 +1,9 @@
use crate::cxx_vector::{CxxVector, VectorElement};
use crate::fmt::display;
use crate::kind::Trivial;
use crate::memory::SharedPtrTarget;
use crate::string::CxxString;
use crate::ExternType;
use crate::{ExternType, SharedPtr};
use core::ffi::c_void;
use core::fmt::{self, Debug, Display};
use core::marker::PhantomData;
Expand Down Expand Up @@ -107,6 +108,15 @@ where
ty: PhantomData,
}
}

/// Convert this UniquePtr to a SharedPtr, analogous to constructor (13) for [std::shared\_ptr](https://en.cppreference.com/w/cpp/memory/shared_ptr/shared_ptr)
pub fn to_shared(self) -> SharedPtr<T> where T: SharedPtrTarget {
unsafe { SharedPtr::from_unmanaged(self.into_raw()) }
}
}

impl<T> UniquePtr<T>
where T: UniquePtrTarget + SharedPtrTarget {
}

unsafe impl<T> Send for UniquePtr<T> where T: Send + UniquePtrTarget {}
Expand Down Expand Up @@ -225,6 +235,7 @@ pub unsafe trait UniquePtrTarget {
unsafe fn __release(repr: MaybeUninit<*mut c_void>) -> *mut Self;
#[doc(hidden)]
unsafe fn __drop(repr: MaybeUninit<*mut c_void>);

}

extern "C" {
Expand Down
8 changes: 8 additions & 0 deletions tests/test.rs
Original file line number Diff line number Diff line change
Expand Up @@ -280,6 +280,14 @@ fn test_shared_ptr_weak_ptr() {
assert!(weak_ptr.upgrade().is_null());
}

#[test]
fn test_unique_to_shared_ptr() {
let unique = ffi::c_return_unique_ptr_string();
let ptr = &*unique as *const _;
let shared = unique.to_shared();
assert_eq!(&*shared as *const _, ptr);
}

#[test]
fn test_c_ns_method_calls() {
let unique_ptr = ffi2::ns_c_return_unique_ptr_ns();
Expand Down

0 comments on commit c2967b7

Please sign in to comment.