Add support for method and signal parameter names in introspection

This commit is contained in:
sangelovic
2020-01-27 07:57:38 +01:00
committed by Stanislav Angelovič
parent 10977c6137
commit eade6a0e44
16 changed files with 329 additions and 110 deletions

View File

@ -31,6 +31,7 @@
#include <sdbus-c++/TypeTraits.h> #include <sdbus-c++/TypeTraits.h>
#include <sdbus-c++/Flags.h> #include <sdbus-c++/Flags.h>
#include <string> #include <string>
#include <vector>
#include <type_traits> #include <type_traits>
#include <chrono> #include <chrono>
#include <cstdint> #include <cstdint>
@ -45,6 +46,9 @@ namespace sdbus {
namespace sdbus { namespace sdbus {
template <typename... _Args>
inline constexpr bool are_strings_v = std::conjunction<std::is_convertible<_Args, std::string>...>::value;
class MethodRegistrator class MethodRegistrator
{ {
public: public:
@ -57,6 +61,12 @@ namespace sdbus {
std::enable_if_t<!is_async_method_v<_Function>, MethodRegistrator&> implementedAs(_Function&& callback); std::enable_if_t<!is_async_method_v<_Function>, MethodRegistrator&> implementedAs(_Function&& callback);
template <typename _Function> template <typename _Function>
std::enable_if_t<is_async_method_v<_Function>, MethodRegistrator&> implementedAs(_Function&& callback); std::enable_if_t<is_async_method_v<_Function>, MethodRegistrator&> implementedAs(_Function&& callback);
MethodRegistrator& withInputParamNames(std::vector<std::string> paramNames);
template <typename... _String>
std::enable_if_t<are_strings_v<_String...>, MethodRegistrator&> withInputParamNames(_String... paramNames);
MethodRegistrator& withOutputParamNames(std::vector<std::string> paramNames);
template <typename... _String>
std::enable_if_t<are_strings_v<_String...>, MethodRegistrator&> withOutputParamNames(_String... paramNames);
MethodRegistrator& markAsDeprecated(); MethodRegistrator& markAsDeprecated();
MethodRegistrator& markAsPrivileged(); MethodRegistrator& markAsPrivileged();
MethodRegistrator& withNoReply(); MethodRegistrator& withNoReply();
@ -66,7 +76,9 @@ namespace sdbus {
const std::string& methodName_; const std::string& methodName_;
std::string interfaceName_; std::string interfaceName_;
std::string inputSignature_; std::string inputSignature_;
std::vector<std::string> inputParamNames_;
std::string outputSignature_; std::string outputSignature_;
std::vector<std::string> outputParamNames_;
method_callback methodCallback_; method_callback methodCallback_;
Flags flags_; Flags flags_;
int exceptions_{}; // Number of active exceptions when SignalRegistrator is constructed int exceptions_{}; // Number of active exceptions when SignalRegistrator is constructed
@ -81,6 +93,9 @@ namespace sdbus {
SignalRegistrator& onInterface(std::string interfaceName); SignalRegistrator& onInterface(std::string interfaceName);
template <typename... _Args> SignalRegistrator& withParameters(); template <typename... _Args> SignalRegistrator& withParameters();
template <typename... _Args> SignalRegistrator& withParameters(std::vector<std::string> paramNames);
template <typename... _Args, typename... _String>
std::enable_if_t<are_strings_v<_String...>, SignalRegistrator&> withParameters(_String... paramNames);
SignalRegistrator& markAsDeprecated(); SignalRegistrator& markAsDeprecated();
private: private:
@ -88,6 +103,7 @@ namespace sdbus {
const std::string& signalName_; const std::string& signalName_;
std::string interfaceName_; std::string interfaceName_;
std::string signalSignature_; std::string signalSignature_;
std::vector<std::string> paramNames_;
Flags flags_; Flags flags_;
int exceptions_{}; // Number of active exceptions when SignalRegistrator is constructed int exceptions_{}; // Number of active exceptions when SignalRegistrator is constructed
}; };

View File

@ -70,7 +70,14 @@ namespace sdbus {
// Therefore, we can allow registerMethod() to throw even if we are in the destructor. // Therefore, we can allow registerMethod() to throw even if we are in the destructor.
// Bottomline is, to be on the safe side, the caller must take care of catching and reacting // Bottomline is, to be on the safe side, the caller must take care of catching and reacting
// to the exception thrown from here if the caller is a destructor itself. // to the exception thrown from here if the caller is a destructor itself.
object_.registerMethod(interfaceName_, methodName_, inputSignature_, outputSignature_, std::move(methodCallback_), flags_); object_.registerMethod( interfaceName_
, std::move(methodName_)
, std::move(inputSignature_)
, std::move(inputParamNames_)
, std::move(outputSignature_)
, std::move(outputParamNames_)
, std::move(methodCallback_)
, std::move(flags_));
} }
inline MethodRegistrator& MethodRegistrator::onInterface(std::string interfaceName) inline MethodRegistrator& MethodRegistrator::onInterface(std::string interfaceName)
@ -81,7 +88,8 @@ namespace sdbus {
} }
template <typename _Function> template <typename _Function>
inline std::enable_if_t<!is_async_method_v<_Function>, MethodRegistrator&> MethodRegistrator::implementedAs(_Function&& callback) inline std::enable_if_t<!is_async_method_v<_Function>, MethodRegistrator&>
MethodRegistrator::implementedAs(_Function&& callback)
{ {
inputSignature_ = signature_of_function_input_arguments<_Function>::str(); inputSignature_ = signature_of_function_input_arguments<_Function>::str();
outputSignature_ = signature_of_function_output_arguments<_Function>::str(); outputSignature_ = signature_of_function_output_arguments<_Function>::str();
@ -110,7 +118,8 @@ namespace sdbus {
} }
template <typename _Function> template <typename _Function>
inline std::enable_if_t<is_async_method_v<_Function>, MethodRegistrator&> MethodRegistrator::implementedAs(_Function&& callback) inline std::enable_if_t<is_async_method_v<_Function>, MethodRegistrator&>
MethodRegistrator::implementedAs(_Function&& callback)
{ {
inputSignature_ = signature_of_function_input_arguments<_Function>::str(); inputSignature_ = signature_of_function_input_arguments<_Function>::str();
outputSignature_ = signature_of_function_output_arguments<_Function>::str(); outputSignature_ = signature_of_function_output_arguments<_Function>::str();
@ -130,6 +139,32 @@ namespace sdbus {
return *this; return *this;
} }
inline MethodRegistrator& MethodRegistrator::withInputParamNames(std::vector<std::string> paramNames)
{
inputParamNames_ = std::move(paramNames);
return *this;
}
template <typename... _String>
inline std::enable_if_t<are_strings_v<_String...>, MethodRegistrator&> MethodRegistrator::withInputParamNames(_String... paramNames)
{
return withInputParamNames({paramNames...});
}
inline MethodRegistrator& MethodRegistrator::withOutputParamNames(std::vector<std::string> paramNames)
{
outputParamNames_ = std::move(paramNames);
return *this;
}
template <typename... _String>
inline std::enable_if_t<are_strings_v<_String...>, MethodRegistrator&> MethodRegistrator::withOutputParamNames(_String... paramNames)
{
return withOutputParamNames({paramNames...});
}
inline MethodRegistrator& MethodRegistrator::markAsDeprecated() inline MethodRegistrator& MethodRegistrator::markAsDeprecated()
{ {
flags_.set(Flags::DEPRECATED); flags_.set(Flags::DEPRECATED);
@ -179,7 +214,11 @@ namespace sdbus {
// Therefore, we can allow registerSignal() to throw even if we are in the destructor. // Therefore, we can allow registerSignal() to throw even if we are in the destructor.
// Bottomline is, to be on the safe side, the caller must take care of catching and reacting // Bottomline is, to be on the safe side, the caller must take care of catching and reacting
// to the exception thrown from here if the caller is a destructor itself. // to the exception thrown from here if the caller is a destructor itself.
object_.registerSignal(interfaceName_, signalName_, signalSignature_, flags_); object_.registerSignal( interfaceName_
, std::move(signalName_)
, std::move(signalSignature_)
, std::move(paramNames_)
, std::move(flags_) );
} }
inline SignalRegistrator& SignalRegistrator::onInterface(std::string interfaceName) inline SignalRegistrator& SignalRegistrator::onInterface(std::string interfaceName)
@ -197,6 +236,23 @@ namespace sdbus {
return *this; return *this;
} }
template <typename... _Args>
inline SignalRegistrator& SignalRegistrator::withParameters(std::vector<std::string> paramNames)
{
paramNames_ = std::move(paramNames);
return withParameters<_Args...>();
}
template <typename... _Args, typename... _String>
inline std::enable_if_t<are_strings_v<_String...>, SignalRegistrator&>
SignalRegistrator::withParameters(_String... paramNames)
{
static_assert(sizeof...(_Args) == sizeof...(_String), "Numbers of signal parameters and their names don't match");
return withParameters<_Args...>({paramNames...});
}
inline SignalRegistrator& SignalRegistrator::markAsDeprecated() inline SignalRegistrator& SignalRegistrator::markAsDeprecated()
{ {
flags_.set(Flags::DEPRECATED); flags_.set(Flags::DEPRECATED);

View File

@ -74,9 +74,37 @@ namespace sdbus {
* @throws sdbus::Error in case of failure * @throws sdbus::Error in case of failure
*/ */
virtual void registerMethod( const std::string& interfaceName virtual void registerMethod( const std::string& interfaceName
, const std::string& methodName , std::string methodName
, const std::string& inputSignature , std::string inputSignature
, const std::string& outputSignature , std::string outputSignature
, method_callback methodCallback
, Flags flags = {} ) = 0;
/*!
* @brief Registers method that the object will provide on D-Bus
*
* @param[in] interfaceName Name of an interface that the method will belong to
* @param[in] methodName Name of the method
* @param[in] inputSignature D-Bus signature of method input parameters
* @param[in] inputNames Names of input parameters
* @param[in] outputSignature D-Bus signature of method output parameters
* @param[in] outputNames Names of output parameters
* @param[in] methodCallback Callback that implements the body of the method
* @param[in] flags D-Bus method flags (privileged, deprecated, or no reply)
*
* Provided names of input and output parameters will be included in the introspection
* description (given that at least version 242 of underlying libsystemd library is
* used; otherwise, names of parameters are ignored). This usually helps better describe
* the API to the introspector.
*
* @throws sdbus::Error in case of failure
*/
virtual void registerMethod( const std::string& interfaceName
, std::string methodName
, std::string inputSignature
, const std::vector<std::string>& inputNames
, std::string outputSignature
, const std::vector<std::string>& outputNames
, method_callback methodCallback , method_callback methodCallback
, Flags flags = {} ) = 0; , Flags flags = {} ) = 0;
@ -91,8 +119,30 @@ namespace sdbus {
* @throws sdbus::Error in case of failure * @throws sdbus::Error in case of failure
*/ */
virtual void registerSignal( const std::string& interfaceName virtual void registerSignal( const std::string& interfaceName
, const std::string& signalName , std::string signalName
, const std::string& signature , std::string signature
, Flags flags = {} ) = 0;
/*!
* @brief Registers signal that the object will emit on D-Bus
*
* @param[in] interfaceName Name of an interface that the signal will fall under
* @param[in] signalName Name of the signal
* @param[in] signature D-Bus signature of signal parameters
* @param[in] paramNames Names of parameters of the signal
* @param[in] flags D-Bus signal flags (deprecated)
*
* Provided names of signal output parameters will be included in the introspection
* description (given that at least version 242 of underlying libsystemd library is
* used; otherwise, names of parameters are ignored). This usually helps better describe
* the API to the introspector.
*
* @throws sdbus::Error in case of failure
*/
virtual void registerSignal( const std::string& interfaceName
, std::string signalName
, std::string signature
, const std::vector<std::string>& paramNames
, Flags flags = {} ) = 0; , Flags flags = {} ) = 0;
/*! /*!
@ -107,8 +157,8 @@ namespace sdbus {
* @throws sdbus::Error in case of failure * @throws sdbus::Error in case of failure
*/ */
virtual void registerProperty( const std::string& interfaceName virtual void registerProperty( const std::string& interfaceName
, const std::string& propertyName , std::string propertyName
, const std::string& signature , std::string signature
, property_get_callback getCallback , property_get_callback getCallback
, Flags flags = {} ) = 0; , Flags flags = {} ) = 0;
@ -125,8 +175,8 @@ namespace sdbus {
* @throws sdbus::Error in case of failure * @throws sdbus::Error in case of failure
*/ */
virtual void registerProperty( const std::string& interfaceName virtual void registerProperty( const std::string& interfaceName
, const std::string& propertyName , std::string propertyName
, const std::string& signature , std::string signature
, property_get_callback getCallback , property_get_callback getCallback
, property_set_callback setCallback , property_set_callback setCallback
, Flags flags = {} ) = 0; , Flags flags = {} ) = 0;

View File

@ -45,51 +45,83 @@ Object::Object(sdbus::internal::IConnection& connection, std::string objectPath)
} }
void Object::registerMethod( const std::string& interfaceName void Object::registerMethod( const std::string& interfaceName
, const std::string& methodName , std::string methodName
, const std::string& inputSignature , std::string inputSignature
, const std::string& outputSignature , std::string outputSignature
, method_callback methodCallback
, Flags flags )
{
registerMethod( interfaceName
, std::move(methodName)
, std::move(inputSignature)
, {}
, std::move(outputSignature)
, {}
, std::move(methodCallback)
, std::move(flags) );
}
void Object::registerMethod( const std::string& interfaceName
, std::string methodName
, std::string inputSignature
, const std::vector<std::string>& inputNames
, std::string outputSignature
, const std::vector<std::string>& outputNames
, method_callback methodCallback , method_callback methodCallback
, Flags flags ) , Flags flags )
{ {
SDBUS_THROW_ERROR_IF(!methodCallback, "Invalid method callback provided", EINVAL); SDBUS_THROW_ERROR_IF(!methodCallback, "Invalid method callback provided", EINVAL);
auto& interface = interfaces_[interfaceName]; auto& interface = interfaces_[interfaceName];
InterfaceData::MethodData methodData{inputSignature, outputSignature, std::move(methodCallback), flags}; InterfaceData::MethodData methodData{ std::move(inputSignature)
auto inserted = interface.methods_.emplace(methodName, std::move(methodData)).second; , std::move(outputSignature)
, paramNamesToString(inputNames) + paramNamesToString(outputNames)
, std::move(methodCallback)
, std::move(flags) };
auto inserted = interface.methods.emplace(std::move(methodName), std::move(methodData)).second;
SDBUS_THROW_ERROR_IF(!inserted, "Failed to register method: method already exists", EINVAL); SDBUS_THROW_ERROR_IF(!inserted, "Failed to register method: method already exists", EINVAL);
} }
void Object::registerSignal( const std::string& interfaceName void Object::registerSignal( const std::string& interfaceName
, const std::string& signalName , std::string signalName
, const std::string& signature , std::string signature
, Flags flags )
{
registerSignal(interfaceName, std::move(signalName), std::move(signature), {}, std::move(flags));
}
void Object::registerSignal( const std::string& interfaceName
, std::string signalName
, std::string signature
, const std::vector<std::string>& paramNames
, Flags flags ) , Flags flags )
{ {
auto& interface = interfaces_[interfaceName]; auto& interface = interfaces_[interfaceName];
InterfaceData::SignalData signalData{signature, flags}; InterfaceData::SignalData signalData{std::move(signature), paramNamesToString(paramNames), std::move(flags)};
auto inserted = interface.signals_.emplace(signalName, std::move(signalData)).second; auto inserted = interface.signals.emplace(std::move(signalName), std::move(signalData)).second;
SDBUS_THROW_ERROR_IF(!inserted, "Failed to register signal: signal already exists", EINVAL); SDBUS_THROW_ERROR_IF(!inserted, "Failed to register signal: signal already exists", EINVAL);
} }
void Object::registerProperty( const std::string& interfaceName void Object::registerProperty( const std::string& interfaceName
, const std::string& propertyName , std::string propertyName
, const std::string& signature , std::string signature
, property_get_callback getCallback , property_get_callback getCallback
, Flags flags ) , Flags flags )
{ {
registerProperty( interfaceName registerProperty( interfaceName
, propertyName , std::move(propertyName)
, signature , std::move(signature)
, getCallback , std::move(getCallback)
, property_set_callback{} , {}
, flags ); , std::move(flags) );
} }
void Object::registerProperty( const std::string& interfaceName void Object::registerProperty( const std::string& interfaceName
, const std::string& propertyName , std::string propertyName
, const std::string& signature , std::string signature
, property_get_callback getCallback , property_get_callback getCallback
, property_set_callback setCallback , property_set_callback setCallback
, Flags flags ) , Flags flags )
@ -98,8 +130,11 @@ void Object::registerProperty( const std::string& interfaceName
auto& interface = interfaces_[interfaceName]; auto& interface = interfaces_[interfaceName];
InterfaceData::PropertyData propertyData{signature, std::move(getCallback), std::move(setCallback), flags}; InterfaceData::PropertyData propertyData{ std::move(signature)
auto inserted = interface.properties_.emplace(propertyName, std::move(propertyData)).second; , std::move(getCallback)
, std::move(setCallback)
, std::move(flags)};
auto inserted = interface.properties.emplace(std::move(propertyName), std::move(propertyData)).second;
SDBUS_THROW_ERROR_IF(!inserted, "Failed to register property: property already exists", EINVAL); SDBUS_THROW_ERROR_IF(!inserted, "Failed to register property: property already exists", EINVAL);
} }
@ -107,7 +142,7 @@ void Object::registerProperty( const std::string& interfaceName
void Object::setInterfaceFlags(const std::string& interfaceName, Flags flags) void Object::setInterfaceFlags(const std::string& interfaceName, Flags flags)
{ {
auto& interface = interfaces_[interfaceName]; auto& interface = interfaces_[interfaceName];
interface.flags_ = flags; interface.flags = flags;
} }
void Object::finishRegistration() void Object::finishRegistration()
@ -192,10 +227,10 @@ sdbus::IConnection& Object::getConnection() const
const std::vector<sd_bus_vtable>& Object::createInterfaceVTable(InterfaceData& interfaceData) const std::vector<sd_bus_vtable>& Object::createInterfaceVTable(InterfaceData& interfaceData)
{ {
auto& vtable = interfaceData.vtable_; auto& vtable = interfaceData.vtable;
assert(vtable.empty()); assert(vtable.empty());
vtable.push_back(createVTableStartItem(interfaceData.flags_.toSdBusInterfaceFlags())); vtable.push_back(createVTableStartItem(interfaceData.flags.toSdBusInterfaceFlags()));
registerMethodsToVTable(interfaceData, vtable); registerMethodsToVTable(interfaceData, vtable);
registerSignalsToVTable(interfaceData, vtable); registerSignalsToVTable(interfaceData, vtable);
registerPropertiesToVTable(interfaceData, vtable); registerPropertiesToVTable(interfaceData, vtable);
@ -206,14 +241,15 @@ const std::vector<sd_bus_vtable>& Object::createInterfaceVTable(InterfaceData& i
void Object::registerMethodsToVTable(const InterfaceData& interfaceData, std::vector<sd_bus_vtable>& vtable) void Object::registerMethodsToVTable(const InterfaceData& interfaceData, std::vector<sd_bus_vtable>& vtable)
{ {
for (const auto& item : interfaceData.methods_) for (const auto& item : interfaceData.methods)
{ {
const auto& methodName = item.first; const auto& methodName = item.first;
const auto& methodData = item.second; const auto& methodData = item.second;
vtable.push_back(createVTableMethodItem( methodName.c_str() vtable.push_back(createVTableMethodItem( methodName.c_str()
, methodData.inputArgs_.c_str() , methodData.inputArgs.c_str()
, methodData.outputArgs_.c_str() , methodData.outputArgs.c_str()
, methodData.paramNames.c_str()
, &Object::sdbus_method_callback , &Object::sdbus_method_callback
, methodData.flags_.toSdBusMethodFlags() )); , methodData.flags_.toSdBusMethodFlags() ));
} }
@ -221,35 +257,36 @@ void Object::registerMethodsToVTable(const InterfaceData& interfaceData, std::ve
void Object::registerSignalsToVTable(const InterfaceData& interfaceData, std::vector<sd_bus_vtable>& vtable) void Object::registerSignalsToVTable(const InterfaceData& interfaceData, std::vector<sd_bus_vtable>& vtable)
{ {
for (const auto& item : interfaceData.signals_) for (const auto& item : interfaceData.signals)
{ {
const auto& signalName = item.first; const auto& signalName = item.first;
const auto& signalData = item.second; const auto& signalData = item.second;
vtable.push_back(createVTableSignalItem( signalName.c_str() vtable.push_back(createVTableSignalItem( signalName.c_str()
, signalData.signature_.c_str() , signalData.signature.c_str()
, signalData.flags_.toSdBusSignalFlags() )); , signalData.paramNames.c_str()
, signalData.flags.toSdBusSignalFlags() ));
} }
} }
void Object::registerPropertiesToVTable(const InterfaceData& interfaceData, std::vector<sd_bus_vtable>& vtable) void Object::registerPropertiesToVTable(const InterfaceData& interfaceData, std::vector<sd_bus_vtable>& vtable)
{ {
for (const auto& item : interfaceData.properties_) for (const auto& item : interfaceData.properties)
{ {
const auto& propertyName = item.first; const auto& propertyName = item.first;
const auto& propertyData = item.second; const auto& propertyData = item.second;
if (!propertyData.setCallback_) if (!propertyData.setCallback)
vtable.push_back(createVTablePropertyItem( propertyName.c_str() vtable.push_back(createVTablePropertyItem( propertyName.c_str()
, propertyData.signature_.c_str() , propertyData.signature.c_str()
, &Object::sdbus_property_get_callback , &Object::sdbus_property_get_callback
, propertyData.flags_.toSdBusPropertyFlags() )); , propertyData.flags.toSdBusPropertyFlags() ));
else else
vtable.push_back(createVTableWritablePropertyItem( propertyName.c_str() vtable.push_back(createVTableWritablePropertyItem( propertyName.c_str()
, propertyData.signature_.c_str() , propertyData.signature.c_str()
, &Object::sdbus_property_get_callback , &Object::sdbus_property_get_callback
, &Object::sdbus_property_set_callback , &Object::sdbus_property_set_callback
, propertyData.flags_.toSdBusWritablePropertyFlags() )); , propertyData.flags.toSdBusWritablePropertyFlags() ));
} }
} }
@ -257,7 +294,15 @@ void Object::activateInterfaceVTable( const std::string& interfaceName
, InterfaceData& interfaceData , InterfaceData& interfaceData
, const std::vector<sd_bus_vtable>& vtable ) , const std::vector<sd_bus_vtable>& vtable )
{ {
interfaceData.slot_ = connection_.addObjectVTable(objectPath_, interfaceName, &vtable[0], this); interfaceData.slot = connection_.addObjectVTable(objectPath_, interfaceName, &vtable[0], this);
}
std::string Object::paramNamesToString(const std::vector<std::string>& paramNames)
{
std::string names;
for (const auto& name : paramNames)
names += name + '\0';
return names;
} }
int Object::sdbus_method_callback(sd_bus_message *sdbusMessage, void *userData, sd_bus_error *retError) int Object::sdbus_method_callback(sd_bus_message *sdbusMessage, void *userData, sd_bus_error *retError)
@ -268,7 +313,7 @@ int Object::sdbus_method_callback(sd_bus_message *sdbusMessage, void *userData,
auto message = Message::Factory::create<MethodCall>(sdbusMessage, &object->connection_.getSdBusInterface()); auto message = Message::Factory::create<MethodCall>(sdbusMessage, &object->connection_.getSdBusInterface());
// Note: The lookup can be optimized by using sorted vectors instead of associative containers // Note: The lookup can be optimized by using sorted vectors instead of associative containers
auto& callback = object->interfaces_[message.getInterfaceName()].methods_[message.getMemberName()].callback_; auto& callback = object->interfaces_[message.getInterfaceName()].methods[message.getMemberName()].callback;
assert(callback); assert(callback);
try try
@ -295,7 +340,7 @@ int Object::sdbus_property_get_callback( sd_bus */*bus*/
assert(object != nullptr); assert(object != nullptr);
// Note: The lookup can be optimized by using sorted vectors instead of associative containers // Note: The lookup can be optimized by using sorted vectors instead of associative containers
auto& callback = object->interfaces_[interface].properties_[property].getCallback_; auto& callback = object->interfaces_[interface].properties[property].getCallback;
// Getter can be empty - the case of "write-only" property // Getter can be empty - the case of "write-only" property
if (!callback) if (!callback)
{ {
@ -329,7 +374,7 @@ int Object::sdbus_property_set_callback( sd_bus */*bus*/
assert(object != nullptr); assert(object != nullptr);
// Note: The lookup can be optimized by using sorted vectors instead of associative containers // Note: The lookup can be optimized by using sorted vectors instead of associative containers
auto& callback = object->interfaces_[interface].properties_[property].setCallback_; auto& callback = object->interfaces_[interface].properties[property].setCallback;
assert(callback); assert(callback);
auto value = Message::Factory::create<PropertySetCall>(sdbusValue, &object->connection_.getSdBusInterface()); auto value = Message::Factory::create<PropertySetCall>(sdbusValue, &object->connection_.getSdBusInterface());

View File

@ -47,26 +47,38 @@ namespace internal {
Object(sdbus::internal::IConnection& connection, std::string objectPath); Object(sdbus::internal::IConnection& connection, std::string objectPath);
void registerMethod( const std::string& interfaceName void registerMethod( const std::string& interfaceName
, const std::string& methodName , std::string methodName
, const std::string& inputSignature , std::string inputSignature
, const std::string& outputSignature , std::string outputSignature
, method_callback methodCallback
, Flags flags ) override;
void registerMethod( const std::string& interfaceName
, std::string methodName
, std::string inputSignature
, const std::vector<std::string>& inputNames
, std::string outputSignature
, const std::vector<std::string>& outputNames
, method_callback methodCallback , method_callback methodCallback
, Flags flags ) override; , Flags flags ) override;
void registerSignal( const std::string& interfaceName void registerSignal( const std::string& interfaceName
, const std::string& signalName , std::string signalName
, const std::string& signature , std::string signature
, Flags flags ) override;
void registerSignal( const std::string& interfaceName
, std::string signalName
, std::string signature
, const std::vector<std::string>& paramNames
, Flags flags ) override; , Flags flags ) override;
void registerProperty( const std::string& interfaceName void registerProperty( const std::string& interfaceName
, const std::string& propertyName , std::string propertyName
, const std::string& signature , std::string signature
, property_get_callback getCallback , property_get_callback getCallback
, Flags flags ) override; , Flags flags ) override;
void registerProperty( const std::string& interfaceName void registerProperty( const std::string& interfaceName
, const std::string& propertyName , std::string propertyName
, const std::string& signature , std::string signature
, property_get_callback getCallback , property_get_callback getCallback
, property_set_callback setCallback , property_set_callback setCallback
, Flags flags ) override; , Flags flags ) override;
@ -98,32 +110,34 @@ namespace internal {
using MethodName = std::string; using MethodName = std::string;
struct MethodData struct MethodData
{ {
std::string inputArgs_; const std::string inputArgs;
std::string outputArgs_; const std::string outputArgs;
method_callback callback_; const std::string paramNames;
method_callback callback;
Flags flags_; Flags flags_;
}; };
std::map<MethodName, MethodData> methods_; std::map<MethodName, MethodData> methods;
using SignalName = std::string; using SignalName = std::string;
struct SignalData struct SignalData
{ {
std::string signature_; const std::string signature;
Flags flags_; const std::string paramNames;
Flags flags;
}; };
std::map<SignalName, SignalData> signals_; std::map<SignalName, SignalData> signals;
using PropertyName = std::string; using PropertyName = std::string;
struct PropertyData struct PropertyData
{ {
std::string signature_; const std::string signature;
property_get_callback getCallback_; property_get_callback getCallback;
property_set_callback setCallback_; property_set_callback setCallback;
Flags flags_; Flags flags;
}; };
std::map<PropertyName, PropertyData> properties_; std::map<PropertyName, PropertyData> properties;
std::vector<sd_bus_vtable> vtable_; std::vector<sd_bus_vtable> vtable;
Flags flags_; Flags flags;
SlotPtr slot_; SlotPtr slot;
}; };
static const std::vector<sd_bus_vtable>& createInterfaceVTable(InterfaceData& interfaceData); static const std::vector<sd_bus_vtable>& createInterfaceVTable(InterfaceData& interfaceData);
@ -133,6 +147,7 @@ namespace internal {
void activateInterfaceVTable( const std::string& interfaceName void activateInterfaceVTable( const std::string& interfaceName
, InterfaceData& interfaceData , InterfaceData& interfaceData
, const std::vector<sd_bus_vtable>& vtable ); , const std::vector<sd_bus_vtable>& vtable );
static std::string paramNamesToString(const std::vector<std::string>& paramNames);
static int sdbus_method_callback(sd_bus_message *sdbusMessage, void *userData, sd_bus_error *retError); static int sdbus_method_callback(sd_bus_message *sdbusMessage, void *userData, sd_bus_error *retError);
static int sdbus_property_get_callback( sd_bus *bus static int sdbus_property_get_callback( sd_bus *bus

View File

@ -36,18 +36,46 @@ sd_bus_vtable createVTableStartItem(uint64_t flags)
sd_bus_vtable createVTableMethodItem( const char *member sd_bus_vtable createVTableMethodItem( const char *member
, const char *signature , const char *signature
, const char *result , const char *result
, const char *paramNames
, sd_bus_message_handler_t handler , sd_bus_message_handler_t handler
, uint64_t flags ) , uint64_t flags )
{ {
#if LIBSYSTEMD_VERSION>=242
// We have to expand macro SD_BUS_METHOD_WITH_NAMES manually here, because the macro expects literal char strings
/*struct sd_bus_vtable vtableItem = SD_BUS_METHOD_WITH_NAMES(member, signature, innames, result, outnames, handler, flags);*/
struct sd_bus_vtable vtableItem =
{
.type = _SD_BUS_VTABLE_METHOD,
.flags = flags,
.x = {
.method = {
.member = member,
.signature = signature,
.result = result,
.handler = handler,
.offset = 0,
.names = paramNames,
},
},
};
#else
(void)paramNames;
struct sd_bus_vtable vtableItem = SD_BUS_METHOD(member, signature, result, handler, flags); struct sd_bus_vtable vtableItem = SD_BUS_METHOD(member, signature, result, handler, flags);
#endif
return vtableItem; return vtableItem;
} }
sd_bus_vtable createVTableSignalItem( const char *member sd_bus_vtable createVTableSignalItem( const char *member
, const char *signature , const char *signature
, const char *outnames
, uint64_t flags ) , uint64_t flags )
{ {
#if LIBSYSTEMD_VERSION>=242
struct sd_bus_vtable vtableItem = SD_BUS_SIGNAL_WITH_NAMES(member, signature, outnames, flags);
#else
(void)outnames;
struct sd_bus_vtable vtableItem = SD_BUS_SIGNAL(member, signature, flags); struct sd_bus_vtable vtableItem = SD_BUS_SIGNAL(member, signature, flags);
#endif
return vtableItem; return vtableItem;
} }

View File

@ -38,10 +38,12 @@ sd_bus_vtable createVTableStartItem(uint64_t flags);
sd_bus_vtable createVTableMethodItem( const char *member sd_bus_vtable createVTableMethodItem( const char *member
, const char *signature , const char *signature
, const char *result , const char *result
, const char *paramNames
, sd_bus_message_handler_t handler , sd_bus_message_handler_t handler
, uint64_t flags ); , uint64_t flags );
sd_bus_vtable createVTableSignalItem( const char *member sd_bus_vtable createVTableSignalItem( const char *member
, const char *signature , const char *signature
, const char *outnames
, uint64_t flags ); , uint64_t flags );
sd_bus_vtable createVTablePropertyItem( const char *member sd_bus_vtable createVTablePropertyItem( const char *member
, const char *signature , const char *signature

View File

@ -60,17 +60,18 @@ protected:
object_.setInterfaceFlags(INTERFACE_NAME).markAsDeprecated().withPropertyUpdateBehavior(sdbus::Flags::EMITS_NO_SIGNAL); object_.setInterfaceFlags(INTERFACE_NAME).markAsDeprecated().withPropertyUpdateBehavior(sdbus::Flags::EMITS_NO_SIGNAL);
object_.registerMethod("noArgNoReturn").onInterface(INTERFACE_NAME).implementedAs([this](){ return this->noArgNoReturn(); }); object_.registerMethod("noArgNoReturn").onInterface(INTERFACE_NAME).implementedAs([this](){ return this->noArgNoReturn(); });
object_.registerMethod("getInt").onInterface(INTERFACE_NAME).implementedAs([this](){ return this->getInt(); }); object_.registerMethod("getInt").onInterface(INTERFACE_NAME).withOutputParamNames("anInt").implementedAs([this](){ return this->getInt(); });
object_.registerMethod("getTuple").onInterface(INTERFACE_NAME).implementedAs([this](){ return this->getTuple(); }); object_.registerMethod("getTuple").onInterface(INTERFACE_NAME).implementedAs([this](){ return this->getTuple(); });
object_.registerMethod("multiply").onInterface(INTERFACE_NAME).implementedAs([this](const int64_t& a, const double& b){ return this->multiply(a, b); }); object_.registerMethod("multiply").onInterface(INTERFACE_NAME).withInputParamNames("a", "b").withOutputParamNames("result").implementedAs([this](const int64_t& a, const double& b){ return this->multiply(a, b); });
object_.registerMethod("multiplyWithNoReply").onInterface(INTERFACE_NAME).implementedAs([this](const int64_t& a, const double& b){ this->multiplyWithNoReply(a, b); }).markAsDeprecated().withNoReply(); object_.registerMethod("multiplyWithNoReply").onInterface(INTERFACE_NAME).implementedAs([this](const int64_t& a, const double& b){ this->multiplyWithNoReply(a, b); }).markAsDeprecated().withNoReply();
object_.registerMethod("getInts16FromStruct").onInterface(INTERFACE_NAME).implementedAs([this]( object_.registerMethod("getInts16FromStruct").onInterface(INTERFACE_NAME).implementedAs([this](
const sdbus::Struct<uint8_t, int16_t, double, std::string, std::vector<int16_t>>& x){ return this->getInts16FromStruct(x); }); const sdbus::Struct<uint8_t, int16_t, double, std::string, std::vector<int16_t>>& x){ return this->getInts16FromStruct(x); });
object_.registerMethod("processVariant").onInterface(INTERFACE_NAME).implementedAs([this](sdbus::Variant& v){ return this->processVariant(v); }); object_.registerMethod("processVariant").onInterface(INTERFACE_NAME).implementedAs([this](sdbus::Variant& v){ return this->processVariant(v); });
object_.registerMethod("getMapOfVariants").onInterface(INTERFACE_NAME).implementedAs([this]( object_.registerMethod("getMapOfVariants").onInterface(INTERFACE_NAME)
.withInputParamNames("x", "y").withOutputParamNames("aMapOfVariants").implementedAs([this](
const std::vector<int32_t>& x, const sdbus::Struct<sdbus::Variant, sdbus::Variant>& y){ return this->getMapOfVariants(x ,y); }); const std::vector<int32_t>& x, const sdbus::Struct<sdbus::Variant, sdbus::Variant>& y){ return this->getMapOfVariants(x ,y); });
object_.registerMethod("getStructInStruct").onInterface(INTERFACE_NAME).implementedAs([this](){ return this->getStructInStruct(); }); object_.registerMethod("getStructInStruct").onInterface(INTERFACE_NAME).implementedAs([this](){ return this->getStructInStruct(); });
@ -110,8 +111,9 @@ protected:
// registration of signals is optional, it is useful because of introspection // registration of signals is optional, it is useful because of introspection
object_.registerSignal("simpleSignal").onInterface(INTERFACE_NAME).markAsDeprecated(); object_.registerSignal("simpleSignal").onInterface(INTERFACE_NAME).markAsDeprecated();
object_.registerSignal("signalWithMap").onInterface(INTERFACE_NAME).withParameters<std::map<int32_t, std::string>>(); // Note: sd-bus of libsystemd up to v244 has a bug where it doesn't generate signal parameter names in introspection XML. Signal param names commented temporarily.
object_.registerSignal("signalWithVariant").onInterface(INTERFACE_NAME).withParameters<sdbus::Variant>(); object_.registerSignal("signalWithMap").onInterface(INTERFACE_NAME).withParameters<std::map<int32_t, std::string>>(/*"aMap"*/);
object_.registerSignal("signalWithVariant").onInterface(INTERFACE_NAME).withParameters<sdbus::Variant>(/*"aVariant"*/);
object_.registerProperty("state").onInterface(INTERFACE_NAME).withGetter([this](){ return this->state(); }).markAsDeprecated().withUpdateBehavior(sdbus::Flags::CONST_PROPERTY_VALUE); 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_INVALIDATION_SIGNAL); 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);
@ -250,16 +252,16 @@ R"delimiter(<!DOCTYPE node PUBLIC "-//freedesktop//DTD D-BUS Object Introspectio
<annotation name="org.freedesktop.DBus.Deprecated" value="true"/> <annotation name="org.freedesktop.DBus.Deprecated" value="true"/>
</method> </method>
<method name="getInt"> <method name="getInt">
<arg type="i" direction="out"/> <arg type="i" name="anInt" direction="out"/>
</method> </method>
<method name="getInts16FromStruct"> <method name="getInts16FromStruct">
<arg type="(yndsan)" direction="in"/> <arg type="(yndsan)" direction="in"/>
<arg type="an" direction="out"/> <arg type="an" direction="out"/>
</method> </method>
<method name="getMapOfVariants"> <method name="getMapOfVariants">
<arg type="ai" direction="in"/> <arg type="ai" name="x" direction="in"/>
<arg type="(vv)" direction="in"/> <arg type="(vv)" name="y" direction="in"/>
<arg type="a{iv}" direction="out"/> <arg type="a{iv}" name="aMapOfVariants" direction="out"/>
</method> </method>
<method name="getObjectPath"> <method name="getObjectPath">
<arg type="o" direction="out"/> <arg type="o" direction="out"/>
@ -278,9 +280,9 @@ R"delimiter(<!DOCTYPE node PUBLIC "-//freedesktop//DTD D-BUS Object Introspectio
<arg type="h" direction="out"/> <arg type="h" direction="out"/>
</method> </method>
<method name="multiply"> <method name="multiply">
<arg type="x" direction="in"/> <arg type="x" name="a" direction="in"/>
<arg type="d" direction="in"/> <arg type="d" name="b" direction="in"/>
<arg type="d" direction="out"/> <arg type="d" name="result" direction="out"/>
</method> </method>
<method name="multiplyWithNoReply"> <method name="multiplyWithNoReply">
<arg type="x" direction="in"/> <arg type="x" direction="in"/>

View File

@ -22,9 +22,9 @@ protected:
perftests_adaptor(sdbus::IObject& object) perftests_adaptor(sdbus::IObject& object)
: object_(object) : object_(object)
{ {
object_.registerMethod("sendDataSignals").onInterface(INTERFACE_NAME).implementedAs([this](const uint32_t& numberOfSignals, const uint32_t& signalMsgSize){ return this->sendDataSignals(numberOfSignals, signalMsgSize); }); object_.registerMethod("sendDataSignals").onInterface(INTERFACE_NAME).withInputParamNames("numberOfSignals", "signalMsgSize").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_.registerMethod("concatenateTwoStrings").onInterface(INTERFACE_NAME).withInputParamNames("string1", "string2").withOutputParamNames("result").implementedAs([this](const std::string& string1, const std::string& string2){ return this->concatenateTwoStrings(string1, string2); });
object_.registerSignal("dataSignal").onInterface(INTERFACE_NAME).withParameters<std::string>(); object_.registerSignal("dataSignal").onInterface(INTERFACE_NAME).withParameters<std::string>("data");
} }
~perftests_adaptor() = default; ~perftests_adaptor() = default;

View File

@ -24,7 +24,7 @@ protected:
thermometer_adaptor(sdbus::IObject& object) thermometer_adaptor(sdbus::IObject& object)
: object_(object) : object_(object)
{ {
object_.registerMethod("getCurrentTemperature").onInterface(INTERFACE_NAME).implementedAs([this](){ return this->getCurrentTemperature(); }); object_.registerMethod("getCurrentTemperature").onInterface(INTERFACE_NAME).withOutputParamNames("result").implementedAs([this](){ return this->getCurrentTemperature(); });
} }
~thermometer_adaptor() = default; ~thermometer_adaptor() = default;

View File

@ -23,8 +23,8 @@ protected:
concatenator_adaptor(sdbus::IObject& object) concatenator_adaptor(sdbus::IObject& object)
: object_(object) : object_(object)
{ {
object_.registerMethod("concatenate").onInterface(INTERFACE_NAME).implementedAs([this](sdbus::Result<std::string>&& result, std::map<std::string, sdbus::Variant> params){ this->concatenate(std::move(result), std::move(params)); }); object_.registerMethod("concatenate").onInterface(INTERFACE_NAME).withInputParamNames("params").withOutputParamNames("result").implementedAs([this](sdbus::Result<std::string>&& result, std::map<std::string, sdbus::Variant> params){ this->concatenate(std::move(result), std::move(params)); });
object_.registerSignal("concatenatedSignal").onInterface(INTERFACE_NAME).withParameters<std::string>(); object_.registerSignal("concatenatedSignal").onInterface(INTERFACE_NAME).withParameters<std::string>("concatenatedString");
} }
~concatenator_adaptor() = default; ~concatenator_adaptor() = default;

View File

@ -24,7 +24,7 @@ protected:
thermometer_adaptor(sdbus::IObject& object) thermometer_adaptor(sdbus::IObject& object)
: object_(object) : object_(object)
{ {
object_.registerMethod("getCurrentTemperature").onInterface(INTERFACE_NAME).implementedAs([this](){ return this->getCurrentTemperature(); }); object_.registerMethod("getCurrentTemperature").onInterface(INTERFACE_NAME).withOutputParamNames("result").implementedAs([this](){ return this->getCurrentTemperature(); });
} }
~thermometer_adaptor() = default; ~thermometer_adaptor() = default;
@ -53,8 +53,8 @@ protected:
factory_adaptor(sdbus::IObject& object) factory_adaptor(sdbus::IObject& object)
: object_(object) : object_(object)
{ {
object_.registerMethod("createDelegateObject").onInterface(INTERFACE_NAME).implementedAs([this](sdbus::Result<sdbus::ObjectPath>&& result){ this->createDelegateObject(std::move(result)); }); object_.registerMethod("createDelegateObject").onInterface(INTERFACE_NAME).withOutputParamNames("delegate").implementedAs([this](sdbus::Result<sdbus::ObjectPath>&& 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(); object_.registerMethod("destroyDelegateObject").onInterface(INTERFACE_NAME).withInputParamNames("delegate").implementedAs([this](sdbus::Result<>&& result, sdbus::ObjectPath delegate){ this->destroyDelegateObject(std::move(result), std::move(delegate)); }).withNoReply();
} }
~factory_adaptor() = default; ~factory_adaptor() = default;

View File

@ -204,14 +204,17 @@ std::tuple<std::string, std::string> AdaptorGenerator::processMethods(const Node
Nodes inArgs = args.select("direction" , "in"); Nodes inArgs = args.select("direction" , "in");
Nodes outArgs = args.select("direction" , "out"); Nodes outArgs = args.select("direction" , "out");
std::string argStr, argTypeStr; std::string argStr, argTypeStr, argStringsStr, outArgStringsStr;
std::tie(argStr, argTypeStr, std::ignore) = argsToNamesAndTypes(inArgs, async); std::tie(argStr, argTypeStr, std::ignore, argStringsStr) = argsToNamesAndTypes(inArgs, async);
std::tie(std::ignore, std::ignore, std::ignore, outArgStringsStr) = argsToNamesAndTypes(outArgs);
using namespace std::string_literals; using namespace std::string_literals;
registrationSS << tab << tab << "object_.registerMethod(\"" registrationSS << tab << tab << "object_.registerMethod(\""
<< methodName << "\")" << methodName << "\")"
<< ".onInterface(INTERFACE_NAME)" << ".onInterface(INTERFACE_NAME)"
<< (!argStringsStr.empty() ? (".withInputParamNames(" + argStringsStr + ")") : "")
<< (!outArgStringsStr.empty() ? (".withOutputParamNames(" + outArgStringsStr + ")") : "")
<< ".implementedAs(" << ".implementedAs("
<< "[this](" << "[this]("
<< (async ? "sdbus::Result<" + outArgsToType(outArgs, true) + ">&& result" + (argTypeStr.empty() ? "" : ", ") : "") << (async ? "sdbus::Result<" + outArgsToType(outArgs, true) + ">&& result" + (argTypeStr.empty() ? "" : ", ") : "")
@ -259,8 +262,8 @@ std::tuple<std::string, std::string> AdaptorGenerator::processSignals(const Node
Nodes args = (*signal)["arg"]; Nodes args = (*signal)["arg"];
std::string argStr, argTypeStr, typeStr;; std::string argStr, argTypeStr, typeStr, argStringsStr;
std::tie(argStr, argTypeStr, typeStr) = argsToNamesAndTypes(args); std::tie(argStr, argTypeStr, typeStr, argStringsStr) = argsToNamesAndTypes(args);
signalRegistrationSS << tab << tab signalRegistrationSS << tab << tab
<< "object_.registerSignal(\"" << name << "\")" << "object_.registerSignal(\"" << name << "\")"
@ -268,7 +271,7 @@ std::tuple<std::string, std::string> AdaptorGenerator::processSignals(const Node
if (args.size() > 0) if (args.size() > 0)
{ {
signalRegistrationSS << ".withParameters<" << typeStr << ">()"; signalRegistrationSS << ".withParameters<" << typeStr << ">(" << argStringsStr << ")";
} }
signalRegistrationSS << annotationRegistration; signalRegistrationSS << annotationRegistration;

View File

@ -105,9 +105,9 @@ std::tuple<unsigned, std::string> BaseGenerator::generateNamespaces(const std::s
} }
std::tuple<std::string, std::string, std::string> BaseGenerator::argsToNamesAndTypes(const Nodes& args, bool async) const std::tuple<std::string, std::string, std::string, std::string> BaseGenerator::argsToNamesAndTypes(const Nodes& args, bool async) const
{ {
std::ostringstream argSS, argTypeSS, typeSS; std::ostringstream argSS, argTypeSS, typeSS, argStringsSS;
for (size_t i = 0; i < args.size(); ++i) for (size_t i = 0; i < args.size(); ++i)
{ {
@ -115,6 +115,7 @@ std::tuple<std::string, std::string, std::string> BaseGenerator::argsToNamesAndT
if (i > 0) if (i > 0)
{ {
argSS << ", "; argSS << ", ";
argStringsSS << ", ";
argTypeSS << ", "; argTypeSS << ", ";
typeSS << ", "; typeSS << ", ";
} }
@ -125,6 +126,7 @@ std::tuple<std::string, std::string, std::string> BaseGenerator::argsToNamesAndT
argName = "arg" + std::to_string(i); argName = "arg" + std::to_string(i);
} }
auto type = signature_to_type(arg->get("type")); auto type = signature_to_type(arg->get("type"));
argStringsSS << "\"" << argName << "\"";
if (!async) if (!async)
{ {
argSS << argName; argSS << argName;
@ -138,7 +140,7 @@ std::tuple<std::string, std::string, std::string> BaseGenerator::argsToNamesAndT
typeSS << type; typeSS << type;
} }
return std::make_tuple(argSS.str(), argTypeSS.str(), typeSS.str()); return std::make_tuple(argSS.str(), argTypeSS.str(), typeSS.str(), argStringsSS.str());
} }
/** /**

View File

@ -88,7 +88,7 @@ protected:
* @param args * @param args
* @return tuple: argument names, argument types and names, argument types * @return tuple: argument names, argument types and names, argument types
*/ */
std::tuple<std::string, std::string, std::string> argsToNamesAndTypes(const sdbuscpp::xml::Nodes& args, bool async = false) const; std::tuple<std::string, std::string, std::string, std::string> argsToNamesAndTypes(const sdbuscpp::xml::Nodes& args, bool async = false) const;
/** /**
* Output arguments to return type * Output arguments to return type

View File

@ -169,9 +169,9 @@ std::tuple<std::string, std::string> ProxyGenerator::processMethods(const Nodes&
auto retType = outArgsToType(outArgs); auto retType = outArgsToType(outArgs);
std::string inArgStr, inArgTypeStr; std::string inArgStr, inArgTypeStr;
std::tie(inArgStr, inArgTypeStr, std::ignore) = argsToNamesAndTypes(inArgs); std::tie(inArgStr, inArgTypeStr, std::ignore, std::ignore) = argsToNamesAndTypes(inArgs);
std::string outArgStr, outArgTypeStr; std::string outArgStr, outArgTypeStr;
std::tie(outArgStr, outArgTypeStr, std::ignore) = argsToNamesAndTypes(outArgs); std::tie(outArgStr, outArgTypeStr, std::ignore, std::ignore) = argsToNamesAndTypes(outArgs);
definitionSS << tab << (async ? "void" : retType) << " " << name << "(" << inArgTypeStr << ")" << endl definitionSS << tab << (async ? "void" : retType) << " " << name << "(" << inArgTypeStr << ")" << endl
<< tab << "{" << endl; << tab << "{" << endl;
@ -239,7 +239,7 @@ std::tuple<std::string, std::string> ProxyGenerator::processSignals(const Nodes&
nameBigFirst[0] = islower(nameBigFirst[0]) ? nameBigFirst[0] + 'A' - 'a' : nameBigFirst[0]; nameBigFirst[0] = islower(nameBigFirst[0]) ? nameBigFirst[0] + 'A' - 'a' : nameBigFirst[0];
std::string argStr, argTypeStr; std::string argStr, argTypeStr;
std::tie(argStr, argTypeStr, std::ignore) = argsToNamesAndTypes(args); std::tie(argStr, argTypeStr, std::ignore, std::ignore) = argsToNamesAndTypes(args);
registrationSS << tab << tab << "proxy_" registrationSS << tab << tab << "proxy_"
".uponSignal(\"" << name << "\")" ".uponSignal(\"" << name << "\")"