* Types.h: add deduction guides for Struct from std::tuple
C++23 changed the generation of implicit deduction guides. This causes
the compiler to also see deduction guides for std::tuple as candidates
for sdbus::Struct.
Because of the competing guides the compiler doesn't know which one to pick.
This seems to be implemented from gcc 15 on and is thus causing breakage there.
To fix this we need to add explicit deduction guides when std::tuple is passed
to sdbus::Struct.
fixes https://github.com/Kistler-Group/sdbus-cpp/issues/524
* refactor: remove std::decay_t wrapper
We need to be able to create sdbus::Structs
with element types being references.
---------
Co-authored-by: Stanislav Angelovič <stanislav.angelovic@protonmail.com>
* feat: add export support
This makes sdbus-c++ consumable from the build tree without the need for
an explicit installation. This can be very handy for e.g. testing
purposes. Crucially, downstream projects will depend on upstream to
properly export everything. Otherwise, they can't be built as static
libraries, even if sdbus-c++ is only a private dependency.
See also https://runebook.dev/en/docs/cmake/command/export
* fix(cmake): avoid possibly empty EXPORT_SET
EXPORT_SET is empty when SDBUSCPP_INSTALL is OFF,
which leads to targets file with no targets.
---------
Co-authored-by: Stanislav Angelovič <stanislav.angelovic@protonmail.com>
At the moment, downstream projects will have to differentiate based off the way the obtained sdbus-c++ in CMake. If they use `find_package`, the target they have to use is `SDBusCpp::sdbus-c++`, whereas the target is merely `sdbus-c++` if they use `FetchContent` (i.e. use without installation).
By creating an alias target, it is now always possible to use the `DBusCpp::sdbus-c++` target regardless of how the library was obtained.
* Change CPACK_COMPONENTS_ALL variable in CMakeLists.txt according to components names referenced in install function call
* Remove redundant sdbus-c++ from Debian packages
---------
Co-authored-by: Stanislav Angelovič <stanislav.angelovic@protonmail.com>
* test: add Variant move test
* fix: provide signature_of<_T&&>
Provide signature_of specialization for rvalue references resp.
allow when forwarding references resolve to rvalue references
signature_of<_T&&> is needed e.g. for std::map::try_emplace() when the
emplaced sdbus:: type is passed as rvalue reference, otherwise the
static_assert "Unsupported D-Bus type ..." would trigger
See https://github.com/Kistler-Group/sdbus-cpp/issues/513#issuecomment-3429733769
for an elaborate explanation
Signed-off-by: Simon Braunschmidt <simon.braunschmidt@iba-group.com>
---------
Signed-off-by: Simon Braunschmidt <simon.braunschmidt@iba-group.com>
Co-authored-by: Stanislav Angelovic <stanislav.angelovic.ext@siemens.com>
This implements three variants of `GetManagedObjectsAsync()` API into the standard `ObjectManager` client interface.
---------
Signed-off-by: Joel Winarske <joel.winarske@gmail.com>
Co-authored-by: Stanislav Angelovič <stanislav.angelovic@protonmail.com>
Add `Message::getCookie()` and `MethodReply::getReplyCookie()` functions, based on underlying sd-bus cookie functions. They can be useful when pairing method call messages and method call reply messages.
---------
Co-authored-by: Dylan Howey <dylan.howey@evgo.com>
Co-authored-by: Stanislav Angelovič <stanislav.angelovic@protonmail.com>
* Bump to latest versions of upload-artifact and checkout GitHub scripts
* Remove obsolete Ubuntu-20.04 image
* Introduce Ubuntu-24.04 image
* Other related updates and fixes in the CI
Before the patch, generating an adaptor from https://gitlab.freedesktop.org/hadess/mpris-spec/-/blob/master/spec/org.mpris.MediaPlayer2.xml
would produce incorrect code like this:
```
m_object.addVTable( sdbus::setInterfaceFlags().withPropertyUpdateBehavior(sdbus::Flags::EMITS_CHANGE_SIGNAL);
, sdbus::registerMethod("Raise").implementedAs([this](){ return this->Raise(); })
, sdbus::registerMethod("Quit").implementedAs([this](){ return this->Quit(); })
...
```
With this patch, the code produced is:
```
m_object.addVTable( sdbus::setInterfaceFlags().withPropertyUpdateBehavior(sdbus::Flags::EMITS_CHANGE_SIGNAL)
, sdbus::registerMethod("Raise").implementedAs([this](){ return this->Raise(); })
, sdbus::registerMethod("Quit").implementedAs([this](){ return this->Quit(); })
...
```
This allows nesting variants, i.e. allows a variant to contain another variant as its value. Until now, there was no such possibility, since the default generated copy constructor would be invoked which would create a copy of source variant instead of embed the source variant as a value in the destination variant. The default generated copy constructor is kept, for it makes sense too, but a new tag-based overload is added for embedding the source variant into the destination variant.
This extends the functionality of SDBUSCPP_REGISTER_STRUCT macro.
It now provides functionality for serializing a user-defined struct as an a{sv} dictionary, and for deserializing an a{sv} dictionary into a user-defined struct. The former one is achieved by decorating the struct with sdbus::as_dictionary(struct), the latter one is an automatic behavior -- when sdbus-c++ is asked to deserialize into a struct but the data in the message is of type a{sv}, then the dict-to-struct deserialization is performed automatically.
There are some aspects of behavior in the serialization/deserialization functionality that can be customized by the client. Newly introduced SDBUSCPP_ENABLE_NESTED_STRUCT2DICT_SERIALIZATION and SDBUSCPP_ENABLE_RELAXED_DICT2STRUCT_DESERIALIZATION macros serve the purpose.
Until now, the solution to ensure that even large messages are fully sent out has been to flush the connection queues after each sending of a message, which is likely an unnecessary call (with unnecessary cost) in vast majority of cases, and which may block the connection from doing other work until the large message is fully sent out. This was a rather quick, hacky workaround.
Now, after the sending the message we check whether it has been sent out fully or not. If not (outbound queues are non-empty), then we send a wake-up signal to the connection event loop. The event loop thread then fetches new sd-bus timeouts and events and will see that there are pending outbound messages to process, and will process them together with any other prospective pending events, until there is nothing to process (i.e., the outbound message has been fully dispatched).
This reorganizes the layers of abstraction in the sense how `Message` depends on `Connection` and vice versa. Now, `Message` has a link to the `Connection`. This replaces the shortcut link to the low-level `SdBus` interface that the `Message` kept. The interactions from `Message` now go through `Connection` which forwards them to `SdBus`. `Connection` is now a sole owner of the low-level `SdBus` interface. This allows for future changes around `SdBus` (e.g. a change from virtual functions back to non-virtual functions) without affecting the rest of the library. `Proxy`s and `Object`s can now send messages directly without having to go through `Connection`. The `Connection` no more depends on `Message` business-logic methods; it serves only as a factory for messages.
The flow for creating messages: `Proxy`/`Object` -> `Connection` -> `SdBus`
The flow for sending messages: (`Proxy`/`Object` ->) `Message` -> `Connection` -> `SdBus`
This also better reflects how dependencies are managed in the underlying sd-bus library.
Additionally, `getSdBusInterface()` methods are removed which was anyway planned, and improves the design by "Tell, don't ask" principle.
This refactoring is the necessary enabler for other upcoming improvements (regarding sending long messages, or creds refactoring, for example).
Fix inconsistencies in documentation and CMake files regarding minimum required libsystemd version (which is v238 for sdbus-c++ v2.0). Also fix compiler error bug in sdbus-c++ code when compiled against older libsystemd versions. Plus some extra related cleanups.
This fixes the template specialization ambiguity error when a signature_of applied upon a const (and/or volatile) enum type would render the const specialization and the enum specialization as two equally-ranked candidates.
This makes that you can use these macros in headers as well as
source files.
Else you will get a warning about multiple definitions of the same
function.
This introduces SDBUSCPP_REGISTER_STRUCT macro that helps clients conveniently, in one line, teach sdbus-c++ to recognize and accept their custom C++ struct types wherever D-Bus structs are expected in a D-Bus API.
The macro saves some boilerplate that would otherwise be needed on client side for every registered struct.
Make all the API consistent by using return_slot_t-based overloads for returning the slots to clients, and overloads without that tag for "floating" slots. floating_slot_t tag was previously added for API backwards compatibility reasons, but now is a (counter-)duplicate to the return_slot_t.
Moving adaptor or proxy instances changes their `this` pointer. But `this` is captured by value in closures used by those instances, and this remains unchanged on move, leading to accessing an invalid instance when a lambda expression executes. Supporting move semantics would require unsubscribing/unregistering vtable, handlers, etc. and re-subscribing and re-registering all that, which is too complicated and may have side effects. Hence it has been decided that these classes are not moveable. One may use an indirection with e.g. `std::unique_ptr` to get move semantics.
Since sdbus-c++ knows types of D-Bus call/signal/property input/output parameters at compile time, why not assemble the D-Bus signature strings at compile time, too, instead of assembling them at run time as std::string with likely cost of (unnecessary) heap allocations...
std::array is well supported constexpr type in C++20, so we harness it to build the D-Bus signature string and store it into the binary at compile time.
Having explicit conversion operator is a good practice according to the C++ core guidelines, as it makes the code safer and better follows the principle of least astonishment. Also, it is consistent with the standard library style, where wrappers like std::variant, std::any, std::optional... also do not provide an implicit conversion to the underlying type. Last but not least, it paves the way for the upcoming std::variant <-> sdbus::Variant implicit conversions without surprising behavior in some edge cases.
This introduces strong types for `std::string`-based D-Bus types. This facilitates safer, less error-prone and more expressive API.
What previously was `auto proxy = createProxy("org.sdbuscpp.concatenator", "/org/sdbuscpp/concatenator");` is now written like `auto proxy = createProxy(ServiceName{"org.sdbuscpp.concatenator"}, ObjectPath{"/org/sdbuscpp/concatenator"});`.
These types are:
* `ObjectPath` type for the object path (the type has been around already but now is also used consistently in sdbus-c++ API for object path strings),
* `InterfaceName` type for D-Bus interface names,
* `BusName` (and its aliases `ServiceName` and `ConnectionName`) type for bus/service/connection names,
* `MemberName` (and its aliases `MethodName`, `SignalName` and `PropertyName`) type for D-Bus method, signal and property names,
* `Signature` type for the D-Bus signature (the type has been around already but now is also used consistently in sdbus-c++ API for signature strings),
* `Error::Name` type for D-Bus error names.
As of now sdbus-c++ supports C++20 but does not require it, and the used C++20 features are conditionally compiled depending on whether they are available or not.