diff --git a/CMakeLists.txt b/CMakeLists.txt index e704aa9..57e972d 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -65,7 +65,7 @@ set(SDBUSCPP_PUBLIC_HDRS ${SDBUSCPP_INCLUDE_DIR}/IConnection.h ${SDBUSCPP_INCLUDE_DIR}/AdaptorInterfaces.h ${SDBUSCPP_INCLUDE_DIR}/ProxyInterfaces.h - ${SDBUSCPP_INCLUDE_DIR}/Introspection.h + ${SDBUSCPP_INCLUDE_DIR}/StandardInterfaces.h ${SDBUSCPP_INCLUDE_DIR}/IObject.h ${SDBUSCPP_INCLUDE_DIR}/IProxy.h ${SDBUSCPP_INCLUDE_DIR}/Message.h diff --git a/cmake/LibsystemdExternalProject.cmake b/cmake/LibsystemdExternalProject.cmake index 33ec2af..d93ec06 100644 --- a/cmake/LibsystemdExternalProject.cmake +++ b/cmake/LibsystemdExternalProject.cmake @@ -41,6 +41,7 @@ ExternalProject_Add(LibsystemdBuildProject COMMAND ${MESON} --buildtype=${LIBSYSTEMD_BUILD_TYPE} -Dstatic-libsystemd=pic BUILD_COMMAND ${BUILD_VERSION_H} COMMAND ${NINJA} -C libsystemd.a + BUILD_ALWAYS 1 INSTALL_COMMAND "" LOG_DOWNLOAD 1 LOG_UPDATE 1 LOG_CONFIGURE 1 LOG_BUILD 1) diff --git a/docs/using-sdbus-c++.md b/docs/using-sdbus-c++.md index ae620ac..4119de4 100644 --- a/docs/using-sdbus-c++.md +++ b/docs/using-sdbus-c++.md @@ -551,20 +551,20 @@ namespace sdbuscpp { class Concatenator_adaptor { public: - static constexpr const char* interfaceName = "org.sdbuscpp.Concatenator"; + static constexpr const char* INTERFACE_NAME = "org.sdbuscpp.Concatenator"; protected: Concatenator_adaptor(sdbus::IObject& object) : object_(object) { - object_.registerMethod("concatenate").onInterface(interfaceName).implementedAs([this](const std::vector& numbers, const std::string& separator){ return this->concatenate(numbers, separator); }); - object_.registerSignal("concatenated").onInterface(interfaceName).withParameters(); + object_.registerMethod("concatenate").onInterface(INTERFACE_NAME).implementedAs([this](const std::vector& numbers, const std::string& separator){ return this->concatenate(numbers, separator); }); + object_.registerSignal("concatenated").onInterface(INTERFACE_NAME).withParameters(); } public: void concatenated(const std::string& concatenatedString) { - object_.emitSignal("concatenated").onInterface(interfaceName).withArguments(concatenatedString); + object_.emitSignal("concatenated").onInterface(INTERFACE_NAME).withArguments(concatenatedString); } private: @@ -601,13 +601,13 @@ namespace sdbuscpp { class Concatenator_proxy { public: - static constexpr const char* interfaceName = "org.sdbuscpp.Concatenator"; + static constexpr const char* INTERFACE_NAME = "org.sdbuscpp.Concatenator"; protected: Concatenator_proxy(sdbus::IProxy& proxy) : proxy_(proxy) { - proxy_.uponSignal("concatenated").onInterface(interfaceName).call([this](const std::string& concatenatedString){ this->onConcatenated(concatenatedString); }); + proxy_.uponSignal("concatenated").onInterface(INTERFACE_NAME).call([this](const std::string& concatenatedString){ this->onConcatenated(concatenatedString); }); } virtual void onConcatenated(const std::string& concatenatedString) = 0; @@ -616,7 +616,7 @@ public: std::string concatenate(const std::vector& numbers, const std::string& separator) { std::string result; - proxy_.callMethod("concatenate").onInterface(interfaceName).withArguments(numbers, separator).storeResultsTo(result); + proxy_.callMethod("concatenate").onInterface(INTERFACE_NAME).withArguments(numbers, separator).storeResultsTo(result); return result; } diff --git a/include/sdbus-c++/AdaptorInterfaces.h b/include/sdbus-c++/AdaptorInterfaces.h index 5b2a53d..2131ac9 100644 --- a/include/sdbus-c++/AdaptorInterfaces.h +++ b/include/sdbus-c++/AdaptorInterfaces.h @@ -130,6 +130,30 @@ namespace sdbus { getObject().unregister(); } + /*! + * @brief Adds an ObjectManager interface at the path of this D-Bus object + * + * Creates an ObjectManager interface at the specified object path on + * the connection. This is a convenient way to interrogate a connection + * to see what objects it has. + * + * @throws sdbus::Error in case of failure + */ + void addObjectManager() + { + getObject().addObjectManager(); + } + + /*! + * @brief Removes an ObjectManager interface from the path of this D-Bus object + * + * @throws sdbus::Error in case of failure + */ + void removeObjectManager() + { + getObject().removeObjectManager(); + } + protected: using base_type = AdaptorInterfaces; }; diff --git a/include/sdbus-c++/ConvenienceApiClasses.h b/include/sdbus-c++/ConvenienceApiClasses.h index 57d8c8f..f125efb 100644 --- a/include/sdbus-c++/ConvenienceApiClasses.h +++ b/include/sdbus-c++/ConvenienceApiClasses.h @@ -220,6 +220,7 @@ namespace sdbus { PropertySetter(IProxy& proxy, const std::string& propertyName); PropertySetter& onInterface(const std::string& interfaceName); template void toValue(const _Value& value); + void toValue(const sdbus::Variant& value); private: IProxy& proxy_; diff --git a/include/sdbus-c++/ConvenienceApiClasses.inl b/include/sdbus-c++/ConvenienceApiClasses.inl index 47603e1..ee3c0b7 100644 --- a/include/sdbus-c++/ConvenienceApiClasses.inl +++ b/include/sdbus-c++/ConvenienceApiClasses.inl @@ -596,13 +596,18 @@ namespace sdbus { template inline void PropertySetter::toValue(const _Value& value) + { + PropertySetter::toValue(sdbus::Variant{value}); + } + + inline void PropertySetter::toValue(const sdbus::Variant& value) { SDBUS_THROW_ERROR_IF(interfaceName_.empty(), "DBus interface not specified when setting a property", EINVAL); proxy_ .callMethod("Set") .onInterface("org.freedesktop.DBus.Properties") - .withArguments(interfaceName_, propertyName_, sdbus::Variant{value}); + .withArguments(interfaceName_, propertyName_, value); } } diff --git a/include/sdbus-c++/IConnection.h b/include/sdbus-c++/IConnection.h index 9eab0ab..6f6feca 100644 --- a/include/sdbus-c++/IConnection.h +++ b/include/sdbus-c++/IConnection.h @@ -45,6 +45,8 @@ namespace sdbus { class IConnection { public: + virtual ~IConnection() = default; + /*! * @brief Requests D-Bus name on the connection * @@ -91,7 +93,7 @@ namespace sdbus { virtual void leaveProcessingLoop() = 0; /*! - * @brief Add an ObjectManager at the specified D-Bus object path + * @brief Adds an ObjectManager at the specified D-Bus object path * * Creates an ObjectManager interface at the specified object path on * the connection. This is a convenient way to interrogate a connection @@ -99,13 +101,9 @@ namespace sdbus { * * @throws sdbus::Error in case of failure */ - virtual void addObjectManager( const std::string& objectPath ) = 0; - - inline virtual ~IConnection() = 0; + virtual void addObjectManager(const std::string& objectPath) = 0; }; - IConnection::~IConnection() {} - /*! * @brief Creates/opens D-Bus system connection * diff --git a/include/sdbus-c++/IObject.h b/include/sdbus-c++/IObject.h index 6ca6f92..d109986 100644 --- a/include/sdbus-c++/IObject.h +++ b/include/sdbus-c++/IObject.h @@ -57,6 +57,8 @@ namespace sdbus { class IObject { public: + virtual ~IObject() = default; + /*! * @brief Registers method that the object will provide on D-Bus * @@ -192,6 +194,30 @@ namespace sdbus { */ virtual sdbus::IConnection& getConnection() const = 0; + /*! + * @brief Adds an ObjectManager interface at the path of this D-Bus object + * + * Creates an ObjectManager interface at the specified object path on + * the connection. This is a convenient way to interrogate a connection + * to see what objects it has. + * + * @throws sdbus::Error in case of failure + */ + virtual void addObjectManager() = 0; + + /*! + * @brief Removes an ObjectManager interface from the path of this D-Bus object + * + * @throws sdbus::Error in case of failure + */ + virtual void removeObjectManager() = 0; + + /*! + * @brief Tests whether ObjectManager interface is added at the path of this D-Bus object + * @return True if ObjectManager interface is there, false otherwise + */ + virtual bool hasObjectManager() const = 0; + /*! * @brief Registers method that the object will provide on D-Bus * @@ -287,8 +313,6 @@ namespace sdbus { * @throws sdbus::Error in case of failure */ SignalEmitter emitSignal(const std::string& signalName); - - virtual ~IObject() = 0; }; inline MethodRegistrator IObject::registerMethod(const std::string& methodName) @@ -316,8 +340,6 @@ namespace sdbus { return SignalEmitter(*this, signalName); } - inline IObject::~IObject() {} - /*! * @brief Creates instance representing a D-Bus object * diff --git a/include/sdbus-c++/IProxy.h b/include/sdbus-c++/IProxy.h index ace464c..0855319 100644 --- a/include/sdbus-c++/IProxy.h +++ b/include/sdbus-c++/IProxy.h @@ -58,6 +58,8 @@ namespace sdbus { class IProxy { public: + virtual ~IProxy() = default; + /*! * @brief Creates a method call message * @@ -259,8 +261,6 @@ namespace sdbus { * @throws sdbus::Error in case of failure */ PropertySetter setProperty(const std::string& propertyName); - - virtual ~IProxy() = default; }; inline MethodInvoker IProxy::callMethod(const std::string& methodName) diff --git a/include/sdbus-c++/Introspection.h b/include/sdbus-c++/Introspection.h deleted file mode 100644 index 03b3050..0000000 --- a/include/sdbus-c++/Introspection.h +++ /dev/null @@ -1,84 +0,0 @@ -/** - * (C) 2017 KISTLER INSTRUMENTE AG, Winterthur, Switzerland - * - * @file Introspection.h - * - * Created on: Dec 13, 2016 - * Project: sdbus-c++ - * Description: High-level D-Bus IPC C++ library based on sd-bus - * - * This file is part of sdbus-c++. - * - * sdbus-c++ is free software; you can redistribute it and/or modify it - * under the terms of the GNU Lesser General Public License as published by - * the Free Software Foundation, either version 2.1 of the License, or - * (at your option) any later version. - * - * sdbus-c++ is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU Lesser General Public License for more details. - * - * You should have received a copy of the GNU Lesser General Public License - * along with sdbus-c++. If not, see . - */ - -#ifndef SDBUS_CXX_INTROSPECTION_H_ -#define SDBUS_CXX_INTROSPECTION_H_ - -#include -#include -#include - -namespace sdbus { - - // Proxy for introspection - class introspectable_proxy - { - static constexpr const char* interfaceName = "org.freedesktop.DBus.Introspectable"; - - protected: - introspectable_proxy(sdbus::IProxy& object) - : object_(object) - { - } - - public: - std::string Introspect() - { - std::string xml; - object_.callMethod("Introspect").onInterface(interfaceName).storeResultsTo(xml); - return xml; - } - - private: - sdbus::IProxy& object_; - }; - - // Adaptor is not necessary if we want to rely on sdbus-provided introspection -// class introspectable_adaptor -// { -// static constexpr const char* interfaceName = "org.freedesktop.DBus.Introspectable"; -// -// protected: -// introspectable_adaptor(sdbus::IObject& object) -// : object_(object) -// { -// object_.registerMethod("Introspect").onInterface(interfaceName).implementedAs([this](){ return object_.introspect(); }); -// } -// -// public: -// std::string introspect() -// { -// std::string xml; -// object_.callMethod("Introspect").onInterface(interfaceName).storeResultsTo(xml); -// return xml; -// } -// -// private: -// sdbus::IObject& object_; -// }; - -} - -#endif /* SDBUS_CXX_INTROSPECTION_H_ */ diff --git a/include/sdbus-c++/StandardInterfaces.h b/include/sdbus-c++/StandardInterfaces.h new file mode 100644 index 0000000..a4016f2 --- /dev/null +++ b/include/sdbus-c++/StandardInterfaces.h @@ -0,0 +1,185 @@ +/** + * (C) 2017 KISTLER INSTRUMENTE AG, Winterthur, Switzerland + * + * @file StandardInterfaces.h + * + * Created on: Dec 13, 2016 + * Project: sdbus-c++ + * Description: High-level D-Bus IPC C++ library based on sd-bus + * + * This file is part of sdbus-c++. + * + * sdbus-c++ is free software; you can redistribute it and/or modify it + * under the terms of the GNU Lesser General Public License as published by + * the Free Software Foundation, either version 2.1 of the License, or + * (at your option) any later version. + * + * sdbus-c++ is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public License + * along with sdbus-c++. If not, see . + */ + +#ifndef SDBUS_CXX_STANDARDINTERFACES_H_ +#define SDBUS_CXX_STANDARDINTERFACES_H_ + +#include +#include +#include +#include +#include +#include + +namespace sdbus { + + // Proxy for peer + class Peer_proxy + { + static constexpr const char* INTERFACE_NAME = "org.freedesktop.DBus.Peer"; + + protected: + Peer_proxy(sdbus::IProxy& proxy) + : proxy_(proxy) + { + } + + public: + void Ping() + { + proxy_.callMethod("Ping").onInterface(INTERFACE_NAME); + } + + std::string GetMachineId() + { + std::string machineUUID; + proxy_.callMethod("GetMachineId").onInterface(INTERFACE_NAME).storeResultsTo(machineUUID); + return machineUUID; + } + + private: + sdbus::IProxy& proxy_; + }; + + // Proxy for introspection + class Introspectable_proxy + { + static constexpr const char* INTERFACE_NAME = "org.freedesktop.DBus.Introspectable"; + + protected: + Introspectable_proxy(sdbus::IProxy& proxy) + : proxy_(proxy) + { + } + + public: + std::string Introspect() + { + std::string xml; + proxy_.callMethod("Introspect").onInterface(INTERFACE_NAME).storeResultsTo(xml); + return xml; + } + + private: + sdbus::IProxy& proxy_; + }; + + // Proxy for properties + class Properties_proxy + { + static constexpr const char* INTERFACE_NAME = "org.freedesktop.DBus.Properties"; + + protected: + Properties_proxy(sdbus::IProxy& proxy) + : proxy_(proxy) + { + proxy_ + .uponSignal("PropertiesChanged") + .onInterface(INTERFACE_NAME) + .call([this]( const std::string& interfaceName + , const std::map& changedProperties + , const std::vector& invalidatedProperties ) + { + this->onPropertiesChanged(interfaceName, changedProperties, invalidatedProperties); + }); + } + + virtual void onPropertiesChanged( const std::string& interfaceName + , const std::map& changedProperties + , const std::vector& invalidatedProperties ) = 0; + + public: + sdbus::Variant Get(const std::string& interfaceName, const std::string& propertyName) + { + return proxy_.getProperty(propertyName).onInterface(interfaceName); + } + + void Set(const std::string& interfaceName, const std::string& propertyName, const sdbus::Variant& value) + { + proxy_.setProperty(propertyName).onInterface(interfaceName).toValue(value); + } + + std::map GetAll(const std::string& interfaceName) + { + std::map props; + proxy_.callMethod("GetAll").onInterface(INTERFACE_NAME).withArguments(interfaceName).storeResultsTo(props); + return props; + } + + private: + sdbus::IProxy& proxy_; + }; + + // Proxy for object manager + class ObjectManager_proxy + { + static constexpr const char* INTERFACE_NAME = "org.freedesktop.DBus.ObjectManager"; + + protected: + ObjectManager_proxy(sdbus::IProxy& proxy) + : proxy_(proxy) + { + proxy_ + .uponSignal("InterfacesAdded") + .onInterface(INTERFACE_NAME) + .call([this]( const sdbus::ObjectPath& objectPath + , const std::map>& interfacesAndProperties ) + { + this->onInterfacesAdded(objectPath, interfacesAndProperties); + }); + + proxy_ + .uponSignal("InterfacesRemoved") + .onInterface(INTERFACE_NAME) + .call([this]( const sdbus::ObjectPath& objectPath + , const std::vector& interfaces ) + { + this->onInterfacesRemoved(objectPath, interfaces); + }); + } + + virtual void onInterfacesAdded( const sdbus::ObjectPath& objectPath + , const std::map>& interfacesAndProperties) = 0; + virtual void onInterfacesRemoved( const sdbus::ObjectPath& objectPath + , const std::vector& interfaces) = 0; + + public: + std::map>> GetManagedObjects() + { + std::map>> objectsInterfacesAndProperties; + proxy_.callMethod("GetManagedObjects").onInterface(INTERFACE_NAME).storeResultsTo(objectsInterfacesAndProperties); + return objectsInterfacesAndProperties; + } + + private: + sdbus::IProxy& proxy_; + }; + + // Adaptors for the above-listed standard D-Bus interfaces are not necessary because the functionality + // is provided automatically for each D-Bus object by underlying libsystemd (with the exception of + // object manager which is provided but needs to be added explicitly, see IObject::addObjectManager). +} + +#endif /* SDBUS_CXX_STANDARDINTERFACES_H_ */ diff --git a/include/sdbus-c++/sdbus-c++.h b/include/sdbus-c++/sdbus-c++.h index 5d17146..00598bd 100644 --- a/include/sdbus-c++/sdbus-c++.h +++ b/include/sdbus-c++/sdbus-c++.h @@ -28,9 +28,10 @@ #include #include #include +#include #include #include #include #include -#include #include +#include diff --git a/src/Connection.cpp b/src/Connection.cpp index 3892567..bf01ef1 100644 --- a/src/Connection.cpp +++ b/src/Connection.cpp @@ -103,19 +103,28 @@ ISdBus& Connection::getSdBusInterface() return *iface_.get(); } -void Connection::addObjectManager( const std::string& objectPath ) +void Connection::addObjectManager(const std::string& objectPath) { + Connection::addObjectManager(objectPath, nullptr); +} + +SlotPtr Connection::addObjectManager(const std::string& objectPath, void* /*dummy*/) +{ + sd_bus_slot *slot{}; + auto r = iface_->sd_bus_add_object_manager( bus_.get() - , NULL + , &slot , objectPath.c_str() ); SDBUS_THROW_ERROR_IF(r < 0, "Failed to add object manager", -r); + + return {slot, [this](void *slot){ iface_->sd_bus_slot_unref((sd_bus_slot*)slot); }}; } -sd_bus_slot* Connection::addObjectVTable( const std::string& objectPath - , const std::string& interfaceName - , const sd_bus_vtable* vtable - , void* userData ) +SlotPtr Connection::addObjectVTable( const std::string& objectPath + , const std::string& interfaceName + , const sd_bus_vtable* vtable + , void* userData ) { sd_bus_slot *slot{}; @@ -128,12 +137,7 @@ sd_bus_slot* Connection::addObjectVTable( const std::string& objectPath SDBUS_THROW_ERROR_IF(r < 0, "Failed to register object vtable", -r); - return slot; -} - -void Connection::removeObjectVTable(sd_bus_slot* vtableHandle) -{ - iface_->sd_bus_slot_unref(vtableHandle); + return {slot, [this](void *slot){ iface_->sd_bus_slot_unref((sd_bus_slot*)slot); }}; } MethodCall Connection::createMethodCall( const std::string& destination @@ -172,11 +176,11 @@ Signal Connection::createSignal( const std::string& objectPath return Signal{sdbusSignal, iface_.get(), adopt_message}; } -sd_bus_slot* Connection::registerSignalHandler( const std::string& objectPath - , const std::string& interfaceName - , const std::string& signalName - , sd_bus_message_handler_t callback - , void* userData ) +SlotPtr Connection::registerSignalHandler( const std::string& objectPath + , const std::string& interfaceName + , const std::string& signalName + , sd_bus_message_handler_t callback + , void* userData ) { sd_bus_slot *slot{}; @@ -185,12 +189,7 @@ sd_bus_slot* Connection::registerSignalHandler( const std::string& objectPath SDBUS_THROW_ERROR_IF(r < 0, "Failed to register signal handler", -r); - return slot; -} - -void Connection::unregisterSignalHandler(sd_bus_slot* handlerCookie) -{ - iface_->sd_bus_slot_unref(handlerCookie); + return {slot, [this](void *slot){ iface_->sd_bus_slot_unref((sd_bus_slot*)slot); }}; } sd_bus* Connection::openBus(Connection::BusType type) diff --git a/src/Connection.h b/src/Connection.h index 4ede286..990bb8e 100644 --- a/src/Connection.h +++ b/src/Connection.h @@ -56,31 +56,32 @@ namespace sdbus { namespace internal { void enterProcessingLoop() override; void enterProcessingLoopAsync() override; void leaveProcessingLoop() override; - void addObjectManager( const std::string& objectPath ) override; + + void addObjectManager(const std::string& objectPath) override; + SlotPtr addObjectManager(const std::string& objectPath, void* /*dummy*/) override; const ISdBus& getSdBusInterface() const override; ISdBus& getSdBusInterface() override; - sd_bus_slot* addObjectVTable( const std::string& objectPath - , const std::string& interfaceName - , const sd_bus_vtable* vtable - , void* userData ) override; - void removeObjectVTable(sd_bus_slot* vtableHandle) override; + SlotPtr addObjectVTable( const std::string& objectPath + , const std::string& interfaceName + , const sd_bus_vtable* vtable + , void* userData ) override; MethodCall createMethodCall( const std::string& destination , const std::string& objectPath , const std::string& interfaceName , const std::string& methodName ) const override; + Signal createSignal( const std::string& objectPath , const std::string& interfaceName , const std::string& signalName ) const override; - sd_bus_slot* registerSignalHandler( const std::string& objectPath - , const std::string& interfaceName - , const std::string& signalName - , sd_bus_message_handler_t callback - , void* userData ) override; - void unregisterSignalHandler(sd_bus_slot* handlerCookie) override; + SlotPtr registerSignalHandler( const std::string& objectPath + , const std::string& interfaceName + , const std::string& signalName + , sd_bus_message_handler_t callback + , void* userData ) override; private: sd_bus* openBus(Connection::BusType type); diff --git a/src/IConnection.h b/src/IConnection.h index 30fb061..8bf5f7a 100644 --- a/src/IConnection.h +++ b/src/IConnection.h @@ -29,6 +29,7 @@ #include #include #include +#include // Forward declaration namespace sdbus { @@ -44,17 +45,20 @@ namespace sdbus { namespace sdbus { namespace internal { + using SlotPtr = std::unique_ptr>; + class IConnection { public: + virtual ~IConnection() = default; + virtual const ISdBus& getSdBusInterface() const = 0; virtual ISdBus& getSdBusInterface() = 0; - virtual sd_bus_slot* addObjectVTable( const std::string& objectPath - , const std::string& interfaceName - , const sd_bus_vtable* vtable - , void* userData ) = 0; - virtual void removeObjectVTable(sd_bus_slot* vtableHandle) = 0; + virtual SlotPtr addObjectVTable( const std::string& objectPath + , const std::string& interfaceName + , const sd_bus_vtable* vtable + , void* userData ) = 0; virtual MethodCall createMethodCall( const std::string& destination , const std::string& objectPath @@ -65,17 +69,16 @@ namespace internal { , const std::string& interfaceName , const std::string& signalName ) const = 0; - virtual sd_bus_slot* registerSignalHandler( const std::string& objectPath - , const std::string& interfaceName - , const std::string& signalName - , sd_bus_message_handler_t callback - , void* userData ) = 0; - virtual void unregisterSignalHandler(sd_bus_slot* handlerCookie) = 0; + virtual SlotPtr registerSignalHandler( const std::string& objectPath + , const std::string& interfaceName + , const std::string& signalName + , sd_bus_message_handler_t callback + , void* userData ) = 0; virtual void enterProcessingLoopAsync() = 0; virtual void leaveProcessingLoop() = 0; - virtual ~IConnection() = default; + virtual SlotPtr addObjectManager(const std::string& objectPath, void* /*dummy*/ = nullptr) = 0; }; } diff --git a/src/Object.cpp b/src/Object.cpp index cd57bd0..8186589 100644 --- a/src/Object.cpp +++ b/src/Object.cpp @@ -140,6 +140,21 @@ sdbus::IConnection& Object::getConnection() const return dynamic_cast(connection_); } +void Object::addObjectManager() +{ + objectManagerSlot_ = connection_.addObjectManager(objectPath_); +} + +void Object::removeObjectManager() +{ + objectManagerSlot_.reset(); +} + +bool Object::hasObjectManager() const +{ + return objectManagerSlot_ != nullptr; +} + const std::vector& Object::createInterfaceVTable(InterfaceData& interfaceData) { auto& vtable = interfaceData.vtable_; @@ -207,10 +222,7 @@ void Object::activateInterfaceVTable( const std::string& interfaceName , InterfaceData& interfaceData , const std::vector& vtable ) { - // Tell, don't ask - auto slot = connection_.addObjectVTable(objectPath_, interfaceName, &vtable[0], this); - interfaceData.slot_.reset(slot); - interfaceData.slot_.get_deleter() = [this](sd_bus_slot *slot){ connection_.removeObjectVTable(slot); }; + interfaceData.slot_ = connection_.addObjectVTable(objectPath_, interfaceName, &vtable[0], this); } int Object::sdbus_method_callback(sd_bus_message *sdbusMessage, void *userData, sd_bus_error *retError) diff --git a/src/Object.h b/src/Object.h index efe29f6..abf0932 100644 --- a/src/Object.h +++ b/src/Object.h @@ -80,6 +80,10 @@ namespace internal { sdbus::IConnection& getConnection() const override; + void addObjectManager() override; + void removeObjectManager() override; + bool hasObjectManager() const override; + private: using InterfaceName = std::string; struct InterfaceData @@ -112,7 +116,7 @@ namespace internal { std::vector vtable_; Flags flags_; - std::unique_ptr> slot_; + SlotPtr slot_; }; static const std::vector& createInterfaceVTable(InterfaceData& interfaceData); @@ -143,6 +147,7 @@ namespace internal { sdbus::internal::IConnection& connection_; std::string objectPath_; std::map interfaces_; + SlotPtr objectManagerSlot_; }; } diff --git a/src/Proxy.cpp b/src/Proxy.cpp index af5d342..f64f7ea 100644 --- a/src/Proxy.cpp +++ b/src/Proxy.cpp @@ -113,13 +113,11 @@ void Proxy::registerSignalHandlers(sdbus::internal::IConnection& connection) { const auto& signalName = signalItem.first; auto& slot = signalItem.second.slot_; - auto* rawSlotPtr = connection.registerSignalHandler( objectPath_ - , interfaceName - , signalName - , &Proxy::sdbus_signal_callback - , this ); - slot.reset(rawSlotPtr); - slot.get_deleter() = [&connection](sd_bus_slot *slot){ connection.unregisterSignalHandler(slot); }; + slot = connection.registerSignalHandler( objectPath_ + , interfaceName + , signalName + , &Proxy::sdbus_signal_callback + , this ); } } } diff --git a/src/Proxy.h b/src/Proxy.h index 928751e..e564626 100644 --- a/src/Proxy.h +++ b/src/Proxy.h @@ -27,6 +27,7 @@ #define SDBUS_CXX_INTERNAL_PROXY_H_ #include +#include "IConnection.h" #include #include #include @@ -34,11 +35,6 @@ #include #include -// Forward declarations -namespace sdbus { namespace internal { - class IConnection; -}} - namespace sdbus { namespace internal { @@ -83,7 +79,7 @@ namespace internal { struct SignalData { signal_handler callback_; - std::unique_ptr> slot_; + SlotPtr slot_; }; std::map signals_; }; diff --git a/tests/integrationtests/AdaptorAndProxy_test.cpp b/tests/integrationtests/AdaptorAndProxy_test.cpp index 7810db2..de394dd 100644 --- a/tests/integrationtests/AdaptorAndProxy_test.cpp +++ b/tests/integrationtests/AdaptorAndProxy_test.cpp @@ -45,6 +45,7 @@ using ::testing::Eq; using ::testing::Gt; using ::testing::ElementsAre; +using ::testing::SizeIs; using namespace std::chrono_literals; namespace @@ -65,6 +66,18 @@ public: s_connection->releaseName(INTERFACE_NAME); } + static void waitUntil(std::atomic& flag, std::chrono::milliseconds timeout = 1s) + { + std::chrono::milliseconds elapsed{}; + std::chrono::milliseconds step{5ms}; + do { + std::this_thread::sleep_for(step); + elapsed += step; + if (elapsed > timeout) + throw std::runtime_error("Waiting timed out"); + } while (!flag); + } + private: void SetUp() override { @@ -396,30 +409,117 @@ TEST_F(SdbusTestObject, EmitsSignalWithoutRegistrationSuccesfully) // Properties -TEST_F(SdbusTestObject, ReadsReadPropertySuccesfully) +TEST_F(SdbusTestObject, ReadsReadOnlyPropertySuccesfully) { - ASSERT_THAT(m_proxy->state(), Eq(STRING_VALUE)); + ASSERT_THAT(m_proxy->state(), Eq(DEFAULT_STATE_VALUE)); +} + +TEST_F(SdbusTestObject, FailsWritingToReadOnlyProperty) +{ + ASSERT_THROW(m_proxy->state("new_value"), sdbus::Error); } TEST_F(SdbusTestObject, WritesAndReadsReadWritePropertySuccesfully) { - uint32_t x = 42; - ASSERT_NO_THROW(m_proxy->action(x)); - ASSERT_THAT(m_proxy->action(), Eq(x)); + uint32_t newActionValue = 5678; + + m_proxy->action(newActionValue); + + ASSERT_THAT(m_proxy->action(), Eq(newActionValue)); } -TEST_F(SdbusTestObject, WritesToWritePropertySuccesfully) +// Standard D-Bus interfaces + +TEST_F(SdbusTestObject, PingsViaPeerInterface) { - auto x = true; - ASSERT_NO_THROW(m_proxy->blocking(x)); + ASSERT_NO_THROW(m_proxy->Ping()); } -TEST_F(SdbusTestObject, CannotReadFromWriteProperty) +TEST_F(SdbusTestObject, AnswersMachineUuidViaPeerInterface) { - ASSERT_THROW(m_proxy->blocking(), sdbus::Error); + ASSERT_NO_THROW(m_proxy->GetMachineId()); } -TEST_F(SdbusTestObject, AnswersXmlApiDescriptionOnIntrospection) +TEST_F(SdbusTestObject, AnswersXmlApiDescriptionViaIntrospectableInterface) { ASSERT_THAT(m_proxy->Introspect(), Eq(m_adaptor->getExpectedXmlApiDescription())); } + +TEST_F(SdbusTestObject, GetsPropertyViaPropertiesInterface) +{ + ASSERT_THAT(m_proxy->Get(INTERFACE_NAME, "state").get(), Eq(DEFAULT_STATE_VALUE)); +} + +TEST_F(SdbusTestObject, SetsPropertyViaPropertiesInterface) +{ + uint32_t newActionValue = 2345; + + m_proxy->Set(INTERFACE_NAME, "action", newActionValue); + + ASSERT_THAT(m_proxy->action(), Eq(newActionValue)); +} + +TEST_F(SdbusTestObject, GetsAllPropertiesViaPropertiesInterface) +{ + const auto properties = m_proxy->GetAll(INTERFACE_NAME); + + ASSERT_THAT(properties, SizeIs(3)); + EXPECT_THAT(properties.at("state").get(), Eq(DEFAULT_STATE_VALUE)); + EXPECT_THAT(properties.at("action").get(), Eq(DEFAULT_ACTION_VALUE)); + EXPECT_THAT(properties.at("blocking").get(), Eq(DEFAULT_BLOCKING_VALUE)); +} + +// TODO: Uncomment once we have support for PropertiesChanged signals +//TEST_F(SdbusTestObject, GetsSignalOnChangedPropertiesViaPropertiesInterface) +//{ +// std::atomic signalReceived{false}; +// m_proxy->m_onPropertiesChangedHandler = [&signalReceived](const std::string& interfaceName, const std::map& changedProperties, const std::vector& invalidatedProperties) +// { +// EXPECT_THAT(interfaceName, Eq(INTERFACE_NAME)); +// EXPECT_THAT(changedProperties, SizeIs(2)); +// EXPECT_THAT(changedProperties.at("blocking").get(), Eq(false)); +// EXPECT_THAT(invalidatedProperties, SizeIs(0)); +// signalReceived = true; +// }; +// +// m_proxy->blocking(!DEFAULT_BLOCKING_VALUE); +// waitUntil(signalReceived); +//} + +TEST_F(SdbusTestObject, DoesNotProvideObjectManagerInterfaceByDefault) +{ + ASSERT_THROW(m_proxy->GetManagedObjects(), sdbus::Error); +} + +TEST_F(SdbusTestObject, ProvidesObjectManagerInterfaceWhenExplicitlyAdded) +{ + m_adaptor->addObjectManager(); + + ASSERT_NO_THROW(m_proxy->GetManagedObjects()); +} + +TEST_F(SdbusTestObject, GetsZeroManagedObjectsIfHasNoSubPathObjects) +{ + m_adaptor->addObjectManager(); + + const auto objectsInterfacesAndProperties = m_proxy->GetManagedObjects(); + + ASSERT_THAT(objectsInterfacesAndProperties, SizeIs(0)); +} + +TEST_F(SdbusTestObject, GetsManagedObjectsSuccessfully) +{ + m_adaptor->addObjectManager(); + auto subObject1 = sdbus::createObject(*s_connection, "/sub/path1"); + subObject1->registerProperty("aProperty1").onInterface("org.sdbuscpp.integrationtests.iface1").withGetter([]{return uint8_t{123};}); + subObject1->finishRegistration(); + auto subObject2 = sdbus::createObject(*s_connection, "/sub/path2"); + subObject2->registerProperty("aProperty2").onInterface("org.sdbuscpp.integrationtests.iface2").withGetter([]{return "hi";}); + subObject2->finishRegistration(); + + const auto objectsInterfacesAndProperties = m_proxy->GetManagedObjects(); + + ASSERT_THAT(objectsInterfacesAndProperties, SizeIs(2)); + EXPECT_THAT(objectsInterfacesAndProperties.at("/sub/path1").at("org.sdbuscpp.integrationtests.iface1").at("aProperty1").get(), Eq(123)); + EXPECT_THAT(objectsInterfacesAndProperties.at("/sub/path2").at("org.sdbuscpp.integrationtests.iface2").at("aProperty2").get(), Eq("hi")); +} diff --git a/tests/integrationtests/TestingAdaptor.h b/tests/integrationtests/TestingAdaptor.h index c4668a2..4eb0d49 100644 --- a/tests/integrationtests/TestingAdaptor.h +++ b/tests/integrationtests/TestingAdaptor.h @@ -177,15 +177,16 @@ protected: throw sdbus::createError(1, "A test error occurred"); } - std::string state() { return STRING_VALUE; } + std::string state() { return m_state; } uint32_t action() { return m_action; } void action(const uint32_t& value) { m_action = value; } bool blocking() { return m_blocking; } void blocking(const bool& value) { m_blocking = value; } private: - uint32_t m_action; - bool m_blocking; + const std::string m_state{DEFAULT_STATE_VALUE}; + uint32_t m_action{DEFAULT_ACTION_VALUE}; + bool m_blocking{DEFAULT_BLOCKING_VALUE}; // For dont-expect-reply method call verifications mutable std::atomic m_multiplyCalled{}; diff --git a/tests/integrationtests/TestingProxy.h b/tests/integrationtests/TestingProxy.h index 38458d4..fc60ef0 100644 --- a/tests/integrationtests/TestingProxy.h +++ b/tests/integrationtests/TestingProxy.h @@ -28,7 +28,11 @@ #include "proxy-glue.h" -class TestingProxy : public sdbus::ProxyInterfaces<::testing_proxy, sdbus::introspectable_proxy> +class TestingProxy : public sdbus::ProxyInterfaces< ::testing_proxy + , sdbus::Peer_proxy + , sdbus::Introspectable_proxy + , sdbus::Properties_proxy + , sdbus::ObjectManager_proxy > { public: TestingProxy(std::string destination, std::string objectPath) @@ -73,13 +77,36 @@ protected: m_DoOperationClientSideAsyncReplyHandler(returnValue, error); } -private: + // Signals of standard D-Bus interfaces + + void onPropertiesChanged( const std::string& interfaceName + , const std::map& changedProperties + , const std::vector& invalidatedProperties ) override + { + if (m_onPropertiesChangedHandler) + m_onPropertiesChangedHandler(interfaceName, changedProperties, invalidatedProperties); + } + + void onInterfacesAdded( const sdbus::ObjectPath& /*objectPath*/ + , const std::map>& /*interfacesAndProperties*/) override + { + // Intentionally left empty + } + void onInterfacesRemoved( const sdbus::ObjectPath& /*objectPath*/ + , const std::vector& /*interfaces*/) override + { + // Intentionally left empty + } + +//private: +public: int m_simpleCallCounter{}; std::map m_map; double m_variantValue; std::map m_signature; std::function m_DoOperationClientSideAsyncReplyHandler; + std::function& changedProperties, const std::vector& invalidatedProperties)> m_onPropertiesChangedHandler; }; diff --git a/tests/integrationtests/adaptor-glue.h b/tests/integrationtests/adaptor-glue.h index 78f1713..95dfba5 100644 --- a/tests/integrationtests/adaptor-glue.h +++ b/tests/integrationtests/adaptor-glue.h @@ -111,8 +111,9 @@ protected: object_.registerSignal("signalWithVariant").onInterface(INTERFACE_NAME).withParameters(); object_.registerProperty("state").onInterface(INTERFACE_NAME).withGetter([this](){ return this->state(); }).markAsDeprecated().withUpdateBehavior(sdbus::Flags::CONST_PROPERTY_VALUE); - object_.registerProperty("action").onInterface(INTERFACE_NAME).withGetter([this](){ return this->action(); }).withSetter([this](const uint32_t& value){ this->action(value); }).withUpdateBehavior(sdbus::Flags::EMITS_NO_SIGNAL); - object_.registerProperty("blocking").onInterface(INTERFACE_NAME)./*withGetter([this](){ return this->blocking(); }).*/withSetter([this](const bool& value){ this->blocking(value); }); + object_.registerProperty("action").onInterface(INTERFACE_NAME).withGetter([this](){ return this->action(); }).withSetter([this](const uint32_t& value){ this->action(value); }).withUpdateBehavior(sdbus::Flags::EMITS_INVALIDATION_SIGNAL); + //object_.registerProperty("blocking").onInterface(INTERFACE_NAME)./*withGetter([this](){ return this->blocking(); }).*/withSetter([this](const bool& value){ this->blocking(value); }); + object_.registerProperty("blocking").onInterface(INTERFACE_NAME).withGetter([this](){ return this->blocking(); }).withSetter([this](const bool& value){ this->blocking(value); }); } @@ -294,7 +295,7 @@ R"delimiter( - + diff --git a/tests/integrationtests/defs.h b/tests/integrationtests/defs.h index 61a9fe0..304678e 100644 --- a/tests/integrationtests/defs.h +++ b/tests/integrationtests/defs.h @@ -41,6 +41,10 @@ const std::string STRING_VALUE{"sdbus-c++-testing"}; const sdbus::Signature SIGNATURE_VALUE{"a{is}"}; const sdbus::ObjectPath OBJECT_PATH_VALUE{"/"}; +const std::string DEFAULT_STATE_VALUE{"default-state-value"}; +const uint32_t DEFAULT_ACTION_VALUE{999}; +const bool DEFAULT_BLOCKING_VALUE{true}; + constexpr const double DOUBLE_VALUE{3.24L}; #endif /* SDBUS_CPP_INTEGRATIONTESTS_DEFS_H_ */ diff --git a/tests/integrationtests/proxy-glue.h b/tests/integrationtests/proxy-glue.h index c393608..1c8971b 100644 --- a/tests/integrationtests/proxy-glue.h +++ b/tests/integrationtests/proxy-glue.h @@ -211,6 +211,11 @@ public: return object_.getProperty("state").onInterface(INTERFACE_NAME); } + void state(const std::string& value) + { + object_.setProperty("state").onInterface(INTERFACE_NAME).toValue(value); + } + uint32_t action() { return object_.getProperty("action").onInterface(INTERFACE_NAME); diff --git a/tests/perftests/perftests-adaptor.h b/tests/perftests/perftests-adaptor.h index 3370481..b84b8dd 100644 --- a/tests/perftests/perftests-adaptor.h +++ b/tests/perftests/perftests-adaptor.h @@ -3,8 +3,8 @@ * This file was automatically generated by sdbus-c++-xml2cpp; DO NOT EDIT! */ -#ifndef __sdbuscpp__perftest_adaptor_h__adaptor__H__ -#define __sdbuscpp__perftest_adaptor_h__adaptor__H__ +#ifndef __sdbuscpp__perftests_adaptor_h__adaptor__H__ +#define __sdbuscpp__perftests_adaptor_h__adaptor__H__ #include #include @@ -16,21 +16,21 @@ namespace sdbuscpp { class perftests_adaptor { public: - static constexpr const char* interfaceName = "org.sdbuscpp.perftests"; + static constexpr const char* INTERFACE_NAME = "org.sdbuscpp.perftests"; protected: perftests_adaptor(sdbus::IObject& object) : object_(object) { - object_.registerMethod("sendDataSignals").onInterface(interfaceName).implementedAs([this](const uint32_t& numberOfSignals, const uint32_t& signalMsgSize){ return this->sendDataSignals(numberOfSignals, signalMsgSize); }); - object_.registerMethod("concatenateTwoStrings").onInterface(interfaceName).implementedAs([this](const std::string& string1, const std::string& string2){ return this->concatenateTwoStrings(string1, string2); }); - object_.registerSignal("dataSignal").onInterface(interfaceName).withParameters(); + object_.registerMethod("sendDataSignals").onInterface(INTERFACE_NAME).implementedAs([this](const uint32_t& numberOfSignals, const uint32_t& signalMsgSize){ return this->sendDataSignals(numberOfSignals, signalMsgSize); }); + object_.registerMethod("concatenateTwoStrings").onInterface(INTERFACE_NAME).implementedAs([this](const std::string& string1, const std::string& string2){ return this->concatenateTwoStrings(string1, string2); }); + object_.registerSignal("dataSignal").onInterface(INTERFACE_NAME).withParameters(); } public: void dataSignal(const std::string& data) { - object_.emitSignal("dataSignal").onInterface(interfaceName).withArguments(data); + object_.emitSignal("dataSignal").onInterface(INTERFACE_NAME).withArguments(data); } private: diff --git a/tests/perftests/perftests-proxy.h b/tests/perftests/perftests-proxy.h index bbbde8f..906657f 100644 --- a/tests/perftests/perftests-proxy.h +++ b/tests/perftests/perftests-proxy.h @@ -3,8 +3,8 @@ * This file was automatically generated by sdbus-c++-xml2cpp; DO NOT EDIT! */ -#ifndef __sdbuscpp__perftest_proxy_h__proxy__H__ -#define __sdbuscpp__perftest_proxy_h__proxy__H__ +#ifndef __sdbuscpp__perftests_proxy_h__proxy__H__ +#define __sdbuscpp__perftests_proxy_h__proxy__H__ #include #include @@ -16,13 +16,13 @@ namespace sdbuscpp { class perftests_proxy { public: - static constexpr const char* interfaceName = "org.sdbuscpp.perftests"; + static constexpr const char* INTERFACE_NAME = "org.sdbuscpp.perftests"; protected: perftests_proxy(sdbus::IProxy& proxy) : proxy_(proxy) { - proxy_.uponSignal("dataSignal").onInterface(interfaceName).call([this](const std::string& data){ this->onDataSignal(data); }); + proxy_.uponSignal("dataSignal").onInterface(INTERFACE_NAME).call([this](const std::string& data){ this->onDataSignal(data); }); } virtual void onDataSignal(const std::string& data) = 0; @@ -30,13 +30,13 @@ protected: public: void sendDataSignals(const uint32_t& numberOfSignals, const uint32_t& signalMsgSize) { - proxy_.callMethod("sendDataSignals").onInterface(interfaceName).withArguments(numberOfSignals, signalMsgSize); + proxy_.callMethod("sendDataSignals").onInterface(INTERFACE_NAME).withArguments(numberOfSignals, signalMsgSize); } std::string concatenateTwoStrings(const std::string& string1, const std::string& string2) { std::string result; - proxy_.callMethod("concatenateTwoStrings").onInterface(interfaceName).withArguments(string1, string2).storeResultsTo(result); + proxy_.callMethod("concatenateTwoStrings").onInterface(INTERFACE_NAME).withArguments(string1, string2).storeResultsTo(result); return result; } diff --git a/tests/stresstests/celsius-thermometer-adaptor.h b/tests/stresstests/celsius-thermometer-adaptor.h index bbc5c7a..c84f7f5 100644 --- a/tests/stresstests/celsius-thermometer-adaptor.h +++ b/tests/stresstests/celsius-thermometer-adaptor.h @@ -18,13 +18,13 @@ namespace celsius { class thermometer_adaptor { public: - static constexpr const char* interfaceName = "org.sdbuscpp.stresstests.celsius.thermometer"; + static constexpr const char* INTERFACE_NAME = "org.sdbuscpp.stresstests.celsius.thermometer"; protected: thermometer_adaptor(sdbus::IObject& object) : object_(object) { - object_.registerMethod("getCurrentTemperature").onInterface(interfaceName).implementedAs([this](){ return this->getCurrentTemperature(); }); + object_.registerMethod("getCurrentTemperature").onInterface(INTERFACE_NAME).implementedAs([this](){ return this->getCurrentTemperature(); }); } private: diff --git a/tests/stresstests/celsius-thermometer-proxy.h b/tests/stresstests/celsius-thermometer-proxy.h index 39850f7..4b5d090 100644 --- a/tests/stresstests/celsius-thermometer-proxy.h +++ b/tests/stresstests/celsius-thermometer-proxy.h @@ -18,7 +18,7 @@ namespace celsius { class thermometer_proxy { public: - static constexpr const char* interfaceName = "org.sdbuscpp.stresstests.celsius.thermometer"; + static constexpr const char* INTERFACE_NAME = "org.sdbuscpp.stresstests.celsius.thermometer"; protected: thermometer_proxy(sdbus::IProxy& proxy) @@ -30,7 +30,7 @@ public: uint32_t getCurrentTemperature() { uint32_t result; - proxy_.callMethod("getCurrentTemperature").onInterface(interfaceName).storeResultsTo(result); + proxy_.callMethod("getCurrentTemperature").onInterface(INTERFACE_NAME).storeResultsTo(result); return result; } diff --git a/tests/stresstests/concatenator-adaptor.h b/tests/stresstests/concatenator-adaptor.h index 0621d45..89ce88a 100644 --- a/tests/stresstests/concatenator-adaptor.h +++ b/tests/stresstests/concatenator-adaptor.h @@ -17,20 +17,20 @@ namespace stresstests { class concatenator_adaptor { public: - static constexpr const char* interfaceName = "org.sdbuscpp.stresstests.concatenator"; + static constexpr const char* INTERFACE_NAME = "org.sdbuscpp.stresstests.concatenator"; protected: concatenator_adaptor(sdbus::IObject& object) : object_(object) { - object_.registerMethod("concatenate").onInterface(interfaceName).implementedAs([this](sdbus::Result&& result, std::map params){ this->concatenate(std::move(result), std::move(params)); }); - object_.registerSignal("concatenatedSignal").onInterface(interfaceName).withParameters(); + object_.registerMethod("concatenate").onInterface(INTERFACE_NAME).implementedAs([this](sdbus::Result&& result, std::map params){ this->concatenate(std::move(result), std::move(params)); }); + object_.registerSignal("concatenatedSignal").onInterface(INTERFACE_NAME).withParameters(); } public: void concatenatedSignal(const std::string& concatenatedString) { - object_.emitSignal("concatenatedSignal").onInterface(interfaceName).withArguments(concatenatedString); + object_.emitSignal("concatenatedSignal").onInterface(INTERFACE_NAME).withArguments(concatenatedString); } private: diff --git a/tests/stresstests/concatenator-proxy.h b/tests/stresstests/concatenator-proxy.h index 9b60e04..423254c 100644 --- a/tests/stresstests/concatenator-proxy.h +++ b/tests/stresstests/concatenator-proxy.h @@ -17,13 +17,13 @@ namespace stresstests { class concatenator_proxy { public: - static constexpr const char* interfaceName = "org.sdbuscpp.stresstests.concatenator"; + static constexpr const char* INTERFACE_NAME = "org.sdbuscpp.stresstests.concatenator"; protected: concatenator_proxy(sdbus::IProxy& proxy) : proxy_(proxy) { - proxy_.uponSignal("concatenatedSignal").onInterface(interfaceName).call([this](const std::string& concatenatedString){ this->onConcatenatedSignal(concatenatedString); }); + proxy_.uponSignal("concatenatedSignal").onInterface(INTERFACE_NAME).call([this](const std::string& concatenatedString){ this->onConcatenatedSignal(concatenatedString); }); } virtual void onConcatenatedSignal(const std::string& concatenatedString) = 0; @@ -33,7 +33,7 @@ protected: public: void concatenate(const std::map& params) { - proxy_.callMethodAsync("concatenate").onInterface(interfaceName).withArguments(params).uponReplyInvoke([this](const sdbus::Error* error, const std::string& result){ this->onConcatenateReply(result, error); }); + proxy_.callMethodAsync("concatenate").onInterface(INTERFACE_NAME).withArguments(params).uponReplyInvoke([this](const sdbus::Error* error, const std::string& result){ this->onConcatenateReply(result, error); }); } private: diff --git a/tests/stresstests/fahrenheit-thermometer-adaptor.h b/tests/stresstests/fahrenheit-thermometer-adaptor.h index 71e57dc..36c7cfd 100644 --- a/tests/stresstests/fahrenheit-thermometer-adaptor.h +++ b/tests/stresstests/fahrenheit-thermometer-adaptor.h @@ -18,13 +18,13 @@ namespace fahrenheit { class thermometer_adaptor { public: - static constexpr const char* interfaceName = "org.sdbuscpp.stresstests.fahrenheit.thermometer"; + static constexpr const char* INTERFACE_NAME = "org.sdbuscpp.stresstests.fahrenheit.thermometer"; protected: thermometer_adaptor(sdbus::IObject& object) : object_(object) { - object_.registerMethod("getCurrentTemperature").onInterface(interfaceName).implementedAs([this](){ return this->getCurrentTemperature(); }); + object_.registerMethod("getCurrentTemperature").onInterface(INTERFACE_NAME).implementedAs([this](){ return this->getCurrentTemperature(); }); } private: @@ -45,14 +45,14 @@ namespace thermometer { class factory_adaptor { public: - static constexpr const char* interfaceName = "org.sdbuscpp.stresstests.fahrenheit.thermometer.factory"; + static constexpr const char* INTERFACE_NAME = "org.sdbuscpp.stresstests.fahrenheit.thermometer.factory"; protected: factory_adaptor(sdbus::IObject& object) : object_(object) { - object_.registerMethod("createDelegateObject").onInterface(interfaceName).implementedAs([this](sdbus::Result&& result){ this->createDelegateObject(std::move(result)); }); - object_.registerMethod("destroyDelegateObject").onInterface(interfaceName).implementedAs([this](sdbus::Result<>&& result, sdbus::ObjectPath delegate){ this->destroyDelegateObject(std::move(result), std::move(delegate)); }).withNoReply(); + object_.registerMethod("createDelegateObject").onInterface(INTERFACE_NAME).implementedAs([this](sdbus::Result&& result){ this->createDelegateObject(std::move(result)); }); + object_.registerMethod("destroyDelegateObject").onInterface(INTERFACE_NAME).implementedAs([this](sdbus::Result<>&& result, sdbus::ObjectPath delegate){ this->destroyDelegateObject(std::move(result), std::move(delegate)); }).withNoReply(); } private: diff --git a/tests/stresstests/fahrenheit-thermometer-proxy.h b/tests/stresstests/fahrenheit-thermometer-proxy.h index f8af47f..ce2a8a8 100644 --- a/tests/stresstests/fahrenheit-thermometer-proxy.h +++ b/tests/stresstests/fahrenheit-thermometer-proxy.h @@ -18,7 +18,7 @@ namespace fahrenheit { class thermometer_proxy { public: - static constexpr const char* interfaceName = "org.sdbuscpp.stresstests.fahrenheit.thermometer"; + static constexpr const char* INTERFACE_NAME = "org.sdbuscpp.stresstests.fahrenheit.thermometer"; protected: thermometer_proxy(sdbus::IProxy& proxy) @@ -30,7 +30,7 @@ public: uint32_t getCurrentTemperature() { uint32_t result; - proxy_.callMethod("getCurrentTemperature").onInterface(interfaceName).storeResultsTo(result); + proxy_.callMethod("getCurrentTemperature").onInterface(INTERFACE_NAME).storeResultsTo(result); return result; } @@ -49,7 +49,7 @@ namespace thermometer { class factory_proxy { public: - static constexpr const char* interfaceName = "org.sdbuscpp.stresstests.fahrenheit.thermometer.factory"; + static constexpr const char* INTERFACE_NAME = "org.sdbuscpp.stresstests.fahrenheit.thermometer.factory"; protected: factory_proxy(sdbus::IProxy& proxy) @@ -61,13 +61,13 @@ public: sdbus::ObjectPath createDelegateObject() { sdbus::ObjectPath result; - proxy_.callMethod("createDelegateObject").onInterface(interfaceName).storeResultsTo(result); + proxy_.callMethod("createDelegateObject").onInterface(INTERFACE_NAME).storeResultsTo(result); return result; } void destroyDelegateObject(const sdbus::ObjectPath& delegate) { - proxy_.callMethod("destroyDelegateObject").onInterface(interfaceName).withArguments(delegate).dontExpectReply(); + proxy_.callMethod("destroyDelegateObject").onInterface(INTERFACE_NAME).withArguments(delegate).dontExpectReply(); } private: diff --git a/tests/unittests/mocks/SdBusMock.h b/tests/unittests/mocks/SdBusMock.h index 91c72f4..da37595 100644 --- a/tests/unittests/mocks/SdBusMock.h +++ b/tests/unittests/mocks/SdBusMock.h @@ -51,6 +51,7 @@ public: MOCK_METHOD3(sd_bus_request_name, int(sd_bus *bus, const char *name, uint64_t flags)); MOCK_METHOD2(sd_bus_release_name, int(sd_bus *bus, const char *name)); MOCK_METHOD6(sd_bus_add_object_vtable, int(sd_bus *bus, sd_bus_slot **slot, const char *path, const char *interface, const sd_bus_vtable *vtable, void *userdata)); + MOCK_METHOD3(sd_bus_add_object_manager, int(sd_bus *bus, sd_bus_slot **slot, const char *path)); MOCK_METHOD5(sd_bus_add_match, int(sd_bus *bus, sd_bus_slot **slot, const char *match, sd_bus_message_handler_t callback, void *userdata)); MOCK_METHOD1(sd_bus_slot_unref, sd_bus_slot*(sd_bus_slot *slot)); diff --git a/tools/xml2cpp-codegen/AdaptorGenerator.cpp b/tools/xml2cpp-codegen/AdaptorGenerator.cpp index 056caa5..fafe3e5 100644 --- a/tools/xml2cpp-codegen/AdaptorGenerator.cpp +++ b/tools/xml2cpp-codegen/AdaptorGenerator.cpp @@ -80,7 +80,7 @@ std::string AdaptorGenerator::processInterface(Node& interface) const body << "class " << className << endl << "{" << endl << "public:" << endl - << tab << "static constexpr const char* interfaceName = \"" << ifaceName << "\";" << endl << endl + << tab << "static constexpr const char* INTERFACE_NAME = \"" << ifaceName << "\";" << endl << endl << "protected:" << endl << tab << className << "(sdbus::IObject& object)" << endl << tab << tab << ": object_(object)" << endl; @@ -109,7 +109,7 @@ std::string AdaptorGenerator::processInterface(Node& interface) const if(!annotationRegistration.empty()) { std::stringstream str; - str << tab << tab << "object_.setInterfaceFlags(interfaceName)" << annotationRegistration << ";" << endl; + str << tab << tab << "object_.setInterfaceFlags(INTERFACE_NAME)" << annotationRegistration << ";" << endl; annotationRegistration = str.str(); } @@ -207,7 +207,7 @@ std::tuple AdaptorGenerator::processMethods(const Node registrationSS << tab << tab << "object_.registerMethod(\"" << methodName << "\")" - << ".onInterface(interfaceName)" + << ".onInterface(INTERFACE_NAME)" << ".implementedAs(" << "[this](" << (async ? "sdbus::Result<" + outArgsToType(outArgs, true) + ">&& result" + (argTypeStr.empty() ? "" : ", ") : "") @@ -260,7 +260,7 @@ std::tuple AdaptorGenerator::processSignals(const Node signalRegistrationSS << tab << tab << "object_.registerSignal(\"" << name << "\")" - ".onInterface(interfaceName)"; + ".onInterface(INTERFACE_NAME)"; if (args.size() > 0) { @@ -273,7 +273,7 @@ std::tuple AdaptorGenerator::processSignals(const Node signalMethodSS << tab << "void " << name << "(" << argTypeStr << ")" << endl << tab << "{" << endl << tab << tab << "object_.emitSignal(\"" << name << "\")" - ".onInterface(interfaceName)"; + ".onInterface(INTERFACE_NAME)"; if (!argStr.empty()) { @@ -322,7 +322,7 @@ std::tuple AdaptorGenerator::processProperties(const N registrationSS << tab << tab << "object_.registerProperty(\"" << propertyName << "\")" - << ".onInterface(interfaceName)"; + << ".onInterface(INTERFACE_NAME)"; if (propertyAccess == "read" || propertyAccess == "readwrite") { diff --git a/tools/xml2cpp-codegen/ProxyGenerator.cpp b/tools/xml2cpp-codegen/ProxyGenerator.cpp index 2c5f572..c2f4f58 100644 --- a/tools/xml2cpp-codegen/ProxyGenerator.cpp +++ b/tools/xml2cpp-codegen/ProxyGenerator.cpp @@ -80,7 +80,7 @@ std::string ProxyGenerator::processInterface(Node& interface) const body << "class " << className << endl << "{" << endl << "public:" << endl - << tab << "static constexpr const char* interfaceName = \"" << ifaceName << "\";" << endl << endl + << tab << "static constexpr const char* INTERFACE_NAME = \"" << ifaceName << "\";" << endl << endl << "protected:" << endl << tab << className << "(sdbus::IProxy& proxy)" << endl << tab << tab << ": proxy_(proxy)" << endl; @@ -169,7 +169,7 @@ std::tuple ProxyGenerator::processMethods(const Nodes& } definitionSS << tab << tab << "proxy_.callMethod" << (async ? "Async" : "") << "(\"" << name << "\")" - ".onInterface(interfaceName)"; + ".onInterface(INTERFACE_NAME)"; if (inArgs.size() > 0) { @@ -220,7 +220,7 @@ std::tuple ProxyGenerator::processSignals(const Nodes& registrationSS << tab << tab << "proxy_" ".uponSignal(\"" << name << "\")" - ".onInterface(interfaceName)" + ".onInterface(INTERFACE_NAME)" ".call([this](" << argTypeStr << ")" "{ this->on" << nameBigFirst << "(" << argStr << "); });" << endl; @@ -248,7 +248,7 @@ std::string ProxyGenerator::processProperties(const Nodes& properties) const propertySS << tab << propertyType << " " << propertyName << "()" << endl << tab << "{" << endl; propertySS << tab << tab << "return proxy_.getProperty(\"" << propertyName << "\")" - ".onInterface(interfaceName)"; + ".onInterface(INTERFACE_NAME)"; propertySS << ";" << endl << tab << "}" << endl << endl; } @@ -257,7 +257,7 @@ std::string ProxyGenerator::processProperties(const Nodes& properties) const propertySS << tab << "void " << propertyName << "(" << propertyTypeArg << ")" << endl << tab << "{" << endl; propertySS << tab << tab << "proxy_.setProperty(\"" << propertyName << "\")" - ".onInterface(interfaceName)" + ".onInterface(INTERFACE_NAME)" ".toValue(" << propertyArg << ")"; propertySS << ";" << endl << tab << "}" << endl << endl; }