diff --git a/api/sixtyfps-rs/lib.rs b/api/sixtyfps-rs/lib.rs index ba37a94ba..e0887fe02 100644 --- a/api/sixtyfps-rs/lib.rs +++ b/api/sixtyfps-rs/lib.rs @@ -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, *}; } diff --git a/api/sixtyfps-rs/sixtyfps-rs-macro/lib.rs b/api/sixtyfps-rs/sixtyfps-rs-macro/lib.rs index 79dbaaf24..c1c085022 100644 --- a/api/sixtyfps-rs/sixtyfps-rs-macro/lib.rs +++ b/api/sixtyfps-rs/sixtyfps-rs-macro/lib.rs @@ -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 = 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)); } } ) diff --git a/helper_crates/vtable/macro/macro.rs b/helper_crates/vtable/macro/macro.rs index f7cc2ef9a..492b7f657 100644 --- a/helper_crates/vtable/macro/macro.rs +++ b/helper_crates/vtable/macro/macro.rs @@ -280,7 +280,7 @@ pub fn vtable(_attr: TokenStream, item: TokenStream) -> TokenStream { fn new_box>(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 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; } } } diff --git a/helper_crates/vtable/src/lib.rs b/helper_crates/vtable/src/lib.rs index a1a2ffdd4..94b027169 100644 --- a/helper_crates/vtable/src/lib.rs +++ b/helper_crates/vtable/src/lib.rs @@ -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>(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>(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 } } diff --git a/helper_crates/vtable/tests/test_vtable.rs b/helper_crates/vtable/tests/test_vtable.rs index 272923bd1..d66efdfaf 100644 --- a/helper_crates/vtable/tests/test_vtable.rs +++ b/helper_crates/vtable/tests/test_vtable.rs @@ -56,4 +56,16 @@ fn test() { let bx2 = VBox::::new(SomeStruct(23)); assert_eq!(bx2.foo(3), 26); assert_eq!(bx2.get_vtable().CONSTANT, 88); + + let mut hello = SomeStruct(44); + { + let xref = VRef::::new(&hello); + assert_eq!(xref.foo(0), 44); + } + { + let mut xref = VRefMut::::new(&mut hello); + assert_eq!(xref.foo_mut(2), 46); + let xref2 = xref.borrow(); + assert_eq!(xref2.foo(1), 47); + } } diff --git a/sixtyfps_runtime/corelib/abi/primitives.rs b/sixtyfps_runtime/corelib/abi/primitives.rs index e9c04b712..7b23a173b 100644 --- a/sixtyfps_runtime/corelib/abi/primitives.rs +++ b/sixtyfps_runtime/corelib/abi/primitives.rs @@ -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;