Windows ランタイム C++ テンプレート ライブラリ (WRL)
C++/CXでもない、標準のC++からWinRTのAPIが使用できる方法が以下のサイトであったので、いろいろと調べてみました。
(C++/CLIからできないことはテスト済み)
WRL を使用して非同期操作を完了する
http://msdn.microsoft.com/ja-jp/library/vstudio/hh973451.aspx
エラー処理を省略するなどしてソースを見やすくしました。
環境 : VisualStudio 2012 / Windows 8
プロジェクトは、C++ の空のプロジェクトを使い、runtimeobject.libを「追加の依存ファイル」に追加します。
#include <Windows.Foundation.h>
#include <Windows.System.Threading.h>
#include <wrl/event.h>
#include <stdio.h>
#include <Objbase.h>
using namespace ABI::Windows::Foundation;
using namespace ABI::Windows::System::Threading;
using namespace Microsoft::WRL;
using namespace Microsoft::WRL::Wrappers;
int main()
{
// Initialize the Windows Runtime.
RoInitializeWrapper initialize(RO_INIT_MULTITHREADED);
// Get the activation factory for the IThreadPoolTimer interface.
ComPtr<IThreadPoolTimerStatics> timerFactory;
HRESULT hr = GetActivationFactory(HStringReference(RuntimeClass_Windows_System_Threading_ThreadPoolTimer).Get(), &timerFactory);
// Create an event that is set after the timer callback completes. We later use this event to wait for the timer to complete.
// This event is for demonstration only in a console app. In most apps, you typically don't wait for async operations to complete.
Event timerCompleted(CreateEventEx(NULL, NULL, CREATE_EVENT_MANUAL_RESET, WRITE_OWNER | EVENT_ALL_ACCESS));
// Create a timer that prints a message after 2 seconds.
TimeSpan delay;
delay.Duration = 20000000; // 2 seconds.
auto callback = Callback<ITimerElapsedHandler>([&timerCompleted](IThreadPoolTimer* timer) -> HRESULT
{
TimeSpan delay;
HRESULT hr = timer->get_Delay(&delay);
if (SUCCEEDED(hr))
{
printf("Timer duration: %2.2f seconds.\n", delay.Duration / 10000000.0);
}
// Set the completion event and return.
SetEvent(timerCompleted.Get());
return hr;
});
ComPtr<IThreadPoolTimer> timer;
hr = timerFactory->CreateTimer(callback.Get(), delay, &timer);
printf("Timer started...\n");
// Wait for the timer to complete.
WaitForSingleObjectEx(timerCompleted.Get(), INFINITE, FALSE);
// All smart pointers and RAII objects go out of scope here.
}
cl.exe wrl-consume-asyncOp.cpp runtimeobject.lib
VisualStudioを使わなくても、コンパイルは上のように簡単にできますが、使うプロジェクトとか、ヘッダの中身を確認したかったので、あえて使ってみました。
(たしかに標準C++であるという確認のため)
実行すると以下のようにコンソールに出力します。
Timer started.
Timer duration: 2.00 seconds.
二秒後にコールバックを登録した処理を動作させるものです。WinRTのランタイムでなくてもできることですが、現在は標準C++からでもWinRTのAPIがコールできるという確認にとどめたいと思います。もっとWinRTらしい使い方を見つけたらまたテストしたいと思います。
あと、WRTが低レベル、C++/CXが高レベルという位置づけのようです。
ストアアプリがネイティブコードを出力しているということが少し実感できました。(よりハードに使いところで動作させることは、逆行する動きなのかそれともこれかのトレンドなのか・・)