mirror of
https://github.com/slint-ui/slint.git
synced 2025-08-04 18:58:36 +00:00
corelib: Remove the extern
call in the vtable for wasm
In fact, remove it for non-C++ Because wasm doesn't support C-unwind. And actually warns about incompatible ABI for the rest Fixes #8449
This commit is contained in:
parent
f39b3ab888
commit
f91b61c8ee
8 changed files with 78 additions and 18 deletions
|
@ -68,7 +68,7 @@ allowing to access methods from the trait directly from VRef.
|
|||
This macro does the following transformation:
|
||||
|
||||
For function type fields:
|
||||
- The ABI of each functions is changed to `extern "C"`
|
||||
- If the function has no ABI, it is changed to `extern "C"` (unless `no_extern` is passed as `#[vtable(no_extern)]`)
|
||||
- `unsafe` is added to the signature, since it is unsafe to call these functions directly from
|
||||
the vtable without having a valid pointer to the actual object. But if the original function was
|
||||
marked unsafe, the unsafety is forwarded to the trait.
|
||||
|
@ -165,7 +165,9 @@ assert_eq!(dog.is_hungry, true);
|
|||
|
||||
*/
|
||||
#[proc_macro_attribute]
|
||||
pub fn vtable(_attr: TokenStream, item: TokenStream) -> TokenStream {
|
||||
pub fn vtable(attr: TokenStream, item: TokenStream) -> TokenStream {
|
||||
let no_extern = attr.to_string().trim() == "no_extern";
|
||||
|
||||
let mut input = parse_macro_input!(item as ItemStruct);
|
||||
|
||||
let fields = if let Fields::Named(fields) = &mut input.fields {
|
||||
|
@ -394,7 +396,7 @@ pub fn vtable(_attr: TokenStream, item: TokenStream) -> TokenStream {
|
|||
{
|
||||
return Error::new(a.span(), "invalid ABI").to_compile_error().into();
|
||||
}
|
||||
} else {
|
||||
} else if !no_extern {
|
||||
f.abi = Some(parse_str("extern \"C\"").unwrap());
|
||||
}
|
||||
sig_extern.abi.clone_from(&f.abi);
|
||||
|
@ -478,9 +480,10 @@ pub fn vtable(_attr: TokenStream, item: TokenStream) -> TokenStream {
|
|||
continue;
|
||||
}
|
||||
if ident == "dealloc" {
|
||||
let abi = &sig_extern.abi;
|
||||
vtable_ctor.push(quote!(#ident: {
|
||||
#[allow(unsafe_code)]
|
||||
unsafe extern "C" fn #ident(_: &#vtable_name, ptr: *mut u8, layout: vtable::Layout) {
|
||||
unsafe #abi fn #ident(_: &#vtable_name, ptr: *mut u8, layout: vtable::Layout) {
|
||||
use ::core::convert::TryInto;
|
||||
vtable::internal::dealloc(ptr, layout.try_into().unwrap())
|
||||
}
|
||||
|
|
|
@ -26,6 +26,7 @@ struct AnimalVTable {
|
|||
/// the self object.
|
||||
///
|
||||
/// Note: the #[vtable] macro will automatically add `extern "C"` if that is missing.
|
||||
/// (unless `no_extern` is specified)
|
||||
make_noise: fn(VRef<AnimalVTable>, i32) -> i32,
|
||||
|
||||
/// if there is a 'drop' member, it is considered as the destructor.
|
||||
|
|
|
@ -207,3 +207,30 @@ pub fn slint_doc_str(input: TokenStream) -> TokenStream {
|
|||
assert!(visitor.1, "No slint link found");
|
||||
quote!(#doc).into()
|
||||
}
|
||||
|
||||
/// Attribute macro that removes `extern "..."` from the function signatures
|
||||
///
|
||||
/// This is useful because wasm does not support `extern "C-unwind"` and also
|
||||
/// warn about ABI incompatibilities we wouldn't care about.
|
||||
///
|
||||
/// (can be applied to a function or a vtable struct)
|
||||
#[proc_macro_attribute]
|
||||
pub fn remove_extern(_attr: TokenStream, item: TokenStream) -> TokenStream {
|
||||
let mut input = syn::parse_macro_input!(item as syn::Item);
|
||||
|
||||
match &mut input {
|
||||
syn::Item::Fn(item_fn) => {
|
||||
item_fn.sig.abi.take();
|
||||
}
|
||||
syn::Item::Struct(item_struct) => {
|
||||
for f in item_struct.fields.iter_mut() {
|
||||
if let syn::Type::BareFn(f) = &mut f.ty {
|
||||
f.abi.take();
|
||||
}
|
||||
}
|
||||
}
|
||||
_ => (),
|
||||
}
|
||||
|
||||
quote!(#input).into()
|
||||
}
|
||||
|
|
|
@ -20,15 +20,16 @@ mod htmlimage;
|
|||
mod svg;
|
||||
|
||||
#[allow(missing_docs)]
|
||||
#[vtable::vtable]
|
||||
#[cfg_attr(not(feature = "ffi"), i_slint_core_macros::remove_extern)]
|
||||
#[vtable::vtable(no_extern)]
|
||||
#[repr(C)]
|
||||
pub struct OpaqueImageVTable {
|
||||
drop_in_place: fn(VRefMut<OpaqueImageVTable>) -> Layout,
|
||||
dealloc: fn(&OpaqueImageVTable, ptr: *mut u8, layout: Layout),
|
||||
drop_in_place: extern "C-unwind" fn(VRefMut<OpaqueImageVTable>) -> Layout,
|
||||
dealloc: extern "C-unwind" fn(&OpaqueImageVTable, ptr: *mut u8, layout: Layout),
|
||||
/// Returns the image size
|
||||
size: fn(VRef<OpaqueImageVTable>) -> IntSize,
|
||||
size: extern "C-unwind" fn(VRef<OpaqueImageVTable>) -> IntSize,
|
||||
/// Returns a cache key
|
||||
cache_key: fn(VRef<OpaqueImageVTable>) -> ImageCacheKey,
|
||||
cache_key: extern "C-unwind" fn(VRef<OpaqueImageVTable>) -> ImageCacheKey,
|
||||
}
|
||||
|
||||
#[cfg(feature = "svg")]
|
||||
|
|
|
@ -41,7 +41,8 @@ impl From<IndexRange> for core::ops::Range<usize> {
|
|||
}
|
||||
|
||||
/// A ItemTree is representing an unit that is allocated together
|
||||
#[vtable]
|
||||
#[cfg_attr(not(feature = "ffi"), i_slint_core_macros::remove_extern)]
|
||||
#[vtable(no_extern)]
|
||||
#[repr(C)]
|
||||
pub struct ItemTreeVTable {
|
||||
/// Visit the children of the item at index `index`.
|
||||
|
@ -150,10 +151,10 @@ pub struct ItemTreeVTable {
|
|||
),
|
||||
|
||||
/// in-place destructor (for VRc)
|
||||
pub drop_in_place: unsafe fn(VRefMut<ItemTreeVTable>) -> vtable::Layout,
|
||||
pub drop_in_place: unsafe extern "C-unwind" fn(VRefMut<ItemTreeVTable>) -> vtable::Layout,
|
||||
|
||||
/// dealloc function (for VRc)
|
||||
pub dealloc: unsafe fn(&ItemTreeVTable, ptr: *mut u8, layout: vtable::Layout),
|
||||
pub dealloc: unsafe extern "C-unwind" fn(&ItemTreeVTable, ptr: *mut u8, layout: vtable::Layout),
|
||||
}
|
||||
|
||||
#[cfg(test)]
|
||||
|
@ -1047,8 +1048,9 @@ impl<'a> From<&'a [ItemTreeNode]> for ItemTreeNodeArray<'a> {
|
|||
}
|
||||
}
|
||||
|
||||
#[cfg_attr(not(feature = "ffi"), i_slint_core_macros::remove_extern)]
|
||||
#[vtable(no_extern)]
|
||||
#[repr(C)]
|
||||
#[vtable]
|
||||
/// Object to be passed in visit_item_children method of the ItemTree.
|
||||
pub struct ItemVisitorVTable {
|
||||
/// Called for each child of the visited item
|
||||
|
@ -1057,14 +1059,14 @@ pub struct ItemVisitorVTable {
|
|||
/// as the parent's ItemTree.
|
||||
/// `index` is to be used again in the visit_item_children function of the ItemTree (the one passed as parameter)
|
||||
/// and `item` is a reference to the item itself
|
||||
visit_item: fn(
|
||||
visit_item: extern "C-unwind" fn(
|
||||
VRefMut<ItemVisitorVTable>,
|
||||
item_tree: &VRc<ItemTreeVTable, vtable::Dyn>,
|
||||
index: u32,
|
||||
item: Pin<VRef<ItemVTable>>,
|
||||
) -> VisitChildrenResult,
|
||||
/// Destructor
|
||||
drop: fn(VRefMut<ItemVisitorVTable>),
|
||||
drop: extern "C-unwind" fn(VRefMut<ItemVisitorVTable>),
|
||||
}
|
||||
|
||||
/// Type alias to `vtable::VRefMut<ItemVisitorVTable>`
|
||||
|
|
|
@ -112,7 +112,8 @@ pub enum RenderingResult {
|
|||
}
|
||||
|
||||
/// Items are the nodes in the render tree.
|
||||
#[vtable]
|
||||
#[cfg_attr(not(feature = "ffi"), i_slint_core_macros::remove_extern)]
|
||||
#[vtable(no_extern)]
|
||||
#[repr(C)]
|
||||
pub struct ItemVTable {
|
||||
/// This function is called by the run-time after the memory for the item
|
||||
|
|
|
@ -135,6 +135,7 @@ internal-json = ["dep:serde_json"]
|
|||
i-slint-compiler = { workspace = true }
|
||||
i-slint-common = { workspace = true }
|
||||
i-slint-core = { workspace = true, features = ["default", "rtti"] }
|
||||
i-slint-core-macros = { workspace = true }
|
||||
i-slint-backend-selector = { workspace = true, features = ["rtti"] }
|
||||
|
||||
vtable = { workspace = true }
|
||||
|
|
|
@ -705,6 +705,7 @@ impl ItemTreeDescription<'_> {
|
|||
}
|
||||
}
|
||||
|
||||
#[cfg_attr(not(feature = "ffi"), i_slint_core_macros::remove_extern)]
|
||||
extern "C-unwind" fn visit_children_item(
|
||||
component: ItemTreeRefPin,
|
||||
index: isize,
|
||||
|
@ -1845,6 +1846,7 @@ pub fn get_repeater_by_name<'a, 'id>(
|
|||
(rep_in_comp.offset.apply_pin(instance_ref.instance), rep_in_comp.item_tree_to_repeat.clone())
|
||||
}
|
||||
|
||||
#[cfg_attr(not(feature = "ffi"), i_slint_core_macros::remove_extern)]
|
||||
extern "C-unwind" fn layout_info(
|
||||
component: ItemTreeRefPin,
|
||||
orientation: Orientation,
|
||||
|
@ -1878,6 +1880,7 @@ extern "C-unwind" fn layout_info(
|
|||
result
|
||||
}
|
||||
|
||||
#[cfg_attr(not(feature = "ffi"), i_slint_core_macros::remove_extern)]
|
||||
unsafe extern "C-unwind" fn get_item_ref(component: ItemTreeRefPin, index: u32) -> Pin<ItemRef> {
|
||||
let tree = get_item_tree(component);
|
||||
match &tree[index as usize] {
|
||||
|
@ -1893,6 +1896,7 @@ unsafe extern "C-unwind" fn get_item_ref(component: ItemTreeRefPin, index: u32)
|
|||
}
|
||||
}
|
||||
|
||||
#[cfg_attr(not(feature = "ffi"), i_slint_core_macros::remove_extern)]
|
||||
extern "C-unwind" fn get_subtree_range(component: ItemTreeRefPin, index: u32) -> IndexRange {
|
||||
generativity::make_guard!(guard);
|
||||
let instance_ref = unsafe { InstanceRef::from_pin_ref(component, guard) };
|
||||
|
@ -1922,6 +1926,7 @@ extern "C-unwind" fn get_subtree_range(component: ItemTreeRefPin, index: u32) ->
|
|||
}
|
||||
}
|
||||
|
||||
#[cfg_attr(not(feature = "ffi"), i_slint_core_macros::remove_extern)]
|
||||
extern "C-unwind" fn get_subtree(
|
||||
component: ItemTreeRefPin,
|
||||
index: u32,
|
||||
|
@ -1960,6 +1965,7 @@ extern "C-unwind" fn get_subtree(
|
|||
}
|
||||
}
|
||||
|
||||
#[cfg_attr(not(feature = "ffi"), i_slint_core_macros::remove_extern)]
|
||||
extern "C-unwind" fn get_item_tree(component: ItemTreeRefPin) -> Slice<ItemTreeNode> {
|
||||
generativity::make_guard!(guard);
|
||||
let instance_ref = unsafe { InstanceRef::from_pin_ref(component, guard) };
|
||||
|
@ -1967,6 +1973,7 @@ extern "C-unwind" fn get_item_tree(component: ItemTreeRefPin) -> Slice<ItemTreeN
|
|||
unsafe { core::mem::transmute::<&[ItemTreeNode], &[ItemTreeNode]>(tree) }.into()
|
||||
}
|
||||
|
||||
#[cfg_attr(not(feature = "ffi"), i_slint_core_macros::remove_extern)]
|
||||
extern "C-unwind" fn subtree_index(component: ItemTreeRefPin) -> usize {
|
||||
generativity::make_guard!(guard);
|
||||
let instance_ref = unsafe { InstanceRef::from_pin_ref(component, guard) };
|
||||
|
@ -1977,6 +1984,7 @@ extern "C-unwind" fn subtree_index(component: ItemTreeRefPin) -> usize {
|
|||
}
|
||||
}
|
||||
|
||||
#[cfg_attr(not(feature = "ffi"), i_slint_core_macros::remove_extern)]
|
||||
unsafe extern "C-unwind" fn parent_node(component: ItemTreeRefPin, result: &mut ItemWeak) {
|
||||
generativity::make_guard!(guard);
|
||||
let instance_ref = InstanceRef::from_pin_ref(component, guard);
|
||||
|
@ -2016,6 +2024,7 @@ unsafe extern "C-unwind" fn parent_node(component: ItemTreeRefPin, result: &mut
|
|||
}
|
||||
}
|
||||
|
||||
#[cfg_attr(not(feature = "ffi"), i_slint_core_macros::remove_extern)]
|
||||
unsafe extern "C-unwind" fn embed_component(
|
||||
component: ItemTreeRefPin,
|
||||
parent_component: &ItemTreeWeak,
|
||||
|
@ -2046,6 +2055,7 @@ unsafe extern "C-unwind" fn embed_component(
|
|||
extra_data.embedding_position.set((parent_component.clone(), parent_item_tree_index)).is_ok()
|
||||
}
|
||||
|
||||
#[cfg_attr(not(feature = "ffi"), i_slint_core_macros::remove_extern)]
|
||||
extern "C-unwind" fn item_geometry(component: ItemTreeRefPin, item_index: u32) -> LogicalRect {
|
||||
generativity::make_guard!(guard);
|
||||
let instance_ref = unsafe { InstanceRef::from_pin_ref(component, guard) };
|
||||
|
@ -2068,6 +2078,7 @@ extern "C-unwind" fn item_geometry(component: ItemTreeRefPin, item_index: u32) -
|
|||
|
||||
// silence the warning despite `AccessibleRole` is a `#[non_exhaustive]` enum from another crate.
|
||||
#[allow(improper_ctypes_definitions)]
|
||||
#[cfg_attr(not(feature = "ffi"), i_slint_core_macros::remove_extern)]
|
||||
extern "C-unwind" fn accessible_role(component: ItemTreeRefPin, item_index: u32) -> AccessibleRole {
|
||||
generativity::make_guard!(guard);
|
||||
let instance_ref = unsafe { InstanceRef::from_pin_ref(component, guard) };
|
||||
|
@ -2086,6 +2097,7 @@ extern "C-unwind" fn accessible_role(component: ItemTreeRefPin, item_index: u32)
|
|||
}
|
||||
}
|
||||
|
||||
#[cfg_attr(not(feature = "ffi"), i_slint_core_macros::remove_extern)]
|
||||
extern "C-unwind" fn accessible_string_property(
|
||||
component: ItemTreeRefPin,
|
||||
item_index: u32,
|
||||
|
@ -2115,6 +2127,7 @@ extern "C-unwind" fn accessible_string_property(
|
|||
}
|
||||
}
|
||||
|
||||
#[cfg_attr(not(feature = "ffi"), i_slint_core_macros::remove_extern)]
|
||||
extern "C-unwind" fn accessibility_action(
|
||||
component: ItemTreeRefPin,
|
||||
item_index: u32,
|
||||
|
@ -2150,6 +2163,7 @@ extern "C-unwind" fn accessibility_action(
|
|||
};
|
||||
}
|
||||
|
||||
#[cfg_attr(not(feature = "ffi"), i_slint_core_macros::remove_extern)]
|
||||
extern "C-unwind" fn supported_accessibility_actions(
|
||||
component: ItemTreeRefPin,
|
||||
item_index: u32,
|
||||
|
@ -2172,6 +2186,7 @@ extern "C-unwind" fn supported_accessibility_actions(
|
|||
val
|
||||
}
|
||||
|
||||
#[cfg_attr(not(feature = "ffi"), i_slint_core_macros::remove_extern)]
|
||||
extern "C-unwind" fn item_element_infos(
|
||||
component: ItemTreeRefPin,
|
||||
item_index: u32,
|
||||
|
@ -2186,6 +2201,7 @@ extern "C-unwind" fn item_element_infos(
|
|||
true
|
||||
}
|
||||
|
||||
#[cfg_attr(not(feature = "ffi"), i_slint_core_macros::remove_extern)]
|
||||
extern "C-unwind" fn window_adapter(
|
||||
component: ItemTreeRefPin,
|
||||
do_create: bool,
|
||||
|
@ -2200,14 +2216,22 @@ extern "C-unwind" fn window_adapter(
|
|||
}
|
||||
}
|
||||
|
||||
unsafe extern "C" fn drop_in_place(component: vtable::VRefMut<ItemTreeVTable>) -> vtable::Layout {
|
||||
#[cfg_attr(not(feature = "ffi"), i_slint_core_macros::remove_extern)]
|
||||
unsafe extern "C-unwind" fn drop_in_place(
|
||||
component: vtable::VRefMut<ItemTreeVTable>,
|
||||
) -> vtable::Layout {
|
||||
let instance_ptr = component.as_ptr() as *mut Instance<'static>;
|
||||
let layout = (*instance_ptr).type_info().layout();
|
||||
dynamic_type::TypeInfo::drop_in_place(instance_ptr);
|
||||
layout.into()
|
||||
}
|
||||
|
||||
unsafe extern "C" fn dealloc(_vtable: &ItemTreeVTable, ptr: *mut u8, layout: vtable::Layout) {
|
||||
#[cfg_attr(not(feature = "ffi"), i_slint_core_macros::remove_extern)]
|
||||
unsafe extern "C-unwind" fn dealloc(
|
||||
_vtable: &ItemTreeVTable,
|
||||
ptr: *mut u8,
|
||||
layout: vtable::Layout,
|
||||
) {
|
||||
std::alloc::dealloc(ptr, layout.try_into().unwrap());
|
||||
}
|
||||
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue