34
Introduction to Writing Metro Style Apps in Native C++ Marc Grégoire Software Architect marc.gregoire@nuonsoft. com http://www.nuonsoft.com / http://www.nuonsoft.com /blog May 8 th 2012

Introduction to Writing Metro Style Apps in Native C++ Marc Grégoire Software Architect [email protected]

Embed Size (px)

Citation preview

Page 2: Introduction to Writing Metro Style Apps in Native C++ Marc Grégoire Software Architect marc.gregoire@nuonsoft.com

Agenda

Windows 8 Platform Windows Runtime (WinRT) C++ Extensions (C++/CX) Asynchronous programming model Libraries (WinRT STL) XAML

Page 3: Introduction to Writing Metro Style Apps in Native C++ Marc Grégoire Software Architect marc.gregoire@nuonsoft.com

Windows 8 Platform

Windows Core OS Services

JavaScript(Chakra)

C#VB

Metro style Apps

Communication & Data

Application Model

Devices & Printing

WinRT APIs

Graphics & Media

XAML HTML / CSS

HTMLJavaScrip

t

CC++

C#VB

Desktop Apps

Win32

.NET / SL

Internet Explorer

CC++

Syste

m S

erv

ices

Vie w

Mod

el

Con

troll

er

Core

CC++

XAML

Page 4: Introduction to Writing Metro Style Apps in Native C++ Marc Grégoire Software Architect marc.gregoire@nuonsoft.com

Windows 8 Platform – Where can C++ be used?

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

Page 5: Introduction to Writing Metro Style Apps in Native C++ Marc Grégoire Software Architect marc.gregoire@nuonsoft.com

Windows Runtime

Set of language extensions and libraries to allow direct consumption and authoring of WinRT types Strongly-typed system for Windows Runtime Automatically reference counted Exception-based Deep integration with STL Well defined binary contract across module

boundaries, ABI-safe

Page 6: Introduction to Writing Metro Style Apps in Native C++ Marc Grégoire Software Architect marc.gregoire@nuonsoft.com

C++ Extensions (C++/CX)

Page 7: Introduction to Writing Metro Style Apps in Native C++ Marc Grégoire Software Architect marc.gregoire@nuonsoft.com

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

Page 8: Introduction to Writing Metro Style Apps in Native C++ Marc Grégoire Software Architect marc.gregoire@nuonsoft.com

C++ Extensions (C++/CX)

ModuleInternals

written in C++

WinRT External Surface

for WinRT callers/callees

C/C++ External Surface

for native callers/callees

Page 9: Introduction to Writing Metro Style Apps in Native C++ Marc Grégoire Software Architect marc.gregoire@nuonsoft.com

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 = 1p = nullptr; // ref count = 0 ~Person()

Page 10: Introduction to Writing Metro Style Apps in Native C++ Marc Grégoire Software Architect marc.gregoire@nuonsoft.com

Automatic Lifetime Management

On the stack, or as a member of another WinRT type

Example:{ Person p; p.Name = "John"; /* ... */} // ~Person()

Page 11: Introduction to Writing Metro Style Apps in Native C++ Marc Grégoire Software Architect marc.gregoire@nuonsoft.com

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(const std::wstring& passwd);};

Public/protected methods only WinRT parameters

Private/internal methods any C++ types as parameters

Usage:Person^ p = ref new Person("John");p->Greet(ref new Person("Jim"));

Page 12: Introduction to Writing Metro Style Apps in Native C++ Marc Grégoire Software Architect marc.gregoire@nuonsoft.com

WinRT Interface

Definingpublic interface class IShape{ void Draw();};

Inheritingpublic interface class ISelectableShape : IShape{ void Select();};

Implementingref class Rectangle : ISelectableShape{ public: virtual void Draw(); virtual void Select();};

UsingIShape^ shape = ref new Rectangle();shape->Draw();

