Most developers using C++/CX have not explored further the possibility of implementing a native C++ WRL solution or share code base which can compile both to C++ WRL or C++/CX. It is however possible with some more internal and detailed knowledge of the WRL. MSDN partially documents this though there are cases where sample code for implementing Platform objects or accessing certain statics or interfaces is simply not documented and must be discovered. As objects are inspectable, the interfaces may not even be exposed in the libraries but instead only available either through documentation, or in the code itself which can of course be inspected at runtime.
One should be familiar with C++, IDL, basic WRL, the Windows Runtime and C++/CX to be able to manage an entire project in native C++ and be aware of the significant overhead required with the main savings being in size from not having to link with the C++/CX platform wrapper library.
Using the code
- Applications are launched through
WinMain and must call
RoInitialize to make an MTA COM thread before using the
IApplicationStatics Start method which provides an
IApplicationInitializationCallback. The callback object implements only
IUnknown and which only contains an Invoke method which constructs the application object on an STA callback thread.
WindowsString* functions must be used for various specific functionality although if the functionality can be found in some of the wrapper libraries it is preferable to use the wrappers such as using
Microsoft::WRL::ActivateInstance as opposed to
RoActivateInstance or using
HString instead of
- There is no reference for which native C++ interfaces are implemented on various
RuntimeClass_* objects. You may find it in the documentation or by disassembling the actual DLL modules. It is important to write an
IInspectable interface listing debug tool to check the interfaces on various WinRT objects so you can be sure how to safely and properly cast and use them.
- All reference operators must generally be translated to pointers: "
^" -> "
*". Generally, the references should be wrapped in
Microsoft::WRL::ComPtr<> so they are cleaned up appropriately.
- All "ref new" must be replaced with "
Microsoft::WRL::Make" for internal objects or "
Microsoft::WRL::ActivateInstance" for external ones unless a *Factory is available in which case it created through a static method call as described below.
- All static method calls must be replaced with an
IActivationFactory which is created using a
RuntimeClass_* name through "
Microsoft::WRL::GetActivationFactory". This factory will return an object from which the desired
*Statics interface must be queried.
- All objects must be referenced by the interface typically prefixed with a
I* and must include appropriate header files. Object references must be tracked using the
Microsoft::WRL::ComPtr wrappers or
HString wrappers for string otherwise special care must be taken to do perform
Release. All namespaces must be prefixed with "
- All derived XAML objects should implement an
*Impl base class that is an
InspectableClass and implements any
I*Overrides interfaces. On creation, the
CreateInstance call will "mix" the base class with the internal inner implementation which must be stored for aggregation. A derived class must override
QueryInterface and delegate any interfaces not implemented on the
*Impl base classes to the aggregated internal inner implementation.
Platform namespace objects must be re-implemented with an equivalent object either already provided in the header files or custom implemented as is done in the C++/CX library.
Platform::Object is equivalent to
Platform::Exception must be transformed to be thrown with the Ro* functions and caught with a structured exception for
- Event handlers must use a pointer to an interface generally with an "Invoke" method. Custom event handlers can be implemented
EventSource object to keep track of cookies or custom written EventSources that use the global interface table (GIT), custom marshalling or contexts.
- Any objects in the Platform namespace must be translated to use equivalents such as
IInspectable for objects, any type created using the
IPropertyValueStatics interface unless you want to roll your own custom implementation which implements all of the same objects that those do. This also allows the WinRT primitive types to "grow" a vtable so they can be all treated as
- IDL must be used to expose interfaces of WinRT components through a
- Microsoft can use desktop-app only functionality in its own vccorlib.dll for example: Only Microsoft's C++/CX library can use the desktop-app only
CoRevokeInitializeSpy function for their factory cache mechanism in Windows Store apps yet if coding in native C++, you will have to do implement the equivalent code without the functions provided by this interface or do without factory caching altogether.
- Microsoft provides the following important information on Casting (C++/CX): http://msdn.microsoft.com/en-us/library/windows/apps/hh755802.aspx.
The reinterpret_cast table is repeated here as it is essential when going between the two styles:
Points of Interest
- Microsoft tasks library already has task interfaces to wrap
IAsync* which can be translated to native C++. Returning a custom
IAsync* object also can be wrapped by building a wrapper on top of
IAsyncBase. Special care must be taken to handle contexts when using UI objects that require STA thread calls and can be derived from the tasks library code. Please see my other article on the task library for WRL.
- Microsoft Media Foundation objects can be implemented by deriving from
IMediaExtension and making the object "activatable" through the
ActivatableClass macro which exports the interface through
DllGetClassObject which can be implemented in DLLs as well as executables. Activatable objects must be declared in the application manifest to be given permission.
- Conditional compilation can be used with the
__cplusplus_winrt compiler definition to create source code that can compile under both situations. The projects generally should be separate though as though only the Windows Runtime
/ZW compiler option.