Code Monkey home page Code Monkey logo

sdbus-cpp's Introduction

sdbus-c++

ci license release

sdbus-c++ is a high-level C++ D-Bus library for Linux designed to provide expressive, easy-to-use API in modern C++. It adds another layer of abstraction on top of sd-bus, a nice, fresh C D-Bus implementation by systemd.

sdbus-c++ has been written primarily as a replacement of dbus-c++, which currently suffers from a number of (unresolved) bugs, concurrency issues and inherent design complexities and limitations. sdbus-c++ has learned from dbus-c++ and has chosen a different path, a path of simple yet powerful design that is intuitive and friendly to the user and inherently free of those bugs.

Even though sdbus-c++ uses sd-bus library, it is not necessarily constrained to systemd and can perfectly be used in non-systemd environments as well.

Building and installing the library

The library is built using CMake:

$ mkdir build
$ cd build
$ cmake .. -DCMAKE_BUILD_TYPE=Release ${OTHER_CONFIG_FLAGS}
$ cmake --build .
$ sudo cmake --build . --target install

CMake configuration flags for sdbus-c++

  • SDBUSCPP_BUILD_CODEGEN [boolean]

    Option for building the stub code generator sdbus-c++-xml2cpp for generating the adaptor and proxy interfaces out of the D-Bus IDL XML description. Default value: OFF. Use -DSDBUSCPP_BUILD_CODEGEN=ON flag to turn on building the code gen.

  • SDBUSCPP_BUILD_DOCS [boolean]

    Option for including sdbus-c++ documentation files and tutorials. Default value: ON. With this option turned on, you may also enable/disable the following option:

    • SDBUSCPP_BUILD_DOXYGEN_DOCS [boolean]

      Option for building Doxygen documentation of sdbus-c++ API. If enabled, the documentation must still be built explicitly through cmake --build . --target doc. Default value: OFF. Use -DSDBUSCPP_BUILD_DOXYGEN_DOCS=OFF to disable searching for Doxygen and building Doxygen documentation of sdbus-c++ API.

  • SDBUSCPP_BUILD_TESTS [boolean]

    Option for building sdbus-c++ unit and integration tests, invokable by cmake --build . --target test (Note: before invoking cmake --build . --target test, make sure you copy tests/integrationtests/files/org.sdbuscpp.integrationtests.conf file to /etc/dbus-1/system.d directory). That incorporates downloading and building static libraries of Google Test. Default value: OFF. Use -DBUILD_TESTS=ON to enable building the tests. With this option turned on, you may also enable/disable the following options:

    • SDBUSCPP_BUILD_PERF_TESTS [boolean]

      Option for building sdbus-c++ performance tests. Default value: OFF.

    • SDBUSCPP_BUILD_STRESS_TESTS [boolean]

      Option for building sdbus-c++ stress tests. Default value: OFF.

    • SDBUSCPP_TESTS_INSTALL_PATH [string]

      Path where the test binaries shall get installed. Default value: ${CMAKE_INSTALL_PREFIX}/tests/sdbus-c++ (previously: /opt/test/bin).

  • SDBUSCPP_BUILD_LIBSYSTEMD [boolean]

    Option for building libsystemd as a sd-bus implementation when sdbus-c++ is built, and making libsystemd an integral part of sdbus-c++ library. Default value: OFF, which means that the sd-bus implementation library (libsystemd, libelogind, or basu) will be searched via pkg-config in the system.

    This option may be very helpful in environments where sd-bus implementation library is unavailable (see Solving sd-bus dependency for more information).

    With this option turned off, you may provide the following additional configuration flag:

    • SDBUSCPP_SDBUS_LIB [string]

      Defines which sd-bus implementation library to search for and use. Allowed values: default, systemd, elogind, basu. Default value: default, which means that sdbus-c++ will try to find any of systemd, elogind, basu in the order as listed here.

    With this option turned on, you may provide the following additional configuration flag:

    • SDBUSCPP_LIBSYSTEMD_VERSION [string]

      Defines version of systemd to be downloaded, built and integrated into sdbus-c++. Default value: 242.

    • SDBUSCPP_LIBSYSTEMD_EXTRA_CONFIG_OPTS [string]

      Additional options to be passed as-is to the libsystemd build system (meson for systemd v242) in its configure step. Can be used for passing e.g. toolchain file path in case of cross builds. Default value: empty.

  • CMAKE_BUILD_TYPE [string]

    This is a CMake-builtin option. Set to Release to build sdbus-c++ for production use. Set to Debug if you want to help further develop (and debug) the library :)

  • BUILD_SHARED_LIBS [boolean]

    This is a global CMake flag, promoted in sdbus-c++ project to a CMake option. Use this to control whether sdbus-c++ is built as either a shared or static library. Default value: ON.

  • SDBUSCPP_BUILD_EXAMPLES [boolean]

    Build example programs which are located in the example directory. Examples are not installed. Default value: OFF

Dependencies

  • C++17 - the library uses C++17 features.
  • libsystemd/libelogind/basu - libraries containing sd-bus implementation that sdbus-c++ is written around. In case of libsystemd and libelogind, version >= 236 is needed. (In case you have you're missing any of those sd-bus implementations, don't worry, see Solving sd-bus dependency for more information.)
  • googletest - google unit testing framework, only necessary when building tests, will be downloaded and built automatically.
  • pkgconfig - required for sdbus-c++ to be able to find some dependency packages.
  • expat - necessary when building the xml2cpp binding code generator (SDBUSCPP_BUILD_CODEGEN option is ON).

Licensing

The library is distributed under LGPLv2.1 license, with a specific exception for macro/template/inline code in library header files.

References/documentation

Contributing

Contributions that increase the library quality, functionality, or fix issues are very welcome. To introduce a change, please submit a pull request with a description.

Contact

https://github.com/Kistler-Group/sdbus-cpp

sdbus-cpp's People

Contributors

alivenets avatar anthonybrandon avatar ardazishvili avatar awdavenger avatar b-s-e avatar bluca avatar bobrofon avatar craig-spannring avatar dleeds-cpi avatar dreiss avatar fedyarov avatar georgthegreat avatar granxarixia avatar hellow554 avatar hogliux avatar jaysterling avatar jbeich avatar lctasca avatar lubo-svk avatar lygstate avatar m-blaha avatar marcullo avatar marek-szanyi avatar michab66 avatar olta avatar osamaghanem avatar peckato1 avatar pliniofpa avatar riuriuriu avatar sangelovic avatar

Stargazers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

Watchers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

sdbus-cpp's Issues

Getting something useful out of dbus variant types?

I'm pretty new to C++, but I was trying a simple program to show active NetworkManager connections with sdbus-cpp:

#include <iostream>
#include <typeinfo>
#include <sdbus-c++/sdbus-c++.h>

int main () {
    const char* destination_name = "org.freedesktop.NetworkManager";
    const char* object_path = "/org/freedesktop/NetworkManager";
    auto nm_proxy = sdbus::createObjectProxy(destination_name, object_path);

    // const char* interface_name = "org.freedesktop.NetworkManager";
    auto cons = nm_proxy->getProperty("ActiveConnections").onInterface("org.freedesktop.NetworkManager");
    auto that = cons.get<std::vector<std::string>>();
    for (const auto elem : that) {
        std::cout << elem << '\n';
    }
    return 0;
}

But this fails with:

terminate called after throwing an instance of 'sdbus::Error'
  what():  [System.Error.ENXIO] Failed to enter a variant (No such device or address)
aborted (core dumped)

Would you happen to know what I'm doing wrong? Commenting out the auto that... and the for loop makes the code compile just fine, and if I stick a std::cout << typeid(cons).name() << '\n'; in there, I get N5sdbus7VariantE, which leads me to believe I'm just converting the property wrong?

Problem with compilation

Hi,

when compiling I reached the following issue:

Message.cpp: In member function ‘void sdbus::Message::seal()’:
Message.cpp:553:83: error: ‘sd_bus_message_seal’ was not declared in this scope
auto r = sd_bus_message_seal((sd_bus_message*)msg_, messageCookie, sealTimeout);
^
Message.cpp: In function ‘sdbus::Message sdbus::createPlainMessage()’:
Message.cpp:669:72: error: ‘sd_bus_message_new’ was not declared in this scope
r = sd_bus_message_new(bus, &sdbusMsg, _SD_BUS_MESSAGE_TYPE_INVALID);

