gensrv_cpp.py
Go to the documentation of this file.
1 #!/usr/bin/env python
2 # Software License Agreement (BSD License)
3 #
4 # Copyright (c) 2009, Willow Garage, Inc.
5 # All rights reserved.
6 #
7 # Redistribution and use in source and binary forms, with or without
8 # modification, are permitted provided that the following conditions
9 # are met:
10 #
11 # * Redistributions of source code must retain the above copyright
12 # notice, this list of conditions and the following disclaimer.
13 # * Redistributions in binary form must reproduce the above
14 # copyright notice, this list of conditions and the following
15 # disclaimer in the documentation and/or other materials provided
16 # with the distribution.
17 # * Neither the name of Willow Garage, Inc. nor the names of its
18 # contributors may be used to endorse or promote products derived
19 # from this software without specific prior written permission.
20 #
21 # THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
22 # "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
23 # LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
24 # FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
25 # COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
26 # INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
27 # BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
28 # LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
29 # CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
30 # LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
31 # ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
32 # POSSIBILITY OF SUCH DAMAGE.
33 #
34 
35 ## ROS message source code generation for C++
36 ##
37 ## Converts ROS .msg files in a package into C++ source code implementations.
38 
39 import msg_gen as genmsg_cpp
40 
41 import sys
42 import os
43 import traceback
44 
45 # roslib.msgs contains the utilities for parsing .msg specifications. It is meant to have no rospy-specific knowledge
46 import roslib.srvs
47 import roslib.packages
48 import roslib.gentools
49 from rospkg import RosPack
50 
51 try:
52  from cStringIO import StringIO #Python 2.x
53 except ImportError:
54  from io import StringIO #Python 3.x
55 
56 def write_begin(s, spec, file):
57  """
58  Writes the beginning of the header file: a comment saying it's auto-generated and the include guards
59 
60  @param s: The stream to write to
61  @type s: stream
62  @param spec: The spec
63  @type spec: roslib.srvs.SrvSpec
64  @param file: The file this service is being generated for
65  @type file: str
66  """
67  s.write("/* Auto-generated by genmsg_cpp for file %s */\n"%(file))
68  s.write('#ifndef %s_SERVICE_%s_H\n'%(spec.package.upper(), spec.short_name.upper()))
69  s.write('#define %s_SERVICE_%s_H\n'%(spec.package.upper(), spec.short_name.upper()))
70 
71 def write_end(s, spec):
72  """
73  Writes the end of the header file: the ending of the include guards
74 
75  @param s: The stream to write to
76  @type s: stream
77  @param spec: The spec
78  @type spec: roslib.srvs.SrvSpec
79  """
80  s.write('#endif // %s_SERVICE_%s_H\n'%(spec.package.upper(), spec.short_name.upper()))
81 
83  """
84  Writes the includes that all service need
85 
86  @param s: The stream to write to
87  @type s: stream
88  """
89  s.write('#include "ros/service_traits.h"\n\n')
90 
91 def write_trait_char_class(s, class_name, cpp_msg, value):
92  """
93  Writes a class trait for traits which have static value() members that return const char*
94 
95  e.g. write_trait_char_class(s, "MD5Sum", "std_srvs::Empty", "hello") yields:
96  template<>
97  struct MD5Sum<std_srvs::Empty>
98  {
99  static const char* value() { return "hello"; }
100  static const char* value(const std_srvs::Empty&) { return value(); }
101  };
102 
103  @param s: The stream to write to
104  @type s: stream
105  @param class_name: The name of the trait class
106  @type class_name: str
107  @param cpp_msg: The C++ message declaration, e.g. "std_srvs::Empty"
108  @type cpp_msg: str
109  @param value: The string value to return from the value() function
110  @type value: str
111  """
112  s.write('template<>\nstruct %s<%s> {\n'%(class_name, cpp_msg))
113  s.write(' static const char* value() \n {\n return "%s";\n }\n\n'%(value))
114  s.write(' static const char* value(const %s&) { return value(); } \n'%(cpp_msg))
115  s.write('};\n\n')
116 
117 def write_traits(s, spec, cpp_name_prefix, rospack=None):
118  """
119  Write all the service traits for a message
120 
121  @param s: The stream to write to
122  @type s: stream
123  @param spec: The service spec
124  @type spec: roslib.srvs.SrvSpec
125  @param cpp_name_prefix: The C++ prefix to prepend when referencing the service, e.g. "std_srvs::"
126  @type cpp_name_prefix: str
127  """
128  gendeps_dict = roslib.gentools.get_dependencies(spec, spec.package, rospack=rospack)
129  md5sum = roslib.gentools.compute_md5(gendeps_dict, rospack=rospack)
130 
131  s.write('namespace ros\n{\n')
132  s.write('namespace service_traits\n{\n')
133 
134  request_with_allocator = '%s%s_<ContainerAllocator> '%(cpp_name_prefix, spec.request.short_name)
135  response_with_allocator = '%s%s_<ContainerAllocator> '%(cpp_name_prefix, spec.response.short_name)
136 
137  write_trait_char_class(s, 'MD5Sum', '%s%s'%(cpp_name_prefix, spec.short_name), md5sum);
138  write_trait_char_class(s, 'DataType', '%s%s'%(cpp_name_prefix, spec.short_name), spec.full_name);
139  genmsg_cpp.write_trait_char_class(s, 'MD5Sum', request_with_allocator, md5sum)
140  genmsg_cpp.write_trait_char_class(s, 'DataType', request_with_allocator, spec.full_name)
141  genmsg_cpp.write_trait_char_class(s, 'MD5Sum', response_with_allocator, md5sum)
142  genmsg_cpp.write_trait_char_class(s, 'DataType', response_with_allocator, spec.full_name)
143  s.write('} // namespace service_traits\n')
144  s.write('} // namespace ros\n\n')
145 
146 def generate(srv_path):
147  """
148  Generate a service
149 
150  @param srv_path: the path to the .srv file
151  @type srv_path: str
152  """
153  (package_dir, package) = roslib.packages.get_dir_pkg(srv_path)
154  (_, spec) = roslib.srvs.load_from_file(srv_path, package)
155 
156  s = StringIO()
157  cpp_prefix = '%s::'%(package)
158  write_begin(s, spec, srv_path)
159  genmsg_cpp.write_generic_includes(s)
161  genmsg_cpp.write_includes(s, spec.request)
162  s.write('\n')
163  genmsg_cpp.write_includes(s, spec.response)
164 
165  rospack = RosPack()
166  gendeps_dict = roslib.gentools.get_dependencies(spec, spec.package, rospack=rospack)
167  md5sum = roslib.gentools.compute_md5(gendeps_dict, rospack=rospack)
168 
169  s.write('namespace %s\n{\n'%(package))
170  genmsg_cpp.write_struct(s, spec.request, cpp_prefix, {'ServerMD5Sum': md5sum})
171  genmsg_cpp.write_constant_definitions(s, spec.request)
172  s.write('\n')
173  genmsg_cpp.write_struct(s, spec.response, cpp_prefix, {'ServerMD5Sum': md5sum})
174  genmsg_cpp.write_constant_definitions(s, spec.response)
175  s.write('struct %s\n{\n'%(spec.short_name))
176  s.write('\n')
177  s.write('typedef %s Request;\n'%(spec.request.short_name))
178  s.write('typedef %s Response;\n'%(spec.response.short_name))
179  s.write('Request request;\n')
180  s.write('Response response;\n\n')
181  s.write('typedef Request RequestType;\n')
182  s.write('typedef Response ResponseType;\n')
183  s.write('}; // struct %s\n'%(spec.short_name))
184  s.write('} // namespace %s\n\n'%(package))
185 
186  request_cpp_name = "Request"
187  response_cpp_name = "Response"
188  genmsg_cpp.write_traits(s, spec.request, cpp_prefix, rospack=rospack)
189  s.write('\n')
190  genmsg_cpp.write_traits(s, spec.response, cpp_prefix, rospack=rospack)
191  genmsg_cpp.write_serialization(s, spec.request, cpp_prefix)
192  s.write('\n')
193  genmsg_cpp.write_serialization(s, spec.response, cpp_prefix)
194 
195  write_traits(s, spec, cpp_prefix, rospack=rospack)
196 
197  write_end(s, spec)
198 
199  output_dir = '%s/srv_gen/cpp/include/%s'%(package_dir, package)
200  if (not os.path.exists(output_dir)):
201  # if we're being run concurrently, the above test can report false but os.makedirs can still fail if
202  # another copy just created the directory
203  try:
204  os.makedirs(output_dir)
205  except OSError as e:
206  pass
207 
208  f = open('%s/%s.h'%(output_dir, spec.short_name), 'w')
209  f.write(s.getvalue() + "\n")
210 
211  s.close()
212 
214  for arg in argv[1:]:
215  generate(arg)
216 
217 if __name__ == "__main__":
218  roslib.msgs.set_verbose(False)
219  generate_services(sys.argv)
220 
221 
def generate(srv_path)
Definition: gensrv_cpp.py:146
def generate_services(argv)
Definition: gensrv_cpp.py:213
def write_traits(s, spec, cpp_name_prefix, rospack=None)
Definition: gensrv_cpp.py:117
def write_trait_char_class(s, class_name, cpp_msg, value)
Definition: gensrv_cpp.py:91
def write_generic_includes(s)
Definition: gensrv_cpp.py:82
def write_end(s, spec)
Definition: gensrv_cpp.py:71
def write_begin(s, spec, file)
Definition: gensrv_cpp.py:56


roscpp
Author(s): Morgan Quigley, Josh Faust, Brian Gerkey, Troy Straszheim, Dirk Thomas
autogenerated on Mon Nov 2 2020 03:52:26