Skip to content

Commit 5d71c97

Browse files
authored
Merge pull request #254 from MicrosoftDocs/stwhi-master/cppwinrt-170
more tips
2 parents a7a1e27 + a48b7f8 commit 5d71c97

File tree

8 files changed

+263
-6
lines changed

8 files changed

+263
-6
lines changed

windows-apps-src/cpp-and-winrt-apis/author-coclasses.md

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -55,9 +55,9 @@ The good news is that all it takes to cause **winrt::implements** to support cla
5555

5656
You could do that explicitly, or indirectly by including some other header file such as `ole2.h`. One recommended method is to include the `wil\cppwinrt.h` header file, which is part of the [Windows Implementation Libraries (WIL)](https://github.com/Microsoft/wil). The `wil\cppwinrt.h` header file not only makes sure that `unknwn.h` is included before `winrt/base.h`, it also sets things up so that C++/WinRT and WIL understand each other's exceptions and error codes.
5757

58-
## A basic example
58+
## A simple example of a COM component
5959

60-
Here's a simple example, which you can test out if you paste the code into the `pch.h` and `main.cpp` of a new **Windows Console Application (C++/WinRT)** project.
60+
Here's a simple example of a COM component written using C++/WinRT. This is a full listing of a mini-application, so you can the code out if you paste it into the `pch.h` and `main.cpp` of a new **Windows Console Application (C++/WinRT)** project.
6161

6262
```cppwinrt
6363
// pch.h

windows-apps-src/cpp-and-winrt-apis/index.md

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -49,6 +49,7 @@ C++/WinRT performs better and produces smaller binaries than any other language
4949
| [XAML controls; bind to a C++/WinRT property](binding-property.md) | A property that can be effectively bound to a XAML control is known as an *observable* property. This topic shows how to implement and consume an observable property, and how to bind a XAML control to it. |
5050
| [XAML items controls; bind to a C++/WinRT collection](binding-collection.md) | A collection that can be effectively bound to a XAML items control is known as an *observable* collection. This topic shows how to implement and consume an observable collection, and how to bind a XAML items control to it. |
5151
| [XAML custom (templated) controls with C++/WinRT](xaml-cust-ctrl.md) | This topic walks you through the steps of creating a simple custom control using C++/WinRT. You can build on the info here to create your own feature-rich and customizable UI controls. |
52+
| [Passing parameters into the ABI boundary](pass-parms-to-abi.md) | C++/WinRT simplifies passing parameters into the ABI boundary by providing automatic conversions for common cases. |
5253
| [Consume COM components with C++/WinRT](consume-com.md) | This topic uses a full Direct2D code example to show how to use C++/WinRT to consume COM classes and interfaces. |
5354
| [Author COM components with C++/WinRT](author-coclasses.md) | C++/WinRT can help you to author classic COM components, just as it helps you to author Windows Runtime classes. |
5455
| [Move to C++/WinRT from C++/CX](move-to-winrt-from-cx.md) | This topic shows how to port C++/CX code to its equivalent in C++/WinRT. |

windows-apps-src/cpp-and-winrt-apis/interop-winrt-abi.md

Lines changed: 92 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -11,6 +11,8 @@ ms.localizationpriority: medium
1111

1212
This topic shows how to convert between SDK application binary interface (ABI) and [C++/WinRT](/windows/uwp/cpp-and-winrt-apis/intro-to-using-cpp-with-winrt) objects. You can use these techniques to interop between code that uses these two ways of programming with the Windows Runtime, or you can use them as you gradually move your code from the ABI to C++/WinRT.
1313

14+
In general, C++/WinRT exposes ABI types as **void\***, so that you don't need to include platform header files.
15+
1416
## What is the Windows Runtime ABI, and what are ABI types?
1517
A Windows Runtime class (runtime class) is really an abstraction. This abstraction defines a binary interface (the Application Binary Interface, or ABI) that allows various programming languages to interact with an object. Regardless of programming language, client code interaction with a Windows Runtime object happens at the lowest level, with client language constructs translated into calls into the object's ABI.
1618

@@ -240,9 +242,77 @@ int main()
240242
}
241243
```
242244

245+
## Interoperating with ABI COM interface pointers
246+
247+
The helper function template below illustrates how to copy an ABI COM interface pointer of a given type to its equivalent C++/WinRT projected smart pointer type.
248+
249+
```cppwinrt
250+
template<typename To, typename From>
251+
To to_winrt(From* ptr)
252+
{
253+
To result{ nullptr };
254+
winrt::check_hresult(ptr->QueryInterface(winrt::guid_of<To>(), winrt::put_abi(result)));
255+
return result;
256+
}
257+
...
258+
ID2D1Factory1* com_ptr{ ... };
259+
auto cppwinrt_ptr {to_winrt<winrt::com_ptr<ID2D1Factory1>>(com_ptr)};
260+
```
261+
262+
This next helper function template is equivalent, except that it copies from the smart pointer type from the [Windows Implementation Libraries (WIL)](https://github.com/Microsoft/wil).
263+
264+
```cppwinrt
265+
template<typename To, typename From, typename ErrorPolicy>
266+
To to_winrt(wil::com_ptr_t<From, ErrorPolicy> const& ptr)
267+
{
268+
To result{ nullptr };
269+
if constexpr (std::is_same_v<typename ErrorPolicy::result, void>)
270+
{
271+
ptr.query_to(winrt::guid_of<To>(), winrt::put_abi(result));
272+
}
273+
else
274+
{
275+
winrt::check_result(ptr.query_to(winrt::guid_of<To>(), winrt::put_abi(result)));
276+
}
277+
return result;
278+
}
279+
```
280+
281+
Also see [Consume COM components with C++/WinRT](/windows/uwp/cpp-and-winrt-apis/consume-com).
282+
283+
### Unsafe interop with ABI COM interface pointers
284+
285+
The table that follows shows (in addition to other operations) unsafe conversions between an ABI COM interface pointer of a given type and its equivalent C++/WinRT projected smart pointer type. For the code in the table, assume these declarations.
286+
287+
```cppwinrt
288+
winrt::Sample s;
289+
ISample* p;
290+
291+
void GetSample(_Out_ ISample** pp);
292+
```
293+
294+
Assume further that **ISample** is the default interface for **Sample**.
295+
296+
You can assert that at compile time with this code.
297+
298+
```cppwinrt
299+
static_assert(std::is_same_v<winrt::default_interface<winrt::Sample>, winrt::ISample>);
300+
```
301+
302+
| Operation | How to do it | Notes |
303+
|-|-|-|
304+
| Extract **ISample\*** from **winrt::Sample** | `p = reinterpret_cast<ISample*>(get_abi(s));` | *s* still owns the object. |
305+
| Detach **ISample\*** from **winrt::Sample** | `p = reinterpret_cast<ISample*>(detach_abi(s));` | *s* no longer owns the object. |
306+
| Transfer **ISample\*** to new **winrt::Sample** | `winrt::Sample s{ p, winrt::take_ownership_from_abi };` | *s* takes ownership of the object. |
307+
| Set **ISample\*** into **winrt::Sample** | `*put_abi(s) = p;` | *s* takes ownership of the object. Any object previously owned by *s* is leaked (will assert in debug). |
308+
| Receive **ISample\*** into **winrt::Sample** | `GetSample(reinterpret_cast<ISample**>(put_abi(s)));` | *s* takes ownership of the object. Any object previously owned by *s* is leaked (will assert in debug). |
309+
| Replace **ISample\*** in **winrt::Sample** | `attach_abi(s, p);` | *s* takes ownership of the object. The object previously owned by *s* is freed. |
310+
| Copy **ISample\*** to **winrt::Sample** | `copy_from_abi(s, p);` | *s* makes a new reference to the object. The object previously owned by *s* is freed. |
311+
| Copy **winrt::Sample** to **ISample\*** | `copy_to_abi(s, reinterpret_cast<void*&>(p));` | *p* receives a copy of the object. Any object previously owned by *p* is leaked. |
312+
243313
## Interoperating with the ABI's GUID struct
244314

245-
**GUID** is projected as **winrt::guid**. For APIs that you implement, you must use **winrt::guid** for GUID parameters. Otherwise, there are automatic conversions between **winrt::guid** and **GUID** as long as you include `unknwn.h` (implicitly included by <windows.h> and many other header files) before you include any C++/WinRT headers.
315+
[**GUID**](/previous-versions/aa373931(v%3Dvs.80)) is projected as **winrt::guid**. For APIs that you implement, you must use **winrt::guid** for GUID parameters. Otherwise, there are automatic conversions between **winrt::guid** and **GUID** as long as you include `unknwn.h` (implicitly included by <windows.h> and many other header files) before you include any C++/WinRT headers.
246316

247317
If you don't do that, then you can hard-`reinterpret_cast` between them. For the table that follows, assume these declarations.
248318

@@ -256,6 +326,27 @@ GUID abiguid;
256326
| From **winrt::guid** to **GUID** | `abiguid = winrtguid;` | `abiguid = reinterpret_cast<GUID&>(winrtguid);` |
257327
| From **GUID** to **winrt::guid** | `winrtguid = abiguid;` | `winrtguid = reinterpret_cast<winrt::guid&>(abiguid);` |
258328

329+
## Interoperating with the ABI's HSTRING
330+
331+
The table that follows shows conversions between **winrt::hstring** and [**HSTRING**](/windows/win32/winrt/hstring), and other operations. For the code in the table, assume these declarations.
332+
333+
```cppwinrt
334+
winrt::hstring s;
335+
HSTRING h;
336+
337+
void GetString(_Out_ HSTRING* value);
338+
```
339+
340+
| Operation | How to do it | Notes |
341+
|-|-|-|
342+
| Extract **HSTRING** from **hstring** | `h = static_cast<HSTRING>(get_abi(s));` | *s* still owns the string. |
343+
| Detach **HSTRING** from **hstring** | `h = reinterpret_cast<HSTRING>(detach_abi(s));` | *s* no longer owns the string. |
344+
| Set **HSTRING** into **hstring** | `*put_abi(s) = h;` | *s* takes ownership of string. Any string previously owned by *s* is leaked (will assert in debug). |
345+
| Receive **HSTRING** into **hstring** | `GetString(reinterpret_cast<HSTRING*>(put_abi(s)));` | *s* takes ownership of string. Any string previously owned by *s* is leaked (will assert in debug). |
346+
| Replace **HSTRING** in **hstring** | `attach_abi(s, h);` | *s* takes ownership of string. The string previously owned by *s* is freed. |
347+
| Copy **HSTRING** to **hstring** | `copy_from_abi(s, h);` | *s* makes a private copy of the string. The string previously owned by *s* is freed. |
348+
| Copy **hstring** to **HSTRING** | `copy_to_abi(s, reinterpret_cast<void*&>(h));` | *h* receives a copy of the string. Any string previously owned by *h* is leaked. |
349+
259350
## Important APIs
260351
* [AddRef function](https://docs.microsoft.com/windows/desktop/api/unknwn/nf-unknwn-iunknown-addref)
261352
* [QueryInterface function](https://docs.microsoft.com/windows/desktop/api/unknwn/nf-unknwn-iunknown-queryinterface(q_))

windows-apps-src/cpp-and-winrt-apis/intro-to-using-cpp-with-winrt.md

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -133,6 +133,8 @@ In your C++/WinRT programming, you can use standard C++ language features and [S
133133

134134
> [!WARNING]
135135
> There are also types that you might see if you closely study the C++/WinRT Windows namespace headers. An example is **winrt::param::hstring**, but there are collection examples too. These exist solely to optimize the binding of input parameters, and they yield big performance improvements and make most calling patterns "just work" for related standard C++ types and containers. These types are only ever used by the projection in cases where they add most value. They're highly optimized and they're not for general use; don't be tempted to use them yourself. Nor should you use anything from the `winrt::impl` namespace, since those are implementation types, and therefore subject to change. You should continue to use standard types, or types from the [winrt namespace](/uwp/cpp-ref-for-winrt/winrt).
136+
>
137+
> Also see [Passing parameters into the ABI boundary](/windows/uwp/cpp-and-winrt-apis/pass-parms-to-abi).
136138
137139
## Important APIs
138140
* [winrt::hstring struct](/uwp/cpp-ref-for-winrt/hstring)

windows-apps-src/cpp-and-winrt-apis/news.md

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -284,8 +284,8 @@ The table below contains news and changes for C++/WinRT in the Windows SDK versi
284284

285285
Other changes.
286286

287-
- **Breaking change**. [**winrt::get_abi(winrt::hstring const&)**](/uwp/cpp-ref-for-winrt/get-abi) now returns `void*` instead of `HSTRING`. You can use `static_cast<HSTRING>(get_abi(my_hstring));` to get an HSTRING.
288-
- **Breaking change**. [**winrt::put_abi(winrt::hstring&)**](/uwp/cpp-ref-for-winrt/put-abi) now returns `void**` instead of `HSTRING*`. You can use `reinterpret_cast<HSTRING*>(put_abi(my_hstring));` to get an HSTRING*.
287+
- **Breaking change**. [**winrt::get_abi(winrt::hstring const&)**](/uwp/cpp-ref-for-winrt/get-abi) now returns `void*` instead of `HSTRING`. You can use `static_cast<HSTRING>(get_abi(my_hstring));` to get an HSTRING. See [Interoperating with the ABI's HSTRING](interop-winrt-abi.md#interoperating-with-the-abis-hstring).
288+
- **Breaking change**. [**winrt::put_abi(winrt::hstring&)**](/uwp/cpp-ref-for-winrt/put-abi) now returns `void**` instead of `HSTRING*`. You can use `reinterpret_cast<HSTRING*>(put_abi(my_hstring));` to get an HSTRING*. See [Interoperating with the ABI's HSTRING](interop-winrt-abi.md#interoperating-with-the-abis-hstring).
289289
- **Breaking change**. HRESULT is now projected as **winrt::hresult**. If you need an HRESULT (to do type checking, or to support type traits), then you can `static_cast` a **winrt::hresult**. Otherwise, **winrt::hresult** converts to HRESULT, as long as you include `unknwn.h` before you include any C++/WinRT headers.
290290
- **Breaking change**. GUID is now projected as **winrt::guid**. For APIs that you implement, you must use **winrt::guid** for GUID parameters. Otherwise, **winrt::guid** converts to GUID, as long as you include `unknwn.h` before you include any C++/WinRT headers. See [Interoperating with the ABI's GUID struct](interop-winrt-abi.md#interoperating-with-the-abis-guid-struct).
291291
- **Breaking change**. The [**winrt::handle_type constructor**](/uwp/cpp-ref-for-winrt/handle-type#handle_typehandle_type-constructor) has been hardened by making it explicit (it's now harder to write incorrect code with it). If you need to assign a raw handle value, call the [**handle_type::attach function**](/uwp/cpp-ref-for-winrt/handle-type#handle_typeattach-function) instead.

0 commit comments

Comments
 (0)