Windows 8 and WinRT from a C++ perspective

advertisement
#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.
Download