From 5f23f7d12484d2afafa4e0c739c0be8d5b98af99 Mon Sep 17 00:00:00 2001 From: Andreas Volz Date: Sun, 31 Aug 2008 14:14:04 +0200 Subject: added object support for signal proxy --- tools/xml2cpp.cpp | 161 ++++++++++++++++++++++++++++++++++++++++-------------- 1 file changed, 120 insertions(+), 41 deletions(-) (limited to 'tools') diff --git a/tools/xml2cpp.cpp b/tools/xml2cpp.cpp index 45c8dde..9a5d594 100644 --- a/tools/xml2cpp.cpp +++ b/tools/xml2cpp.cpp @@ -33,6 +33,7 @@ #include #include #include +#include using namespace std; using namespace DBus; @@ -198,25 +199,20 @@ string signature_to_type(const string &signature) void generate_proxy(Xml::Document &doc, const char *filename) { - cerr << "writing " << filename << endl; - - ofstream file(filename); - if (file.bad()) - { - cerr << "unable to write file " << filename << endl; - exit(-1); - } + ostringstream file; + ostringstream headerStream; + vector includeVector; - file << header; + headerStream << header; string filestring = filename; underscorize(filestring); string cond_comp = "__dbusxx__" + filestring + "__PROXY_MARSHAL_H"; - file << "#ifndef " << cond_comp << endl; - file << "#define " << cond_comp << endl; + headerStream << "#ifndef " << cond_comp << endl; + headerStream << "#define " << cond_comp << endl; - file << dbus_includes; + headerStream << dbus_includes; Xml::Node &root = *(doc.root); 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(), signals.begin(), signals.end()); + // gets the name of each interface: string ifacename = iface.get("name"); + + // these interface names are skipped. Not sure why... if (ifacename == "org.freedesktop.DBus.Introspectable" ||ifacename == "org.freedesktop.DBus.Properties") { @@ -242,7 +241,8 @@ void generate_proxy(Xml::Document &doc, const char *filename) istringstream ss(ifacename); string nspace; unsigned int nspaces = 0; - + + // this loop prints all the namespaces defined with while (ss.str().find('.', ss.tellg()) != string::npos) { getline(ss, nspace, '.'); @@ -256,11 +256,13 @@ void generate_proxy(Xml::Document &doc, const char *filename) string ifaceclass; getline(ss, ifaceclass); - + + // a "_proxy" is added to class name to distinguish between proxy and adaptor ifaceclass += "_proxy"; cerr << "generating code for interface " << ifacename << "..." << endl; - + + // the code from class definiton up to opening of the constructor is generated... file << "class " << ifaceclass << endl << " : public ::DBus::InterfaceProxy" << endl << "{" << endl @@ -269,7 +271,8 @@ void generate_proxy(Xml::Document &doc, const char *filename) << tab << ifaceclass << "()" << endl << tab << ": ::DBus::InterfaceProxy(\"" << ifacename << "\")" << 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) { Xml::Node &signal = **si; @@ -280,13 +283,16 @@ void generate_proxy(Xml::Document &doc, const char *filename) << ifaceclass << ", " << signal.get("name") << ", " << stub_name(signal.get("name")) << ");" << endl; } - + + // the constructor ends here file << tab << "}" << endl << endl; -/// write properties + + // write public block header for properties file << "public:" << endl << endl << tab << "/* properties exported by this interface */" << endl; - + + // this loop generates all properties for (Xml::Nodes::iterator pi = properties.begin (); 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 <<"::DBus::Message ret = this->invoke_method (call);" << endl; file << tab << tab << "};" << endl; - } + } } - + + // write public block header for methods file << "public:" << endl << endl << tab << "/* methods exported by this interface," << endl << tab << " * this functions will invoke the corresponding methods on the remote objects" << endl << tab << " */" << endl; - + + // this loop generates all methods for (Xml::Nodes::iterator mi = methods.begin(); mi != methods.end(); ++mi) { Xml::Node &method = **mi; @@ -361,7 +369,7 @@ void generate_proxy(Xml::Document &doc, const char *filename) { file << tab << signature_to_type(args_out.front()->get("type")) << " "; } - + file << method.get("name") << "("; unsigned int i = 0; @@ -454,13 +462,15 @@ void generate_proxy(Xml::Document &doc, const char *filename) file << tab << "}" << endl << endl; } - + + // write public block header for signals file << endl << "public:" << endl << endl << tab << "/* signal handlers for this interface" << endl << tab << " */" << endl; - + + // this loop generates all signals for (Xml::Nodes::iterator si = signals.begin(); si != signals.end(); ++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") << "("; + // this loop generates all argument for a signal unsigned int i = 0; for (Xml::Nodes::iterator ai = args.begin(); ai != args.end(); ++ai, ++i) { 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()) file << arg_name; else @@ -485,13 +511,15 @@ void generate_proxy(Xml::Document &doc, const char *filename) } file << ") = 0;" << endl; } - + + // write private block header for unmarshalers file << endl << "private:" << endl << endl << tab << "/* unmarshalers (to unpack the DBus message before calling the actual signal handler)" << endl << tab << " */" << endl; + // loop to generate all the unmarshalers for (Xml::Nodes::iterator si = signals.begin(); si != signals.end(); ++si) { Xml::Node &signal = **si; @@ -513,25 +541,51 @@ void generate_proxy(Xml::Document &doc, const char *filename) file << tab << tab << signature_to_type(arg.get("type")) << " " ; string arg_name = arg.get("name"); - if (arg_name.length()) - file << arg_name << ";" << " ri >> " << arg_name << ";" << endl; - else - file << "arg" << i << ";" << " ri >> " << "arg" << i << ";" << endl; + + string arg_object = arg.get("object"); + + // 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") << "("; + // generate all arguments for the call to the virtual function unsigned int j = 0; for (Xml::Nodes::iterator ai = args.begin(); ai != args.end(); ++ai, ++j) { Xml::Node &arg = **ai; - string arg_name = arg.get("name"); - if (arg_name.length()) - file << arg_name; - else - file << "arg" << j; - + string arg_name = arg.get("name"); + string arg_object = arg.get("object"); + + if (!arg_name.length()) + { + arg_name = "arg" + j; + } + + if (arg_object.length()) + { + file << "_" << arg_name; + } + else + { + file << arg_name; + } + if (ai+1 != args.end()) file << ", "; } @@ -552,9 +606,34 @@ void generate_proxy(Xml::Document &doc, const char *filename) file << endl; } - file << "#endif//" << cond_comp << endl; + file << "#endif //" << cond_comp << endl; + + cerr << "writing " << filename << endl; + + // remove all duplicates in the header include vector + vector::const_iterator vec_end_it = unique (includeVector.begin (), includeVector.end ()); + + for (vector::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 (); - file.close(); + fileX.close(); } void generate_adaptor(Xml::Document &doc, const char *filename) -- cgit v1.2.1