added object support for signal proxy

This commit is contained in:
Andreas Volz 2008-08-31 14:14:04 +02:00
parent 7db1248454
commit 5f23f7d124

View file

@ -33,6 +33,7 @@
#include <iostream> #include <iostream>
#include <fstream> #include <fstream>
#include <sstream> #include <sstream>
#include <algorithm>
using namespace std; using namespace std;
using namespace DBus; using namespace DBus;
@ -198,25 +199,20 @@ string signature_to_type(const string &signature)
void generate_proxy(Xml::Document &doc, const char *filename) void generate_proxy(Xml::Document &doc, const char *filename)
{ {
cerr << "writing " << filename << endl; ostringstream file;
ostringstream headerStream;
vector <string> includeVector;
ofstream file(filename); headerStream << header;
if (file.bad())
{
cerr << "unable to write file " << filename << endl;
exit(-1);
}
file << header;
string filestring = filename; string filestring = filename;
underscorize(filestring); underscorize(filestring);
string cond_comp = "__dbusxx__" + filestring + "__PROXY_MARSHAL_H"; string cond_comp = "__dbusxx__" + filestring + "__PROXY_MARSHAL_H";
file << "#ifndef " << cond_comp << endl; headerStream << "#ifndef " << cond_comp << endl;
file << "#define " << cond_comp << endl; headerStream << "#define " << cond_comp << endl;
file << dbus_includes; headerStream << dbus_includes;
Xml::Node &root = *(doc.root); Xml::Node &root = *(doc.root);
Xml::Nodes interfaces = root["interface"]; Xml::Nodes interfaces = root["interface"];
@ -231,7 +227,10 @@ void generate_proxy(Xml::Document &doc, const char *filename)
ms.insert(ms.end(), methods.begin(), methods.end()); ms.insert(ms.end(), methods.begin(), methods.end());
ms.insert(ms.end(), signals.begin(), signals.end()); ms.insert(ms.end(), signals.begin(), signals.end());
// gets the name of each interface: <interface name="XYZ">
string ifacename = iface.get("name"); string ifacename = iface.get("name");
// these interface names are skipped. Not sure why...
if (ifacename == "org.freedesktop.DBus.Introspectable" if (ifacename == "org.freedesktop.DBus.Introspectable"
||ifacename == "org.freedesktop.DBus.Properties") ||ifacename == "org.freedesktop.DBus.Properties")
{ {
@ -243,6 +242,7 @@ void generate_proxy(Xml::Document &doc, const char *filename)
string nspace; string nspace;
unsigned int nspaces = 0; unsigned int nspaces = 0;
// this loop prints all the namespaces defined with <interface name="X.Y.Z">
while (ss.str().find('.', ss.tellg()) != string::npos) while (ss.str().find('.', ss.tellg()) != string::npos)
{ {
getline(ss, nspace, '.'); getline(ss, nspace, '.');
@ -257,10 +257,12 @@ void generate_proxy(Xml::Document &doc, const char *filename)
getline(ss, ifaceclass); getline(ss, ifaceclass);
// a "_proxy" is added to class name to distinguish between proxy and adaptor
ifaceclass += "_proxy"; ifaceclass += "_proxy";
cerr << "generating code for interface " << ifacename << "..." << endl; cerr << "generating code for interface " << ifacename << "..." << endl;
// the code from class definiton up to opening of the constructor is generated...
file << "class " << ifaceclass << endl file << "class " << ifaceclass << endl
<< " : public ::DBus::InterfaceProxy" << endl << " : public ::DBus::InterfaceProxy" << endl
<< "{" << endl << "{" << endl
@ -270,6 +272,7 @@ void generate_proxy(Xml::Document &doc, const char *filename)
<< tab << ": ::DBus::InterfaceProxy(\"" << ifacename << "\")" << endl << tab << ": ::DBus::InterfaceProxy(\"" << ifacename << "\")" << endl
<< tab << "{" << endl; << tab << "{" << endl;
// this loop generates code to connect all the signal stubs; this is still inside the constructor
for (Xml::Nodes::iterator si = signals.begin(); si != signals.end(); ++si) for (Xml::Nodes::iterator si = signals.begin(); si != signals.end(); ++si)
{ {
Xml::Node &signal = **si; Xml::Node &signal = **si;
@ -281,12 +284,15 @@ void generate_proxy(Xml::Document &doc, const char *filename)
<< ");" << endl; << ");" << endl;
} }
// the constructor ends here
file << tab << "}" << endl file << tab << "}" << endl
<< endl; << endl;
/// write properties
// write public block header for properties
file << "public:" << endl << endl file << "public:" << endl << endl
<< tab << "/* properties exported by this interface */" << endl; << tab << "/* properties exported by this interface */" << endl;
// this loop generates all properties
for (Xml::Nodes::iterator pi = properties.begin (); for (Xml::Nodes::iterator pi = properties.begin ();
pi != properties.end (); ++pi) pi != properties.end (); ++pi)
{ {
@ -337,15 +343,17 @@ void generate_proxy(Xml::Document &doc, const char *filename)
file << tab << tab << tab <<"wi << value;" << endl; file << tab << tab << tab <<"wi << value;" << endl;
file << tab << tab << tab <<"::DBus::Message ret = this->invoke_method (call);" << endl; file << tab << tab << tab <<"::DBus::Message ret = this->invoke_method (call);" << endl;
file << tab << tab << "};" << endl; file << tab << tab << "};" << endl;
} }
} }
// write public block header for methods
file << "public:" << endl file << "public:" << endl
<< endl << endl
<< tab << "/* methods exported by this interface," << endl << tab << "/* methods exported by this interface," << endl
<< tab << " * this functions will invoke the corresponding methods on the remote objects" << endl << tab << " * this functions will invoke the corresponding methods on the remote objects" << endl
<< tab << " */" << endl; << tab << " */" << endl;
// this loop generates all methods
for (Xml::Nodes::iterator mi = methods.begin(); mi != methods.end(); ++mi) for (Xml::Nodes::iterator mi = methods.begin(); mi != methods.end(); ++mi)
{ {
Xml::Node &method = **mi; Xml::Node &method = **mi;
@ -455,12 +463,14 @@ void generate_proxy(Xml::Document &doc, const char *filename)
<< endl; << endl;
} }
// write public block header for signals
file << endl file << endl
<< "public:" << endl << "public:" << endl
<< endl << endl
<< tab << "/* signal handlers for this interface" << endl << tab << "/* signal handlers for this interface" << endl
<< tab << " */" << endl; << tab << " */" << endl;
// this loop generates all signals
for (Xml::Nodes::iterator si = signals.begin(); si != signals.end(); ++si) for (Xml::Nodes::iterator si = signals.begin(); si != signals.end(); ++si)
{ {
Xml::Node &signal = **si; Xml::Node &signal = **si;
@ -468,13 +478,29 @@ void generate_proxy(Xml::Document &doc, const char *filename)
file << tab << "virtual void " << signal.get("name") << "("; file << tab << "virtual void " << signal.get("name") << "(";
// this loop generates all argument for a signal
unsigned int i = 0; unsigned int i = 0;
for (Xml::Nodes::iterator ai = args.begin(); ai != args.end(); ++ai, ++i) for (Xml::Nodes::iterator ai = args.begin(); ai != args.end(); ++ai, ++i)
{ {
Xml::Node &arg = **ai; Xml::Node &arg = **ai;
file << "const " << signature_to_type(arg.get("type")) << "& ";
string arg_name = arg.get("name"); string arg_name = arg.get("name");
string arg_object = arg.get("object");
// generate basic signature only if no object name available...
if (!arg_object.length())
{
file << "const " << signature_to_type(arg.get("type")) << "& ";
}
// ...or generate object style if available
else
{
file << "const " << arg_object << "& ";
// store a object name to later generate header includes
includeVector.push_back (arg_object);
}
if (arg_name.length()) if (arg_name.length())
file << arg_name; file << arg_name;
else else
@ -486,12 +512,14 @@ void generate_proxy(Xml::Document &doc, const char *filename)
file << ") = 0;" << endl; file << ") = 0;" << endl;
} }
// write private block header for unmarshalers
file << endl file << endl
<< "private:" << endl << "private:" << endl
<< endl << endl
<< tab << "/* unmarshalers (to unpack the DBus message before calling the actual signal handler)" << endl << tab << "/* unmarshalers (to unpack the DBus message before calling the actual signal handler)" << endl
<< tab << " */" << endl; << tab << " */" << endl;
// loop to generate all the unmarshalers
for (Xml::Nodes::iterator si = signals.begin(); si != signals.end(); ++si) for (Xml::Nodes::iterator si = signals.begin(); si != signals.end(); ++si)
{ {
Xml::Node &signal = **si; Xml::Node &signal = **si;
@ -513,24 +541,50 @@ void generate_proxy(Xml::Document &doc, const char *filename)
file << tab << tab << signature_to_type(arg.get("type")) << " " ; file << tab << tab << signature_to_type(arg.get("type")) << " " ;
string arg_name = arg.get("name"); string arg_name = arg.get("name");
if (arg_name.length())
file << arg_name << ";" << " ri >> " << arg_name << ";" << endl; string arg_object = arg.get("object");
else
file << "arg" << i << ";" << " ri >> " << "arg" << i << ";" << endl; // use a default if no arg name given
if (!arg_name.length())
{
arg_name = "arg";
}
file << arg_name << ";" << endl;
file << tab << tab << "ri >> " << arg_name << ";" << endl;
// if a object type is used create a local variable and insert values with '<<' operation
if (arg_object.length())
{
file << tab << tab << arg_object << " _" << arg_name << ";" << endl;
file << tab << tab << "_" << arg_name << " << " << arg_name << ";" << endl;
}
} }
file << tab << tab << signal.get("name") << "("; file << tab << tab << signal.get("name") << "(";
// generate all arguments for the call to the virtual function
unsigned int j = 0; unsigned int j = 0;
for (Xml::Nodes::iterator ai = args.begin(); ai != args.end(); ++ai, ++j) for (Xml::Nodes::iterator ai = args.begin(); ai != args.end(); ++ai, ++j)
{ {
Xml::Node &arg = **ai; Xml::Node &arg = **ai;
string arg_name = arg.get("name"); string arg_name = arg.get("name");
if (arg_name.length()) string arg_object = arg.get("object");
file << arg_name;
else if (!arg_name.length())
file << "arg" << j; {
arg_name = "arg" + j;
}
if (arg_object.length())
{
file << "_" << arg_name;
}
else
{
file << arg_name;
}
if (ai+1 != args.end()) if (ai+1 != args.end())
file << ", "; file << ", ";
@ -552,9 +606,34 @@ void generate_proxy(Xml::Document &doc, const char *filename)
file << endl; file << endl;
} }
file << "#endif//" << cond_comp << endl; file << "#endif //" << cond_comp << endl;
file.close(); cerr << "writing " << filename << endl;
// remove all duplicates in the header include vector
vector<string>::const_iterator vec_end_it = unique (includeVector.begin (), includeVector.end ());
for (vector<string>::const_iterator vec_it = includeVector.begin ();
vec_it != vec_end_it;
++vec_it)
{
const string &include = *vec_it;
headerStream << "#include " << "\"" << include << ".h" << "\"" << endl;
}
headerStream << endl;
ofstream fileX(filename);
if (file.bad())
{
cerr << "unable to write file " << filename << endl;
exit(-1);
}
fileX << headerStream.str ();
fileX << file.str ();
fileX.close();
} }
void generate_adaptor(Xml::Document &doc, const char *filename) void generate_adaptor(Xml::Document &doc, const char *filename)