#comdaybe Windows 8 and WinRT from a C++ perspective Marc Grégoire Who am I? Marc Grégoire MVP VC++ / Microsoft MEET member marc.gregoire@nuonsoft.com http://www.nuonsoft.com/blog/ Founder of the Belgian C++ Users Group (BeCPP) • http://becpp.org/ • • • • • Agenda • • • • • • Windows 8 Platform Windows Runtime (WinRT) C++ Extensions (C++/CX) Asynchronous programming model Libraries (WinRT STL) C++ and XAML Windows 8 Platform Windows 8 Platform Core System Services Model Controller View Metro style Apps XAML XAML C C++ Desktop Apps HTML / CSS C# VB JavaScript (Chakra) HTML JavaScript C C++ C# VB Internet Explorer Win32 .NET / SL Windows Runtime APIs Communication & Data Graphics & Media Devices & Printing Application Model Windows Core OS Services Windows 8 Platform – Where C++? • Metro Hybrid Apps – HTML5 + JavaScript front-end – C++ components • Metro XAML Apps – UI using XAML – C++ code behind • Metro high performance 2D/3D Apps – C++ with DirectX rendering Windows Runtime (WinRT) Windows Runtime (WinRT) • Foundation for building Metro style apps Strongly-typed system Automatically reference counted Exception-based Well defined binary contract across module boundaries, ABI-safe – (For C++) Deep integration with STL – – – – Windows Runtime (WinRT) • Contains classes for UI, Pickers, Controls, Media, XAML, Storage, Network, … • A subset of the Win32 APIs can still be used Windows Runtime (WinRT) User Interface HTML5/CSS XAML DirectX Controls Data Binding SVG Tiles Input Accessibility Printing Devices Geolocation Portable Communications & Data Sensors Media Playback Capture PlayTo NFC Visual Effects Local & Cloud Storage Contracts Background Transfer Notifications Web Streams SMS XML Networking Fundamentals Application Services Threading/Timers Memory Management Authentication Cryptography Globalization Windows Runtime (WinRT) • Includes detailed metadata = complete description of the Windows Runtime • Metadata allows projection into different languages: C++, C#, VB, JavaScript C++ Extensions (C++/CX) C++ Extensions (C++/CX) • Set of language extensions and libraries to allow direct consumption and authoring of WinRT types C++ Extensions (C++/CX) Key Bindings Feature Summary 1. Data Types ref class Reference type value class Value type interface class Interface property Property with get/set event “Delegate property” with add/remove/raise delegate Type-safe function pointer generic Type-safe generics 2. Allocation ref new Reference-counted allocation 3. Pointer & Reference ^ Strong pointer (“hat” or “handle”) % Strong reference C++ Extensions (C++/CX) C/C++ External Surface for native callers/callees Module Internals written in C++ Automatic Lifetime Management • • • • Handle (^ / Hat) is smart pointer to WinRT objects Reference counted Allocated with ref new Example: Person^ p; { Person^ p2 = ref new Person(); p2->Name = "John"; p = p2; } p = nullptr; // // // // // ref ref ref ref ref count count count count count = = = = = 1 1 2 1 0 ~Person() Automatic Lifetime Management • Even easier… • Simply on the stack, or as a member of another WinRT type • Example: { } Person p; p.Name = "John"; /* ... */ // ~Person() WinRT Class • Use ref class to define new WinRT classes (ABI-safe cross-language classes) Usage: • Example: Person^ p = ref new Person("John", "a@b.c"); p->Greet(ref new Person("Jim")); public ref class Person { public: Public/protected methods Person(String^ name, String^ email); void Greet(Person^ other); only WinRT parameters }; internal: ~Person(); void SetPassword(const std::wstring& passwd); Private/internal methods any C++ types as parameters WinRT Interface • Defining public interface class IShape { void Draw(); }; • Inheriting public interface class ISelectableShape : IShape { void Select(); }; • Implementing ref class Rectangle : ISelectableShape { public: virtual void Draw(); virtual void Select(); }; • Using IShape^ shape = ref new Rectangle(); shape->Draw(); WinRT Property • Defining – Trivial properties (with private backing store) public: property String^ Name; – User defined properties public: property Person^ Sibling { Person^ get() { InitSiblings(); return _sibling; } void set(Person^ value) { _sibling = value; NotifySibling(); } } private: Person^ _sibling; • Using Person^ p = ref new Person("John"); p->Sibling = ref new Person(p->Name); WinRT Delegate • Declaring public delegate void PropertyChanged(String^ propName, String^ propValue); • Instantiating – From lambda: auto p = ref new PropertyChanged( [](String^ pn, String^ pv) { cout << pn << " = " << pv; }); • Invoking p("Visible", "f"); – From free-function auto p = ref new PropertyChanged(UIPropertyChanged); – From class-member auto p = ref new PropertyChanged(this, MainPage::OnPropertyChanged); WinRT Event • Defining – Trivial event (with private backing store) public: event PropertyChanged^ OnPropertyChanged; – User defined properties public: event PropertyChanged^ OnNetworkChanged { EventRegistrationToken add(PropertyChanged^); void remove(EventRegistrationToken t); void raise(String^, String^); } WinRT Event • Using – Subscribing person->OnPropertyChanged += propertyChangedDelegate; auto token = person->OnPropertyChanged::add(propertyChangedDelegate); – Unsubscribing person->OnPropertyChanged -= token; person->OnPropertyChanged::remove(token); WinRT Exceptions • Under the covers, WinRT uses COM, thus HRESULTs • WinRT wraps HRESULTs into exceptions WinRT Exceptions • Only a fixed set of exceptions is available HRESULT • Platform::Exception is the E_OUTOFMEMORY E_INVALIDARG base for all WinRT E_NOINTERFACE exceptions E_POINTER E_NOTIMPL • You cannot derive your own E_ACCESSDENIED E_FAIL exceptions from E_BOUNDS E_CHANGED_STATE Platform::Exception REGDB_E_CLASSNOTREG Exception OutOfMemoryException InvalidArgumentException InvalidCastException NullReferenceException NotImplementedException AccessDeniedException FailureException OutOfBoundsException ChangedStateException ClassNotRegisteredException E_DISCONNECTED DisconnectedException E_ABORT OperationCanceledException WinRT Exceptions • Throwing exceptions throw ref new InvalidArgumentException(); throw ref new COMException(hr); • Catching exceptions try { … } catch (OutOfMemoryException^ ex) { … } • Catch all WinRT exceptions: catch (Platform::Exception^ ex) { } • Access HRESULT via ex->HResult WinRT Generics • Defining generic<typename public interface property T property U }; • Using T, typename U> class IPair { First; Second; • Implementing ref class PairStringUri: IPair<String^, Uri^> { public: property String^ First; property Uri^ Second; }; IPair<String^, Uri^>^ uri = ref new PairStringUri(); auto first = uri->First; // String^ auto second = uri->Second; // Uri^ WinRT .winmd Metadata Files • .winmd files – Contain the metadata representation of WinRT types • To consume a winmd file: – Right click on project in Solution Explorer > References > Add New Reference… Or – #using <Company.Component.winmd> – Make sure the winmd and implementation dll is packaged together with your application • To produce a .winmd file: – Start from the “C++ WinRT Component Dll” template – Define public types (ref classes, interfaces, delegates, etc.) WinRT Partial Runtime Classes • Partial class definition partial ref class MainPage: UserControl, IComponentConnector { public: void InitializeComponent(); void Connect() { btn1->Click += ref new EventHandler(this, &MainPage::Button_Click); } }; • Class definition ref class MainPage { public: MainPage() { InitializeComponent(); } void Button_Click(Object^ sender, RoutedEventArgs^ e); }; Async Asynchronous programming model Async with PPL Tasks • Windows 8 Metro only allows asynchronous operations for anything that can take longer than a couple milliseconds • For example: there are no synchronous file operations possible in Metro • Advantage: keeps UI fast and fluid • Disadvantage: programming can be more complex, but new PPL tasks support helps alot here Async with PPL Tasks • Example: – – – – Create a file Open the file Write a string to the file Flush the file Without PPL Tasks StorageFolder^ item = KnownFolders::PicturesLibrary; auto createStorageFileOp = item->CreateFileAsync("myfile.txt"); createStorageFileOp->Completed = ref new AsyncOperationCompletedHandler<StorageFile^>( [](IAsyncOperation<StorageFile^>^ asyncOp, AsyncStatus status) { auto streamRetrievalOp = asyncOp->GetResults()->OpenAsync(FileAccessMode::ReadWrite); streamRetrievalOp->Completed = ref new AsyncOperationCompletedHandler<IRandomAccessStream^>( [](IAsyncOperation<IRandomAccessStream^>^ asyncOp, AsyncStatus status) { IOutputStream^ stream = asyncOp->GetResults()->GetOutputStreamAt(0); DataWriter^ bbrw = ref new DataWriter(stream); bbrw->WriteString("Hello async!"); auto writeBinaryStringOp = bbrw->StoreAsync(); writeBinaryStringOp->Completed = ref new AsyncOperationCompletedHandler<unsigned int>( [stream](IAsyncOperation<unsigned int>^ asyncOp, AsyncStatus status) { int bytes = asyncOp->GetResults(); auto streamFlushOp = stream->FlushAsync(); streamFlushOp->Completed = ref new AsyncOperationCompletedHandler<bool>( [](IAsyncOperation<bool>^ asyncOp, AsyncStatus status) { bool result = asyncOp->GetResults(); }); }); }); }); 33 With PPL Tasks StorageFolder^ item = KnownFolders::PicturesLibrary; auto createStorageFileOp = item->CreateFileAsync("myfile.txt"); task<StorageFile^> createFileTask(createStorageFileOp); IOutputStream^ ostream; createFileTask.then([](StorageFile^ storageFile){ return storageFile->OpenAsync(FileAccessMode::ReadWrite); }).then([](IRandomAccessStream^ rastream) -> task<bool> { ostream = rastream->GetOutputStreamAt(0); DataWriter^ bbrw = ref new DataWriter(ostream); bbrw->WriteString("Hello async!"); return bbrw->StoreAsync(); }).then([ostream](unsigned int bytesWritten) { return ostream->FlushAsync(); }).then([](bool flushed) { }); 34 Libraries (WinRT STL) Vector and ObservableVector • Instantiating using namespace Platform::Collections; Vector<String^>^ items = ref new Vector<String^>(); • Adding elements items->Append("Hello"); • Returning a read-only view of the vector IVectorView<String^>^ view = items->GetView(); • Getting notification for changes items->VectorChanged += ref new VectorChangedEventHandler<String^> (this, &MyClass::VectorChanged); Map and ObservableMap • Defining using namespace Platform::Collections; auto favorites = ref new Map<String^, Uri^>(); • Adding elements favorites->Insert("MSDN", ref new Uri("http://msdn.com")); • Checking and removing elements if (favorites->HasKey("MSDN")) favorites->Remove("MSDN"); Integration with STL Algorithms • WinRT String has Begin()/End() member methods • For WinRT collections, collection.h defines begin() and end() functions • Example: IVector<int>^ v = GetItems(); int sum = 0; std::for_each(begin(v), end(v), [&sum](int element) { sum += element; }); Integration with STL Containers • Conversion is possible between STL containers and WinRT containers • String^ std::wstring (via wchar_t*) • Vector std::vector std::vector<int> v; v.push_back(10); auto items = ref new Vector<int>(v); • Vector std::vector Vector<int>^ items = ...; std::vector<int> v = Windows::Foundation::Collections::to_vector(items); C++ and XAML Windows 8 Platform – Where C++? • Metro Hybrid Apps – HTML5 + Javascript front-end – C++ components • Metro XAML Apps – UI using XAML – C++ code behind • Metro high performance 2D/3D Apps – C++ with DirectX rendering C++ and XAML demo Resources • “Using Windows Runtime With C++” – Herb Sutter – http://channel9.msdn.com/Events/BUILD/BUILD2011/TOOL-532T • “Building Windows Metro style apps in C++/XAML” – Vikas Bhatia, Joanna Mason – http://channel9.msdn.com/Events/BUILD/BUILD2011/TOOL-479T Belgian C++ Users Group (BeCPP) http://BeCPP.org/ Aim? quarterly meetings Audience? free for everyone Where? at Microsoft offices in Zaventem or at sponsor company locations (we’re still looking for hosts / sponsors!) Become a member? http://becpp.org/blog/become-a-member/ Announcements? become member or subscribe to our blog Questions? BeCPP@BeCPP.org Belgian C++ Users Group (BeCPP) • Next meeting: June 27th 2012 • Agenda with top international speakers: – Session 1: What’s new in VC++ 2012 (Rong Lu) – Break – Session 2: C++ AMP (GPGPU Computing) (Kate Gregory) – Drink • Register Now: http://becpp-june.eventbrite.com/ Q&A Thank you! I would like to thank Herb Sutter from Microsoft for his permission to base this presentation on one that he wrote.