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 const_field_offset::FieldOffsets;
|
||||||
pub use corelib::abi::datastructures::{Component, ComponentTO, ComponentVTable, ItemTreeNode};
|
pub use corelib::abi::datastructures::{Component, ComponentTO, ComponentVTable, ItemTreeNode};
|
||||||
pub use corelib::abi::primitives::{Image, ImageVTable, Rectangle, RectangleVTable};
|
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 gl::sixtyfps_runtime_run_component_with_gl_renderer;
|
||||||
pub use once_cell::sync::Lazy;
|
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 {
|
struct #component_id {
|
||||||
#(#item_names : sixtyfps::re_exports::#item_types,)*
|
#(#item_names : sixtyfps::re_exports::#item_types,)*
|
||||||
}
|
}
|
||||||
|
|
||||||
impl core::default::Default for #component_id {
|
impl core::default::Default for #component_id {
|
||||||
fn default() -> Self {
|
fn default() -> Self {
|
||||||
let mut self_ = Self {
|
let mut self_ = Self {
|
||||||
|
@ -168,19 +169,13 @@ pub fn sixtyfps(stream: TokenStream) -> TokenStream {
|
||||||
}
|
}
|
||||||
|
|
||||||
impl #component_id{
|
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::*;
|
use sixtyfps::re_exports::*;
|
||||||
// Would be nice if ComponentVTable::new was const.
|
sixtyfps::re_exports::ComponentVTable_static!(#component_id);
|
||||||
static COMPONENT_VTABLE : Lazy<ComponentVTable> = Lazy::new(|| {
|
let static_self = Box::leak(Box::new(self));
|
||||||
ComponentVTable::new::<#component_id>()
|
sixtyfps_runtime_run_component_with_gl_renderer(VRefMut::new(static_self));
|
||||||
});
|
|
||||||
|
|
||||||
sixtyfps_runtime_run_component_with_gl_renderer(
|
|
||||||
unsafe { VRefMut::from_raw(
|
|
||||||
core::ptr::NonNull::from(&*COMPONENT_VTABLE),
|
|
||||||
core::ptr::NonNull::from(self).cast()
|
|
||||||
)}
|
|
||||||
);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
)
|
)
|
||||||
|
|
|
@ -280,7 +280,7 @@ pub fn vtable(_attr: TokenStream, item: TokenStream) -> TokenStream {
|
||||||
fn new_box<X: HasStaticVTable<#vtable_name>>(value: X) -> VBox<#vtable_name> {
|
fn new_box<X: HasStaticVTable<#vtable_name>>(value: X) -> VBox<#vtable_name> {
|
||||||
// Put the object on the heap and get a pointer to it
|
// Put the object on the heap and get a pointer to it
|
||||||
let ptr = core::ptr::NonNull::from(Box::leak(Box::new(value)));
|
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>;
|
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
|
/// Implements HasStaticVTable<XXXVTable> for the given type
|
||||||
macro_rules! #static_vtable_macro_name {
|
macro_rules! #static_vtable_macro_name {
|
||||||
($ty:ty) => {
|
($ty:ty) => {
|
||||||
unsafe impl ::vtable::HasStaticVTable<#vtable_name> for $ty {
|
unsafe impl vtable::HasStaticVTable<#vtable_name> for $ty {
|
||||||
const VTABLE: #vtable_name = {
|
const VTABLE: #vtable_name = {
|
||||||
|
use vtable::*;
|
||||||
type T = $ty;
|
type T = $ty;
|
||||||
#vtable_name {
|
#vtable_name {
|
||||||
#(#vtable_ctor)*
|
#(#vtable_ctor)*
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
const STATIC_VTABLE : &'static #vtable_name = &Self::VTABLE;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -27,6 +27,7 @@ where
|
||||||
{
|
{
|
||||||
/// Savety: must be a valid VTable for Self
|
/// Savety: must be a valid VTable for Self
|
||||||
const VTABLE: VT::VTable;
|
const VTABLE: VT::VTable;
|
||||||
|
const STATIC_VTABLE: &'static VT::VTable;
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Copy, Clone)]
|
#[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> {
|
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 {
|
unsafe fn from_inner(inner: Inner) -> Self {
|
||||||
Self { inner, phantom: PhantomData }
|
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> {
|
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 {
|
unsafe fn from_inner(inner: Inner) -> Self {
|
||||||
Self { inner, phantom: PhantomData }
|
Self { inner, phantom: PhantomData }
|
||||||
}
|
}
|
||||||
|
|
|
@ -56,4 +56,16 @@ fn test() {
|
||||||
let bx2 = VBox::<HelloVTable>::new(SomeStruct(23));
|
let bx2 = VBox::<HelloVTable>::new(SomeStruct(23));
|
||||||
assert_eq!(bx2.foo(3), 26);
|
assert_eq!(bx2.foo(3), 26);
|
||||||
assert_eq!(bx2.get_vtable().CONSTANT, 88);
|
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]
|
#[no_mangle]
|
||||||
pub static RectangleVTable: ItemVTable = Image::VTABLE;
|
pub static RectangleVTable: ItemVTable = Rectangle::VTABLE;
|
||||||
|
|
||||||
#[no_mangle]
|
#[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