Why do WinRT types have to be sealed? - interop

In several places (e.g. "Creating Windows Runtime Components for JavaScript, in C# and Visual Basic" on MSDN), I've seen it specified that, if you write a class in .NET that you want to use from JavaScript, then you must make it a sealed class.
This seems like an arbitrary restriction. Why can JavaScript only work with sealed classes?

Windows runtime objects exposed to JavaScript applications are sealed from a JavaScript perspective - you can't add expando properties to WinRT objects. But from C++ and C#, winrt objects can be inherited if the object supports inheritance (most Xaml classes support inheritance for instance, but most others don't).
The reason that WinRT objects are sealed from JS is to ensure that the winrt object behave the same regardless of what the app has done - if an app redefines some function property on an object, it could cause other parts of the app to misbehave.

Related

COM Objects in Direct3D

As mentioned in Microsoft documentation there are two ways to create COM objects:
The module that implements the object might provide a function specifically designed to create instances of that object.
Alternatively, COM provides a generic creation function named CoCreateInstance.
In direct3D you can use first method to create Objects like you use D3D11CreateDevice()
but how you do this by the second method.maybe you need CLSID_D3D11CreateDevice which I didn't find.Is there any library to include or maybe it's impossible to create by the second way.
Also I really like to know if there is a way to see COM objects and what interfaces they implement.
DirectX APIs are not "true COM". These APIs derive from IUnknown for reference counting and polymorphic interfaces for versioning, but they do not follow all the other rules of COM objects. The lifetime rules are also modified for "child" objects, and DirectX APIs only support COINIT_MULTITHREADED.
This is a design pattern known informally as "COM lite" or "nano-COM".
Objects are created with a Win32 "flat" factory function
Objects generally support only IUnknown, the main interface, and derived versions of the main interface
Methods on interfaces can return void or HRESULT
Not all methods need to be thread-safe
They do not support COM aggregation
Interface pointers as parameters do not support client-provided implementations
Direct2D/DirectWrite and Windows Imaging Component (WIC) support CoCreateInstance as did did the original XAudio2 for Windows up to version 2.7 and legacy XACT. Otherwise, "DirectX" components do not support registry-based or manifest-based creation.
This pattern provides a stable "Application Binary Interface (ABI)" and maps well to C++ single-inheritance of pure-virtual classes. It provides an easy way to extend with new versions to add methods, and reference-counting for lifetime management. The resulting APIs are generally compatible with the IID_PPV_ARGS macro as well as COM smart-pointers like Microsoft::WRL::ComPtr, winrt::com_ptr, or the older ATL CComPtr.
See Microsoft Docs: Programming DirectX with COM
More recent versions of DirectX like DirectX 12 have adopted "strongly-typed bitmasks" which were not used in older versions. See this blog post.
While historically the DirectX "COM lite" APIs have provided C support through macros, the most recent guidance is to just support C++ and make use of C++11 features like strongly-typed enumerations (a.k.a. scoped enumerations). You'll see this reflected in the DXCore interfaces.

How can I create a COM object in Rust that inherits from a COM object defined in C++?

I am trying to make a Rust program that emulates a webcam. This question and this answer suggest that the best way to do this is by creating a DirectShow source filter. Based on the PushSource sample in the Windows SDK and some C# implementations on CodeProject, it seems like the canonical way to do this is to extend the DirectShow BaseClasses provided in the Windows SDK. However, this is where my understanding breaks down.
I found the cxx crate and was able to get the classes from BaseClasses into my program, but how do I inherit from them or instantiate them? This crate does not seem to be designed for use with COM, and it is not clear how to call the constructors of classes.
Once I have done that first part, how do I expose my new classes as COM components? I found the com crate, but it seems to expect me to import the base classes using their GUIDs. However, I have no idea how to figure out what their GUIDs might be.

What's the difference of Class library and windows runtime component for UWP

I'd like to create a custom charting control for my data, it will be used by uwp store apps, in Visual studio, there is class library project and there is also windows runtime component project, what's the different? which should I use?
Also, user control or template control, which one should I use?
It all depends on what programming language you plan to use, how complex your control will be, if it will be only you using it on a single screen in a single project or other people might use your library and try to restyle the control.
In most of the cases you'll be picking a class library (if you're a C#/VB developer) and go for the templated control for maximum flexibility in styling (and better performance than a user control). This answer by Filip Skakun gives an excellent comparison between both types of controls.
If your custom charting control has to be used in UWP apps written in C++ or JavaScript (WinJS) or is written in C++, you'll have to use a Windows Runtime Component. A class library can only be used in .NET UWP apps. More info on Windows Runtime Component and how to create them is on MSDN.

