gensrv_cpp.py
Go to the documentation of this file.
00001 #!/usr/bin/env python
00002 # Software License Agreement (BSD License)
00003 #
00004 # Copyright (c) 2009, Willow Garage, Inc.
00005 # All rights reserved.
00006 #
00007 # Redistribution and use in source and binary forms, with or without
00008 # modification, are permitted provided that the following conditions
00009 # are met:
00010 #
00011 #  * Redistributions of source code must retain the above copyright
00012 #    notice, this list of conditions and the following disclaimer.
00013 #  * Redistributions in binary form must reproduce the above
00014 #    copyright notice, this list of conditions and the following
00015 #    disclaimer in the documentation and/or other materials provided
00016 #    with the distribution.
00017 #  * Neither the name of Willow Garage, Inc. nor the names of its
00018 #    contributors may be used to endorse or promote products derived
00019 #    from this software without specific prior written permission.
00020 #
00021 # THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
00022 # "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
00023 # LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
00024 # FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
00025 # COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
00026 # INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
00027 # BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
00028 # LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
00029 # CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
00030 # LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
00031 # ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
00032 # POSSIBILITY OF SUCH DAMAGE.
00033 #
00034 
00035 ## ROS message source code generation for C++
00036 ## 
00037 ## Converts ROS .msg files in a package into C++ source code implementations.
00038 
00039 import msg_gen as genmsg_cpp
00040  
00041 import sys
00042 import os
00043 import traceback
00044 
00045 # roslib.msgs contains the utilities for parsing .msg specifications. It is meant to have no rospy-specific knowledge
00046 import roslib.srvs
00047 import roslib.packages
00048 import roslib.gentools
00049 
00050 try:
00051     from cStringIO import StringIO #Python 2.x
00052 except ImportError:
00053     from io import StringIO #Python 3.x
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         # if we're being run concurrently, the above test can report false but os.makedirs can still fail if
00200         # another copy just created the directory
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     


roscpp
Author(s): Morgan Quigley mquigley@cs.stanford.edu, Josh Faust jfaust@willowgarage.com, Brian Gerkey gerkey@willowgarage.com, Troy Straszheim straszheim@willowgarage.com
autogenerated on Sat Dec 28 2013 17:35:52