Could you please give me a hint how to avoid those errors?

BR,

Krzysztof

Branch naming

Proposal: reflect the purpose of the branch in its name(prefix), e.g feature/xxx, bugfix/xxx, etc. Short list of types:

  1. feature
  2. bugfix
  3. refactor
  4. documentation
  5. testing - add unit/integration/... tests
    I can add it to CONTRIBUTING.md (non-existing yet)

When to close a passed file descriptor?

I want my server to pass one end of a socket pair to a client as a return value from a method. I need to close the client side after it is sent. I had a look at sdbus::UnixFd and it does not seem to take ownership. How can I know when it is safe to close the file descriptor so only the client has it?

How to get object path?

Good morning,

My project is based on the auto-generated files using sdbus-c++-xml2cpp. I have the following use case when trying to bring a modem into operation, using the oFono-API:

the "Manager" class reads all available modems with the method GetModems() from org.ofono.Manager. This method returns among other properties, the objectPath to the modem, e.g. /phonesim. For each Modem a instance of the "Modem" class will be instantiated.

Each Modem instance should know its objectPath, because there are the later needed interfaces, like org.ofono.SimManager. So my idea was to call the constructor of "Modem" (inside the Manager class) like this:

this->modems.push_back(new Modem(destination, objectPath, pin, apn));

Whereas objectPath could be the before mentioned /phonesim.

Inside the constructor of "Modem" I have no chance to store the objectPath because of the inherited ProxyInterfaces(std::move(destination), std::move(objectPath)).

So as a workaround I changed the constructor of "Modem" to get an additional parameter "modemObjectPath", which is in fact the same as objectPath.

I am looking forward for some ideas or maybe concepts from the community I missed in this particular case.

Kind Regards

Memory leak when using sdbus::Variant()

Using Valgrind I detected a memory leak when using a Variant variable:

==7100== 7,380 (128 direct, 7,252 indirect) bytes in 2 blocks are definitely lost in loss record 85 of 89
==7100== at 0x4C2FA3F: malloc (in /usr/lib/valgrind/vgpreload_memcheck-amd64-linux.so)
==7100== by 0x4C31D84: realloc (in /usr/lib/valgrind/vgpreload_memcheck-amd64-linux.so)
==7100== by 0x5C3428B: ??? (in /lib/x86_64-linux-gnu/libsystemd.so.0.21.0)
==7100== by 0x5C3CC07: sd_bus_new (in /lib/x86_64-linux-gnu/libsystemd.so.0.21.0)
==7100== by 0x5C2F3AB: sd_bus_open_system (in /lib/x86_64-linux-gnu/libsystemd.so.0.21.0)
==7100== by 0x5C2A010: ??? (in /lib/x86_64-linux-gnu/libsystemd.so.0.21.0)
==7100== by 0x505108A: sdbus::createPlainMessage() (Message.cpp:641)
==7100== by 0x50590B8: sdbus::Variant::Variant() (Types.cpp:35)
==7100== by 0x75B5BA5: sdbus::Variant::Variant<std::__cxx11::basic_string<char, std::char_traits, std::allocator > >(std::__cxx11::basic_string<char, std::char_traits, std::allocator > const&)

Error when implementing DBus ObjectManager

I am attempting to implement the org.freedesktop.DBus.ObjectManager interface, as defined here.

Through introspection of other DBus services, I was able to produce an XML interface definition for the ObjectManager interface. The ObjectManager requires a method GetManagedObjects with the argument signature a{oa{sa{sv}}}, and emits two signals for InterfacesAdded and InterfacesRemoved.

The XML I generated looks like this:

<node>
	<interface name="org.freedesktop.DBus.ObjectManager">
		<method name="GetManagedObjects">
			<arg type="a{oa{sa{sv}}}" name="object_paths_interfaces_and_properties" direction="out"/>
		</method>
		<signal name="InterfacesAdded">
			<arg type="o" name="object_path"/>
			<arg type="a{sa{sv}}" name="interfaces_and_properties"/>
		</signal>
		<signal name="InterfacesRemoved">
			<arg type="o" name="object_path"/>
			<arg type="as" name="interfaces"/>
		</signal>
	</interface>
</node>

The problem I am having is that when I go to create this service and register with DBus, I am getting the following error:

terminate called after throwing an instance of 'sdbus::Error'
  what():  [org.freedesktop.DBus.Error.InvalidArgs] Failed to register object vtable (Invalid argument)

So, it seems that for some reason my implementation is not valid according to the DBus ObjectManager interface. I have not been able to figure out why. If I change my code to use an interface name other than "org.freedesktop.DBus.ObjectManager", it works fine, so it seems that there is some kind of validation going on when I try to register something as an ObjectManager. I have not been able to figure out where my DBus service differs from the spec.