Page 13: Introduction to Writing Metro Style Apps in Native C++ Marc Grégoire Software Architect marc.gregoire@nuonsoft.com

WinRT Property

Defining Trivial properties (with private backing store)

public: property String^ Name;

User defined propertiespublic: property Person^ Sibling {

Person^ get() { InitSiblings(); return _sibling; }

void set(Person^ value) { _sibling = value; NotifySibling(); }

}

private: Person^ _sibling;

UsingPerson^ p = ref new Person("John");

p->Sibling = ref new Person(p->Name);

Page 14: Introduction to Writing Metro Style Apps in Native C++ Marc Grégoire Software Architect marc.gregoire@nuonsoft.com

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-functionauto p = ref new PropertyChanged(UIPropertyChanged);

From class-memberauto p = ref new PropertyChanged(this, MainPage::OnPropertyChanged);

Invokingp("Visible", "f");

Page 15: Introduction to Writing Metro Style Apps in Native C++ Marc Grégoire Software Architect marc.gregoire@nuonsoft.com

WinRT Event Defining

Trivial event (with private backing store)public: event PropertyChanged^ OnPropertyChanged;

User defined propertiespublic: event PropertyChanged^ OnNetworkChanged {

EventRegistrationToken add(PropertyChanged^);

void remove(EventRegistrationToken t);

void raise(String^, String^);

}

Using Subscribing

person->OnPropertyChanged += propertyChangedDelegate;

auto token = person->OnPropertyChanged::add(propertyChangedDelegate);

Unsubscribingperson->OnPropertyChanged -= token;

person->OnPropertyChanged::remove(token);

Page 16: Introduction to Writing Metro Style Apps in Native C++ Marc Grégoire Software Architect marc.gregoire@nuonsoft.com

WinRT Exceptions

Under the covers, WinRT uses COM, thus HRESULTs

WinRT wraps HRESULTs into exceptions Throwing exceptions

throw ref new InvalidArgumentException();

throw ref new COMException(E_*);

Catching exceptionstry { … } catch (OutOfMemoryException^ ex) { … }

Access HRESULT value via ex->HResult

Page 17: Introduction to Writing Metro Style Apps in Native C++ Marc Grégoire Software Architect marc.gregoire@nuonsoft.com

WinRT Exceptions

Only a fixed set of exceptions available

Catch all WinRT exceptions:catch (Platform::Exception^) { }

You cannot derive your ownexceptions from Exception

HRESULT Exception

E_OUTOFMEMORY OutOfMemoryException

E_INVALIDARG InvalidArgumentException

E_NOINTERFACE InvalidCastException

E_POINTER NullReferenceException

E_NOTIMPL NotImplementedException

E_ACCESSDENIED AccessDeniedException

E_FAIL FailureException

E_BOUNDS OutOfBoundsException

E_CHANGED_STATE ChangedStateException

REGDB_E_CLASSNOTREG

ClassNotRegisteredException

E_DISCONNECTED DisconnectedException

E_ABORT OperationCanceledException

Page 18: Introduction to Writing Metro Style Apps in Native C++ Marc Grégoire Software Architect marc.gregoire@nuonsoft.com

WinRT Generics

Defininggeneric<typename T, typename U> public interface class IPair {

property T First;property U Second;

};

Implementingref class PairStringUri: IPair<String^, Uri^> {public:

property String^ First;property Uri^ Second;

};

UsingIPair<String^, Uri^>^ uri = ref new PairStringUri();auto first = uri->First; // String^auto second = uri->Second; // Uri^

Page 19: Introduction to Writing Metro Style Apps in Native C++ Marc Grégoire Software Architect marc.gregoire@nuonsoft.com

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.)

Page 20: Introduction to Writing Metro Style Apps in Native C++ Marc Grégoire Software Architect marc.gregoire@nuonsoft.com

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 definitionref class MainPage{public: MainPage() { InitializeComponent(); } void Button_Click(Object^ sender, RoutedEventArgs^ e);};

