Unable to implement classic COM interface on XAML component with C++/WinRT
See original GitHub issueDescribe the bug
When creating a XAML control/page, it’s not possible to make it implement a classic COM interface (as C++/WinRT does it, by appending it to the base template arguments: Something : SomethingT<Something, IMyClassicInterface>
) because the XAML compiler codegen does not account for this case.
Steps to reproduce the bug
- Create a new blank C++/WinRT UWP app in VS
- Open MainPage.h, and add the following code:
- Include
<windows.ui.xaml.media.dxinterop.h>
. - Change the struct declaration to
struct MainPage : MainPageT<MainPage, ISwapChainPanelNative>
. - Add
IFACEMETHOD(SetSwapChain)(IDXGISwapChain*) noexcept;
to the struct members.
- Include
- In MainPage.cpp, add the implementation:
IFACEMETHODIMP MainPage::SetSwapChain(IDXGISwapChain*) noexcept { // dummy implementation return S_OK; }
- Try building the app.
- Observe compiler errors.
Expected behavior
The app builds fine and a consumer is able to cast the XAML component to ISwapChainPanelNative
and call the method provided by that interface.
Screenshots
Version Info
NuGet package version: [Microsoft.Windows.CppWinRT 2.0.200921.6]
Windows app type:
UWP | Win32 |
---|---|
Yes | Yes |
Windows 10 version | Saw the problem? |
---|---|
Insider Build (xxxxx) | |
May 2020 Update (19041) | Yes |
November 2019 Update (18363) | |
May 2019 Update (18362) | |
October 2018 Update (17763) | |
April 2018 Update (17134) | |
Fall Creators Update (16299) | |
Creators Update (15063) |
Device form factor | Saw the problem? |
---|---|
Desktop | Yes |
Xbox | |
Surface Hub | |
IoT |
Additional context
I replied Yes to the app type being Win32 because this issue showed up in system XAML islands while implementing IInitializeWithWindow
to pass on a window handle to MessageDialog from my hosting code to the XAML code. I’m using MessageDialog because of ContentDialog’s limitation of one dialog open at a time per thread. Implementing threading proved to be a huge pain, so I’ve decided on using MessageDialog for now.
The bug is caused by this line in MainPage.xaml.g.hpp:
template struct MainPageT<struct MainPage>;
It tries to specialize MainPageT
using different parameters than what I used in my declaration, and since the class uses CRTP, it tries to cast this
back to MainPage, but because MainPage actually inherits from a different type (different template instantiations are effectively different types), the cast fails.
Issue Analytics
- State:
- Created 3 years ago
- Reactions:2
- Comments:13 (12 by maintainers)
Top GitHub Comments
@sylveon There was a brief but real moment when I realized I was here because I was also implementing
IInitializeWithWindow
in a XAML islands application that I was quite crestfallen because these are the depths to which we must sink.Why does the XAML generated header need to forcibly instantiate this template anyway? Does it not suffice to let the consumer do it?
I really don’t recommend it, it’s extremely fragile.