00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023
00024
00025
00026
00027
00028
00029
00030
00031
00032
00033
00034
00035
00036
00037
00038
00039 import msg_gen as genmsg_cpp
00040
00041 import sys
00042 import os
00043 import traceback
00044
00045
00046 import roslib.srvs
00047 import roslib.packages
00048 import roslib.gentools
00049
00050 try:
00051 from cStringIO import StringIO
00052 except ImportError:
00053 from io import StringIO
00054
00055 def write_begin(s, spec, file):
00056 """
00057 Writes the beginning of the header file: a comment saying it's auto-generated and the include guards
00058
00059 @param s: The stream to write to
00060 @type s: stream
00061 @param spec: The spec
00062 @type spec: roslib.srvs.SrvSpec
00063 @param file: The file this service is being generated for
00064 @type file: str
00065 """
00066 s.write("/* Auto-generated by genmsg_cpp for file %s */\n"%(file))
00067 s.write('#ifndef %s_SERVICE_%s_H\n'%(spec.package.upper(), spec.short_name.upper()))
00068 s.write('#define %s_SERVICE_%s_H\n'%(spec.package.upper(), spec.short_name.upper()))
00069
00070 def write_end(s, spec):
00071 """
00072 Writes the end of the header file: the ending of the include guards
00073
00074 @param s: The stream to write to
00075 @type s: stream
00076 @param spec: The spec
00077 @type spec: roslib.srvs.SrvSpec
00078 """
00079 s.write('#endif // %s_SERVICE_%s_H\n'%(spec.package.upper(), spec.short_name.upper()))
00080
00081 def write_generic_includes(s):
00082 """
00083 Writes the includes that all service need
00084
00085 @param s: The stream to write to
00086 @type s: stream
00087 """
00088 s.write('#include "ros/service_traits.h"\n\n')
00089
00090 def write_trait_char_class(s, class_name, cpp_msg, value):
00091 """
00092 Writes a class trait for traits which have static value() members that return const char*
00093
00094 e.g. write_trait_char_class(s, "MD5Sum", "std_srvs::Empty", "hello") yields:
00095 template<>
00096 struct MD5Sum<std_srvs::Empty>
00097 {
00098 static const char* value() { return "hello"; }
00099 static const char* value(const std_srvs::Empty&) { return value(); }
00100 };
00101
00102 @param s: The stream to write to
00103 @type s: stream
00104 @param class_name: The name of the trait class
00105 @type class_name: str
00106 @param cpp_msg: The C++ message declaration, e.g. "std_srvs::Empty"
00107 @type cpp_msg: str
00108 @param value: The string value to return from the value() function
00109 @type value: str
00110 """
00111 s.write('template<>\nstruct %s<%s> {\n'%(class_name, cpp_msg))
00112 s.write(' static const char* value() \n {\n return "%s";\n }\n\n'%(value))
00113 s.write(' static const char* value(const %s&) { return value(); } \n'%(cpp_msg))
00114 s.write('};\n\n')
00115
00116 def write_traits(s, spec, cpp_name_prefix):
00117 """
00118 Write all the service traits for a message
00119
00120 @param s: The stream to write to
00121 @type s: stream
00122 @param spec: The service spec
00123 @type spec: roslib.srvs.SrvSpec
00124 @param cpp_name_prefix: The C++ prefix to prepend when referencing the service, e.g. "std_srvs::"
00125 @type cpp_name_prefix: str
00126 """
00127 gendeps_dict = roslib.gentools.get_dependencies(spec, spec.package)
00128 md5sum = roslib.gentools.compute_md5(gendeps_dict)
00129
00130 s.write('namespace ros\n{\n')
00131 s.write('namespace service_traits\n{\n')
00132
00133 request_with_allocator = '%s%s_<ContainerAllocator> '%(cpp_name_prefix, spec.request.short_name)
00134 response_with_allocator = '%s%s_<ContainerAllocator> '%(cpp_name_prefix, spec.response.short_name)
00135
00136 write_trait_char_class(s, 'MD5Sum', '%s%s'%(cpp_name_prefix, spec.short_name), md5sum);
00137 write_trait_char_class(s, 'DataType', '%s%s'%(cpp_name_prefix, spec.short_name), spec.full_name);
00138 genmsg_cpp.write_trait_char_class(s, 'MD5Sum', request_with_allocator, md5sum)
00139 genmsg_cpp.write_trait_char_class(s, 'DataType', request_with_allocator, spec.full_name)
00140 genmsg_cpp.write_trait_char_class(s, 'MD5Sum', response_with_allocator, md5sum)
00141 genmsg_cpp.write_trait_char_class(s, 'DataType', response_with_allocator, spec.full_name)
00142 s.write('} // namespace service_traits\n')
00143 s.write('} // namespace ros\n\n')
00144
00145 def generate(srv_path):
00146 """
00147 Generate a service
00148
00149 @param srv_path: the path to the .srv file
00150 @type srv_path: str
00151 """
00152 (package_dir, package) = roslib.packages.get_dir_pkg(srv_path)
00153 (_, spec) = roslib.srvs.load_from_file(srv_path, package)
00154
00155 s = StringIO()
00156 cpp_prefix = '%s::'%(package)
00157 write_begin(s, spec, srv_path)
00158 genmsg_cpp.write_generic_includes(s)
00159 write_generic_includes(s)
00160 genmsg_cpp.write_includes(s, spec.request)
00161 s.write('\n')
00162 genmsg_cpp.write_includes(s, spec.response)
00163
00164 gendeps_dict = roslib.gentools.get_dependencies(spec, spec.package)
00165 md5sum = roslib.gentools.compute_md5(gendeps_dict)
00166
00167 s.write('namespace %s\n{\n'%(package))
00168 genmsg_cpp.write_struct(s, spec.request, cpp_prefix, {'ServerMD5Sum': md5sum})
00169 genmsg_cpp.write_constant_definitions(s, spec.request)
00170 s.write('\n')
00171 genmsg_cpp.write_struct(s, spec.response, cpp_prefix, {'ServerMD5Sum': md5sum})
00172 genmsg_cpp.write_constant_definitions(s, spec.response)
00173 s.write('struct %s\n{\n'%(spec.short_name))
00174 s.write('\n')
00175 s.write('typedef %s Request;\n'%(spec.request.short_name))
00176 s.write('typedef %s Response;\n'%(spec.response.short_name))
00177 s.write('Request request;\n')
00178 s.write('Response response;\n\n')
00179 s.write('typedef Request RequestType;\n')
00180 s.write('typedef Response ResponseType;\n')
00181 s.write('}; // struct %s\n'%(spec.short_name))
00182 s.write('} // namespace %s\n\n'%(package))
00183
00184 request_cpp_name = "Request"
00185 response_cpp_name = "Response"
00186 genmsg_cpp.write_traits(s, spec.request, cpp_prefix)
00187 s.write('\n')
00188 genmsg_cpp.write_traits(s, spec.response, cpp_prefix)
00189 genmsg_cpp.write_serialization(s, spec.request, cpp_prefix)
00190 s.write('\n')
00191 genmsg_cpp.write_serialization(s, spec.response, cpp_prefix)
00192
00193 write_traits(s, spec, cpp_prefix)
00194
00195 write_end(s, spec)
00196
00197 output_dir = '%s/srv_gen/cpp/include/%s'%(package_dir, package)
00198 if (not os.path.exists(output_dir)):
00199
00200
00201 try:
00202 os.makedirs(output_dir)
00203 except OSError as e:
00204 pass
00205
00206 f = open('%s/%s.h'%(output_dir, spec.short_name), 'w')
00207 f.write(s.getvalue() + "\n")
00208
00209 s.close()
00210
00211 def generate_services(argv):
00212 for arg in argv[1:]:
00213 generate(arg)
00214
00215 if __name__ == "__main__":
00216 roslib.msgs.set_verbose(False)
00217 generate_services(sys.argv)
00218
00219