C++/CX を置き換えるよさげなライブラリ C++WinRT を発見した。

C++/CX の機能を純粋な C++(C++17 とか新しめの)で実装したものらしく、WinRT の C++バインディングのような位置。 C++/CX で

Windows::UI::Core::CoreWindow ^window;

のようなものを

#include <winrt/Windows.UI.Core.h>
winrt::Windows::UI::Core::Core window;

のように置き換える。-> じゃなくて . を使うスマートポインタで実装されている。

  • Migrating C++/CX source code to C++/WinRT

C++/CX で async, await な非同期を実装する道具だった PPL もうまく置き換えているようだ。

  • Using C++ co-routines with C++/WinRT asynchronous methods

やってみる clone https://github.com/Microsoft/cppwinrtをcloneしてincludeできるようにしておく。 C++WinRT はヘッダオンリーライブラリである。 ビルド確認

github.com
github.com favicon https://github.com/Microsoft/cppwinrt/tree/master/10.0.15063.0/Samples/CL

をベース。

main.cpp
#pragma comment(lib, "windowsapp")
#include <winrt/base.h>
int __stdcall wWinMain(HINSTANCE, HINSTANCE, PWSTR, int)
{
winrt::init_apartment();
return 0;
}

あえて CMake で。 CMakeLists.txt

CMAKE_MINIMUM_REQUIRED(VERSION 3.5)
PROJECT(RendererToolkit) # .sln
ADD_DEFINITIONS(
-DWIN32=1
-DUNICODE=1
-D_UNICODE=1
)
SET(CMAKE_C_FLAGS "/ZW /EHsc /await /std:c++latest")
SET(CMAKE_CXX_FLAGS ${CMAKE_C_FLAGS})
INCLUDE_DIRECTORIES(
# 適当にcloneしたパスを参照
${CMAKE_CURRENT_LIST_DIR}/cppwinrt/10.0.15063.0
)
##############################################################################
# project
##############################################################################
SET(PROJECTNAME _SampleCoreWindow)
FILE(GLOB SRCS *.cpp *.h)
ADD_EXECUTABLE(${PROJECTNAME} WIN32 ${SRCS})
TARGET_INCLUDE_DIRECTORIES(${PROJECTNAME} PUBLIC
${SUBRENDERER_INCLUDE}
)

UWP をターゲットにしたプロジェクトを生成する。

> mkdir build
> cd build
build> cmake.exe -DCMAKE_SYSTEM_NAME=WindowsStore -DCMAKE_SYSTEM_VERSION=10.0 -DCMAKE_C_FLAGS=/ZW /EHsc -G "Visual Studio 15 2017 Win64" ..

ビルドすると警告が出る。

warning C4447: スレッド モデルのない 'main' シグネチャが見つかりました。'int main(Platform::Array<Platform::String^>^ args)' の使用を検討してください。

以下のように属性をつければ外せた。

[Platform::MTAThread]
int __stdcall wWinMain(HINSTANCE, HINSTANCE, PWSTR, int)

Debug - X64 - ローカルコンピューター でアプリが起動して、即終了することが確認できればよし。 UWP の作法で空の App を作ってみる

#pragma comment(lib, "windowsapp")
#include <winrt/Windows.ApplicationModel.Core.h>
#include <winrt/Windows.UI.Core.h>
//
// IFrameworkViewSourceとIFrameworkViewを一体化させるのは必要(ばらすとエラーになった)
//
struct App : winrt::implements<App
, winrt::Windows::ApplicationModel::Core::IFrameworkViewSource
, winrt::Windows::ApplicationModel::Core::IFrameworkView>
{
winrt::Windows::ApplicationModel::Core::IFrameworkView CreateView()
{
return *this;
}
void Initialize(winrt::Windows::ApplicationModel::Core::CoreApplicationView const&)
{
}
void Load(winrt::hstring const&)
{
}
void Uninitialize()
{
}
void Run()
{
auto window = winrt::Windows::UI::Core::CoreWindow::GetForCurrentThread();
window.Activate();
//
auto dispatcher = window.Dispatcher();
dispatcher.ProcessEvents(winrt::Windows::UI::Core::CoreProcessEventsOption::ProcessUntilQuit);
}
void SetWindow(winrt::Windows::UI::Core::CoreWindow const&)
{
}
};
int __stdcall wWinMain(HINSTANCE, HINSTANCE, PWSTR, int)
{
winrt::init_apartment();
winrt::Windows::ApplicationModel::Core::CoreApplication::Run(App());
}

警告とは無関係に、実行に

[Platform::MTAThread]winrt::init_apartment(); のどちらかが必要?

IUnknown*を得る winrt::get_abi メモ

github.com
github.com favicon https://github.com/Kitware/CMake/blob/master/Tests/VSWinStorePhone/CMakeLists.txt

VisualStudio2017 の C++/CX Universal D3D11 のテンプレートを C++/WinRT バージョンに改造できた。間違ってもコンパイルが通って実行時エラーになるのに難儀したが、C++/CX よりはだいぶ使い勝手がよさげな感じ。