470 likes | 657 Views
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
E N D
Windows 8 and WinRTfroma 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 Metro style Apps Desktop Apps HTML JavaScript HTML / CSS XAML XAML View JavaScript (Chakra) C C++ C C++ C# VB Model Controller C C++ C# VB Windows Runtime APIs Devices & Printing Communication & Data Graphics & Media System Services .NET / SL Internet Explorer Win32 Application Model Windows Core OS Services Core
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) • 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 Communications & Data Web Contracts Geolocation Portable Sensors NFC Local & Cloud Storage Streams Notifications Background Transfer SMS Media XML Networking Visual Effects Playback Capture PlayTo 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) • Set of language extensions and librariesto allow direct consumptionand authoringof WinRTtypes
C++ Extensions (C++/CX) C/C++ External Surface for native callers/callees WinRT External Surface for WinRT 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(); // ref count = 1 p2->Name = "John"; // ref count = 1 p = p2; // ref count = 2 } // ref count = 1 p = nullptr; // ref count = 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) • Example: public ref class Person { public: Person(String^ name, String^ email); void Greet(Person^ other); internal: ~Person(); void SetPassword(conststd::wstring& passwd); }; Usage: Person^ p = ref new Person("John", "a@b.c"); p->Greet(ref new Person("Jim")); Public/protected methods only WinRT parameters 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; }); • From free-function auto p = ref new PropertyChanged(UIPropertyChanged); • From class-member auto p = ref new PropertyChanged(this, MainPage::OnPropertyChanged); • Invoking p("Visible", "f");
WinRT Event • Defining • Trivial event (with private backing store) public: event PropertyChanged^ OnPropertyChanged; • User defined properties public: event PropertyChanged^ OnNetworkChanged { EventRegistrationTokenadd(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 • Platform::Exception is thebase for all WinRTexceptions • You cannot derive your ownexceptions fromPlatform::Exception
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 T, typename U> public interface class IPair { property T First; property U Second; }; • Implementing ref class PairStringUri: IPair<String^, Uri^> { public: property String^ First; property Uri^ Second; }; • Using 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 onlyallowsasynchronous operations foranythingthatcan take longerthan a couplemilliseconds • For example: there are no synchronous file operations possible in Metro • Advantage: keeps UI fastandfluid • Disadvantage: programmingcanbe more complex, but new PPL tasks support helpsalothere
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(); }); }); }); });
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 intbytesWritten) { return ostream->FlushAsync(); }).then([](bool flushed) { });
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);
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 • 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
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/
Thank you! I would like to thank Herb Sutter from Microsoft for his permission to base this presentation on one that he wrote.