Skip to content

Commit 297454e

Browse files
sylveonkennykerr
andauthored
Allow classic COM interfaces with get_self (#1314)
* Allow classic COM interfaces with get_self Fixes #1312 * Fix mingw builds --------- Co-authored-by: Kenny Kerr <[email protected]>
1 parent d3bb275 commit 297454e

File tree

3 files changed

+58
-0
lines changed

3 files changed

+58
-0
lines changed

strings/base_implements.h

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -242,6 +242,12 @@ WINRT_EXPORT namespace winrt
242242
return &static_cast<impl::produce<D, default_interface<I>>*>(get_abi(from))->shim();
243243
}
244244

245+
template <typename D, typename I>
246+
D* get_self(com_ptr<I> const& from) noexcept
247+
{
248+
return static_cast<D*>(static_cast<impl::producer<D, I>*>(from.get()));
249+
}
250+
245251
template <typename D, typename I>
246252
[[deprecated]] D* from_abi(I const& from) noexcept
247253
{

strings/base_meta.h

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -13,6 +13,9 @@ WINRT_EXPORT namespace winrt
1313
template <typename T>
1414
struct com_ptr;
1515

16+
template <typename D, typename I>
17+
D* get_self(com_ptr<I> const& from) noexcept;
18+
1619
namespace param
1720
{
1821
template <typename T>

test/old_tests/UnitTests/interop.cpp

Lines changed: 49 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,10 @@ using namespace Windows::Foundation;
77

88
namespace
99
{
10+
struct IClassicComInterface : ::IUnknown {};
11+
12+
struct ClassicCom : implements<ClassicCom, IClassicComInterface> {};
13+
1014
struct Stringable : implements<Stringable, IStringable>
1115
{
1216
Stringable(std::wstring_view const& value = L"Stringable") : m_value(value)
@@ -30,8 +34,16 @@ namespace
3034
object->AddRef();
3135
return object->Release();
3236
}
37+
38+
template <typename T>
39+
uint32_t get_ref_count(com_ptr<T> const& object)
40+
{
41+
return get_ref_count(object.get());
42+
}
3343
}
3444

45+
template <> inline constexpr winrt::guid winrt::impl::guid_v<IClassicComInterface>{ 0xc136bb75, 0xbc03, 0x41a6, { 0xa5, 0xdc, 0x5e, 0xfa, 0x67, 0x92, 0x4e, 0xbf } };
46+
3547
TEST_CASE("interop")
3648
{
3749
uint32_t const before = get_module_lock();
@@ -108,6 +120,43 @@ TEST_CASE("self")
108120
REQUIRE(get_ref_count(object) == 1);
109121
object = nullptr;
110122

123+
strong = weak.get();
124+
REQUIRE(!strong);
125+
}
126+
127+
TEST_CASE("self_classic_com")
128+
{
129+
com_ptr<ClassicCom> strong = make_self<ClassicCom>();
130+
131+
REQUIRE(get_ref_count(strong.get()) == 1);
132+
133+
com_ptr<IClassicComInterface> object = strong.as<IClassicComInterface>();
134+
135+
REQUIRE(get_ref_count(strong.get()) == 2);
136+
137+
ClassicCom* ptr = get_self<ClassicCom>(object);
138+
REQUIRE(ptr == strong.get());
139+
140+
REQUIRE(get_ref_count(strong.get()) == 2);
141+
strong = nullptr;
142+
REQUIRE(get_ref_count(object) == 1);
143+
144+
strong = get_self<ClassicCom>(object)->get_strong();
145+
REQUIRE(get_ref_count(object) == 2);
146+
strong = nullptr;
147+
REQUIRE(get_ref_count(object) == 1);
148+
149+
weak_ref<ClassicCom> weak = get_self<ClassicCom>(object)->get_weak();
150+
REQUIRE(get_ref_count(object) == 1); // <-- still just one!
151+
152+
strong = weak.get();
153+
REQUIRE(strong);
154+
REQUIRE(get_ref_count(object) == 2);
155+
156+
strong = nullptr;
157+
REQUIRE(get_ref_count(object) == 1);
158+
object = nullptr;
159+
111160
strong = weak.get();
112161
REQUIRE(!strong);
113162
}

0 commit comments

Comments
 (0)