sdbus-c++ 2.0.0
High-level C++ D-Bus library based on systemd D-Bus implementation
Loading...
Searching...
No Matches
ConvenienceApiClasses.inl
Go to the documentation of this file.
1
27#ifndef SDBUS_CPP_CONVENIENCEAPICLASSES_INL_
28#define SDBUS_CPP_CONVENIENCEAPICLASSES_INL_
29
30#include <sdbus-c++/Error.h>
31#include <sdbus-c++/IObject.h>
32#include <sdbus-c++/IProxy.h>
33#include <sdbus-c++/Message.h>
36#include <sdbus-c++/Types.h>
37
38#include <cassert>
39#include <exception>
40#include <string>
41#include <tuple>
42#include <type_traits>
43
44namespace sdbus {
45
46 /*** ------------- ***/
47 /*** VTableAdder ***/
48 /*** ------------- ***/
49
50 inline VTableAdder::VTableAdder(IObject& object, std::vector<VTableItem> vtable)
51 : object_(object)
52 , vtable_(std::move(vtable))
53 {
54 }
55
56 inline void VTableAdder::forInterface(InterfaceName interfaceName)
57 {
58 object_.addVTable(std::move(interfaceName), std::move(vtable_));
59 }
60
61 inline void VTableAdder::forInterface(std::string interfaceName)
62 {
63 forInterface(InterfaceName{std::move(interfaceName)});
64 }
65
66 [[nodiscard]] inline Slot VTableAdder::forInterface(InterfaceName interfaceName, return_slot_t)
67 {
68 return object_.addVTable(std::move(interfaceName), std::move(vtable_), return_slot);
69 }
70
71 [[nodiscard]] inline Slot VTableAdder::forInterface(std::string interfaceName, return_slot_t)
72 {
73 return forInterface(InterfaceName{std::move(interfaceName)}, return_slot);
74 }
75
76 /*** ------------- ***/
77 /*** SignalEmitter ***/
78 /*** ------------- ***/
79
80 inline SignalEmitter::SignalEmitter(IObject& object, const SignalName& signalName)
81 : SignalEmitter(object, signalName.c_str())
82 {
83 }
84
85 inline SignalEmitter::SignalEmitter(IObject& object, const char* signalName)
86 : object_(object)
87 , signalName_(signalName)
88 , exceptions_(std::uncaught_exceptions())
89 {
90 }
91
92 inline SignalEmitter::~SignalEmitter() noexcept(false) // since C++11, destructors must
93 { // explicitly be allowed to throw
94 // Don't emit the signal if SignalEmitter threw an exception in one of its methods
95 if (std::uncaught_exceptions() != exceptions_)
96 return;
97
98 // emitSignal() can throw. But as the SignalEmitter shall always be used as an unnamed,
99 // temporary object, i.e. not as a stack-allocated object, the double-exception situation
100 // shall never happen. I.e. it should not happen that this destructor is directly called
101 // in the stack-unwinding process of another flying exception (which would lead to immediate
102 // termination). It can be called indirectly in the destructor of another object, but that's
103 // fine and safe provided that the caller catches exceptions thrown from here.
104 // Therefore, we can allow emitSignal() to throw even if we are in the destructor.
105 // Bottomline is, to be on the safe side, the caller must take care of catching and reacting
106 // to the exception thrown from here if the caller is a destructor itself.
107 object_.emitSignal(signal_);
108 }
109
110 inline SignalEmitter& SignalEmitter::onInterface(const InterfaceName& interfaceName)
111 {
112 return onInterface(interfaceName.c_str());
113 }
114
115 inline SignalEmitter& SignalEmitter::onInterface(const std::string& interfaceName)
116 {
117 return onInterface(interfaceName.c_str());
118 }
119
120 inline SignalEmitter& SignalEmitter::onInterface(const char* interfaceName)
121 {
122 signal_ = object_.createSignal(interfaceName, signalName_);
123
124 return *this;
125 }
126
127 template <typename... _Args>
128 inline void SignalEmitter::withArguments(_Args&&... args)
129 {
130 assert(signal_.isValid()); // onInterface() must be placed/called prior to withArguments()
131
132 detail::serialize_pack(signal_, std::forward<_Args>(args)...);
133 }
134
135 /*** ------------- ***/
136 /*** MethodInvoker ***/
137 /*** ------------- ***/
138
139 inline MethodInvoker::MethodInvoker(IProxy& proxy, const MethodName& methodName)
140 : MethodInvoker(proxy, methodName.c_str())
141 {
142 }
143
144 inline MethodInvoker::MethodInvoker(IProxy& proxy, const char* methodName)
145 : proxy_(proxy)
146 , methodName_(methodName)
147 , exceptions_(std::uncaught_exceptions())
148 {
149 }
150
151 inline MethodInvoker::~MethodInvoker() noexcept(false) // since C++11, destructors must
152 { // explicitly be allowed to throw
153 // Don't call the method if it has been called already or if MethodInvoker
154 // threw an exception in one of its methods
155 if (methodCalled_ || std::uncaught_exceptions() != exceptions_)
156 return;
157
158 // callMethod() can throw. But as the MethodInvoker shall always be used as an unnamed,
159 // temporary object, i.e. not as a stack-allocated object, the double-exception situation
160 // shall never happen. I.e. it should not happen that this destructor is directly called
161 // in the stack-unwinding process of another flying exception (which would lead to immediate
162 // termination). It can be called indirectly in the destructor of another object, but that's
163 // fine and safe provided that the caller catches exceptions thrown from here.
164 // Therefore, we can allow callMethod() to throw even if we are in the destructor.
165 // Bottomline is, to be on the safe side, the caller must take care of catching and reacting
166 // to the exception thrown from here if the caller is a destructor itself.
167 proxy_.callMethod(method_, timeout_);
168 }
169
170 inline MethodInvoker& MethodInvoker::onInterface(const InterfaceName& interfaceName)
171 {
172 return onInterface(interfaceName.c_str());
173 }
174
175 inline MethodInvoker& MethodInvoker::onInterface(const std::string& interfaceName)
176 {
177 return onInterface(interfaceName.c_str());
178 }
179
180 inline MethodInvoker& MethodInvoker::onInterface(const char* interfaceName)
181 {
182 method_ = proxy_.createMethodCall(interfaceName, methodName_);
183
184 return *this;
185 }
186
187 inline MethodInvoker& MethodInvoker::withTimeout(uint64_t usec)
188 {
189 timeout_ = usec;
190
191 return *this;
192 }
193
194 template <typename _Rep, typename _Period>
195 inline MethodInvoker& MethodInvoker::withTimeout(const std::chrono::duration<_Rep, _Period>& timeout)
196 {
197 auto microsecs = std::chrono::duration_cast<std::chrono::microseconds>(timeout);
198 return withTimeout(microsecs.count());
199 }
200
201 template <typename... _Args>
202 inline MethodInvoker& MethodInvoker::withArguments(_Args&&... args)
203 {
204 assert(method_.isValid()); // onInterface() must be placed/called prior to this function
205
206 detail::serialize_pack(method_, std::forward<_Args>(args)...);
207
208 return *this;
209 }
210
211 template <typename... _Args>
212 inline void MethodInvoker::storeResultsTo(_Args&... args)
213 {
214 assert(method_.isValid()); // onInterface() must be placed/called prior to this function
215
216 auto reply = proxy_.callMethod(method_, timeout_);
217 methodCalled_ = true;
218
219 detail::deserialize_pack(reply, args...);
220 }
221
222 inline void MethodInvoker::dontExpectReply()
223 {
224 assert(method_.isValid()); // onInterface() must be placed/called prior to this function
225
226 method_.dontExpectReply();
227 }
228
229 /*** ------------------ ***/
230 /*** AsyncMethodInvoker ***/
231 /*** ------------------ ***/
232
233 inline AsyncMethodInvoker::AsyncMethodInvoker(IProxy& proxy, const MethodName& methodName)
234 : AsyncMethodInvoker(proxy, methodName.c_str())
235 {
236 }
237
238 inline AsyncMethodInvoker::AsyncMethodInvoker(IProxy& proxy, const char* methodName)
239 : proxy_(proxy)
240 , methodName_(methodName)
241 {
242 }
243
244 inline AsyncMethodInvoker& AsyncMethodInvoker::onInterface(const InterfaceName& interfaceName)
245 {
246 return onInterface(interfaceName.c_str());
247 }
248
249 inline AsyncMethodInvoker& AsyncMethodInvoker::onInterface(const std::string& interfaceName)
250 {
251 return onInterface(interfaceName.c_str());
252 }
253
254 inline AsyncMethodInvoker& AsyncMethodInvoker::onInterface(const char* interfaceName)
255 {
256 method_ = proxy_.createMethodCall(interfaceName, methodName_);
257
258 return *this;
259 }
260
261 inline AsyncMethodInvoker& AsyncMethodInvoker::withTimeout(uint64_t usec)
262 {
263 timeout_ = usec;
264
265 return *this;
266 }
267
268 template <typename _Rep, typename _Period>
269 inline AsyncMethodInvoker& AsyncMethodInvoker::withTimeout(const std::chrono::duration<_Rep, _Period>& timeout)
270 {
271 auto microsecs = std::chrono::duration_cast<std::chrono::microseconds>(timeout);
272 return withTimeout(microsecs.count());
273 }
274
275 template <typename... _Args>
276 inline AsyncMethodInvoker& AsyncMethodInvoker::withArguments(_Args&&... args)
277 {
278 assert(method_.isValid()); // onInterface() must be placed/called prior to this function
279
280 detail::serialize_pack(method_, std::forward<_Args>(args)...);
281
282 return *this;
283 }
284
285 template <typename _Function>
286 PendingAsyncCall AsyncMethodInvoker::uponReplyInvoke(_Function&& callback)
287 {
288 assert(method_.isValid()); // onInterface() must be placed/called prior to this function
289
290 return proxy_.callMethodAsync(method_, makeAsyncReplyHandler(std::forward<_Function>(callback)), timeout_);
291 }
292
293 template <typename _Function>
294 [[nodiscard]] Slot AsyncMethodInvoker::uponReplyInvoke(_Function&& callback, return_slot_t)
295 {
296 assert(method_.isValid()); // onInterface() must be placed/called prior to this function
297
298 return proxy_.callMethodAsync( method_
299 , makeAsyncReplyHandler(std::forward<_Function>(callback))
300 , timeout_
301 , return_slot );
302 }
303
304 template <typename _Function>
305 inline async_reply_handler AsyncMethodInvoker::makeAsyncReplyHandler(_Function&& callback)
306 {
307 return [callback = std::forward<_Function>(callback)](MethodReply reply, std::optional<Error> error)
308 {
309 // Create a tuple of callback input arguments' types, which will be used
310 // as a storage for the argument values deserialized from the message.
311 tuple_of_function_input_arg_types_t<_Function> args;
312
313 // Deserialize input arguments from the message into the tuple (if no error occurred).
314 if (!error)
315 {
316 try
317 {
318 reply >> args;
319 }
320 catch (const Error& e)
321 {
322 // Pass message deserialization exceptions to the client via callback error parameter,
323 // instead of propagating them up the message loop call stack.
324 sdbus::apply(callback, e, args);
325 return;
326 }
327 }
328
329 // Invoke callback with input arguments from the tuple.
330 sdbus::apply(callback, std::move(error), args);
331 };
332 }
333
334 template <typename... _Args>
335 std::future<future_return_t<_Args...>> AsyncMethodInvoker::getResultAsFuture()
336 {
337 auto promise = std::make_shared<std::promise<future_return_t<_Args...>>>();
338 auto future = promise->get_future();
339
340 uponReplyInvoke([promise = std::move(promise)](std::optional<Error> error, _Args... args)
341 {
342 if (!error)
343 if constexpr (!std::is_void_v<future_return_t<_Args...>>)
344 promise->set_value({std::move(args)...});
345 else
346 promise->set_value();
347 else
348 promise->set_exception(std::make_exception_ptr(*std::move(error)));
349 });
350
351 // Will be std::future<void> for no D-Bus method return value
352 // or std::future<T> for single D-Bus method return value
353 // or std::future<std::tuple<...>> for multiple method return values
354 return future;
355 }
356
357 /*** ---------------- ***/
358 /*** SignalSubscriber ***/
359 /*** ---------------- ***/
360
361 inline SignalSubscriber::SignalSubscriber(IProxy& proxy, const SignalName& signalName)
362 : SignalSubscriber(proxy, signalName.c_str())
363 {
364 }
365
366 inline SignalSubscriber::SignalSubscriber(IProxy& proxy, const char* signalName)
367 : proxy_(proxy)
368 , signalName_(signalName)
369 {
370 }
371
372 inline SignalSubscriber& SignalSubscriber::onInterface(const InterfaceName& interfaceName)
373 {
374 return onInterface(interfaceName.c_str());
375 }
376
377 inline SignalSubscriber& SignalSubscriber::onInterface(const std::string& interfaceName)
378 {
379 return onInterface(interfaceName.c_str());
380 }
381
382 inline SignalSubscriber& SignalSubscriber::onInterface(const char* interfaceName)
383 {
384 interfaceName_ = std::move(interfaceName);
385
386 return *this;
387 }
388
389 template <typename _Function>
390 inline void SignalSubscriber::call(_Function&& callback)
391 {
392 assert(interfaceName_ != nullptr); // onInterface() must be placed/called prior to this function
393
394 proxy_.registerSignalHandler( interfaceName_
395 , signalName_
396 , makeSignalHandler(std::forward<_Function>(callback)) );
397 }
398
399 template <typename _Function>
400 [[nodiscard]] inline Slot SignalSubscriber::call(_Function&& callback, return_slot_t)
401 {
402 assert(interfaceName_ != nullptr); // onInterface() must be placed/called prior to this function
403
404 return proxy_.registerSignalHandler( interfaceName_
405 , signalName_
406 , makeSignalHandler(std::forward<_Function>(callback))
407 , return_slot );
408 }
409
410 template <typename _Function>
411 inline signal_handler SignalSubscriber::makeSignalHandler(_Function&& callback)
412 {
413 return [callback = std::forward<_Function>(callback)](Signal signal)
414 {
415 // Create a tuple of callback input arguments' types, which will be used
416 // as a storage for the argument values deserialized from the signal message.
417 tuple_of_function_input_arg_types_t<_Function> signalArgs;
418
419 // The signal handler can take pure signal parameters only, or an additional `std::optional<Error>` as its first
420 // parameter. In the former case, if the deserialization fails (e.g. due to signature mismatch),
421 // the failure is ignored (and signal simply dropped). In the latter case, the deserialization failure
422 // will be communicated to the client's signal handler as a valid Error object inside the std::optional parameter.
423 if constexpr (has_error_param_v<_Function>)
424 {
425 // Deserialize input arguments from the signal message into the tuple
426 try
427 {
428 signal >> signalArgs;
429 }
430 catch (const sdbus::Error& e)
431 {
432 // Pass message deserialization exceptions to the client via callback error parameter,
433 // instead of propagating them up the message loop call stack.
434 sdbus::apply(callback, e, signalArgs);
435 return;
436 }
437
438 // Invoke callback with no error and input arguments from the tuple.
439 sdbus::apply(callback, {}, signalArgs);
440 }
441 else
442 {
443 // Deserialize input arguments from the signal message into the tuple
444 signal >> signalArgs;
445
446 // Invoke callback with input arguments from the tuple.
447 sdbus::apply(callback, signalArgs);
448 }
449 };
450 }
451
452 /*** -------------- ***/
453 /*** PropertyGetter ***/
454 /*** -------------- ***/
455
456 inline PropertyGetter::PropertyGetter(IProxy& proxy, std::string_view propertyName)
457 : proxy_(proxy)
458 , propertyName_(std::move(propertyName))
459 {
460 }
461
462 inline Variant PropertyGetter::onInterface(std::string_view interfaceName)
463 {
464 Variant var;
465 proxy_.callMethod("Get")
466 .onInterface(DBUS_PROPERTIES_INTERFACE_NAME)
467 .withArguments(interfaceName, propertyName_)
468 .storeResultsTo(var);
469 return var;
470 }
471
472 /*** ------------------- ***/
473 /*** AsyncPropertyGetter ***/
474 /*** ------------------- ***/
475
476 inline AsyncPropertyGetter::AsyncPropertyGetter(IProxy& proxy, std::string_view propertyName)
477 : proxy_(proxy)
478 , propertyName_(std::move(propertyName))
479 {
480 }
481
482 inline AsyncPropertyGetter& AsyncPropertyGetter::onInterface(std::string_view interfaceName)
483 {
484 interfaceName_ = std::move(interfaceName);
485
486 return *this;
487 }
488
489 template <typename _Function>
490 PendingAsyncCall AsyncPropertyGetter::uponReplyInvoke(_Function&& callback)
491 {
492 static_assert( std::is_invocable_r_v<void, _Function, std::optional<Error>, Variant>
493 , "Property get callback function must accept std::optional<Error> and property value as Variant" );
494
495 assert(!interfaceName_.empty()); // onInterface() must be placed/called prior to this function
496
497 return proxy_.callMethodAsync("Get")
498 .onInterface(DBUS_PROPERTIES_INTERFACE_NAME)
499 .withArguments(interfaceName_, propertyName_)
500 .uponReplyInvoke(std::forward<_Function>(callback));
501 }
502
503 template <typename _Function>
504 [[nodiscard]] Slot AsyncPropertyGetter::uponReplyInvoke(_Function&& callback, return_slot_t)
505 {
506 static_assert( std::is_invocable_r_v<void, _Function, std::optional<Error>, Variant>
507 , "Property get callback function must accept std::optional<Error> and property value as Variant" );
508
509 assert(!interfaceName_.empty()); // onInterface() must be placed/called prior to this function
510
511 return proxy_.callMethodAsync("Get")
512 .onInterface(DBUS_PROPERTIES_INTERFACE_NAME)
513 .withArguments(interfaceName_, propertyName_)
514 .uponReplyInvoke(std::forward<_Function>(callback), return_slot);
515 }
516
517 inline std::future<Variant> AsyncPropertyGetter::getResultAsFuture()
518 {
519 assert(!interfaceName_.empty()); // onInterface() must be placed/called prior to this function
520
521 return proxy_.callMethodAsync("Get")
522 .onInterface(DBUS_PROPERTIES_INTERFACE_NAME)
523 .withArguments(interfaceName_, propertyName_)
524 .getResultAsFuture<Variant>();
525 }
526
527 /*** -------------- ***/
528 /*** PropertySetter ***/
529 /*** -------------- ***/
530
531 inline PropertySetter::PropertySetter(IProxy& proxy, std::string_view propertyName)
532 : proxy_(proxy)
533 , propertyName_(std::move(propertyName))
534 {
535 }
536
537 inline PropertySetter& PropertySetter::onInterface(std::string_view interfaceName)
538 {
539 interfaceName_ = std::move(interfaceName);
540
541 return *this;
542 }
543
544 template <typename _Value>
545 inline void PropertySetter::toValue(const _Value& value)
546 {
547 PropertySetter::toValue(Variant{value});
548 }
549
550 template <typename _Value>
551 inline void PropertySetter::toValue(const _Value& value, dont_expect_reply_t)
552 {
553 PropertySetter::toValue(Variant{value}, dont_expect_reply);
554 }
555
556 inline void PropertySetter::toValue(const Variant& value)
557 {
558 assert(!interfaceName_.empty()); // onInterface() must be placed/called prior to this function
559
560 proxy_.callMethod("Set")
561 .onInterface(DBUS_PROPERTIES_INTERFACE_NAME)
562 .withArguments(interfaceName_, propertyName_, value);
563 }
564
565 inline void PropertySetter::toValue(const Variant& value, dont_expect_reply_t)
566 {
567 assert(!interfaceName_.empty()); // onInterface() must be placed/called prior to this function
568
569 proxy_.callMethod("Set")
570 .onInterface(DBUS_PROPERTIES_INTERFACE_NAME)
571 .withArguments(interfaceName_, propertyName_, value)
572 .dontExpectReply();
573 }
574
575 /*** ------------------- ***/
576 /*** AsyncPropertySetter ***/
577 /*** ------------------- ***/
578
579 inline AsyncPropertySetter::AsyncPropertySetter(IProxy& proxy, std::string_view propertyName)
580 : proxy_(proxy)
581 , propertyName_(propertyName)
582 {
583 }
584
585 inline AsyncPropertySetter& AsyncPropertySetter::onInterface(std::string_view interfaceName)
586 {
587 interfaceName_ = std::move(interfaceName);
588
589 return *this;
590 }
591
592 template <typename _Value>
593 inline AsyncPropertySetter& AsyncPropertySetter::toValue(_Value&& value)
594 {
595 return AsyncPropertySetter::toValue(Variant{std::forward<_Value>(value)});
596 }
597
598 inline AsyncPropertySetter& AsyncPropertySetter::toValue(Variant value)
599 {
600 value_ = std::move(value);
601
602 return *this;
603 }
604
605 template <typename _Function>
606 PendingAsyncCall AsyncPropertySetter::uponReplyInvoke(_Function&& callback)
607 {
608 static_assert( std::is_invocable_r_v<void, _Function, std::optional<Error>>
609 , "Property set callback function must accept std::optional<Error> only" );
610
611 assert(!interfaceName_.empty()); // onInterface() must be placed/called prior to this function
612
613 return proxy_.callMethodAsync("Set")
614 .onInterface(DBUS_PROPERTIES_INTERFACE_NAME)
615 .withArguments(interfaceName_, propertyName_, std::move(value_))
616 .uponReplyInvoke(std::forward<_Function>(callback));
617 }
618
619 template <typename _Function>
620 [[nodiscard]] Slot AsyncPropertySetter::uponReplyInvoke(_Function&& callback, return_slot_t)
621 {
622 static_assert( std::is_invocable_r_v<void, _Function, std::optional<Error>>
623 , "Property set callback function must accept std::optional<Error> only" );
624
625 assert(!interfaceName_.empty()); // onInterface() must be placed/called prior to this function
626
627 return proxy_.callMethodAsync("Set")
628 .onInterface(DBUS_PROPERTIES_INTERFACE_NAME)
629 .withArguments(interfaceName_, propertyName_, std::move(value_))
630 .uponReplyInvoke(std::forward<_Function>(callback), return_slot);
631 }
632
633 inline std::future<void> AsyncPropertySetter::getResultAsFuture()
634 {
635 assert(!interfaceName_.empty()); // onInterface() must be placed/called prior to this function
636
637 return proxy_.callMethodAsync("Set")
638 .onInterface(DBUS_PROPERTIES_INTERFACE_NAME)
639 .withArguments(interfaceName_, propertyName_, std::move(value_))
640 .getResultAsFuture<>();
641 }
642
643 /*** ------------------- ***/
644 /*** AllPropertiesGetter ***/
645 /*** ------------------- ***/
646
647 inline AllPropertiesGetter::AllPropertiesGetter(IProxy& proxy)
648 : proxy_(proxy)
649 {
650 }
651
652 inline std::map<PropertyName, Variant> AllPropertiesGetter::onInterface(std::string_view interfaceName)
653 {
654 std::map<PropertyName, Variant> props;
655 proxy_.callMethod("GetAll")
656 .onInterface(DBUS_PROPERTIES_INTERFACE_NAME)
657 .withArguments(std::move(interfaceName))
658 .storeResultsTo(props);
659 return props;
660 }
661
662 /*** ------------------------ ***/
663 /*** AsyncAllPropertiesGetter ***/
664 /*** ------------------------ ***/
665
666 inline AsyncAllPropertiesGetter::AsyncAllPropertiesGetter(IProxy& proxy)
667 : proxy_(proxy)
668 {
669 }
670
671 inline AsyncAllPropertiesGetter& AsyncAllPropertiesGetter::onInterface(std::string_view interfaceName)
672 {
673 interfaceName_ = std::move(interfaceName);
674
675 return *this;
676 }
677
678 template <typename _Function>
679 PendingAsyncCall AsyncAllPropertiesGetter::uponReplyInvoke(_Function&& callback)
680 {
681 static_assert( std::is_invocable_r_v<void, _Function, std::optional<Error>, std::map<PropertyName, Variant>>
682 , "All properties get callback function must accept std::optional<Error> and a map of property names to their values" );
683
684 assert(!interfaceName_.empty()); // onInterface() must be placed/called prior to this function
685
686 return proxy_.callMethodAsync("GetAll")
687 .onInterface(DBUS_PROPERTIES_INTERFACE_NAME)
688 .withArguments(interfaceName_)
689 .uponReplyInvoke(std::forward<_Function>(callback));
690 }
691
692 template <typename _Function>
693 [[nodiscard]] Slot AsyncAllPropertiesGetter::uponReplyInvoke(_Function&& callback, return_slot_t)
694 {
695 static_assert( std::is_invocable_r_v<void, _Function, std::optional<Error>, std::map<PropertyName, Variant>>
696 , "All properties get callback function must accept std::optional<Error> and a map of property names to their values" );
697
698 assert(!interfaceName_.empty()); // onInterface() must be placed/called prior to this function
699
700 return proxy_.callMethodAsync("GetAll")
701 .onInterface(DBUS_PROPERTIES_INTERFACE_NAME)
702 .withArguments(interfaceName_)
703 .uponReplyInvoke(std::forward<_Function>(callback), return_slot);
704 }
705
706 inline std::future<std::map<PropertyName, Variant>> AsyncAllPropertiesGetter::getResultAsFuture()
707 {
708 assert(!interfaceName_.empty()); // onInterface() must be placed/called prior to this function
709
710 return proxy_.callMethodAsync("GetAll")
711 .onInterface(DBUS_PROPERTIES_INTERFACE_NAME)
712 .withArguments(interfaceName_)
713 .getResultAsFuture<std::map<PropertyName, Variant>>();
714 }
715
716} // namespace sdbus
717
718#endif /* SDBUS_CPP_CONVENIENCEAPICLASSES_INL_ */
Definition Error.h:44