Friday, August 24, 2012

C++11 and Modern C++ for Modern Nay Metro Nay Windows 8 Style Apps for the C Programmer

As a developer who almost exclusively does low-level C and C like C++ systems programming for Windows and avoids high-level abstractions like STL, looking at the modern Windows 8 code samples which are decidedly C++11, one can feel like one is reading code from some other language.  At first I was a little bemused at the C++11 syntax used heavily throughout the samples, but as a developer one must keep current and always be moving forward, or become obsolete … right!? RIGHT!?!?  I guess you only need so many Windows kernel programmers.

If you want, you can crazy and program modern apps using JavaScript or C# as you would C++ in the new Windows runtime, but I will start with getting my feet wet with C++.  Plus C# and JavaScript will eventually get thunked down to C++ for the runtime projections, and C++ code calls directly into the projections without thunking.  I guess if you are going with JavaScript or C#, you don’t really care about those kind of things anyway, but I digress.  

I found this MSDN article which is a nice primer.  Read this first: http://msdn.microsoft.com/en-us/library/hh279654.aspx
I think it does a good job going over the big ideas of what this C++11 paradigm in VS12 is about.  To me, it feels like they were trying to take the goals of various C++ programming models found in previous versions of STL, ATL, COM, and so on and refine it to the next "modern" version of C++.  I was resistant at first, but maybe C++11 is for me as I am not a big fan of those C++ programming models because of their various shortcomings and generally avoid them.

You can read all of the official documentation if you have time, but I just like to jump in with the code and get my hands dirty.  Often you learn more anyway when you have to accomplish something.  I am going to start with the device enumeration RT projection, because I normally do a lot of device-related programming and I have done a few posts in the past on how to enumerate devices with the various Windows APIs.

http://code.msdn.microsoft.com/windowsapps/Device-Enumeration-Sample-a6e45169

This sample shows you how to enumerate device containers and interfaces.  The same API is also used for devnodes and everything else.  So, jumping to the containers.xaml.cpp file which enumerates containers you will find the EnumerateDeviceContainers method which does the actual work of enumerating.

void Containers::EnumerateDeviceContainers(Object^ sender, RoutedEventArgs^ eventArgs)
{
    Windows::UI::Xaml::FocusState focusState = EnumerateContainersButton->FocusState;
    EnumerateContainersButton->IsEnabled = false;

    DeviceContainersOutputList->Items->Clear();

    auto properties = ref new Vector();
    properties->Append("System.ItemNameDisplay");
    properties->Append("System.Devices.ModelName");
    properties->Append("System.Devices.Connected");

    task(
        PnpObject::FindAllAsync(PnpObjectType::DeviceContainer, properties))
        .then([this](PnpObjectCollection^ containers)
    {
        rootPage->NotifyUser(containers->Size + " device container(s) found\n\n", NotifyType::StatusMessage);
;

        std::for_each(begin(containers), end(containers),
            [this](PnpObject^ container)
        {
            DisplayDeviceContainer(container);
        });
    });

    EnumerateContainersButton->IsEnabled = true;
}
  

C++/CX Pointers and Handles

For the C++11 uninitiated, there are a lot of weird things going on here.  First off, what does those carat/hat '^' instead of the '*'  mean by the types (ex. PnpObjectCollection^ containers)?
The very basic idea is that * types are the standard pointers that you are familiar with, and the ^ types are really handles to managed allocations.  The simplistic idea is that these var^ var allocation lifetimes are managed for you (think: ATL smart pointers).


Lambda Expressions

Lambdas are used all over the place in the samples.  What are they?  Simplistically they are functions that you can define inline or declare in say a method  ... more or less. ;)

You May go directly to the official documentation on lambdas on MSDN if you want to get it straight from the horse’s mouth.

The syntax: http://msdn.microsoft.com/en-us/library/dd293603.aspx
Use examples of lambdas: http://msdn.microsoft.com/en-us/library/dd293599.aspx

        std::for_each(begin(containers), end(containers),
            [this](PnpObject^ container)
        {
            DisplayDeviceContainer(container);
        });

From the sample, you see this for_each iterator from std.  The last parameter of the for each is the lambda.


[this] <= means you are "capturing" the "this" variable by value
(PnpObject^ container) <= parameter list for the function
{DisplayDeviceContainer(container);} <= this is the body of the function.

Asynchronus Programming

More details:

You may be confused by this syntax:
task(
        PnpObject::FindAllAsync(PnpObjectType::DeviceContainer, properties))
        .then([this](PnpObjectCollection^ containers)
    {
What is this task class actually doing?  Simplistically put, it means execute this task asynchronously.  



No comments:

Post a Comment