Search code examples
c++windows-runtimec++-winrt

I'm getting unresolved external symbol winrt_make_* when trying to compile C++/WinRT blank app from XamlApplication


I am trying to follow the tutorial here: UWP Xaml Hosting API.

I am at the part of the tutorial where I'm supposed to create a blank app that defines a XamlApplication application. I have defined it in my header (.h) as:

#pragma once
#include "App.xaml.g.h"
namespace winrt::UI_Host::implementation
{
    struct App : Microsoft::Toolkit::Win32::UI::XamlHost::XamlApplicationT<App>
    {
        App();
        ~App();
    };
}

My .cpp file has it defined as:

#include "pch.h"
#include "App.h"
using namespace winrt;
using namespace Windows::ApplicationModel;
using namespace Windows::ApplicationModel::Activation;
using namespace Windows::Foundation;
using namespace Windows::UI::Xaml;
using namespace Windows::UI::Xaml::Controls;
using namespace Windows::UI::Xaml::Navigation;
using namespace UI_Host;
using namespace UI_Host::implementation;

winrt::UI_Host::implementation::App::App()
{
    Initialize();
}

winrt::UI_Host::implementation::App::~App()
{
    Close();
}

If I leave my .IDL file as:

namespace UI_Host{}

It compiles fine, but I can't use the App class in my Win32 Program. So I changed the IDL file to this:

namespace UI_Host
{
    [default_interface]
    runtimeclass App : Microsoft.Toolkit.Win32.UI.XamlHost.XamlApplication
    {
        App();
    }
}

But now it won't compile. The error I get when compiling is this:

>module.g.obj : error LNK2019: unresolved external symbol "void * __cdecl winrt_make_UI_Host_App(void)" (?winrt_make_UI_Host_App@@YAPEAXXZ) referenced in function "void * __cdecl winrt_get_activation_factory(class std::basic_string_view<wchar_t,struct std::char_traits<wchar_t> > const &)" (?winrt_get_activation_factory@@YAPEAXAEBV?$basic_string_view@_WU?$char_traits@_W@std@@@std@@@Z)

Does anyone know why?


Solution

  • C++/WinRT 2.0 introduced a breaking change in order to support Optimized Components. It is used when passing -optimize to cppwinrt.exe. This option is enabled by default for new projects.

    The breaking change requires component authors to #include a generated implementation file into the compilation unit that implements that particular type. In your case, you need to #include "App.g.cpp" into App.cpp (make sure to #include it after the header file App.h).

    To allow your code to compile with and without the -optimize flag, you can conditionally include App.g.cpp:

    #include "App.h"
    
    #if __has_include("App.g.cpp")
    #    include "App.g.cpp"
    #endif
    

    For easy to digest lessons you can read Raymond Chen's blog entry titled Why does my C++/WinRT project get errors of the form "Unresolved external symbol void* __cdecl winrt_make_YourNamespace_YourClass(void)"?.