Skip to content

Commit ede68ed

Browse files
authored
Allow capturing from a raw pointer (#896)
1 parent 1502e29 commit ede68ed

File tree

2 files changed

+70
-38
lines changed

2 files changed

+70
-38
lines changed

strings/base_com_ptr.h

Lines changed: 45 additions & 38 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,28 @@
11

2+
WINRT_EXPORT namespace winrt
3+
{
4+
template <typename T>
5+
struct com_ptr;
6+
}
7+
8+
namespace winrt::impl
9+
{
10+
template <typename T, typename F, typename...Args>
11+
int32_t capture_to(void**result, F function, Args&& ...args)
12+
{
13+
return function(args..., guid_of<T>(), result);
14+
}
15+
16+
template <typename T, typename O, typename M, typename...Args, std::enable_if_t<std::is_class_v<O> || std::is_union_v<O>, int> = 0>
17+
int32_t capture_to(void** result, O* object, M method, Args&& ...args)
18+
{
19+
return (object->*method)(args..., guid_of<T>(), result);
20+
}
21+
22+
template <typename T, typename O, typename M, typename...Args>
23+
int32_t capture_to(void** result, com_ptr<O> const& object, M method, Args&& ...args);
24+
}
25+
226
WINRT_EXPORT namespace winrt
327
{
428
template <typename T>
@@ -162,28 +186,16 @@ WINRT_EXPORT namespace winrt
162186
*other = m_ptr;
163187
}
164188

165-
template <typename F, typename...Args>
166-
bool try_capture(F function, Args&&...args)
167-
{
168-
return function(args..., guid_of<T>(), put_void()) >= 0;
169-
}
170-
171-
template <typename O, typename M, typename...Args>
172-
bool try_capture(com_ptr<O> const& object, M method, Args&&...args)
173-
{
174-
return (object.get()->*(method))(args..., guid_of<T>(), put_void()) >= 0;
175-
}
176-
177-
template <typename F, typename...Args>
178-
void capture(F function, Args&&...args)
189+
template <typename...Args>
190+
bool try_capture(Args&&...args)
179191
{
180-
check_hresult(function(args..., guid_of<T>(), put_void()));
192+
return impl::capture_to<T>(put_void(), std::forward<Args>(args)...) >= 0;
181193
}
182194

183-
template <typename O, typename M, typename...Args>
184-
void capture(com_ptr<O> const& object, M method, Args&&...args)
195+
template <typename...Args>
196+
void capture(Args&&...args)
185197
{
186-
check_hresult((object.get()->*(method))(args..., guid_of<T>(), put_void()));
198+
check_hresult(impl::capture_to<T>(put_void(), std::forward<Args>(args)...));
187199
}
188200

189201
private:
@@ -225,33 +237,19 @@ WINRT_EXPORT namespace winrt
225237
type* m_ptr{};
226238
};
227239

228-
template <typename T, typename F, typename...Args>
229-
impl::com_ref<T> try_capture(F function, Args&& ...args)
240+
template <typename T, typename...Args>
241+
impl::com_ref<T> try_capture(Args&& ...args)
230242
{
231243
void* result{};
232-
function(args..., guid_of<T>(), &result);
244+
impl::capture_to<T>(&result, std::forward<Args>(args)...);
233245
return { result, take_ownership_from_abi };
234246
}
235247

236-
template <typename T, typename O, typename M, typename...Args>
237-
impl::com_ref<T> try_capture(com_ptr<O> const& object, M method, Args&& ...args)
238-
{
239-
void* result{};
240-
(object.get()->*(method))(args..., guid_of<T>(), &result);
241-
return { result, take_ownership_from_abi };
242-
}
243-
template <typename T, typename F, typename...Args>
244-
impl::com_ref<T> capture(F function, Args&& ...args)
245-
{
246-
void* result{};
247-
check_hresult(function(args..., guid_of<T>(), &result));
248-
return { result, take_ownership_from_abi };
249-
}
250-
template <typename T, typename O, typename M, typename...Args>
251-
impl::com_ref<T> capture(com_ptr<O> const& object, M method, Args && ...args)
248+
template <typename T, typename...Args>
249+
impl::com_ref<T> capture(Args&& ...args)
252250
{
253251
void* result{};
254-
check_hresult((object.get()->*(method))(args..., guid_of<T>(), &result));
252+
check_hresult(impl::capture_to<T>(&result, std::forward<Args>(args)...));
255253
return { result, take_ownership_from_abi };
256254
}
257255

@@ -340,6 +338,15 @@ WINRT_EXPORT namespace winrt
340338
}
341339
}
342340

