From 4988fcb5438b16dc1540d8cfaac938a9b10d1565 Mon Sep 17 00:00:00 2001 From: Olivier Goffart Date: Fri, 15 May 2020 08:16:49 +0200 Subject: [PATCH] More fix to use vtable for component. All rust code compiles --- api/sixtyfps-rs/sixtyfps-rs-macro/lib.rs | 5 +- helper_crates/vtable/macro/macro.rs | 12 +++- helper_crates/vtable/src/lib.rs | 63 +++++++++++++------ .../corelib/abi/datastructures.rs | 10 +-- sixtyfps_runtime/corelib/lib.rs | 4 +- tools/viewer/main.rs | 25 +++++--- 6 files changed, 80 insertions(+), 39 deletions(-) diff --git a/api/sixtyfps-rs/sixtyfps-rs-macro/lib.rs b/api/sixtyfps-rs/sixtyfps-rs-macro/lib.rs index 8cee777f1..79dbaaf24 100644 --- a/api/sixtyfps-rs/sixtyfps-rs-macro/lib.rs +++ b/api/sixtyfps-rs/sixtyfps-rs-macro/lib.rs @@ -176,9 +176,8 @@ pub fn sixtyfps(stream: TokenStream) -> TokenStream { }); sixtyfps_runtime_run_component_with_gl_renderer( - // FIMXE!!! this does not compile - unsafe { VRefMut::from_inner( - core::ptr::NonNull::new_unchecked(&*COMPONENT_VTABLE as *mut ComponentVTable), + unsafe { VRefMut::from_raw( + core::ptr::NonNull::from(&*COMPONENT_VTABLE), core::ptr::NonNull::from(self).cast() )} ); diff --git a/helper_crates/vtable/macro/macro.rs b/helper_crates/vtable/macro/macro.rs index e13445ca0..26b7ae615 100644 --- a/helper_crates/vtable/macro/macro.rs +++ b/helper_crates/vtable/macro/macro.rs @@ -55,6 +55,10 @@ pub fn vtable(_attr: TokenStream, item: TokenStream) -> TokenStream { let impl_name = quote::format_ident!("{}Impl", trait_name); let type_name = quote::format_ident!("{}Type", trait_name); let module_name = quote::format_ident!("{}_vtable_mod", trait_name); + let ref_name = quote::format_ident!("{}Ref", trait_name); + let refmut_name = quote::format_ident!("{}RefMut", trait_name); + let box_name = quote::format_ident!("{}Box", trait_name); + let vtable_name = input.ident.clone(); let mut drop_impl = None; @@ -386,11 +390,17 @@ pub fn vtable(_attr: TokenStream, item: TokenStream) -> TokenStream { type TraitObject = #to_name; unsafe fn map_to(from: &Self::TraitObject) -> &Self::Trait { from } unsafe fn map_to_mut(from: &mut Self::TraitObject) -> &mut Self::Trait { from } - unsafe fn as_ptr(from: &Self::TraitObject) -> core::ptr::NonNull { from.ptr.cast() } + unsafe fn get_ptr(from: &Self::TraitObject) -> core::ptr::NonNull { from.ptr.cast() } + unsafe fn get_vtable(from: &Self::TraitObject) -> core::ptr::NonNull { from.vtable } + unsafe fn from_raw(vtable: core::ptr::NonNull, ptr: core::ptr::NonNull) -> Self::TraitObject + { #to_name { vtable, ptr : ptr.cast() } } } #drop_impl + pub type #ref_name<'a> = VRef<'a, #vtable_name>; + pub type #refmut_name<'a> = VRefMut<'a, #vtable_name>; + pub type #box_name = VBox<#vtable_name>; } #[doc(inline)] #vis use #module_name::*; diff --git a/helper_crates/vtable/src/lib.rs b/helper_crates/vtable/src/lib.rs index 38e31a95c..75dd3925a 100644 --- a/helper_crates/vtable/src/lib.rs +++ b/helper_crates/vtable/src/lib.rs @@ -1,5 +1,6 @@ use core::ops::{Deref, DerefMut, Drop}; use core::ptr::NonNull; +use core::marker::PhantomData; pub use vtable_macro::vtable; pub unsafe trait VTableMeta { @@ -22,7 +23,12 @@ pub unsafe trait VTableMeta { unsafe fn map_to_mut(to: &mut Self::TraitObject) -> &mut Self::Trait; /// Return a raw pointer to the inside of the impl - unsafe fn as_ptr(from: &Self::TraitObject) -> NonNull; + unsafe fn get_ptr(from: &Self::TraitObject) -> NonNull; + /// return a raw pointer to the vtable + unsafe fn get_vtable(from: &Self::TraitObject) -> NonNull; + + /// Create a trait object from its raw parts + unsafe fn from_raw(vtable: NonNull, ptr: NonNull) -> Self::TraitObject; } pub trait VTableMetaDrop: VTableMeta { @@ -69,8 +75,14 @@ impl VBox { pub unsafe fn inner(x: &Self) -> T::TraitObject { x.inner } - pub unsafe fn as_ptr(x: &Self) -> NonNull { - T::as_ptr(&x.inner) + pub unsafe fn get_ptr(x: &Self) -> NonNull { + T::get_ptr(&x.inner) + } + pub unsafe fn get_vtable(x: &Self) -> NonNull { + T::get_vtable(&x.inner) + } + pub unsafe fn from_raw(vtable: NonNull, ptr: NonNull) -> Self { + Self {inner : T::from_raw(vtable, ptr)} } } @@ -88,15 +100,15 @@ impl VBox { unsafe { self.inner.vtable.as_ref() } }*/ - /* pub fn as_ptr(&self) -> *mut #impl_name { - self.inner.ptr.as_ptr() + /* pub fn get_ptr(&self) -> *mut #impl_name { + self.inner.ptr.get_ptr() }*/ } */ pub struct VRef<'a, T: ?Sized + VTableMeta> { inner: T::TraitObject, - _phantom: core::marker::PhantomData<&'a T::Trait>, + _phantom: PhantomData<&'a T::Trait>, } // Need to implement manually otheriwse it is not implemented if T do not implement Copy / Clone @@ -118,25 +130,25 @@ impl<'a, T: ?Sized + VTableMeta> Deref for VRef<'a, T> { impl<'a, T: ?Sized + VTableMeta> VRef<'a, T> { pub unsafe fn from_inner(inner: T::TraitObject) -> Self { - Self { inner, _phantom: core::marker::PhantomData } + Self { inner, _phantom: PhantomData } } pub unsafe fn inner(x: &Self) -> T::TraitObject { x.inner } - pub unsafe fn as_ptr(x: &Self) -> NonNull { - T::as_ptr(&x.inner) + pub unsafe fn get_ptr(x: &Self) -> NonNull { + T::get_ptr(&x.inner) } -} - -impl<'a, T: ?Sized + VTableMeta> From> for VRef<'a, T> { - fn from(v: VRefMut<'a, T>) -> Self { - unsafe { VRef::from_inner(VRefMut::inner(&v)) } + pub unsafe fn get_vtable(x: &Self) -> NonNull { + T::get_vtable(&x.inner) + } + pub unsafe fn from_raw(vtable: NonNull, ptr: NonNull) -> Self { + Self {inner : T::from_raw(vtable, ptr), _phantom: PhantomData } } } pub struct VRefMut<'a, T: ?Sized + VTableMeta> { inner: T::TraitObject, - _phantom: core::marker::PhantomData<&'a mut T::Trait>, + _phantom: PhantomData<&'a mut T::Trait>, } impl<'a, T: ?Sized + VTableMeta> Deref for VRefMut<'a, T> { @@ -156,12 +168,27 @@ impl<'a, T: ?Sized + VTableMeta> DerefMut for VRefMut<'a, T> { impl<'a, T: ?Sized + VTableMeta> VRefMut<'a, T> { pub unsafe fn from_inner(inner: T::TraitObject) -> Self { - Self { inner, _phantom: core::marker::PhantomData } + Self { inner, _phantom: PhantomData } } pub unsafe fn inner(x: &Self) -> T::TraitObject { x.inner } - pub unsafe fn as_ptr(x: &Self) -> NonNull { - T::as_ptr(&x.inner) + pub unsafe fn get_ptr(x: &Self) -> NonNull { + T::get_ptr(&x.inner) + } + pub unsafe fn get_vtable(x: &Self) -> NonNull { + T::get_vtable(&x.inner) + } + pub unsafe fn from_raw(vtable: NonNull, ptr: NonNull) -> Self { + Self {inner : T::from_raw(vtable, ptr), _phantom: PhantomData } + } + pub fn borrow<'b>(&'b self) -> VRef<'b, T> { + unsafe { VRef::from_inner(VRefMut::inner(self)) } + } + pub fn borrow_mut<'b>(&'b mut self) -> VRefMut<'b, T> { + unsafe { VRefMut::from_inner(VRefMut::inner(self)) } + } + pub fn into_ref(self) -> VRef<'a, T> { + unsafe { VRef::from_inner(VRefMut::inner(&self)) } } } diff --git a/sixtyfps_runtime/corelib/abi/datastructures.rs b/sixtyfps_runtime/corelib/abi/datastructures.rs index 9c3411322..777a1d9d0 100644 --- a/sixtyfps_runtime/corelib/abi/datastructures.rs +++ b/sixtyfps_runtime/corelib/abi/datastructures.rs @@ -185,7 +185,7 @@ fn visit_internal( Item::new( NonNull::new_unchecked(*vtable as *mut _), NonNull::new_unchecked( - (VRef::as_ptr(&component).as_ptr()).offset(*offset) as *mut _, + (VRef::get_ptr(&component).as_ptr()).offset(*offset) as *mut _, ), ) }; @@ -199,7 +199,7 @@ fn visit_internal( } pub fn visit_items_mut( - component: &mut VRefMut<'_, ComponentVTable>, + component: VRefMut<'_, ComponentVTable>, mut visitor: impl FnMut(&mut Item, &State) -> State, state: State, ) { @@ -207,7 +207,7 @@ pub fn visit_items_mut( } fn visit_internal_mut( - component: &mut VRefMut<'_, ComponentVTable>, + mut component: VRefMut<'_, ComponentVTable>, visitor: &mut impl FnMut(&mut Item, &State) -> State, index: isize, state: &State, @@ -219,14 +219,14 @@ fn visit_internal_mut( Item::new( NonNull::new_unchecked(*vtable as *mut _), NonNull::new_unchecked( - (VRefMut::as_ptr(component).as_ptr() as *mut u8).offset(*offset) as *mut _, + (VRefMut::get_ptr(&component).as_ptr() as *mut u8).offset(*offset) as *mut _, ), ) }; let state = visitor(&mut item, state); for c in *children_index..(*children_index + *chilren_count) { - visit_internal_mut(component, visitor, c as isize, &state) + visit_internal_mut(component.borrow_mut(), visitor, c as isize, &state) } } ItemTreeNode::DynamicTree { .. } => todo!(), diff --git a/sixtyfps_runtime/corelib/lib.rs b/sixtyfps_runtime/corelib/lib.rs index e9fb36cb6..dd6ac6634 100644 --- a/sixtyfps_runtime/corelib/lib.rs +++ b/sixtyfps_runtime/corelib/lib.rs @@ -88,7 +88,7 @@ pub fn run_component( // Generate cached rendering data once crate::abi::datastructures::visit_items_mut( - &mut component, + component.borrow_mut(), |item, _| { item_rendering::update_item_rendering_data( item, @@ -100,7 +100,7 @@ pub fn run_component( ); renderer.finish_primitives(rendering_primitives_builder); - let component = vtable::VRef::from(component); + let component = component.into_ref(); main_window.run_event_loop(move |frame, rendering_cache| { item_rendering::render_component_items(component, frame, &rendering_cache); }); diff --git a/tools/viewer/main.rs b/tools/viewer/main.rs index 288807947..b5bc9851c 100644 --- a/tools/viewer/main.rs +++ b/tools/viewer/main.rs @@ -1,4 +1,5 @@ -use corelib::abi::datastructures::{ComponentImpl, ComponentVTable}; +use core::ptr::NonNull; +use corelib::abi::datastructures::{ComponentBox, ComponentRef, ComponentRefMut, ComponentVTable}; use sixtyfps_compiler::object_tree::Expression; use std::collections::HashMap; use structopt::StructOpt; @@ -54,10 +55,14 @@ unsafe fn set_property(ptr: *mut u8, e: &Expression) { T::write(ptr, e); } -unsafe extern "C" fn dummy_destroy(_: *const ComponentVTable, _: *mut ComponentImpl) { +unsafe extern "C" fn dummy_destroy(_: ComponentRefMut) { panic!(); } +unsafe extern "C" fn dummy_create(_: *const ComponentVTable) -> ComponentBox { + panic!() +} + #[repr(C)] struct MyComponentType { ct: ComponentVTable, @@ -65,10 +70,9 @@ struct MyComponentType { } unsafe extern "C" fn item_tree( - c: *const ComponentVTable, - i: *const ComponentImpl, + r: ComponentRef<'_>, ) -> *const corelib::abi::datastructures::ItemTreeNode { - (*(c as *const MyComponentType)).it.as_ptr() + (*(ComponentRef::get_vtable(&r).as_ptr() as *const MyComponentType)).it.as_ptr() } struct RuntimeTypeInfo { @@ -149,7 +153,7 @@ fn main() -> std::io::Result<()> { current_offset += rt.size; }); - let t = ComponentVTable {/* create: None, */ drop: dummy_destroy, item_tree }; + let t = ComponentVTable { create: dummy_create, drop: dummy_destroy, item_tree }; let t = MyComponentType { ct: t, it: tree_array }; let mut my_impl = Vec::::new(); @@ -167,10 +171,11 @@ fn main() -> std::io::Result<()> { } } - gl::sixtyfps_runtime_run_component_with_gl_renderer( - &t as *const MyComponentType as *const ComponentVTable, - std::ptr::NonNull::new(mem).unwrap().cast(), - ); + let component_ref = unsafe { + ComponentRefMut::from_raw(NonNull::from(&t).cast(), NonNull::new(mem).unwrap().cast()) + }; + + gl::sixtyfps_runtime_run_component_with_gl_renderer(component_ref); Ok(()) }