Page 21: Introduction to Writing Metro Style Apps in Native C++ Marc Grégoire Software Architect marc.gregoire@nuonsoft.com

Async

Page 22: Introduction to Writing Metro Style Apps in Native C++ Marc Grégoire Software Architect marc.gregoire@nuonsoft.com

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.

Page 23: Introduction to Writing Metro Style Apps in Native C++ Marc Grégoire Software Architect marc.gregoire@nuonsoft.com

Async with PPL Tasks Example: create a file in the standard

“Pictures” folder, without PPL Tasks:StorageFolder^ folder = KnownFolders::PicturesLibrary;

auto createStorageFileOp = folder->CreateFileAsync("myfile.txt");

createStorageFileOp->Completed =

ref new AsyncOperationCompletedHandler<StorageFile^>(

[](IAsyncOperation<StorageFile^>^ asyncOp, AsyncStatus status) {

StorageFile^ storageFile = asyncOp->GetResults();

/* Do something with the file. */

}

);

Page 24: Introduction to Writing Metro Style Apps in Native C++ Marc Grégoire Software Architect marc.gregoire@nuonsoft.com

Async with PPL Tasks with PPL Tasks:

StorageFolder^ folder = KnownFolders::PicturesLibrary;

create_task(folder->CreateFileAsync("myfile.txt")).then(

[](StorageFile^ storageFile) {

/* Do something with the file. */

}

);

Page 25: Introduction to Writing Metro Style Apps in Native C++ Marc Grégoire Software Architect marc.gregoire@nuonsoft.com

Libraries (WinRT STL)

Page 26: Introduction to Writing Metro Style Apps in Native C++ Marc Grégoire Software Architect marc.gregoire@nuonsoft.com

Vector and ObservableVector Instantiating

using namespace Platform::Collections;Vector<String^>^ items = ref new Vector<String^>();

Adding elementsitems->Append("Hello");

Returning a read-only view of the vectorIVectorView<String^>^ view = items->GetView();

Getting notification for changesitems->VectorChanged += ref new VectorChangedEventHandler<String^> (this, &MyClass::VectorChanged);

Page 27: Introduction to Writing Metro Style Apps in Native C++ Marc Grégoire Software Architect marc.gregoire@nuonsoft.com

Map and ObservableMap Defining

using namespace Platform::Collections;auto favorites = ref new Map<String^, Uri^>();

Adding elementsfavorites->Insert("MSDN", ref new Uri("http://msdn.com"));

Checking and removing elementsif (favorites->HasKey("MSDN")) favorites->Remove("MSDN");

Page 28: Introduction to Writing Metro Style Apps in Native C++ Marc Grégoire Software Architect marc.gregoire@nuonsoft.com

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; });

Page 29: Introduction to Writing Metro Style Apps in Native C++ Marc Grégoire Software Architect marc.gregoire@nuonsoft.com

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::vectorVector<int>^ items = ...;std::vector<int> v = to_vector(items);

Page 30: Introduction to Writing Metro Style Apps in Native C++ Marc Grégoire Software Architect marc.gregoire@nuonsoft.com

XAML

Page 31: Introduction to Writing Metro Style Apps in Native C++ Marc Grégoire Software Architect marc.gregoire@nuonsoft.com

Windows 8 Platform – Where can C++ be used?

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

Page 32: Introduction to Writing Metro Style Apps in Native C++ Marc Grégoire Software Architect marc.gregoire@nuonsoft.com

Demo C++ and XAML

Page 33: Introduction to Writing Metro Style Apps in Native C++ Marc Grégoire Software Architect marc.gregoire@nuonsoft.com

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

Page 34: Introduction to Writing Metro Style Apps in Native C++ Marc Grégoire Software Architect marc.gregoire@nuonsoft.com

Questions

?I would like to thank Herb Sutter

from Microsoft for his permission to base this presentation on one that

he wrote for Build 2011.