Support shared_ptr of primitives
diff --git a/src/cxx.cc b/src/cxx.cc
index ac10df1..2be483d 100644
--- a/src/cxx.cc
+++ b/src/cxx.cc
@@ -331,6 +331,15 @@
const char *Error::what() const noexcept { return this->msg; }
+namespace {
+template <typename T>
+union MaybeUninit {
+ T value;
+ MaybeUninit() {}
+ ~MaybeUninit() {}
+};
+} // namespace
+
} // namespace cxxbridge1
} // namespace rust
@@ -443,6 +452,34 @@
return cxxbridge1$rust_vec$##RUST_TYPE##$stride(); \
}
+#define SHARED_PTR_OPS(RUST_TYPE, CXX_TYPE) \
+ static_assert(sizeof(std::shared_ptr<CXX_TYPE>) == 2 * sizeof(void *), ""); \
+ static_assert(alignof(std::shared_ptr<CXX_TYPE>) == alignof(void *), ""); \
+ void cxxbridge1$std$shared_ptr$##RUST_TYPE##$null( \
+ std::shared_ptr<CXX_TYPE> *ptr) noexcept { \
+ new (ptr) std::shared_ptr<CXX_TYPE>(); \
+ } \
+ CXX_TYPE *cxxbridge1$std$shared_ptr$##RUST_TYPE##$uninit( \
+ std::shared_ptr<CXX_TYPE> *ptr) noexcept { \
+ CXX_TYPE *uninit = \
+ reinterpret_cast<CXX_TYPE *>(new rust::MaybeUninit<CXX_TYPE>); \
+ new (ptr) std::shared_ptr<CXX_TYPE>(uninit); \
+ return uninit; \
+ } \
+ void cxxbridge1$std$shared_ptr$##RUST_TYPE##$clone( \
+ const std::shared_ptr<CXX_TYPE> &self, \
+ std::shared_ptr<CXX_TYPE> *ptr) noexcept { \
+ new (ptr) std::shared_ptr<CXX_TYPE>(self); \
+ } \
+ const CXX_TYPE *cxxbridge1$std$shared_ptr$##RUST_TYPE##$get( \
+ const std::shared_ptr<CXX_TYPE> &self) noexcept { \
+ return self.get(); \
+ } \
+ void cxxbridge1$std$shared_ptr$##RUST_TYPE##$drop( \
+ const std::shared_ptr<CXX_TYPE> *self) noexcept { \
+ self->~shared_ptr(); \
+ }
+
// Usize and isize are the same type as one of the below.
#define FOR_EACH_NUMERIC(MACRO) \
MACRO(u8, uint8_t) \
@@ -468,9 +505,16 @@
MACRO(char, char) \
MACRO(string, rust::String)
+#define FOR_EACH_SHARED_PTR(MACRO) \
+ FOR_EACH_NUMERIC(MACRO) \
+ MACRO(usize, size_t) \
+ MACRO(isize, rust::isize) \
+ MACRO(string, std::string)
+
extern "C" {
FOR_EACH_STD_VECTOR(STD_VECTOR_OPS)
FOR_EACH_RUST_VEC(RUST_VEC_EXTERNS)
+FOR_EACH_SHARED_PTR(SHARED_PTR_OPS)
} // extern "C"
namespace rust {
diff --git a/src/shared_ptr.rs b/src/shared_ptr.rs
index 7fdb356..63ad7d3 100644
--- a/src/shared_ptr.rs
+++ b/src/shared_ptr.rs
@@ -1,3 +1,4 @@
+use crate::cxx_string::CxxString;
use crate::kind::Trivial;
use crate::ExternType;
use core::ffi::c_void;
@@ -189,3 +190,77 @@
#[doc(hidden)]
unsafe fn __drop(this: *mut c_void);
}
+
+macro_rules! impl_shared_ptr_target {
+ ($segment:expr, $name:expr, $ty:ty) => {
+ unsafe impl SharedPtrTarget for $ty {
+ const __NAME: &'static dyn Display = &$name;
+ unsafe fn __null(new: *mut c_void) {
+ extern "C" {
+ attr! {
+ #[link_name = concat!("cxxbridge1$std$shared_ptr$", $segment, "$null")]
+ fn __null(new: *mut c_void);
+ }
+ }
+ __null(new);
+ }
+ unsafe fn __new(value: Self, new: *mut c_void) {
+ extern "C" {
+ attr! {
+ #[link_name = concat!("cxxbridge1$std$shared_ptr$", $segment, "$uninit")]
+ fn __uninit(new: *mut c_void) -> *mut c_void;
+ }
+ }
+ __uninit(new).cast::<$ty>().write(value);
+ }
+ unsafe fn __clone(this: *const c_void, new: *mut c_void) {
+ extern "C" {
+ attr! {
+ #[link_name = concat!("cxxbridge1$std$shared_ptr$", $segment, "$clone")]
+ fn __clone(this: *const c_void, new: *mut c_void);
+ }
+ }
+ __clone(this, new);
+ }
+ unsafe fn __get(this: *const c_void) -> *const Self {
+ extern "C" {
+ attr! {
+ #[link_name = concat!("cxxbridge1$std$shared_ptr$", $segment, "$get")]
+ fn __get(this: *const c_void) -> *const c_void;
+ }
+ }
+ __get(this).cast()
+ }
+ unsafe fn __drop(this: *mut c_void) {
+ extern "C" {
+ attr! {
+ #[link_name = concat!("cxxbridge1$std$shared_ptr$", $segment, "$drop")]
+ fn __drop(this: *mut c_void);
+ }
+ }
+ __drop(this);
+ }
+ }
+ };
+}
+
+macro_rules! impl_shared_ptr_target_for_primitive {
+ ($ty:ident) => {
+ impl_shared_ptr_target!(stringify!($ty), stringify!($ty), $ty);
+ };
+}
+
+impl_shared_ptr_target_for_primitive!(u8);
+impl_shared_ptr_target_for_primitive!(u16);
+impl_shared_ptr_target_for_primitive!(u32);
+impl_shared_ptr_target_for_primitive!(u64);
+impl_shared_ptr_target_for_primitive!(usize);
+impl_shared_ptr_target_for_primitive!(i8);
+impl_shared_ptr_target_for_primitive!(i16);
+impl_shared_ptr_target_for_primitive!(i32);
+impl_shared_ptr_target_for_primitive!(i64);
+impl_shared_ptr_target_for_primitive!(isize);
+impl_shared_ptr_target_for_primitive!(f32);
+impl_shared_ptr_target_for_primitive!(f64);
+
+impl_shared_ptr_target!("string", "CxxString", CxxString);