[−][src]Macro abi_stable::staticref
Allows declaring a StaticRef
constant.
This macro is most useful when declaring an associated constant of non-'static
types.
Example
This example demonstrates how you can construct a pointer to a vtable, constructed at compile-time.
use abi_stable::{ StableAbi, extern_fn_panic_handling, staticref, pointer_trait::CallReferentDrop, prefix_type::{PrefixTypeTrait, WithMetadata}, }; use std::{ mem::ManuallyDrop, ops::Deref, }; fn main(){ let boxed = BoxLike::new(100); assert_eq!(*boxed, 100); assert_eq!(boxed.into_inner(), 100); } /// An ffi-safe `Box<T>` #[repr(C)] #[derive(StableAbi)] pub struct BoxLike<T> { data: *mut T, vtable: VTable_Ref<T>, _marker: std::marker::PhantomData<T>, } impl<T> BoxLike<T>{ pub fn new(value: T) -> Self { let box_ = Box::new(value); Self{ data: Box::into_raw(box_), vtable: VTable::VTABLE, _marker: std::marker::PhantomData, } } /// Extracts the value this owns. pub fn into_inner(self) -> T{ let this = ManuallyDrop::new(self); unsafe{ // Must copy this before calling `self.vtable.destructor()` // because otherwise it would be reading from a dangling pointer. let ret = this.data.read(); this.vtable.destructor()(this.data,CallReferentDrop::No); ret } } } impl<T> Drop for BoxLike<T>{ fn drop(&mut self){ unsafe{ self.vtable.destructor()(self.data, CallReferentDrop::Yes) } } } // `#[sabi(kind(Prefix))]` Declares this type as being a prefix-type, // generating both of these types: // // - VTable_Prefix`: A struct with the fields up to (and including) the field with the // `#[sabi(last_prefix_field)]` attribute. // // - VTable_Ref`: An ffi-safe pointer to `VTable`,with methods to get `VTable`'s fields. // #[repr(C)] #[derive(StableAbi)] #[sabi(kind(Prefix))] struct VTable<T>{ #[sabi(last_prefix_field)] destructor: unsafe extern "C" fn(*mut T, CallReferentDrop), } impl<T> VTable<T>{ staticref!(const VTABLE_VAL: WithMetadata<Self> = WithMetadata::new( PrefixTypeTrait::METADATA, Self{ destructor: destroy_box::<T>, }, )); const VTABLE: VTable_Ref<T> = { VTable_Ref( Self::VTABLE_VAL.as_prefix() ) }; } unsafe extern "C" fn destroy_box<T>(v: *mut T, call_drop: CallReferentDrop) { extern_fn_panic_handling! { let mut box_ = Box::from_raw(v as *mut ManuallyDrop<T>); if call_drop == CallReferentDrop::Yes { ManuallyDrop::drop(&mut *box_); } drop(box_); } } impl<T> Deref for BoxLike<T> { type Target=T; fn deref(&self)->&T{ unsafe{ &(*self.data) } } }