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++/Flags.h>
#include <string>
#include <vector>
#include <type_traits>
#include <chrono>
#include <cstdint>
@ -45,6 +46,9 @@ namespace sdbus {
namespace sdbus {
template <typename... _Args>
inline constexpr bool are_strings_v = std::conjunction<std::is_convertible<_Args, std::string>...>::value;
class MethodRegistrator
{
public:
@ -57,6 +61,12 @@ namespace sdbus {
std::enable_if_t<!is_async_method_v<_Function>, MethodRegistrator&> implementedAs(_Function&& callback);
template <typename _Function>
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& markAsPrivileged();
MethodRegistrator& withNoReply();
@ -66,7 +76,9 @@ namespace sdbus {
const std::string& methodName_;
std::string interfaceName_;
std::string inputSignature_;
std::vector<std::string> inputParamNames_;
std::string outputSignature_;
std::vector<std::string> outputParamNames_;
method_callback methodCallback_;
Flags flags_;
int exceptions_{}; // Number of active exceptions when SignalRegistrator is constructed
@ -81,6 +93,9 @@ namespace sdbus {
SignalRegistrator& onInterface(std::string interfaceName);
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();
private:
@ -88,6 +103,7 @@ namespace sdbus {
const std::string& signalName_;
std::string interfaceName_;
std::string signalSignature_;
std::vector<std::string> paramNames_;
Flags flags_;
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.
// 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.
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)
@ -81,7 +88,8 @@ namespace sdbus {
}
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();
outputSignature_ = signature_of_function_output_arguments<_Function>::str();
@ -110,7 +118,8 @@ namespace sdbus {
}
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();
outputSignature_ = signature_of_function_output_arguments<_Function>::str();
@ -130,6 +139,32 @@ namespace sdbus {
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()
{
flags_.set(Flags::DEPRECATED);
@ -179,7 +214,11 @@ namespace sdbus {
// 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
// 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)
@ -197,6 +236,23 @@ namespace sdbus {
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()
{
flags_.set(Flags::DEPRECATED);

View File

@ -74,9 +74,37 @@ namespace sdbus {
* @throws sdbus::Error in case of failure
*/
virtual void registerMethod( const std::string& interfaceName
, const std::string& methodName
, const std::string& inputSignature
, const std::string& outputSignature
, std::string methodName
, std::string inputSignature
, 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
, Flags flags = {} ) = 0;
@ -91,8 +119,30 @@ namespace sdbus {
* @throws sdbus::Error in case of failure
*/
virtual void registerSignal( const std::string& interfaceName
, const std::string& signalName
, const std::string& signature
, std::string signalName
, 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;
/*!
@ -107,8 +157,8 @@ namespace sdbus {
* @throws sdbus::Error in case of failure
*/
virtual void registerProperty( const std::string& interfaceName
, const std::string& propertyName
, const std::string& signature
, std::string propertyName
, std::string signature
, property_get_callback getCallback
, Flags flags = {} ) = 0;
@ -125,8 +175,8 @@ namespace sdbus {
* @throws sdbus::Error in case of failure
*/
virtual void registerProperty( const std::string& interfaceName
, const std::string& propertyName
, const std::string& signature
, std::string propertyName
, std::string signature
, property_get_callback getCallback
, property_set_callback setCallback
, Flags flags = {} ) = 0;