forked from Kistler-Group/sdbus-cpp
Introduce support for asynchronous D-Bus method calls on the client side (#42)
Fixes #32
This commit is contained in:
@@ -169,17 +169,31 @@ std::tuple<std::string, std::string> AdaptorGenerator::processMethods(const Node
|
||||
const auto& annotationName = annotation.first;
|
||||
const auto& annotationValue = annotation.second;
|
||||
|
||||
if (annotationName == "org.freedesktop.DBus.Deprecated" && annotationValue == "true")
|
||||
annotationRegistration += ".markAsDeprecated()";
|
||||
else if (annotationName == "org.freedesktop.DBus.Method.NoReply" && annotationValue == "true")
|
||||
annotationRegistration += ".withNoReply()";
|
||||
else if (annotationName == "org.freedesktop.DBus.Method.Async" && (annotationValue == "server" || annotationValue == "clientserver"))
|
||||
async = true;
|
||||
else if (annotationName == "org.freedesktop.systemd1.Privileged" && annotationValue == "true")
|
||||
annotationRegistration += ".markAsPrivileged()";
|
||||
if (annotationName == "org.freedesktop.DBus.Deprecated")
|
||||
{
|
||||
if (annotationValue == "true")
|
||||
annotationRegistration += ".markAsDeprecated()";
|
||||
}
|
||||
else if (annotationName == "org.freedesktop.DBus.Method.NoReply")
|
||||
{
|
||||
if (annotationValue == "true")
|
||||
annotationRegistration += ".withNoReply()";
|
||||
}
|
||||
else if (annotationName == "org.freedesktop.DBus.Method.Async")
|
||||
{
|
||||
if (annotationValue == "server" || annotationValue == "clientserver")
|
||||
async = true;
|
||||
}
|
||||
else if (annotationName == "org.freedesktop.systemd1.Privileged")
|
||||
{
|
||||
if (annotationValue == "true")
|
||||
annotationRegistration += ".markAsPrivileged()";
|
||||
}
|
||||
else
|
||||
{
|
||||
std::cerr << "Node: " << methodName << ": "
|
||||
<< "Option '" << annotationName << "' not allowed or supported in this context! Option ignored..." << std::endl;
|
||||
}
|
||||
}
|
||||
|
||||
Nodes args = (*method)["arg"];
|
||||
|
||||
Regular → Executable
+45
-23
@@ -94,10 +94,18 @@ std::string ProxyGenerator::processInterface(Node& interface) const
|
||||
|
||||
body << tab << "{" << endl
|
||||
<< registration
|
||||
<< tab << "}" << endl << endl
|
||||
<< declaration << endl;
|
||||
<< tab << "}" << endl << endl;
|
||||
if (!declaration.empty())
|
||||
body << declaration << endl;
|
||||
|
||||
std::string methodDefinitions, asyncDeclarations;
|
||||
std::tie(methodDefinitions, asyncDeclarations) = processMethods(methods);
|
||||
|
||||
if (!asyncDeclarations.empty())
|
||||
{
|
||||
body << asyncDeclarations << endl;
|
||||
}
|
||||
|
||||
std::string methodDefinitions = processMethods(methods);
|
||||
if (!methodDefinitions.empty())
|
||||
{
|
||||
body << "public:" << endl << methodDefinitions;
|
||||
@@ -117,9 +125,10 @@ std::string ProxyGenerator::processInterface(Node& interface) const
|
||||
return body.str();
|
||||
}
|
||||
|
||||
std::string ProxyGenerator::processMethods(const Nodes& methods) const
|
||||
std::tuple<std::string, std::string> ProxyGenerator::processMethods(const Nodes& methods) const
|
||||
{
|
||||
std::ostringstream methodSS;
|
||||
std::ostringstream definitionSS, asyncDeclarationSS;
|
||||
|
||||
for (const auto& method : methods)
|
||||
{
|
||||
auto name = method->get("name");
|
||||
@@ -128,15 +137,15 @@ std::string ProxyGenerator::processMethods(const Nodes& methods) const
|
||||
Nodes outArgs = args.select("direction" , "out");
|
||||
|
||||
bool dontExpectReply{false};
|
||||
bool async{false};
|
||||
Nodes annotations = (*method)["annotation"];
|
||||
for (const auto& annotation : annotations)
|
||||
{
|
||||
if (annotation->get("name") == "org.freedesktop.DBus.Method.NoReply"
|
||||
&& annotation->get("value") == "true")
|
||||
{
|
||||
if (annotation->get("name") == "org.freedesktop.DBus.Method.NoReply" && annotation->get("value") == "true")
|
||||
dontExpectReply = true;
|
||||
break;
|
||||
}
|
||||
else if (annotation->get("name") == "org.freedesktop.DBus.Method.Async"
|
||||
&& (annotation->get("value") == "client" || annotation->get("value") == "clientserver"))
|
||||
async = true;
|
||||
}
|
||||
if (dontExpectReply && outArgs.size() > 0)
|
||||
{
|
||||
@@ -146,39 +155,52 @@ std::string ProxyGenerator::processMethods(const Nodes& methods) const
|
||||
}
|
||||
|
||||
auto retType = outArgsToType(outArgs);
|
||||
std::string argStr, argTypeStr;
|
||||
std::tie(argStr, argTypeStr, std::ignore) = argsToNamesAndTypes(inArgs);
|
||||
std::string inArgStr, inArgTypeStr;
|
||||
std::tie(inArgStr, inArgTypeStr, std::ignore) = argsToNamesAndTypes(inArgs);
|
||||
std::string outArgStr, outArgTypeStr;
|
||||
std::tie(outArgStr, outArgTypeStr, std::ignore) = argsToNamesAndTypes(outArgs);
|
||||
|
||||
methodSS << tab << retType << " " << name << "(" << argTypeStr << ")" << endl
|
||||
definitionSS << tab << (async ? "void" : retType) << " " << name << "(" << inArgTypeStr << ")" << endl
|
||||
<< tab << "{" << endl;
|
||||
|
||||
if (outArgs.size() > 0)
|
||||
if (outArgs.size() > 0 && !async)
|
||||
{
|
||||
methodSS << tab << tab << retType << " result;" << endl;
|
||||
definitionSS << tab << tab << retType << " result;" << endl;
|
||||
}
|
||||
|
||||
methodSS << tab << tab << "object_.callMethod(\"" << name << "\")"
|
||||
definitionSS << tab << tab << "object_.callMethod" << (async ? "Async" : "") << "(\"" << name << "\")"
|
||||
".onInterface(interfaceName)";
|
||||
|
||||
if (inArgs.size() > 0)
|
||||
{
|
||||
methodSS << ".withArguments(" << argStr << ")";
|
||||
definitionSS << ".withArguments(" << inArgStr << ")";
|
||||
}
|
||||
|
||||
if (outArgs.size() > 0)
|
||||
if (async && !dontExpectReply)
|
||||
{
|
||||
methodSS << ".storeResultsTo(result);" << endl
|
||||
<< tab << tab << "return result";
|
||||
auto nameBigFirst = name;
|
||||
nameBigFirst[0] = islower(nameBigFirst[0]) ? nameBigFirst[0] + 'A' - 'a' : nameBigFirst[0];
|
||||
|
||||
definitionSS << ".uponReplyInvoke([this](const sdbus::Error* error" << (outArgTypeStr.empty() ? "" : ", ") << outArgTypeStr << ")"
|
||||
"{ this->on" << nameBigFirst << "Reply(" << outArgStr << (outArgStr.empty() ? "" : ", ") << "error); })";
|
||||
|
||||
asyncDeclarationSS << tab << "virtual void on" << nameBigFirst << "Reply("
|
||||
<< outArgTypeStr << (outArgTypeStr.empty() ? "" : ", ") << "const sdbus::Error* error) = 0;" << endl;
|
||||
}
|
||||
else if (outArgs.size() > 0)
|
||||
{
|
||||
definitionSS << ".storeResultsTo(result);" << endl
|
||||
<< tab << tab << "return result";
|
||||
}
|
||||
else if (dontExpectReply)
|
||||
{
|
||||
methodSS << ".dontExpectReply()";
|
||||
definitionSS << ".dontExpectReply()";
|
||||
}
|
||||
|
||||
methodSS << ";" << endl << tab << "}" << endl << endl;
|
||||
definitionSS << ";" << endl << tab << "}" << endl << endl;
|
||||
}
|
||||
|
||||
return methodSS.str();
|
||||
return std::make_tuple(definitionSS.str(), asyncDeclarationSS.str());
|
||||
}
|
||||
|
||||
std::tuple<std::string, std::string> ProxyGenerator::processSignals(const Nodes& signals) const
|
||||
|
||||
@@ -56,9 +56,9 @@ private:
|
||||
/**
|
||||
* Generate method calls
|
||||
* @param methods
|
||||
* @return source code
|
||||
* @return tuple: definition of methods, declaration of virtual async reply handlers
|
||||
*/
|
||||
std::string processMethods(const sdbuscpp::xml::Nodes& methods) const;
|
||||
std::tuple<std::string, std::string> processMethods(const sdbuscpp::xml::Nodes& methods) const;
|
||||
|
||||
/**
|
||||
* Generate code for handling signals
|
||||
|
||||
Reference in New Issue
Block a user