7 from vapi_c_gen import (
14 json_to_c_header_name,
17 from vapi_json_parser import JsonParser
20 class CppField(CField):
24 class CppStruct(CStruct):
32 class CppAlias(CAlias):
36 class CppSimpleType(CSimpleType):
40 class CppStructType(CStructType, CppStruct):
44 class CppMessage(CMessage):
45 def get_swap_to_be_template_instantiation(self):
48 "template <> inline void vapi_swap_to_be<%s>(%s *msg)"
49 % (self.get_c_name(), self.get_c_name()),
51 " %s(msg);" % self.get_swap_to_be_func_name(),
56 def get_swap_to_host_template_instantiation(self):
59 "template <> inline void vapi_swap_to_host<%s>(%s *msg)"
60 % (self.get_c_name(), self.get_c_name()),
62 " %s(msg);" % self.get_swap_to_host_func_name(),
67 def get_alloc_template_instantiation(self):
70 "template <> inline %s* vapi_alloc<%s%s>"
75 ", size_t" * len(self.get_alloc_vla_param_names()),
77 [", size_t %s" % n for n in self.get_alloc_vla_param_names()]
81 " %s* result = %s(con.vapi_ctx%s);"
84 self.get_alloc_func_name(),
85 "".join([", %s" % n for n in self.get_alloc_vla_param_names()]),
87 "#if VAPI_CPP_DEBUG_LEAKS",
88 " con.on_shm_data_alloc(result);",
95 def get_cpp_name(self):
96 return "%s%s" % (self.name[0].upper(), self.name[1:])
98 def get_req_template_name(self):
99 if self.reply_is_stream:
104 return "%s<%s, %s%s>" % (
107 self.reply.get_c_name(),
108 "".join([", size_t"] * len(self.get_alloc_vla_param_names())),
111 def get_req_template_instantiation(self):
112 return "template class %s;" % self.get_req_template_name()
114 def get_type_alias(self):
115 return "using %s = %s;" % (self.get_cpp_name(), self.get_req_template_name())
117 def get_reply_template_name(self):
118 return "Msg<%s>" % (self.get_c_name())
120 def get_reply_type_alias(self):
121 return "using %s = %s;" % (self.get_cpp_name(), self.get_reply_template_name())
123 def get_msg_class_instantiation(self):
124 return "template class Msg<%s>;" % self.get_c_name()
126 def get_get_msg_id_t_instantiation(self):
130 "template <> inline vapi_msg_id_t vapi_get_msg_id_t<%s>()"
134 " return ::%s; " % self.get_msg_id_name(),
138 "template <> inline vapi_msg_id_t "
139 "vapi_get_msg_id_t<Msg<%s>>()" % self.get_c_name()
142 " return ::%s; " % self.get_msg_id_name(),
147 def get_cpp_constructor(self):
151 "static void __attribute__((constructor)) "
152 "__vapi_cpp_constructor_%s()" % self.name
156 " vapi::vapi_msg_set_msg_id<%s>(%s);"
157 % (self.get_c_name(), self.get_msg_id_name())
164 def gen_json_header(parser, logger, j, io, gen_h_prefix, add_debug_comments):
165 logger.info("Generating header `%s'" % io.name)
166 orig_stdout = sys.stdout
168 d, f = os.path.split(j)
169 include_guard = "__included_hpp_%s" % (
170 f.replace(".", "_").replace("/", "_").replace("-", "_").replace("@", "_")
172 print("#ifndef %s" % include_guard)
173 print("#define %s" % include_guard)
175 print("#include <vapi/vapi.hpp>")
176 print("#include <%s%s>" % (gen_h_prefix, json_to_c_header_name(f)))
178 print("namespace vapi {")
180 for m in parser.messages_by_json[j].values():
181 # utility functions need to go first, otherwise internal instantiation
182 # causes headaches ...
183 if add_debug_comments:
184 print("/* m.get_swap_to_be_template_instantiation() */")
185 print("%s" % m.get_swap_to_be_template_instantiation())
187 if add_debug_comments:
188 print("/* m.get_swap_to_host_template_instantiation() */")
189 print("%s" % m.get_swap_to_host_template_instantiation())
191 if add_debug_comments:
192 print("/* m.get_get_msg_id_t_instantiation() */")
193 print("%s" % m.get_get_msg_id_t_instantiation())
195 if add_debug_comments:
196 print("/* m.get_cpp_constructor() */")
197 print("%s" % m.get_cpp_constructor())
199 if not m.is_reply and not m.is_event:
200 if add_debug_comments:
201 print("/* m.get_alloc_template_instantiation() */")
202 print("%s" % m.get_alloc_template_instantiation())
204 if add_debug_comments:
205 print("/* m.get_msg_class_instantiation() */")
206 print("%s" % m.get_msg_class_instantiation())
208 if m.is_reply or m.is_event:
209 if add_debug_comments:
210 print("/* m.get_reply_type_alias() */")
211 print("%s" % m.get_reply_type_alias())
213 if add_debug_comments:
214 print("/* m.get_req_template_instantiation() */")
215 print("%s" % m.get_req_template_instantiation())
217 if add_debug_comments:
218 print("/* m.get_type_alias() */")
219 print("%s" % m.get_type_alias())
221 print("}") # namespace vapi
224 sys.stdout = orig_stdout
227 def json_to_cpp_header_name(json_name):
228 if json_name.endswith(".json"):
229 return "%s.vapi.hpp" % os.path.splitext(json_name)[0]
230 raise Exception("Unexpected json name `%s'!" % json_name)
234 parser, logger, prefix, gen_h_prefix, remove_path, add_debug_comments=False
236 if prefix == "" or prefix is None:
239 prefix = "%s/" % prefix
240 if gen_h_prefix is None:
243 gen_h_prefix = "%s/" % gen_h_prefix
244 for j in parser.json_files:
246 d, f = os.path.split(j)
249 with open("%s%s" % (prefix, json_to_cpp_header_name(f)), "w") as io:
250 gen_json_header(parser, logger, j, io, gen_h_prefix, add_debug_comments)
253 if __name__ == "__main__":
255 verbose = int(os.getenv("V", 0))
266 logging.basicConfig(stream=sys.stdout, level=log_level)
267 logger = logging.getLogger("VAPI CPP GEN")
268 logger.setLevel(log_level)
270 argparser = argparse.ArgumentParser(description="VPP C++ API generator")
271 argparser.add_argument(
276 help="json api file" "(may be specified multiple times)",
278 argparser.add_argument("--prefix", action="store", default=None, help="path prefix")
279 argparser.add_argument(
280 "--gen-h-prefix", action="store", default=None, help="generated C header prefix"
282 argparser.add_argument(
283 "--remove-path", action="store_true", help="remove path from filename"
285 args = argparser.parse_args()
287 jsonparser = JsonParser(
290 simple_type_class=CppSimpleType,
291 struct_type_class=CppStructType,
292 field_class=CppField,
294 message_class=CppMessage,
295 alias_class=CppAlias,
299 jsonparser, logger, args.prefix, args.gen_h_prefix, args.remove_path
302 for e in jsonparser.exceptions: