Skip to content

module: define Attribute::uuid() out-of-line so its any_cast cannot mismatch - #322

Open
jhery-rdo wants to merge 1 commit into
AcademySoftwareFoundation:developfrom
jhery-rdo:fix/attribute-uuid-out-of-line-upstream
Open

module: define Attribute::uuid() out-of-line so its any_cast cannot mismatch#322
jhery-rdo wants to merge 1 commit into
AcademySoftwareFoundation:developfrom
jhery-rdo:fix/attribute-uuid-out-of-line-upstream

Conversation

@jhery-rdo

@jhery-rdo jhery-rdo commented Aug 19, 2026

Copy link
Copy Markdown
Contributor

Attribute::uuid() was defined inline in attribute.hpp, so every image that included the header got its own instantiation of get_role_data<utility::Uuid>() and with it its own std::any_cast<Uuid> call site.

std::any_cast matches on type_info identity, not on type name, and typeinfo for xstudio::utility::Uuid is emitted privately into each image rather than exported from a single library. A plugin's typeid(Uuid) is therefore a different object from the one libmodule used when Attribute's constructor stored the UuidRole data, and the cast throws bad_any_cast even though both sides are the same type.

Reproduced on macOS (Apple Silicon, 1.3.0) with a Blackmagic DeckLink card and Desktop Video installed. BMDecklinkPlugin::attribute_changed() compares the incoming uuid against resolutions_->uuid(), start_stop_->uuid() and nine others; the first of those calls during plugin construction throws:

AttributeData::get() [T = xstudio::utility::Uuid] Attempt to get
AttributeData with type N7xstudio7utility4UuidE as type
N7xstudio7utility4UuidE
StudioUI::loadVideoOutputPlugin(...) error("bad any cast")

Spawn fails, so initialise() never runs, so the register_viewport_dockable_widget() call that creates the SDI output button never happens. The button is simply absent from the toolbar, and nothing in the default log points at the cause.

Defining uuid() in attribute.cpp means the cast is instantiated exactly once, in the same image that wrote the role data, so it cannot mismatch regardless of a plugin's visibility flags or the toolchain's RTTI emission. Attribute::operator==(const Attribute &) and operator==(const utility::Uuid &) both call uuid() and are fixed by the same change.

Other in-tree plugins call Attribute::uuid() from their own translation units too, so this is not specific to the DeckLink plugin -- that is just the one that calls it during construction and therefore hits it every time.

…ismatch

Attribute::uuid() was defined inline in attribute.hpp, so every image that
included the header got its own instantiation of get_role_data<utility::Uuid>()
and with it its own std::any_cast<Uuid> call site.

std::any_cast matches on type_info identity, not on type name, and typeinfo for
xstudio::utility::Uuid is emitted privately into each image rather than exported
from a single library. A plugin's typeid(Uuid) is therefore a different object
from the one libmodule used when Attribute's constructor stored the UuidRole
data, and the cast throws bad_any_cast even though both sides are the same type.

Reproduced on macOS (Apple Silicon, 1.3.0) with a Blackmagic DeckLink card and
Desktop Video installed. BMDecklinkPlugin::attribute_changed() compares the
incoming uuid against resolutions_->uuid(), start_stop_->uuid() and nine others;
the first of those calls during plugin construction throws:

    AttributeData::get() [T = xstudio::utility::Uuid] Attempt to get
    AttributeData with type N7xstudio7utility4UuidE as type
    N7xstudio7utility4UuidE
    StudioUI::loadVideoOutputPlugin(...) error("bad any cast")

Spawn fails, so initialise() never runs, so the
register_viewport_dockable_widget() call that creates the SDI output button
never happens. The button is simply absent from the toolbar, and nothing in the
default log points at the cause.

Defining uuid() in attribute.cpp means the cast is instantiated exactly once, in
the same image that wrote the role data, so it cannot mismatch regardless of a
plugin's visibility flags or the toolchain's RTTI emission.
Attribute::operator==(const Attribute &) and operator==(const utility::Uuid &)
both call uuid() and are fixed by the same change.

Other in-tree plugins call Attribute::uuid() from their own translation units
too, so this is not specific to the DeckLink plugin -- that is just the one that
calls it during construction and therefore hits it every time.

Verified on the affected machine: the SDI output button is back.
@jhery-rdo
jhery-rdo force-pushed the fix/attribute-uuid-out-of-line-upstream branch from 9b7f154 to 2b18a25 Compare August 19, 2026 21:14
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant