7 from vapi_c_gen import CField, CEnum, CStruct, CSimpleType, CStructType,\
8 CMessage, json_to_c_header_name, CAlias
9 from vapi_json_parser import JsonParser
12 class CppField(CField):
16 class CppStruct(CStruct):
24 class CppAlias(CAlias):
28 class CppSimpleType (CSimpleType):
32 class CppStructType (CStructType, CppStruct):
36 class CppMessage (CMessage):
37 def get_swap_to_be_template_instantiation(self):
39 "template <> inline void vapi_swap_to_be<%s>(%s *msg)" %
40 (self.get_c_name(), self.get_c_name()),
42 " %s(msg);" % self.get_swap_to_be_func_name(),
46 def get_swap_to_host_template_instantiation(self):
48 "template <> inline void vapi_swap_to_host<%s>(%s *msg)" %
49 (self.get_c_name(), self.get_c_name()),
51 " %s(msg);" % self.get_swap_to_host_func_name(),
55 def get_alloc_template_instantiation(self):
57 "template <> inline %s* vapi_alloc<%s%s>"
58 "(Connection &con%s)" %
59 (self.get_c_name(), self.get_c_name(),
60 ", size_t" * len(self.get_alloc_vla_param_names()),
61 "".join([", size_t %s" % n for n in
62 self.get_alloc_vla_param_names()])
65 " %s* result = %s(con.vapi_ctx%s);" %
66 (self.get_c_name(), self.get_alloc_func_name(),
68 for n in self.get_alloc_vla_param_names()])),
69 "#if VAPI_CPP_DEBUG_LEAKS",
70 " con.on_shm_data_alloc(result);",
76 def get_cpp_name(self):
77 return "%s%s" % (self.name[0].upper(), self.name[1:])
79 def get_req_template_name(self):
80 if self.reply_is_stream:
85 return "%s<%s, %s%s>" % (
88 self.reply.get_c_name(),
89 "".join([", size_t"] * len(self.get_alloc_vla_param_names()))
92 def get_req_template_instantiation(self):
93 return "template class %s;" % self.get_req_template_name()
95 def get_type_alias(self):
96 return "using %s = %s;" % (
97 self.get_cpp_name(), self.get_req_template_name())
99 def get_reply_template_name(self):
100 return "Msg<%s>" % (self.get_c_name())
102 def get_reply_type_alias(self):
103 return "using %s = %s;" % (
104 self.get_cpp_name(), self.get_reply_template_name())
106 def get_msg_class_instantiation(self):
107 return "template class Msg<%s>;" % self.get_c_name()
109 def get_get_msg_id_t_instantiation(self):
111 ("template <> inline vapi_msg_id_t vapi_get_msg_id_t<%s>()"
112 % self.get_c_name()),
114 " return ::%s; " % self.get_msg_id_name(),
117 ("template <> inline vapi_msg_id_t "
118 "vapi_get_msg_id_t<Msg<%s>>()" % self.get_c_name()),
120 " return ::%s; " % self.get_msg_id_name(),
124 def get_cpp_constructor(self):
126 ('static void __attribute__((constructor)) '
127 '__vapi_cpp_constructor_%s()'
130 (' vapi::vapi_msg_set_msg_id<%s>(%s);' % (
131 self.get_c_name(), self.get_msg_id_name())),
136 def gen_json_header(parser, logger, j, io, gen_h_prefix, add_debug_comments):
137 logger.info("Generating header `%s'" % io.name)
138 orig_stdout = sys.stdout
140 d, f = os.path.split(j)
141 include_guard = "__included_hpp_%s" % (
142 f.replace(".", "_").replace("/", "_").replace("-", "_").replace(
144 print("#ifndef %s" % include_guard)
145 print("#define %s" % include_guard)
147 print("#include <vapi/vapi.hpp>")
148 print("#include <%s%s>" % (gen_h_prefix, json_to_c_header_name(f)))
150 print("namespace vapi {")
152 for m in parser.messages_by_json[j].values():
153 # utility functions need to go first, otherwise internal instantiation
154 # causes headaches ...
155 if add_debug_comments:
156 print("/* m.get_swap_to_be_template_instantiation() */")
157 print("%s" % m.get_swap_to_be_template_instantiation())
159 if add_debug_comments:
160 print("/* m.get_swap_to_host_template_instantiation() */")
161 print("%s" % m.get_swap_to_host_template_instantiation())
163 if add_debug_comments:
164 print("/* m.get_get_msg_id_t_instantiation() */")
165 print("%s" % m.get_get_msg_id_t_instantiation())
167 if add_debug_comments:
168 print("/* m.get_cpp_constructor() */")
169 print("%s" % m.get_cpp_constructor())
171 if not m.is_reply and not m.is_event:
172 if add_debug_comments:
173 print("/* m.get_alloc_template_instantiation() */")
174 print("%s" % m.get_alloc_template_instantiation())
176 if add_debug_comments:
177 print("/* m.get_msg_class_instantiation() */")
178 print("%s" % m.get_msg_class_instantiation())
180 if m.is_reply or m.is_event:
181 if add_debug_comments:
182 print("/* m.get_reply_type_alias() */")
183 print("%s" % m.get_reply_type_alias())
185 if add_debug_comments:
186 print("/* m.get_req_template_instantiation() */")
187 print("%s" % m.get_req_template_instantiation())
189 if add_debug_comments:
190 print("/* m.get_type_alias() */")
191 print("%s" % m.get_type_alias())
193 print("}") # namespace vapi
196 sys.stdout = orig_stdout
199 def json_to_cpp_header_name(json_name):
200 if json_name.endswith(".json"):
201 return "%s.vapi.hpp" % os.path.splitext(json_name)[0]
202 raise Exception("Unexpected json name `%s'!" % json_name)
205 def gen_cpp_headers(parser, logger, prefix, gen_h_prefix, remove_path,
206 add_debug_comments=False):
207 if prefix == "" or prefix is None:
210 prefix = "%s/" % prefix
211 if gen_h_prefix is None:
214 gen_h_prefix = "%s/" % gen_h_prefix
215 for j in parser.json_files:
217 d, f = os.path.split(j)
220 with open('%s%s' % (prefix, json_to_cpp_header_name(f)), "w") as io:
221 gen_json_header(parser, logger, j, io,
222 gen_h_prefix, add_debug_comments)
225 if __name__ == '__main__':
227 verbose = int(os.getenv("V", 0))
238 logging.basicConfig(stream=sys.stdout, level=log_level)
239 logger = logging.getLogger("VAPI CPP GEN")
240 logger.setLevel(log_level)
242 argparser = argparse.ArgumentParser(description="VPP C++ API generator")
243 argparser.add_argument('files', metavar='api-file', action='append',
244 type=str, help='json api file'
245 '(may be specified multiple times)')
246 argparser.add_argument('--prefix', action='store', default=None,
248 argparser.add_argument('--gen-h-prefix', action='store', default=None,
249 help='generated C header prefix')
250 argparser.add_argument('--remove-path', action='store_true',
251 help='remove path from filename')
252 args = argparser.parse_args()
254 jsonparser = JsonParser(logger, args.files,
255 simple_type_class=CppSimpleType,
256 struct_type_class=CppStructType,
257 field_class=CppField,
259 message_class=CppMessage,
260 alias_class=CppAlias)
262 gen_cpp_headers(jsonparser, logger, args.prefix, args.gen_h_prefix,
265 for e in jsonparser.exceptions: