mirror of
https://github.com/topjohnwu/cxx.git
synced 2025-02-24 10:03:39 +00:00
Allow creation of UniquePtrs to trivial aliased types.
This commit is contained in:
parent
e35673d7de
commit
d75f7e2911
@ -1245,7 +1245,12 @@ fn write_unique_ptr_common(out: &mut OutFile, ty: &Type, types: &Types) {
|
||||
let instance = to_mangled(&out.namespace, ty);
|
||||
|
||||
let can_construct_from_value = match ty {
|
||||
Type::Ident(ident) => types.structs.contains_key(ident),
|
||||
// Some aliases are to opaque types; some are to trivial types.
|
||||
// We can't know at code generation time, so we generate both C++
|
||||
// and Rust side bindings for a "new" method anyway. But that
|
||||
// Rust code will explode at runtime if anyone tries to call it on
|
||||
// an opaque type.
|
||||
Type::Ident(ident) => types.structs.contains_key(ident) || types.aliases.contains_key(ident),
|
||||
_ => false,
|
||||
};
|
||||
|
||||
|
@ -814,13 +814,22 @@ fn expand_unique_ptr(
|
||||
let link_release = format!("{}release", prefix);
|
||||
let link_drop = format!("{}drop", prefix);
|
||||
|
||||
let new_method = if types.structs.contains_key(ident) {
|
||||
let new_method = if types.structs.contains_key(ident) || types.aliases.contains_key(ident) {
|
||||
let trivial_assertion: Option<syn::Stmt> = if types.aliases.contains_key(ident) {
|
||||
Some(parse_quote! {
|
||||
< < #ident as :: cxx :: ExternType > :: Kind as :: cxx :: kind :: Kind > :: assert_trivial();
|
||||
})
|
||||
} else {
|
||||
None
|
||||
};
|
||||
|
||||
Some(quote! {
|
||||
fn __new(mut value: Self) -> *mut ::std::ffi::c_void {
|
||||
extern "C" {
|
||||
#[link_name = #link_new]
|
||||
fn __new(this: *mut *mut ::std::ffi::c_void, value: *mut #ident);
|
||||
}
|
||||
#trivial_assertion
|
||||
let mut repr = ::std::ptr::null_mut::<::std::ffi::c_void>();
|
||||
unsafe { __new(&mut repr, &mut value) }
|
||||
repr
|
||||
|
@ -165,9 +165,17 @@ pub mod kind {
|
||||
/// indirection.
|
||||
pub enum Trivial {}
|
||||
|
||||
pub trait Kind: private::Sealed {}
|
||||
impl Kind for Opaque {}
|
||||
impl Kind for Trivial {}
|
||||
pub trait Kind: private::Sealed {
|
||||
fn assert_trivial();
|
||||
}
|
||||
impl Kind for Opaque {
|
||||
fn assert_trivial() {
|
||||
panic!("Type not trivial");
|
||||
}
|
||||
}
|
||||
impl Kind for Trivial {
|
||||
fn assert_trivial() {}
|
||||
}
|
||||
}
|
||||
|
||||
mod private {
|
||||
|
@ -12,12 +12,14 @@
|
||||
pub mod ffi2 {
|
||||
impl UniquePtr<D> {}
|
||||
impl UniquePtr<E> {}
|
||||
impl UniquePtr<F> {}
|
||||
|
||||
extern "C" {
|
||||
include!("tests/ffi/tests.h");
|
||||
|
||||
type D = crate::other::D;
|
||||
type E = crate::other::E;
|
||||
type F = crate::other::F;
|
||||
|
||||
fn c_take_trivial_ptr(d: UniquePtr<D>);
|
||||
fn c_take_trivial_ref(d: &D);
|
||||
|
@ -14,15 +14,23 @@ mod other {
|
||||
use cxx::kind::{Opaque, Trivial};
|
||||
use cxx::{type_id, CxxString, ExternType};
|
||||
|
||||
// Trivial.
|
||||
#[repr(C)]
|
||||
pub struct D {
|
||||
d: u64,
|
||||
pub d: u64,
|
||||
}
|
||||
|
||||
// Opaque, and has realistic complexity.
|
||||
#[repr(C)]
|
||||
pub struct E {
|
||||
e: u64,
|
||||
e_str: CxxString,
|
||||
e: u64,
|
||||
}
|
||||
|
||||
// Opaque, but simple enough that bad code can try to create it.
|
||||
#[repr(C)]
|
||||
pub struct F {
|
||||
pub f: u64,
|
||||
}
|
||||
|
||||
unsafe impl ExternType for D {
|
||||
@ -34,6 +42,11 @@ mod other {
|
||||
type Id = type_id!("tests::E");
|
||||
type Kind = Opaque;
|
||||
}
|
||||
|
||||
unsafe impl ExternType for F {
|
||||
type Id = type_id!("tests::F");
|
||||
type Kind = Opaque;
|
||||
}
|
||||
}
|
||||
|
||||
#[cxx::bridge(namespace = tests)]
|
||||
|
@ -37,6 +37,10 @@ struct E {
|
||||
std::string e_str;
|
||||
};
|
||||
|
||||
struct F {
|
||||
uint64_t f;
|
||||
};
|
||||
|
||||
enum COwnedEnum {
|
||||
CVal1,
|
||||
CVal2,
|
||||
|
@ -199,6 +199,7 @@ fn test_extern_trivial() {
|
||||
check!(ffi2::c_take_trivial(d));
|
||||
let d = ffi2::c_return_trivial_ptr();
|
||||
check!(ffi2::c_take_trivial_ptr(d));
|
||||
cxx::UniquePtr::new(ffi2::D { d: 42 });
|
||||
}
|
||||
|
||||
#[test]
|
||||
@ -206,4 +207,7 @@ fn test_extern_opaque() {
|
||||
let e = ffi2::c_return_opaque_ptr();
|
||||
check!(ffi2::c_take_opaque_ref(e.as_ref().unwrap()));
|
||||
check!(ffi2::c_take_opaque_ptr(e));
|
||||
assert!(std::panic::catch_unwind(|| {
|
||||
cxx::UniquePtr::new(ffi2::F { f: 42 })
|
||||
}).is_err());
|
||||
}
|
||||
|
Loading…
x
Reference in New Issue
Block a user