I have copied below the code from 3 files: the source code of the simple application I am trying to run, the class I created for the ObjectManager adapter, and the auto-generated adapter glue code that was generated using the sdbus-c++-xml2cpp` tool.

I have also tried manually registering the interface, using gattService->registerMethod(interfaceName, "GetManagedObjects", "", "a{oa{sa{sv}}}", &GetManagedObjects) rather than the stubs generated from XML, but I still got the same error.

Any help is greatly appreciated!

Source code of simple-gatt-service.cpp

#include "interfaces/objectmanager_adapter.h"
#include <vector>
#include <string>
#include <iostream>
#include <unistd.h>


int main(int argc, char *argv[])
{
    // Create D-Bus connection to the system bus and requests name on it.
    const char* serviceName = "org.gattservice";
    auto connection = sdbus::createSystemBusConnection(serviceName);

    // Create D-Bus object.
    const char* objectPath = "/org/gattservice";
    
    auto gattService = sdbus::createObject(*connection, objectPath);
    ObjectManagerAdapter objectManager(*connection, objectPath);

    connection->enterProcessingLoop();
}

Source code of objectmanager_adapter.h

#include "objectmanager_adapter_glue.h"

using ObjectManagerAdapterInterface = sdbus::AdaptorInterfaces<org::freedesktop::DBus::ObjectManager_adaptor>;

class ObjectManagerAdapter : public ObjectManagerAdapterInterface
{
public:
    ObjectManagerAdapter(sdbus::IConnection& connection, std::string objectPath)
        : ObjectManagerAdapterInterface(connection, objectPath)
    {
        registerAdaptor();
    }

    ~ObjectManagerAdapter()
    {
        unregisterAdaptor();
    }
private:
    std::map<sdbus::ObjectPath, std::map<std::string, std::map<std::string, sdbus::Variant>>> GetManagedObjects() override
    {
        std::map<sdbus::ObjectPath, std::map<std::string, std::map<std::string, sdbus::Variant>>> mapOfObjects;

        return {mapOfObjects};
    }
};

Source code of objectmanager_adapter_glue.h (auto-generated from xml)

/*
 * This file was automatically generated by sdbus-c++-xml2cpp; DO NOT EDIT!
 */

#ifndef __sdbuscpp__objectmanager_adapter_glue_h__adaptor__H__
#define __sdbuscpp__objectmanager_adapter_glue_h__adaptor__H__

#include <sdbus-c++/sdbus-c++.h>
#include <string>
#include <tuple>

namespace org {
namespace freedesktop {
namespace DBus {

class ObjectManager_adaptor
{
public:
    static constexpr const char* interfaceName = "org.freedesktop.DBus.ObjectManager";

protected:
    ObjectManager_adaptor(sdbus::IObject& object)
        : object_(object)
    {
        object_.registerMethod("GetManagedObjects").onInterface(interfaceName).implementedAs([this](){ return this->GetManagedObjects(); });
        object_.registerSignal("InterfacesAdded").onInterface(interfaceName).withParameters<sdbus::ObjectPath, std::map<std::string, std::map<std::string, sdbus::Variant>>>();
        object_.registerSignal("InterfacesRemoved").onInterface(interfaceName).withParameters<sdbus::ObjectPath, std::vector<std::string>>();
    }

public:
    void InterfacesAdded(const sdbus::ObjectPath& object_path, const std::map<std::string, std::map<std::string, sdbus::Variant>>& interfaces_and_properties)
    {
        object_.emitSignal("InterfacesAdded").onInterface(interfaceName).withArguments(object_path, interfaces_and_properties);
    }

    void InterfacesRemoved(const sdbus::ObjectPath& object_path, const std::vector<std::string>& interfaces)
    {
        object_.emitSignal("InterfacesRemoved").onInterface(interfaceName).withArguments(object_path, interfaces);
    }

private:
    virtual std::map<sdbus::ObjectPath, std::map<std::string, std::map<std::string, sdbus::Variant>>> GetManagedObjects() = 0;

private:
    sdbus::IObject& object_;
};

}}} // namespaces

#endif

struct too long....

I got the IDL XML,looks like this:

<?xml version="1.0" encoding="UTF-8"?>
<node name="/tg/gnss">
    <interface name="tg.gnss">
        <signal name="GnssBroadcastData">
            <arg name="data" type="(yddddddddddx)"/>
        </signal>
    </interface>
</node>

and then sdbus-c++ stub generators code :


/*
 * This file was automatically generated by sdbus-c++-xml2cpp; DO NOT EDIT!
 */

#ifndef __sdbuscpp__gnssAdaptor_h__adaptor__H__
#define __sdbuscpp__gnssAdaptor_h__adaptor__H__

#include <sdbus-c++/sdbus-c++.h>
#include <string>
#include <tuple>

namespace tg {

class gnss_adaptor
{
public:
    static constexpr const char* INTERFACE_NAME = "tg.gnss";

protected:
    gnss_adaptor(sdbus::IObject& object)
        : object_(object)
    {
        object_.registerSignal("GnssBroadcastData").onInterface(INTERFACE_NAME).withParameters<sdbus::Struct<uint8_t, double, double, double, double, double, double, double, double, double, double, int64_t>>();
    }

public:
    void emitGnssBroadcastData(const sdbus::Struct<uint8_t, double, double, double, double, double, double, double, double, double, double, int64_t>& data)
    {
        object_.emitSignal("GnssBroadcastData").onInterface(INTERFACE_NAME).withArguments(data);
    }

private:
    sdbus::IObject& object_;
};

} // namespaces

#endif

the sdbus::Struct<uint8_t, double, double, double, double, double, double, double, double, double, double, int64_t> is too long.....

typedef sdbus::Struct<uint8_t, double, double, double, double, double, double, double, double, double, double, int64_t>  GnssBroadcastStruct;

define it with typedef, wouldn't it look better?

Make signal emission thread-safe

This could also be solved at a different level by an event-based mechanism -- the library would have to publish its event data in that case, and users could add their own fds to polling.

Minor bugs in tutorial (doc/using-sdbus-c++.md)

In convenience layer client implementation there is a bug in line 23: keyword this should be removed.

concatenatorProxy->uponSignal("concatenated").onInterface(interfaceName).call([->this<-](const std::string& str){ onConcatenated(str); });

Later, in client implementation using sdbusc++ stub generator, the sleep(1) method is undefined so #include <unistd.h> should be added.

Error when communicating with UDisk2 Raid

I am using sdbus-c++ to interface with UDisk2 and encountered an interesting problem. I don't know if you can really do anything about it, but I thought it was best to mention it anyways.

If you use a method call to stop a raid:
mRaidProxy>callMethodAsync("Stop").onInterface("org.freedesktop.UDisks2.MDRaid").withArguments(std::map<std::string, sdbus::Variant>());
This causes the following error:
'sdbus::Error' what(): [org.freedesktop.DBus.Error.UnknownMethod] No such interface “org.freedesktop.UDisks2.MDRaid” on object at path /org/freedesktop/UDisks2/mdraid/082bd1b0_830621df_84f8c775_5b2a1938
The command actually goes through and works fine. The best I can tell it is because that action will close the remote object /org/freedesktop/UDisks2/mdraid/082bd1b0_830621df_84f8c775_5b2a1938 which is what the proxy is connected to.

Doing it as an async returns fine without any issue.

Proxy with signal reception connected to session bus

I have a problem with receiving signals in proxy connected to session bus.
I use sdbus::createSessionBusConnection() and pass this object to interface class constructor.
Everything works properly when proxy class consists only methods and properties.
Problems are with classes with signals - client doesn't receive signals (methods and properties works properly)
I tried to add enterProcessingLoopAsync() after proxy class init. In this case signals receiving works properly. But access to methods and properties doesn't work. I got errors: org.freedesktop.DBus.Error.InconsistentMessage
or
org.freedesktop.DBus.Error.Timeout

How to use proxy with signals connected to session bus.

Publishing on conan

Hi,

First of all, thanks for this nifty lib. Very easy to use.

I'm currently using it for a pet project of mine. I use conan for resolving dependencies.

I found a conanfile for sdbus-cpp here. It's a bit outdated, so I fixed it (here). I then publish this on a repository I created on bintray.

I was wondering if you would be interested in integrating this in the project.

I feel like other people could benefit from this, and I think it would be best if someone actively involved in the project had ownership of the artifact and repository.

That being said, if you don't wish to do this, I'm okay with keeping my conanfile and maintaining my own artifact on bintray for my project.

If you were to set up some CI as mentioned #44, you could probably automate the publication of tagged versions, too.

SIGSEGV for containsValueOfType<std::string>()

I'm receiving a message from dbus, that contains a std::map <std::string, sdbus::Variant>.
Variant can be either boolean or std::string.

When iterating the contents, .containsValueOfType<bool>() works,
while .containsValueOfType<std::string>() leads to SIGSEGV,
though reading the string using
get<std::string>();
works fine.

std::map ‹std::string, sdbus::Variant›  result;

managerProxy->callMethod("GetProperties").onInterface(interfaceName).withArguments().storeResultsTo(result);

    for (auto const& x : result) {
        if (x.second.containsValueOfType‹bool›()) {
            boolVal = x.second.get‹bool›();
            std::cout << "boolVal: " << boolVal << "\n";
        } else /* if (x.second.containsValueOfType‹std::string›()) */ { // would SIGSEGV
            stringVal = x.second.get‹std::string›(); // works fine
            std::cout << "stringVal: " << stringVal << "\n";
        }
(gdb) backtrace
#0  strlen () at ../sysdeps/arm/armv6t2/strlen.S:85
#1  0x54ab2b46 in std::char_traits‹char›::length (__s=0x0) at /usr/include/c++/7/bits/char_traits.h:320
#2  std::__cxx11::basic_string‹char, std::char_traits‹char›, std::allocator‹char› ›::assign (__s=0x0, this=0x7efff2c4)
    at /usr/include/c++/7/bits/basic_string.h:1419
#3  std::__cxx11::basic_string‹char, std::char_traits‹char›, std::allocator‹char› ›::operator= (__s=0x0, this=0x7efff2c4)
    at /usr/include/c++/7/bits/basic_string.h:694
#4  sdbus::Message::peekType (this=‹optimized out›, type="", contents="") at Message.cpp:639
#5  0x54ab44ea in sdbus::Variant::peekValueType[abi:cxx11]() const (this=‹optimized out›) at Types.cpp:56
#6  0x54aaeba6 in sdbus::Variant::containsValueOfType‹std::__cxx11::basic_string‹char, std::char_traits‹char›, std::allocator‹char› › › (
    this=0x54ad2510) at ./include/sdbus-c++/Types.h:81
#7  0x54aadaac in main () at get_properties.cpp:30

Interacting with systemd services programmatically in c++

I'm looking for a way from my c++ project to be able to do from code things that a user can do with systemctl
For example: systemctl restart some.service
Before I invest time in learning about sdbus-cpp, I just want to know if that something that can be done with this library.

TIA,
-Jon

Proxy::sdbus_signal_handler() is returning wrong value.

Proxy::sdbus_signal_handler() returns 1 (indicating that no more handlers should be invoked), but I believe it should return 0 instead (causing all other handlers to be invoked).

As the code is currently, listening to a signal works for a single proxy, but when there are multiple proxies listening to the same signal, only one of them will actually be triggered.

diff --git a/src/Proxy.cpp b/src/Proxy.cpp
index 4873544..f833e01 100644
--- a/src/Proxy.cpp
+++ b/src/Proxy.cpp
@@ -264,7 +264,7 @@ int Proxy::sdbus_signal_handler(sd_bus_message *sdbusMessage, void *userData, sd

callback(message);

-    return 1;
+    return 0;
}

}

BUILD_LIBSYSTEMD not effect

Hi, i got some trouble at v0.6.0

This is my config :
cmake .. -DCMAKE_BUILD_TYPE=Release -DBUILD_CODE_GEN=ON -DBUILD_LIBSYSTEMD=ON -DBUILD_DOC=OFF

But:
CMake checking libsystemd.
-- Checking for module 'libsystemd>=236'
-- Requested 'libsystemd >= 236' but version of systemd is 229
You may find new versions of systemd at http://www.freedesktop.org/wiki/Software/systemd
CMake Error at /usr/share/cmake-3.14/Modules/FindPkgConfig.cmake:457 (message):
A required package was not found
Call Stack (most recent call first):
/usr/share/cmake-3.14/Modules/FindPkgConfig.cmake:642 (_pkg_check_modules_internal)
CMakeLists.txt:16 (pkg_check_modules)
-- Configuring incomplete, errors occurred!
See also "/home/conn/build_imx6/sdbus-cpp/build/CMakeFiles/CMakeOutput.log".

using enterProcessingLoopAsync() does not create the DBus Object when defining a DBus Service

Using the enterProcessingLoopAsyc() function does not create the DBus Object for a defined Service, whereas enterProcessingLoop() does create the Object as expected.
My code looks like this:

void registerDBusService() {
    serviceConnection = sdbus::createSystemBusConnection(serviceServiceName.c_str());
    auto _serviceObject = sdbus::createObject(*serviceConnection, serviceObjectPath.c_str());
    service = _serviceObject.get();
    service->registerMethod("Connect").onInterface(serviceInterface).implementedAs(serviceConnect);
    service->registerMethod("Disconnect").onInterface(serviceInterface).implementedAs(serviceDisconnect);
    service->registerMethod("Restart").onInterface(serviceInterface).implementedAs(serviceRestart);
    service->registerMethod("Status").onInterface(serviceInterface).implementedAs(serviceStatus);
    service->finishRegistration();
    serviceConnection->enterProcessingLoopAsync(); //fails to create the DBus Object
}

Issue compiling on Ubuntu 19.10 (gcc 8.3)

Hi,

I am trying to get the basic working through the client example of https://github.com/Kistler-Group/sdbus-cpp/blob/master/docs/using-sdbus-c%2B%2B.md#implementing-the-concatenator-example-using-basic-sdbus-c-api-layer using the v0.8.1 release.

The library appears successfully compiled according to:
cmake -S. -B./build -GNinja -DCMAKE_EXPORT_COMPILE_COMMANDS=ON && cmake --build build && cd build && sudo ninja install

The client example is built using the CMakeLists.txt:
cat CMakeLists.txt
cmake_minimum_required (VERSION 3.13)

project (sdbus-test)

find_package (sdbus-c++ REQUIRED)

add_executable (sdbus-test src/main.cpp)
target_link_libraries(sdbus-test PRIVATE SDBusCpp::sdbus-c++)

which fails according to
cmake -S. -B./build -GNinja -DCMAKE_EXPORT_COMPILE_COMMANDS=ON && cmake --build build/
-- The C compiler identification is GNU 8.3.0
-- The CXX compiler identification is GNU 8.3.0
-- Check for working C compiler: /usr/bin/cc
-- Check for working C compiler: /usr/bin/cc -- works
-- Detecting C compiler ABI info
-- Detecting C compiler ABI info - done
-- Detecting C compile features
-- Detecting C compile features - done
-- Check for working CXX compiler: /usr/bin/c++
-- Check for working CXX compiler: /usr/bin/c++ -- works
-- Detecting CXX compiler ABI info
-- Detecting CXX compiler ABI info - done
-- Detecting CXX compile features
-- Detecting CXX compile features - done
-- Configuring done
-- Generating done
-- Build files have been written to: /home/martin/work/sdbus-cpp-test/build
[1/2] Building CXX object CMakeFiles/sdbus-test.dir/src/main.cpp.o
FAILED: CMakeFiles/sdbus-test.dir/src/main.cpp.o
/usr/bin/c++ -isystem /usr/local/include -MD -MT CMakeFiles/sdbus-test.dir/src/main.cpp.o -MF CMakeFiles/sdbus-test.dir/src/main.cpp.o.d -o CMakeFiles/sdbus-test.dir/src/main.cpp.o -c ../src/main.cpp
In file included from /usr/local/include/sdbus-c++/Message.h:30,
from /usr/local/include/sdbus-c++/ConvenienceApiClasses.h:30,
from /usr/local/include/sdbus-c++/IObject.h:30,
from /usr/local/include/sdbus-c++/sdbus-c++.h:28,
from ../src/main.cpp:1:
/usr/local/include/sdbus-c++/TypeTraits.h: In function ‘constexpr decltype(auto) sdbus::detail::apply_impl(_Function&&, _Tuple&&, std::index_sequence<_I ...>)’:
/usr/local/include/sdbus-c++/TypeTraits.h:541:33: error: ‘is_void_v’ is not a member of ‘std’
if constexpr (!std::is_void_v<function_result_t<_Function>>)
^~~~~~~~~
/usr/local/include/sdbus-c++/TypeTraits.h:541:33: note: suggested alternative: ‘is_void’
if constexpr (!std::is_void_v<function_result_t<_Function>>)
^~~~~~~~~
is_void
/usr/local/include/sdbus-c++/TypeTraits.h:541:70: error: expected primary-expression before ‘>’ token
if constexpr (!std::is_void_v<function_result_t<_Function>>)
^~
/usr/local/include/sdbus-c++/TypeTraits.h:541:72: error: expected primary-expression before ‘)’ token
if constexpr (!std::is_void_v<function_result_t<_Function>>)
^
In file included from /usr/local/include/sdbus-c++/IObject.h:489,
from /usr/local/include/sdbus-c++/sdbus-c++.h:28,
from ../src/main.cpp:1:
/usr/local/include/sdbus-c++/ConvenienceApiClasses.inl: In member function ‘sdbus::MethodRegistrator& sdbus::MethodRegistrator::withInputParamNames(_String ...)’:
/usr/local/include/sdbus-c++/ConvenienceApiClasses.inl:135:28: error: ‘conjunction_v’ is not a member of ‘std’
static_assert(std::conjunction_v<std::is_convertible<_String, std::string>...>, "Parameter names must be (convertible to) strings");
^~~~~~~~~~~~~
/usr/local/include/sdbus-c++/ConvenienceApiClasses.inl:135:28: note: suggested alternative: ‘function’
static_assert(std::conjunction_v<std::is_convertible<_String, std::string>...>, "Parameter names must be (convertible to) strings");
^~~~~~~~~~~~~
function
/usr/local/include/sdbus-c++/ConvenienceApiClasses.inl:135:83: error: expected primary-expression before ‘...’ token
static_assert(std::conjunction_v<std::is_convertible<_String, std::string>...>, "Parameter names must be (convertible to) strings");
^~~
/usr/local/include/sdbus-c++/ConvenienceApiClasses.inl:135:83: error: expected ‘,’ before ‘...’ token
static_assert(std::conjunction_v<std::is_convertible<_String, std::string>...>, "Parameter names must be (convertible to) strings");
^~~
,
/usr/local/include/sdbus-c++/ConvenienceApiClasses.inl:135:83: error: expected string-literal before ‘...’ token
static_assert(std::conjunction_v<std::is_convertible<_String, std::string>...>, "Parameter names must be (convertible to) strings");
^~~
/usr/local/include/sdbus-c++/ConvenienceApiClasses.inl:135:83: error: expected ‘)’ before ‘...’ token
static_assert(std::conjunction_v<std::is_convertible<_String, std::string>...>, "Parameter names must be (convertible to) strings");
~ ^~~
)
In file included from /usr/local/include/sdbus-c++/IObject.h:489,
from /usr/local/include/sdbus-c++/sdbus-c++.h:28,
from ../src/main.cpp:1:
/usr/local/include/sdbus-c++/ConvenienceApiClasses.inl: In member function ‘sdbus::MethodRegistrator& sdbus::MethodRegistrator::withOutputParamNames(_String ...)’:
/usr/local/include/sdbus-c++/ConvenienceApiClasses.inl:150:28: error: ‘conjunction_v’ is not a member of ‘std’
static_assert(std::conjunction_v<std::is_convertible<_String, std::string>...>, "Parameter names must be (convertible to) strings");
^~~~~~~~~~~~~
/usr/local/include/sdbus-c++/ConvenienceApiClasses.inl:150:28: note: suggested alternative: ‘function’
static_assert(std::conjunction_v<std::is_convertible<_String, std::string>...>, "Parameter names must be (convertible to) strings");
^~~~~~~~~~~~~
function
/usr/local/include/sdbus-c++/ConvenienceApiClasses.inl:150:83: error: expected primary-expression before ‘...’ token
static_assert(std::conjunction_v<std::is_convertible<_String, std::string>...>, "Parameter names must be (convertible to) strings");
^~~
/usr/local/include/sdbus-c++/ConvenienceApiClasses.inl:150:83: error: expected ‘,’ before ‘...’ token
static_assert(std::conjunction_v<std::is_convertible<_String, std::string>...>, "Parameter names must be (convertible to) strings");
^~~
,
/usr/local/include/sdbus-c++/ConvenienceApiClasses.inl:150:83: error: expected string-literal before ‘...’ token
static_assert(std::conjunction_v<std::is_convertible<_String, std::string>...>, "Parameter names must be (convertible to) strings");
^~~
/usr/local/include/sdbus-c++/ConvenienceApiClasses.inl:150:83: error: expected ‘)’ before ‘...’ token
static_assert(std::conjunction_v<std::is_convertible<_String, std::string>...>, "Parameter names must be (convertible to) strings");
~ ^~~
)
/usr/local/include/sdbus-c++/ConvenienceApiClasses.inl: In member function ‘sdbus::SignalRegistrator& sdbus::SignalRegistrator::withParameters(_String ...)’:
/usr/local/include/sdbus-c++/ConvenienceApiClasses.inl:237:28: error: ‘conjunction_v’ is not a member of ‘std’
static_assert(std::conjunction_v<std::is_convertible<_String, std::string>...>, "Parameter names must be (convertible to) strings");
^~~~~~~~~~~~~
/usr/local/include/sdbus-c++/ConvenienceApiClasses.inl:237:28: note: suggested alternative: ‘function’
static_assert(std::conjunction_v<std::is_convertible<_String, std::string>...>, "Parameter names must be (convertible to) strings");
^~~~~~~~~~~~~
function
/usr/local/include/sdbus-c++/ConvenienceApiClasses.inl:237:83: error: expected primary-expression before ‘...’ token
static_assert(std::conjunction_v<std::is_convertible<_String, std::string>...>, "Parameter names must be (convertible to) strings");
^~~
/usr/local/include/sdbus-c++/ConvenienceApiClasses.inl:237:83: error: expected ‘,’ before ‘...’ token
static_assert(std::conjunction_v<std::is_convertible<_String, std::string>...>, "Parameter names must be (convertible to) strings");
^~~
,
/usr/local/include/sdbus-c++/ConvenienceApiClasses.inl:237:83: error: expected string-literal before ‘...’ token
static_assert(std::conjunction_v<std::is_convertible<_String, std::string>...>, "Parameter names must be (convertible to) strings");
^~~
/usr/local/include/sdbus-c++/ConvenienceApiClasses.inl:237:83: error: expected ‘)’ before ‘...’ token
static_assert(std::conjunction_v<std::is_convertible<_String, std::string>...>, "Parameter names must be (convertible to) strings");
~ ^~~
)
In file included from /usr/local/include/sdbus-c++/Message.h:30,
from /usr/local/include/sdbus-c++/ConvenienceApiClasses.h:30,
from /usr/local/include/sdbus-c++/IObject.h:30,
from /usr/local/include/sdbus-c++/sdbus-c++.h:28,
from ../src/main.cpp:1:
/usr/local/include/sdbus-c++/TypeTraits.h: In instantiation of ‘constexpr decltype(auto) sdbus::detail::apply_impl(_Function&&, _Tuple&&, std::index_sequence<_I ...>) [with _Function = const sdbus::Properties_proxy::Properties_proxy(sdbus::IProxy&)::<lambda(const string&, const std::map<std::__cxx11::basic_string, sdbus::Variant>&, const std::vector<std::__cxx11::basic_string >&)>&; _Tuple = std::tuple<std::__cxx11::basic_string<char, std::char_traits, std::allocator >, std::map<std::__cxx11::basic_string<char, std::char_traits, std::allocator >, sdbus::Variant, std::less<std::_cxx11::basic
string<char, std::char_traits, std::allocator > >, std::allocator<std::pair<const std::__cxx11::basic_string<char, std::char_traits, std::allocator >, sdbus::Variant> > >, std::vector<std::__cxx11::basic_string<char, std::char_traits, std::allocator >, std::allocator<std::__cxx11::basic_string<char, std::char_traits, std::allocator > > > >&; long unsigned int ..._I = {0, 1, 2}; std::index_sequence<_I ...> = std::integer_sequence<long unsigned int, 0, 1, 2>]’:
/usr/local/include/sdbus-c++/TypeTraits.h:553:34: required from ‘constexpr decltype(auto) sdbus::apply(_Function&&, _Tuple&&) [with _Function = const sdbus::Properties_proxy::Properties_proxy(sdbus::IProxy&)::<lambda(const string&, const std::map<std::__cxx11::basic_string, sdbus::Variant>&, const std::vector<std::__cxx11::basic_string >&)>&; _Tuple = std::tuple<std::__cxx11::basic_string<char, std::char_traits, std::allocator >, std::map<std::__cxx11::basic_string<char, std::char_traits, std::allocator >, sdbus::Variant, std::less<std::__cxx11::basic_string<char, std::char_traits, st
d::allocator > >, std::allocator<std::pair<const std::__cxx11::basic_string<char, std::char_traits, std::allocator >, sdbus::Variant> > >, std::vector<std::__cxx11::basic_string<char, std::char_traits, std::allocator >, std::allocator<std::__cxx11::basic_string<char, std::char_traits, std::allocator > > > >&]’
/usr/local/include/sdbus-c++/ConvenienceApiClasses.inl:634:25: required from ‘void sdbus::SignalSubscriber::call(_Function&&) [with _Function = sdbus::Properties_proxy::Properties_proxy(sdbus::IProxy&)::<lambda(const string&, const std::map<std::__cxx11::basic_string, sdbus::Variant>&, const std::vector<std::__cxx11::basic_string >&)>]’
/usr/local/include/sdbus-c++/StandardInterfaces.h:111:30: required from here
/usr/local/include/sdbus-c++/TypeTraits.h:544:107: error: inconsistent deduction for auto return type: ‘void’ and then ‘std::tuple<>’
return std::forward<_Function>(f)(std::get<_I>(std::forward<_Tuple>(t))...), std::tuple<>{};
^
/usr/local/include/sdbus-c++/TypeTraits.h:544:107: error: return-statement with a value, in function returning ‘void’ [-fpermissive]
/usr/local/include/sdbus-c++/TypeTraits.h: In instantiation of ‘constexpr decltype(auto) sdbus::detail::apply_impl(_Function&&, _Tuple&&, std::index_sequence<_I ...>) [with _Function = const sdbus::ObjectManager_proxy::ObjectManager_proxy(sdbus::IProxy&)::<lambda(const sdbus::ObjectPath&, const std::map<std::__cxx11::basic_string, std::map<std::__cxx11::basic_string, sdbus::Variant> >&)>&; _Tuple = std::tuple<sdbus::ObjectPath, std::map<std::__cxx11::basic_string<char, std::char_traits, std::allocator >, std::map<std::__cxx11::basic_string<char, std::char_traits, std::allocator >, sdbus::Vari
ant, std::less<std::__cxx11::basic_string<char, std::char_traits, std::allocator > >, std::allocator<std::pair<const std::__cxx11::basic_string<char, std::char_traits, std::allocator >, sdbus::Variant> > >, std::less<std::__cxx11::basic_string<char, std::char_traits, std::allocator > >, std::allocator<std::pair<const std::__cxx11::basic_string<char, std::char_traits, std::allocator >, std::map<std::__cxx11::basic_string<char, std::char_traits, std::allocator >, sdbus::Variant, std::less<std::__cxx11::basic_string<char, std::char_traits, std::allocator > >,
std::allocator<std::pair<const std::__cxx11::basic_string<char, std::char_traits, std::allocator >, sdbus::Variant> > > > > > >&; long unsigned int ..._I = {0, 1}; std::index_sequence<_I ...> = std::integer_sequence<long unsigned int, 0, 1>]’:
/usr/local/include/sdbus-c++/TypeTraits.h:553:34: required from ‘constexpr decltype(auto) sdbus::apply(_Function&&, _Tuple&&) [with _Function = const sdbus::ObjectManager_proxy::ObjectManager_proxy(sdbus::IProxy&)::<lambda(const sdbus::ObjectPath&, const std::map<std::__cxx11::basic_string, std::map<std::__cxx11::basic_string, sdbus::Variant> >&)>&; _Tuple = std::tuple<sdbus::ObjectPath, std::map<std::__cxx11::basic_string<char, std::char_traits, std::allocator >, std::map<std::__cxx11::basic_string<char, std::char_traits, std::allocator >, sdbus::Variant, std::less<std::__cxx11::basic_stri
ng<char, std::char_traits, std::allocator > >, std::allocator<std::pair<const std::__cxx11::basic_string<char, std::char_traits, std::allocator >, sdbus::Variant> > >, std::less<std::__cxx11::basic_string<char, std::char_traits, std::allocator > >, std::allocator<std::pair<const std::__cxx11::basic_string<char, std::char_traits, std::allocator >, std::map<std::__cxx11::basic_string<char, std::char_traits, std::allocator >, sdbus::Variant, std::less<std::__cxx11::basic_string<char, std::char_traits, std::allocator > >, std::allocator<std::pair<const std::__c
xx11::basic_string<char, std::char_traits, std::allocator >, sdbus::Variant> > > > > > >&]’
/usr/local/include/sdbus-c++/ConvenienceApiClasses.inl:634:25: required from ‘void sdbus::SignalSubscriber::call(_Function&&) [with _Function = sdbus::ObjectManager_proxy::ObjectManager_proxy(sdbus::IProxy&)::<lambda(const sdbus::ObjectPath&, const std::map<std::__cxx11::basic_string, std::map<std::__cxx11::basic_string, sdbus::Variant> >&)>]’
/usr/local/include/sdbus-c++/StandardInterfaces.h:158:30: required from here
/usr/local/include/sdbus-c++/TypeTraits.h:544:107: error: inconsistent deduction for auto return type: ‘void’ and then ‘std::tuple<>’
/usr/local/include/sdbus-c++/TypeTraits.h:544:107: error: return-statement with a value, in function returning ‘void’ [-fpermissive]
/usr/local/include/sdbus-c++/TypeTraits.h: In instantiation of ‘constexpr decltype(auto) sdbus::detail::apply_impl(_Function&&, _Tuple&&, std::index_sequence<_I ...>) [with _Function = const sdbus::ObjectManager_proxy::ObjectManager_proxy(sdbus::IProxy&)::<lambda(const sdbus::ObjectPath&, const std::vector<std::__cxx11::basic_string >&)>&; _Tuple = std::tuple<sdbus::ObjectPath, std::vector<std::__cxx11::basic_string<char, std::char_traits, std::allocator >, std::allocator<std::__cxx11::basic_string<char, std::char_traits, std::allocator > > > >&; long unsigned int ..._I = {0, 1}; std::index_sequenc
e<_I ...> = std::integer_sequence<long unsigned int, 0, 1>]’:
/usr/local/include/sdbus-c++/TypeTraits.h:553:34: required from ‘constexpr decltype(auto) sdbus::apply(_Function&&, _Tuple&&) [with _Function = const sdbus::ObjectManager_proxy::ObjectManager_proxy(sdbus::IProxy&)::<lambda(const sdbus::ObjectPath&, const std::vector<std::__cxx11::basic_string >&)>&; _Tuple = std::tuple<sdbus::ObjectPath, std::vector<std::__cxx11::basic_string<char, std::char_traits, std::allocator >, std::allocator<std::__cxx11::basic_string<char, std::char_traits, std::allocator > > > >&]’
/usr/local/include/sdbus-c++/ConvenienceApiClasses.inl:634:25: required from ‘void sdbus::SignalSubscriber::call(_Function&&) [with _Function = sdbus::ObjectManager_proxy::ObjectManager_proxy(sdbus::IProxy&)::<lambda(const sdbus::ObjectPath&, const std::vector<std::__cxx11::basic_string >&)>]’
/usr/local/include/sdbus-c++/StandardInterfaces.h:167:30: required from here
/usr/local/include/sdbus-c++/TypeTraits.h:544:107: error: inconsistent deduction for auto return type: ‘void’ and then ‘std::tuple<>’
/usr/local/include/sdbus-c++/TypeTraits.h:544:107: error: return-statement with a value, in function returning ‘void’ [-fpermissive]
In file included from /usr/include/c++/8/functional:59,
from /usr/local/include/sdbus-c++/TypeTraits.h:35,
from /usr/local/include/sdbus-c++/Message.h:30,
from /usr/local/include/sdbus-c++/ConvenienceApiClasses.h:30,
from /usr/local/include/sdbus-c++/IObject.h:30,
from /usr/local/include/sdbus-c++/sdbus-c++.h:28,
from ../src/main.cpp:1:
/usr/include/c++/8/bits/std_function.h: At global scope:
/usr/include/c++/8/bits/std_function.h:666:7: error: ‘std::function<_Res(_ArgTypes ...)>::function(_Functor) [with _Functor = sdbus::SignalSubscriber::call(_Function&&) [with _Function = sdbus::Properties_proxy::Properties_proxy(sdbus::IProxy&)::<lambda(const string&, const std::map<std::__cxx11::basic_string, sdbus::Variant>&, const std::vector<std::__cxx11::basic_string >&)>]::<lambda(sdbus::Signal&)>; = void; = void; _Res = void; _ArgTypes = {sdbus::Signal&}]’, declared using local type ‘sdbus::SignalSubscriber::call(_Function&&) [with _Function = sdbus::Propertie
s_proxy::Properties_proxy(sdbus::IProxy&)::<lambda(const string&, const std::map<std::__cxx11::basic_string, sdbus::Variant>&, const std::vector<std::__cxx11::basic_string >&)>]::<lambda(sdbus::Signal&)>’, is used but never defined [-fpermissive]
function<_Res(_ArgTypes...)>::
^~~~~~~~~~~~~~~~~~~~~~~~~~~~
/usr/include/c++/8/bits/std_function.h:666:7: error: ‘std::function<_Res(_ArgTypes ...)>::function(_Functor) [with _Functor = sdbus::SignalSubscriber::call(_Function&&) [with _Function = sdbus::ObjectManager_proxy::ObjectManager_proxy(sdbus::IProxy&)::<lambda(const sdbus::ObjectPath&, const std::map<std::__cxx11::basic_string, std::map<std::__cxx11::basic_string, sdbus::Variant> >&)>]::<lambda(sdbus::Signal&)>; = void; = void; _Res = void; _ArgTypes = {sdbus::Signal&}]’, declared using local type ‘sdbus::SignalSubscriber::call(_Function&&) [with _Function = sdbus::Ob
jectManager_proxy::ObjectManager_proxy(sdbus::IProxy&)::<lambda(const sdbus::ObjectPath&, const std::map<std::__cxx11::basic_string, std::map<std::__cxx11::basic_string, sdbus::Variant> >&)>]::<lambda(sdbus::Signal&)>’, is used but never defined [-fpermissive]
/usr/include/c++/8/bits/std_function.h:666:7: error: ‘std::function<_Res(_ArgTypes ...)>::function(_Functor) [with _Functor = sdbus::SignalSubscriber::call(_Function&&) [with _Function = sdbus::ObjectManager_proxy::ObjectManager_proxy(sdbus::IProxy&)::<lambda(const sdbus::ObjectPath&, const std::vector<std::__cxx11::basic_string >&)>]::<lambda(sdbus::Signal&)>; = void; = void; _Res = void; _ArgTypes = {sdbus::Signal&}]’, declared using local type ‘sdbus::SignalSubscriber::call(_Function&&) [with _Function = sdbus::ObjectManager_proxy::ObjectManager_proxy(sdbus::IProxy&)::<
lambda(const sdbus::ObjectPath&, const std::vector<std::__cxx11::basic_string >&)>]::<lambda(sdbus::Signal&)>’, is used but never defined [-fpermissive]
ninja: build stopped: subcommand failed.

What am I missing here?

Thanks,
Martin

Implementation lacks naming of method arguments

The dbus Introspector is able to show the names of the arguments of a method.
Example with connman:

> dbus-send --system --type=method_call --dest=net.connman --print-reply / org.freedesktop.DBus.Introspectable.Introspect
[..]
<method name="RequestPrivateNetwork">
 <arg name="path" type="o" direction="out"/>
 <arg name="settings" type="a{sv}" direction="out"/>
 <arg name="socket" type="h" direction="out"/> </method>
[..]

The relevant code for this seems to be in https://git.kernel.org/pub/scm/network/connman/connman.git/tree/src/manager.c#n576

sdbus-c++ seems to lack this naming!
See example below where it only show the arguments but not the name tag:

  <method name="getData">
   <arg type="u" direction="in"/>
   <arg type="b" direction="in"/>
  </method>
[..]

The xml code is as following:

      <method name="getData">
         <arg type="u" name="timestamp" direction="in" />
         <arg type="b" name="absoluteTimestamp" direction="in" />
      </method>

Receive array

Is it possible to handle a message that contains an array?

I'm trying to read song metadata from Clementine. On the bus, it looks like this:

method call time=1519588131.715176 sender=:1.261 -> destination=org.mpris.clementine serial=2 path=/Player; interface=org.freedesktop.MediaPlayer; member=GetMetadata
method return time=1519588131.715434 sender=:1.169 -> destination=:1.261 serial=602 reply_serial=2
   array [
      dict entry(
         string "album"
         variant             string "Rayn Project (Ptrance)"
      )
      ...

Add support for the UNIX_FD type

Currently there is no support for the UNIX_FD "h" type.

From the spec

UNIX_FD | 32-bit unsigned integer in the message's byte order. The actual file descriptors need to be transferred out-of-band via some platform specific mechanism. On the wire, values of this type store the index to the file descriptor in the array of file descriptors that accompany the message.

Honor annotations in DBus IDL XML

If applicable, sdbus-c++ stub generators should honor well known DBus XML annotations, so that via annotations, client developers can provide additional metadata to their DBus interfaces.

Method, interface, property, signal, and argument elements in DBus XML description may have "annotations", which are generic key/value pairs of metadata (more info at https://dbus.freedesktop.org/doc/dbus-specification.html#introspection-format). We shall evaluate whether the original dbus-c++ implementation of the stub generators supported these annotations, and if yes, which specific annotations were supported, and extend our sdbus-c++ stub generator implementation to honor, too.

This issue is related to sdbuscpp-xml2cpp code generator.

Server with Async methods hogs the CPU

When you create a server with async methods and run it and then call one of the async methods the processing loop will start hogging the CPU.
Can be seen in "top" and using gprof or callgrind (to pinpoint the locations).

Support for method call timeout

sdbus-c++ lacks support for user-provided timeouts when calling D-Bus methods. The API should be extended in order for users to be able to provide custom timeouts if needed.

Async timeout handling does not work as expected

It seems that call timeouts set for example via AsyncMethodInvoker::withTimeout() are not correctly handled by sdbus-cpp's event loop. This can be demonstrated by adjusting test SdbusTestObject.ThrowsTimeoutErrorWhenMethodTimesOut in such a way that it also asserts that the expected exception is thrown after roughly 500ms.

As far as I can see, there are two reasons for this:

  1. sd_bus_get_timeout() actually returns an absolute time point from which one has to subtract the current CLOCK_MONOTONIC time in order to get a relative time that can be passed to poll()
  2. At the time when the main thread starts an async call C with some small timeout T2, the event loop thread might already be blocked waiting in poll() with some timeout T1 > T2. If no other io-event occurs, this means that the timeout exception for C will be delayed until the call to poll() returns.

Build problem when option BUILD_LIBSYSTEMD is set ON

Hi,
My build process fails when the BUILD_LIBSYSTEMD option is set ON.
the message I get:
"ninja: error: 'third_party/sdbus-cpp/libsystemd-v242/src/LibsystemdBuildProject-build/libsystemd.a', needed by 'third_party/sdbus-cpp/libsdbus-c++.so.0.7.2', missing and no known rule to make it".
I have ninja, meson and other required programs installed.
After some research, also tried to use full path in the following line, but it didn't help -
"set_target_properties(Systemd::Libsystemd PROPERTIES IMPORTED_LOCATION ${SYSTEMD_LIBRARY_DIRS}/libsystemd.a)".

I've tried to build on another computer, results were the same. Any help would be truly appreciated.

org.freedesktop.DBus.Error.FileNotFound errors in non-systemd environment

Hi,

I am trying to use the sdbus-c++ 0.6.0 package on a non-systemd environment. That is, I have generated libsystemd.so.0.25.0 from systemd-241 as per instructions in https://github.com/Kistler-Group/sdbus-cpp/blob/master/docs/using-sdbus-c++.md#solving-libsystemd-dependency. These are built on an ARM cross compilation environment.

While running the sdbus-c++-unit-tests, there are 27 failures (out of 68 tests) with the below error message for all of these failures:

"[org.freedesktop.DBus.Error.FileNotFound] Failed to get default system bus (No such file or directory)" thrown in the test body.

And, the same kind of error when sdbus-c++-integration-tests is run as below:

terminate called after throwing an instance of 'sdbus::Error'
what(): [org.freedesktop.DBus.Error.FileNotFound] Failed to open bus (No such file or directory)
Aborted

Full log is in the attached text file.

sdbus_cpp_test_failures.txt

Has anybody got these tests working on a non-systemd environment.? Any idea if I am doing anything wrong w.r.t these tests.? Or is there any other prerequisite step that I may be missing before running these tests.? Any help, is much appreciated.

regards,
Raghunath

The library cannot find the headers for libsystemd

I have installed libsystemd-dev on Ubuntu 18.04. Running the command pkg-config --cflags --libs libsystemd returns -lsystemd. So I am sure I have libsystemd-dev installed correctly.

systemctl --version
systemd 237

Output of cmake:

-- The C compiler identification is GNU 7.4.0
-- The CXX compiler identification is GNU 7.4.0
-- Check for working C compiler: /usr/bin/cc
-- Check for working C compiler: /usr/bin/cc -- works
-- Detecting C compiler ABI info
-- Detecting C compiler ABI info - done
-- Detecting C compile features
-- Detecting C compile features - done
-- Check for working CXX compiler: /usr/bin/c++
-- Check for working CXX compiler: /usr/bin/c++ -- works
-- Detecting CXX compiler ABI info
-- Detecting CXX compiler ABI info - done
-- Detecting CXX compile features
-- Detecting CXX compile features - done
-- Found PkgConfig: /usr/bin/pkg-config (found version "0.29.1") 
-- Checking for modules 'GLOBAL;libsystemd>=236'
--   No package 'GLOBAL' found
CMake Error at CMakeLists.txt:21 (message):
  libsystemd of version at least 236 is required, but was not found (you may
  turn BUILD_LIBSYSTEMD on for sdbus-c++ to try downloading and building
  libsystemd in as part of sdbus-c++ during configuration)

Any idea what I am missing here? Thank you in advance.

Async server implementation

Suppose a server operation doesnt take an insignificant amount of time and multiple clients attempt to get service.
The last ones will be starved or even timeout since right now handling is done one by one serially.
Can you provide an async replying mechanism ?

dbus-c++ had a relatively recent patch for that.

Compiler warning on returning from non-void function without return statement

Integration tests compilation emits the following warnings: (gcc 8.2.0)

| test/integrationtests/proxy-glue.h: In member function 'uint32_t testing_proxy::doOperationClientSideAsync(uint32_t)':
| test/integrationtests/proxy-glue.h:152:5: warning: no return statement in function returning non-void [-Wreturn-type]
|      }
|      ^
| test/integrationtests/proxy-glue.h: In member function 'uint32_t testing_proxy::doErroneousOperationClientSideAsync()':
| test/integrationtests/proxy-glue.h:160:5: warning: no return statement in function returning non-void [-Wreturn-type]
|      }
|      ^

What is the right approach for designing async methods? Should doOperationClientSideAsync() and doErroneousOperationClientSideAsync() be void functions?

BR,
Vilo

std::terminate called by uncaught exceptions in Connection thread.

Hi Stano, I hope you are doing well.

There's a bug where Connection::enterProcessingLoop() calls methods which might throw. Exceptions are never caught by this thread which causes it to die -> call std::terminate on the process.

For instance, Connection::processPendingRequest() throws if iface_->sd_busProcess(...) returns an error.

In this case, terminate() is called since there is no try/catch in the thread function.

I could help fixing this but I currently don't know how this lib intends to gracefully handle this situation. Do you want to transport the exception to the caller thread?

Signal receiver event loop

Hello,

My question is: how to organize main client's loop properly without any sleep calls. Is there any method like poll for signal or wait for event? Wold be nice to clarify that moment in library's manual.

Thank you for the great library, great job!

Support for client tracking

Hi guys,

first I want to thank you all for this cool new DBus lib.

I just started an evaluation to to see if the lib fits our needs and after a minor issue with Unix FD support I came across another use case that is essential for us:
Client Tracking
From what I've seen this seems not to be supported by sdbus-cpp but seems to be in the underlying sdbus lib (via sd_bus_track_add_sender etc.).

Is there a way for doing such things in sdbus-cpp that I missed or if it's not is there a plan for adding such functionality?

Thank you in advance...

Race condition in Proxy::callMethod

There is a race condition in Proxy::callMethod(), in particular in Proxy::sendMethodCallMessageAndWaitForReply() that could lead to an invalid access of an already destroyed CallData object.

The race is as follows:

  1. Thread TM enters Proxy::sendMethodCallMessageAndWaitForReply(), creates a local CallData object, and blocks waiting in syncCallReplyData.waitForMethodReply()
  2. Thread TE enters Proxy::sdbus_async_reply_handler() reading the valid stack-allocated CallData object of TM.
  3. Thread TE invokes the callback associated with CallData, thereby signaling the condition on which TM waits
  4. Thread TE leaves Proxy::sdbus_async_reply_handler() and on destruction of the scope guard, accesses CallData again.
  5. Thread TM leaves Proxy::sendMethodCallMessageAndWaitForReply() thereby destroying the local CallData object.

DATA RACE occurs in step 4/5. That is, if step 5 finishes before step 4, then the SCOPE_EXIT block in Proxy::sdbus_async_reply_handler() invokes undefined behaviour.

POSSIBLE FIX
An easy fix would be to copy the slot-ptr to a local variable key on entry to Proxy::sdbus_async_reply_handler(). The SCOPE_EXIT could then check that copy and only access the CallData object if key is not null

diff --git a/src/Proxy.cpp b/src/Proxy.cpp
index f4222fa..e0d602a 100644
--- a/src/Proxy.cpp
+++ b/src/Proxy.cpp
@@ -200,12 +200,13 @@ int Proxy::sdbus_async_reply_handler(sd_bus_message *sdbusMessage, void *userDat
     assert(asyncCallData != nullptr);
     assert(asyncCallData->callback);
     auto& proxy = asyncCallData->proxy;
+    auto key = asyncCallData->slot.get();
 
     SCOPE_EXIT
     {
         // Slot may be null if we're doing blocking synchronous call implemented by means of asynchronous call,
         // because in that case the call data is still alive on the stack, we don't need to manage it separately.
-        if (asyncCallData->slot)
+        if (key)
             proxy.pendingAsyncCalls_.removeCall(asyncCallData->slot.get());
     };

0.3.3 release doesn't build out of the box by unittests build

master is also affected by this issue:

sdbus-cpp/test/unittests/Types_test.cpp: In member function ‘virtual void AVariant_CanBeConstructedFromAComplexValue_Test::TestBody()’:
sdbus-cpp/test/unittests/Types_test.cpp:69:35: error: unnecessary parentheses in declaration of ‘value’ [-Werror=parentheses]
     ASSERT_NO_THROW(sdbus::Variant(value));
                                   ^

Possible fix there: merhalak@93248b80a2ea1f418f88e545fe933532c690a515

High-Level (stub) Support for PropertiesChanged signal

Hey Stano, I hope you are doing well.

I recently had to observe D-Bus properties for changes and was able do do it with sdbus-cpp. Nevertheless I was wondering if there could be a more convenient way to do it. Maybe I just didn't see it.

The generated client stub code provides nice methods to get/set the property, depending on the chosen access attribute in the IDL. Nevertheless it doesn't provide callbacks or similar means to inform the client if a property changes it's value.

It was possible to implement the observer functionality via the basic API layer by registering for PropertiesChanged on the org.freedesktop.DBus.Properties interface. Nevertheless I needed to create a separate sdbus::IProxy instance as the generated stub or the sdbus::ProxyInterfaces do not give public access to it's sdbus::IProxy. I think the extra proxy is not that much a problem since we can provide the same sdbus::IConnection for both instances and therefore use the same event loop. Nevertheless I was wondering if:

  • There is already a more convenient way to observe a property?
  • If not, could the generated stub code provide a convenient way? How would it look like? Maybe someone at Kistler finds the time to implement it.
  • Is there a reason the sdbus::IProxy of the stub is not exposed so we can't register further signals on it manually?

Kind Regards
Urs

sdbus-c++-xml2cpp doesn't detect that input file doesn't exist

Hi Stano,

While setting up a new project I found that sdbus-c++-xml2cpp doesn't properly detect that input file doesn't exist. If I run this command (none of the files exist), then the output is confusing:

./sdbus-c++-xml2cpp --proxy=sample-client-glue.h /tmp/sample.xml
Parsing error: line 1, column 0: no element found

The problem is here: https://github.com/Kistler-Group/sdbus-cpp/blob/master/tools/xml2cpp-codegen/xml2cpp.cpp#L152

The condition should be if (input.fail()), as fail() covers both failbit and badbit iostate. Then the output is correct:

./sdbus-c++-xml2cpp --proxy=sample-client-glue.h /tmp/sample.xml
Unable to open file /tmp/sample.xml

BR,
Vilo

Class that inherits from multiple proxies

The tutorial shows inheritance from a single proxy class (with a comment on where to place more interfaces).
The problem here are:

  1. It's not clear to which bus it will connect.
  2. Isnt clear if it will share connection between parents (it will).

SdbusTestObject.AnswersMachineUuidViaPeerInterface throws

The SdbusTestObject.AnswersMachineUuidViaPeerInterface is expected not to throw, but on our "Beaglebone-like" board it does throw:

[ RUN ] SdbusTestObject.AnswersMachineUuidViaPeerInterface
terminate called after throwing an instance of 'sdbus::Error'
what(): [org.freedesktop.DBus.Error.FileNotFound] Failed to process bus requests (No such file or directory)

Note that there was #74 created for the terminate caused by the exception. This Issue is about the exception happening at all.

Is there a new pre-condition for the integration-tests? Some files missing?

Integration tests cleanup

Integration tests need cleanup -- the adaptor and proxy class should be generated from an IDL description, and individual related test groupings could be split into multiple cpp files (instead of one big AdaptorAndProxy_test.cpp). This will increase readability and tests will better serve as a sdbus-c++ usage example for new users.

autotools alternatives

Hey, I just wanted to drop a line and ask if there was any intention to move to a different build system.

systemd uses meson now along with many other projects. It would be nice if this project used a modern build system also. 👍

PS. Thanks for the great library.

Implicit connection to System bus

Thanks for open sourcing! This looks really nice and clean.

I ran into an issue with the tutorial, where createObjectProxy() without a connection argument implicitly connects to the System bus, while I needed the Session bus. This was a major stumbling block for me, as I'm new to dbus and didn't know there are multiple busses. Something mentioning the System and Session busses in the tutorial would be awesome :)

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. 📊📈🎉

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google ❤️ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.