Universal Windows Platform Apps and C++/CLI (VS 2015 RC1)

I have some C++/CLI code which derives from the .NET System Namespace classes.
Is there a way to reuse this code for Universal Windows Platform Apps?
I can't get a reference to the System Namespace in C++, though in C# it is possible. It looks like there is only support for C++/Cx code and not for managed C++/CLI.
The syntax and keywords of the C++/CX extension resembles C++/CLI a great deal. But that's where similarity ends, they have nothing whatsoever in common. C++/CX gets compiled directly to native code, just like native C++. But C++/CLI is compiled to MSIL, the intermediate language of .NET. Their syntax looks so similar because they both solve the same problem, interfacing C++ to a foreign type system. .NET's in the case of C++/CLI, WinRT in the case of C++/CX.
Which is the basic reason why you cannot use the System namespace, it is a .NET namespace. You instead use the std namespace, along with the Platform and Windows namespaces for WinRT specific types. The compiler cannot import .NET reference assemblies with the /ZW compile option in effect, only WinRT metadata files, the ones with the .winmd filename extension. Which are an extension to the COM .tlb type library file format, the ones you previously had to import with the #import directive.
Which in itself is another major source for confusion, the internal .winmd file format was based on the format of .NET metadata. Most .NET decompilers can show you the content of a .winmd file because of this. But again just a superficial similarity, it is completely unrelated to a .NET assembly. It can just contain declarations, not code. Best to compare it to a .h file you'd use in a native C++ project. Or a .tlb file if you previously had exposure to COM.
Knowing how COM works can be very helpful to grok what this is all about. It is in fact COM that lies at the core of WinRT, the basic reason why your C++/CX project can be easily used by a program written in a completely different language like Javascript or VB.NET. A WinRT app is actually an out-of-process COM server. A class library or WinRT component is actually an in-process COM server. COM object factories work differently, the scope is limited to the files named in the package manifest. C++/CX is part of the language projection that hides COM, along with the C++ libraries you link that implement the Platform namespaces. WinRT would be still-born if programmers had to write traditional COM client code. You still can in native C++, the WRL library does little to hide the plumbing.
WinRT readily supports code written in a managed language like C# or VB.NET, the language projection is built into the framework and highly invisible. But not C++/CLI, a structural limitation. A Store/Phone/Universal app targets a subset of the .NET Framework named .NETCore. Better known these days as CoreCLR, the parts that were open-sourced. Which does not support module initializers, critical to C++/CLI.
Enough introduction and getting to the answer: no, you have no use for your C++/CLI code and you'll have to rewrite it. You'll have a decent shot at porting the native C++ code that your C++/CLI wrapper interfaced with, as long as it observes the api limitations. You should always start there first, given that it is easy to do and instantly tells you if your native C++ code is using verboten api functions, the kind that drains a battery too quickly or violates the sandbox restrictions.
The ref class wrappers however have to be significantly tweaked. Little reason to assume that will be a major obstacle, it could still structurally be similar. Biggest limitations are the lack of support for implementation inheritance, a COM restriction, and having to replace the code that used .NET Framework types with equivalent C++ code. The typical hangup is that there tends to be a lot of it, the original author would normally have favored the very convenient .NET types over the standard C++ library types. YMMV.

Possible for Win32 App calling an WinRT API?

Assuming that I am on Windows 8+ and I have a Win32/C App. Can my Win32 App call into WinRT API?
Short answer - yes: How to: Activate and Use a Windows Runtime Component Using WRL
Long answer:
Windows Runtime is heavily based upon COM technology. The Windows Runtime components are actually some kind of COM objects. So the common rules for instantiating and using COM objects apply to Windows Runtime components.
First, you must initialize the Windows Runtime environment. There's a useful class called RoInitializeWrapper you can use to do this. Then, you use an activation factory to obtain a pointer to the Windows Runtime component's interface. You work with the interface, and when you finished, you must uninitialize the Windows Runtime environment by destroying your RoInitializeWrapper.

Resources