For C#, XAML transpiles to .cs
(*.g.cs
) files and needs no IDL files.
Similarly in C++, why can't XAML be transpiled to .cpp
(*.g.cpp
) files? Why does it need any IDL files at all?
I don't understand.
There's a fair bit of confusion in the question as to how the individual pieces fit together. The main driver for the translation is the IDL file. Irrespective of whether it is authored by a developer or synthesized by the IDE, it is the IDL that produces WINMD (Windows Metadata) files describing the interfaces and runtime classes in a language-agnostic fashion.
The WINMD's are used by all tooling that needs to look up types, query for members (such as properties, events, delegates), and produce application packages.
XAML, on the other hand, isn't part of the compilation process at all. While some of its contents are verified at compile time, it usually gets translated into a compact binary representation (XBF) that's loaded and parsed at runtime to instantiate types.
The question as to why IDL's are required with C++/WinRT (and not with C# or C++/CX) is easily answered: It's simply not possible to derive enough information from C++ class definitions to unambiguously deduce the required metadata.
As an easy example, consider properties. While both C# as well as C++/CX have dedicated language constructs to describe properties, this is not the case in C++. C++/WinRT projects properties to member functions that take zero or one argument (for getters and setters, respectively). If you were to automatically deduce metadata from a C++ class definition, a tool would have to disambiguate between a property and a method. There are other challenges, too, and while Kenny Kerr has repeatedly voiced the desire to get better IDE support for C++/WinRT, the Visual Studio team doesn't seem to care much (see this comment, for example).
For the foreseeable future you should be prepared to author IDL files if you choose to use C++/WinRT.
I like this question a lot, and I also like IInspectable's answer. I want to take a different approach to answering it, though.
In short:
You have to write IDLs for C++/WinRT because C++/WinRT does not (cannot) automatically generate WinMDs from your code, which the XAML compiler uses to understand what controls and types are available.
C# and C++/CX automatically generate the appropriate WinMDs from your code, so you don't need to create IDLs.
.g.cpp
files?For C#, XAML transpiles to
.cs
(*.g.cs
) files and needs no IDL files.Similarly in C++, why can't XAML be transpiled to
.cpp
(*.g.cpp
) files?
XAML does create code files for you! No matter what language you use, C# or C++ (both C++/WinRT and C++/CX), the XAML compiler does generate files for you---for example, in my current C++/WinRT work, I see MyControl.g.h
, MyControl.g.cpp
, MyControl.xaml.g.h
, and MyControl.xaml.g.hpp
.
Part of that is C++/WinRT, part of that is the XAML compiler. This code is automatically included in your project in complex ways (read about XamlTypeInfo
if you're curious---the Visual Studio team has an old blog post).
Why does it need any IDL files at all?
But this is the key point---these generated code files are not what the XAML compiler needs, in either language.
The XAML compiler needs .winmd
s.
WinMD files are basically "type descriptions" for WinRT code (the type of code Windows APIs use). You can actually look through them with tools like ildasm
. XAML uses these types for things like x:Bind
---and simply knowing about controls.
Example
For example, take this code:
<!-- MyPage.xaml --> <MyControl Title="{x:Bind MyViewModel.CoolTitle, Mode=OneWay}" />
How does XAML know about
MyControl
? How does it know aboutMyViewModel
, or thatMyViewModel
has aCoolTitle
property?
In C# and C++/CX, the language's compiler (eg the C# compiler or the C++/CX compiler) reads your types and generates WinMDs automatically. In C#'s case, that's just how .NET works---every class eventually winds up in a WinMD somewhere/can be described via WinMD. In C++/CX's case, that's what the "CX" part was---an extension to the C++ language that let you create WinRT types "in the code." Hat pointers (^
and ref new
) and all of that.
However, in C++/WinRT, we don't generate WinMDs automatically.
C++/WinRT offers a lot of benefits over C++/CX, but a key difference is that it doesn't have a special compiler---so it can't read your code and generate WinMD files. Instead, you have to write the IDL yourself.
Hope that helps!