341+
namespace winrt::impl
342+
{
343+
template <typename T, typename O, typename M, typename...Args>
344+
int32_t capture_to(void** result, com_ptr<O> const& object, M method, Args&& ...args)
345+
{
346+
return (object.get()->*(method))(args..., guid_of<T>(), result);
347+
}
348+
}
349+
343350
template <typename T>
344351
void** IID_PPV_ARGS_Helper(winrt::com_ptr<T>* ptr) noexcept
345352
{

test/old_tests/UnitTests/capture.cpp

Lines changed: 25 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -39,46 +39,71 @@ HRESULT __stdcall CreateCapture(int value, GUID const& iid, void** object) noexc
3939

4040
TEST_CASE("capture")
4141
{
42+
// Capture from global function.
4243
com_ptr<ICapture> a = capture<ICapture>(CreateCapture, 10);
4344
REQUIRE(a->GetValue() == 10);
4445
a = nullptr;
4546
a.capture(CreateCapture, 20);
4647
REQUIRE(a->GetValue() == 20);
4748

49+
// Capture from com_ptr + method.
4850
auto b = capture<ICapture>(a, &ICapture::CreateMemberCapture, 30);
4951
REQUIRE(b->GetValue() == 30);
5052
b = nullptr;
5153
b.capture(a, &ICapture::CreateMemberCapture, 40);
5254
REQUIRE(b->GetValue() == 40);
5355

56+
// Capture from raw pointer + method.
57+
b = nullptr;
58+
b = capture<ICapture>(a.get(), &ICapture::CreateMemberCapture, 30);
59+
REQUIRE(b->GetValue() == 30);
60+
b = nullptr;
61+
b.capture(a.get(), &ICapture::CreateMemberCapture, 40);
62+
REQUIRE(b->GetValue() == 40);
63+
5464
com_ptr<IDispatch> d;
5565

5666
REQUIRE_THROWS_AS(capture<IDispatch>(CreateCapture, 0), hresult_no_interface);
5767
REQUIRE_THROWS_AS(d.capture(CreateCapture, 0), hresult_no_interface);
5868
REQUIRE_THROWS_AS(capture<IDispatch>(a, &ICapture::CreateMemberCapture, 0), hresult_no_interface);
5969
REQUIRE_THROWS_AS(d.capture(a, &ICapture::CreateMemberCapture, 0), hresult_no_interface);
70+
REQUIRE_THROWS_AS(capture<IDispatch>(a.get(), &ICapture::CreateMemberCapture, 0), hresult_no_interface);
71+
REQUIRE_THROWS_AS(d.capture(a.get(), &ICapture::CreateMemberCapture, 0), hresult_no_interface);
6072
}
6173

6274
TEST_CASE("try_capture")
6375
{
6476
// Identical to the "capture" test above, just with different
6577
// error handling.
78+
79+
// Capture from global function.
6680
com_ptr<ICapture> a = try_capture<ICapture>(CreateCapture, 10);
6781
REQUIRE(a->GetValue() == 10);
6882
a = nullptr;
6983
REQUIRE(a.try_capture(CreateCapture, 20));
7084
REQUIRE(a->GetValue() == 20);
7185

86+
// Capture from com_ptr + method.
7287
auto b = try_capture<ICapture>(a, &ICapture::CreateMemberCapture, 30);
7388
REQUIRE(b->GetValue() == 30);
7489
b = nullptr;
7590
REQUIRE(b.try_capture(a, &ICapture::CreateMemberCapture, 40));
7691
REQUIRE(b->GetValue() == 40);
7792

93+
// Capture from raw pointer + method.
94+
b = nullptr;
95+
b = try_capture<ICapture>(a.get(), &ICapture::CreateMemberCapture, 30);
96+
REQUIRE(b->GetValue() == 30);
97+
b = nullptr;
98+
b.try_capture(a.get(), &ICapture::CreateMemberCapture, 40);
99+
REQUIRE(b->GetValue() == 40);
100+
78101
com_ptr<IDispatch> d;
79102

80103
REQUIRE(!try_capture<IDispatch>(CreateCapture, 0));
81104
REQUIRE(!d.try_capture(CreateCapture, 0));
82105
REQUIRE(!try_capture<IDispatch>(a, &ICapture::CreateMemberCapture, 0));
83106
REQUIRE(!d.try_capture(a, &ICapture::CreateMemberCapture, 0));
107+
REQUIRE(!try_capture<IDispatch>(a.get(), &ICapture::CreateMemberCapture, 0));
108+
REQUIRE(!d.try_capture(a.get(), &ICapture::CreateMemberCapture, 0));
84109
}

0 commit comments

Comments
 (0)