mirror of
https://github.com/slint-ui/slint.git
synced 2025-10-03 07:04:34 +00:00
vtable: add safe way to construct references
This commit is contained in:
parent
810a3905a7
commit
aff3d7e14b
6 changed files with 48 additions and 17 deletions
|
@ -5,7 +5,8 @@ pub mod re_exports {
|
|||
pub use const_field_offset::FieldOffsets;
|
||||
pub use corelib::abi::datastructures::{Component, ComponentTO, ComponentVTable, ItemTreeNode};
|
||||
pub use corelib::abi::primitives::{Image, ImageVTable, Rectangle, RectangleVTable};
|
||||
pub use corelib::ComponentVTable_static;
|
||||
pub use gl::sixtyfps_runtime_run_component_with_gl_renderer;
|
||||
pub use once_cell::sync::Lazy;
|
||||
pub use vtable::*;
|
||||
pub use vtable::{self, *};
|
||||
}
|
||||
|
|
|
@ -146,6 +146,7 @@ pub fn sixtyfps(stream: TokenStream) -> TokenStream {
|
|||
struct #component_id {
|
||||
#(#item_names : sixtyfps::re_exports::#item_types,)*
|
||||
}
|
||||
|
||||
impl core::default::Default for #component_id {
|
||||
fn default() -> Self {
|
||||
let mut self_ = Self {
|
||||
|
@ -168,19 +169,13 @@ pub fn sixtyfps(stream: TokenStream) -> TokenStream {
|
|||
}
|
||||
|
||||
impl #component_id{
|
||||
fn run(&mut self) {
|
||||
// FIXME: we need a static lifetime for winit run, so this takes the component by value and put it in a leaked box
|
||||
// Ideally we would not need a static lifetime to run the engine. (eg: use run_return function of winit)
|
||||
fn run(self) {
|
||||
use sixtyfps::re_exports::*;
|
||||
// Would be nice if ComponentVTable::new was const.
|
||||
static COMPONENT_VTABLE : Lazy<ComponentVTable> = Lazy::new(|| {
|
||||
ComponentVTable::new::<#component_id>()
|
||||
});
|
||||
|
||||
sixtyfps_runtime_run_component_with_gl_renderer(
|
||||
unsafe { VRefMut::from_raw(
|
||||
core::ptr::NonNull::from(&*COMPONENT_VTABLE),
|
||||
core::ptr::NonNull::from(self).cast()
|
||||
)}
|
||||
);
|
||||
sixtyfps::re_exports::ComponentVTable_static!(#component_id);
|
||||
let static_self = Box::leak(Box::new(self));
|
||||
sixtyfps_runtime_run_component_with_gl_renderer(VRefMut::new(static_self));
|
||||
}
|
||||
}
|
||||
)
|
||||
|
|
|
@ -280,7 +280,7 @@ pub fn vtable(_attr: TokenStream, item: TokenStream) -> TokenStream {
|
|||
fn new_box<X: HasStaticVTable<#vtable_name>>(value: X) -> VBox<#vtable_name> {
|
||||
// Put the object on the heap and get a pointer to it
|
||||
let ptr = core::ptr::NonNull::from(Box::leak(Box::new(value)));
|
||||
unsafe { VBox::from_raw(core::ptr::NonNull::from(&X::VTABLE), ptr.cast()) }
|
||||
unsafe { VBox::from_raw(core::ptr::NonNull::from(X::STATIC_VTABLE), ptr.cast()) }
|
||||
}
|
||||
}
|
||||
pub type #box_name = VBox<#vtable_name>;
|
||||
|
@ -457,13 +457,15 @@ pub fn vtable(_attr: TokenStream, item: TokenStream) -> TokenStream {
|
|||
/// Implements HasStaticVTable<XXXVTable> for the given type
|
||||
macro_rules! #static_vtable_macro_name {
|
||||
($ty:ty) => {
|
||||
unsafe impl ::vtable::HasStaticVTable<#vtable_name> for $ty {
|
||||
unsafe impl vtable::HasStaticVTable<#vtable_name> for $ty {
|
||||
const VTABLE: #vtable_name = {
|
||||
use vtable::*;
|
||||
type T = $ty;
|
||||
#vtable_name {
|
||||
#(#vtable_ctor)*
|
||||
}
|
||||
};
|
||||
const STATIC_VTABLE : &'static #vtable_name = &Self::VTABLE;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -27,6 +27,7 @@ where
|
|||
{
|
||||
/// Savety: must be a valid VTable for Self
|
||||
const VTABLE: VT::VTable;
|
||||
const STATIC_VTABLE: &'static VT::VTable;
|
||||
}
|
||||
|
||||
#[derive(Copy, Clone)]
|
||||
|
@ -115,6 +116,16 @@ impl<'a, T: ?Sized + VTableMeta> Deref for VRef<'a, T> {
|
|||
}
|
||||
|
||||
impl<'a, T: ?Sized + VTableMeta> VRef<'a, T> {
|
||||
pub fn new<X: HasStaticVTable<T>>(value: &'a X) -> Self {
|
||||
Self {
|
||||
inner: Inner {
|
||||
vtable: X::STATIC_VTABLE as *const T::VTable as *const u8,
|
||||
ptr: value as *const X as *const u8,
|
||||
},
|
||||
phantom: PhantomData,
|
||||
}
|
||||
}
|
||||
|
||||
unsafe fn from_inner(inner: Inner) -> Self {
|
||||
Self { inner, phantom: PhantomData }
|
||||
}
|
||||
|
@ -145,6 +156,16 @@ impl<'a, T: ?Sized + VTableMeta> DerefMut for VRefMut<'a, T> {
|
|||
}
|
||||
|
||||
impl<'a, T: ?Sized + VTableMeta> VRefMut<'a, T> {
|
||||
pub fn new<X: HasStaticVTable<T>>(value: &'a mut X) -> Self {
|
||||
Self {
|
||||
inner: Inner {
|
||||
vtable: X::STATIC_VTABLE as *const T::VTable as *const u8,
|
||||
ptr: value as *mut X as *const u8,
|
||||
},
|
||||
phantom: PhantomData,
|
||||
}
|
||||
}
|
||||
|
||||
unsafe fn from_inner(inner: Inner) -> Self {
|
||||
Self { inner, phantom: PhantomData }
|
||||
}
|
||||
|
|
|
@ -56,4 +56,16 @@ fn test() {
|
|||
let bx2 = VBox::<HelloVTable>::new(SomeStruct(23));
|
||||
assert_eq!(bx2.foo(3), 26);
|
||||
assert_eq!(bx2.get_vtable().CONSTANT, 88);
|
||||
|
||||
let mut hello = SomeStruct(44);
|
||||
{
|
||||
let xref = VRef::<HelloVTable>::new(&hello);
|
||||
assert_eq!(xref.foo(0), 44);
|
||||
}
|
||||
{
|
||||
let mut xref = VRefMut::<HelloVTable>::new(&mut hello);
|
||||
assert_eq!(xref.foo_mut(2), 46);
|
||||
let xref2 = xref.borrow();
|
||||
assert_eq!(xref2.foo(1), 47);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -84,7 +84,7 @@ impl ItemConsts for Image {
|
|||
}
|
||||
|
||||
#[no_mangle]
|
||||
pub static RectangleVTable: ItemVTable = Image::VTABLE;
|
||||
pub static RectangleVTable: ItemVTable = Rectangle::VTABLE;
|
||||
|
||||
#[no_mangle]
|
||||
pub static ImageVTable: ItemVTable = Rectangle::VTABLE;
|
||||
pub static ImageVTable: ItemVTable = Image::VTABLE;
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue