52

Watching the //BUILD stuff, I saw that WinRT API's can be consumed by C code:

enter image description here

I am rather excited about a fresh C API available to Win32 developers.

Where can I find information on the C WinRT API? How is it better than the existing Win32 C API?

pnuts
  • 58,317
  • 11
  • 87
  • 139
Andrew
  • 829
  • 1
  • 8
  • 9
  • 1
    As I understand it the WinRT API requires the use of new extensions in the C/C++ compiler. That's based on some light reading around the web, so I could be completely off the mark. – Mark Ransom Sep 15 '11 at 19:25
  • This means MinGW will not be able to utilize WinRT? And since they mention C, will Microsoft start supporting C99, and not just the subset of C++? – Maister Sep 15 '11 at 19:49
  • 6
    @Mark The extensions are not required, they just make your life easier. – Pavel Minaev Sep 15 '11 at 20:00
  • @Pavel Without the extensions, you're better off using the old Win32 API. – Andrew Sep 15 '11 at 20:02
  • @Maister : Last time I checked, no, Microsoft won't support C99, at least, for now. Given the choice between C and C++, their priority is C++11. See: http://stackoverflow.com/questions/146381/visual-studio-support-for-new-c-c-standards – paercebal Sep 15 '11 at 20:11
  • 4
    @Andrew You will have to use WinRT for UI in Metro apps, Win32 is not really an option. Some Win32 calls are allowed, but not most of the UI-related ones. – Pavel Minaev Sep 15 '11 at 20:23
  • @paercebal: This decision is from 2008, i would like to hear an update if they still do not want support C99. almost 4 years later there might be some change in their minds. The usuage of C99 in open source libraries is increasing. – Lothar Sep 16 '11 at 07:21
  • 2
    @Lothar : A quick Google search led to the Visual Studio team's blog, which confirms the C99's suport won't get better. Search for "C99" in the article, and you'll see VC11 won't support new features when compared to VC10. https://blogs.msdn.com/b/vcblog/archive/2011/09/12/10209291.aspx – paercebal Sep 16 '11 at 08:30
  • 4
    It would be rather masochistic to use WinRT from C. – David Heffernan Sep 17 '11 at 07:45
  • 3
    The world is full of C compilers. MS doesn't have a C compiler and has not had one for years and years. Why would they start now? – David Heffernan Sep 17 '11 at 08:19

1 Answers1

73

WinRT is fundamentally COM, so using WinRT components from C is like using COM components from C. Like before, you get .idl files for all WinRT components, and also .h files produced from those .idl files. The .h files include both C++ and C declarations (wrapped in #ifdef __cplusplus as needed). You can just #include them and start hacking away.

It's not exactly neat, though, e.g. something like this C++/CX:

Windows::UI::Xaml::Controls::TextBlock^ tb = ...;
tb->Text = "Foo";

which is equivalent to this vanilla C++:

Windows::UI::Xaml::Controls::ITextBlock* tb = ...;
HSTRING hs;
HRESULT hr = WindowsStringCreate(L"Foo", 3, &hs);
// check hr for errors
hr = tb->set_Text(hs);
// check hr for errors
tb->Release();

would be written in C as:

__x_Windows_CUI_CXaml_CControls_CITextBlock* tb = ...;
HRESULT hr;
HSTRING hs;
hr = WindowsCreateString(L"Foo", 3, &hs);
// check hr for errors
hr = __x_Windows_CUI_CXaml_CControls_CITextBlock_put_Text(tb, hs);
// check hr for errors
IUnknown_Release(tb);

Look inside "C:\Program Files (x86)\Windows Kits\8.0\Include\winrt" in Developer Preview to see the .idl and .h files.

Pavel Minaev
  • 99,783
  • 25
  • 219
  • 289
  • 3
    can you explain the use of the circumflex (^) here? i thought it was for references to managed objects, but aren't these COM pointers? how would this code look in /real/ C++ ? – Spongman Sep 17 '11 at 04:06
  • 11
    `T^` are references to managed objects in C++/CLI. The above is rather C++/CX, which reuses (most) of the same syntax for WinRT. In this case, `T^` are smart pointers to WinRT objects - more specifically, to interfaces inheriting from `IInspectable` (which in turn inherits from `IUnknown`, so they are also COM objects). When you copy them around, `AddRef` and `Release` are called as needed, and same when they go out of scope. If you `dynamic_cast` some `T^` to some other `U^`, this will actually do a `QueryInterface`. There are also `T%` types, which are to `T^` as `U&` is to `U*`. – Pavel Minaev Sep 17 '11 at 06:43
  • 3
    Isn't there a ComPtr class that can be used and which would make it almost identical to the ^ version? – Filip Frącz Sep 19 '11 at 07:19
  • 3
    @Filip `ComPtr` is there, but it would only let you get rid of `Release()` call. I couldn't find any `HSTRING` wrapper. I think I'll leave the sample as is, so that the correspondence between C and C++ versions is more obvious. – Pavel Minaev Sep 19 '11 at 08:19
  • 3
    @peterchen The nice thing about `HSTRING` is that, on one hand, it has a separately stored length like `BSTR`; but on the other hand, it lets you reuse an existing buffer without copying when passing strings as arguments (via `WindowsCreateStringReference`). Also, its contract says that it has to be immutable. So it's not there just for the sake of being different, but brings some real benefits. – Pavel Minaev Sep 19 '11 at 17:11
  • 3
    @PavelMinaev I know it's been almost a year, but would you consider expanding the example with more complete examples, or links to further info? (I'm upvoting as is, but having more info in the same place would be great.) – Ivan Vučica Nov 16 '12 at 22:05
  • @IvanVučica I'm not sure what else is there to document. For ABI-level WinRT progrmaming in general, there are a lot of more detailed docs - e.g. WRL doc pages (http://msdn.microsoft.com/en-us/library/vstudio/hh438466.aspx). Adapting that for C is straightforward, since the only thing that changes is how the calls look due to explicit vtables, and namespaces being embedded directly into names - which is largely covered by this answer (and the specific names you can always look up in the header files). – Pavel Minaev Nov 22 '12 at 00:48
  • 4
    @PavelMinaev Ah! I took another look at the headers, and currently the definition from your example is: `__x_ABI_CWindows_CUI_CXaml_CControls_CITextBlock`. This is what has confused me when trying out your example. When writing the comment, though, what I had in mind is a minimal, complete, pure C program -- which would certainly fit the OP's question and deserve copious amounts of gratitude from fans of C. – Ivan Vučica Nov 22 '12 at 13:38
  • Another thing is that the compiler can be smarter about removing redundant addref/release calls if you use ^. It won't attempt that when you pass ComPtr by value as far as I've heard. – CÅdahl Nov 18 '14 at 11:41
  • @PavelMinaev Windows Runtime C++ Template Library (WRL) have `HSTRING` wrapper called [HString](https://learn.microsoft.com/en-us/cpp/windows/wrl/hstring-class) and [HStringReference](https://learn.microsoft.com/en-us/cpp/windows/wrl/hstringreference-class) wrapper around `WindowsCreateStringReference` method. C++ part can be changed to: `hr = tb->set_Text(HStringReference(L"Foo").Get());` – DJm00n Mar 16 '19 at 15:39
  • I wanted to keep the wrappers down to a minimum to do a clean baseline comparison. (Note that this answer is likely very outdated by now in any case. The ABI is still C-compatible, but I'm not sure IDL generation for C still works, or whether it behaves the same.) – Pavel Minaev Mar 16 '19 at 23:08