Windows Dev. Site

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が高レベルという位置づけのようです。
ストアアプリがネイティブコードを出力しているということが少し実感できました。(よりハードに使いところで動作させることは、逆行する動きなのかそれともこれかのトレンドなのか・・)