sdbus++: generate vtable for server bindings

Change-Id: I605a5f5db4fb2d395acab533305c7d52638fe4ce
Signed-off-by: Patrick Williams <patrick@stwcx.xyz>
diff --git a/tools/templates/interface.mako.server.cpp b/tools/templates/interface.mako.server.cpp
index 590ee6b..382ae7c 100644
--- a/tools/templates/interface.mako.server.cpp
+++ b/tools/templates/interface.mako.server.cpp
@@ -24,6 +24,14 @@
 ${ m.cpp_prototype(loader, interface=interface, ptype='callback-cpp') }
     % endfor
 
+const vtable::vtable_t ${classname}::_vtable[] = {
+    vtable::start(),
+    % for m in interface.methods:
+${ m.cpp_prototype(loader, interface=interface, ptype='vtable') }
+    % endfor
+    vtable::end()
+};
+
     % for s in namespaces:
 } // namespace ${s}
     % endfor
diff --git a/tools/templates/method.mako.prototype.hpp b/tools/templates/method.mako.prototype.hpp
index e26e726..29d75c8 100644
--- a/tools/templates/method.mako.prototype.hpp
+++ b/tools/templates/method.mako.prototype.hpp
@@ -6,7 +6,7 @@
             return method.returns[0].typeName
         else:
             return "std::tuple<" + \
-                   ", ".join([ r.typeName for r in method.returns ]) + \
+                   returns_as_list() + \
                    ">"
 
     def parameters(defaultValue=False):
@@ -19,12 +19,18 @@
     def parameters_as_list():
         return ", ".join([ p.camelCase for p in method.parameters ])
 
+    def parameters_types_as_list():
+        return ", ".join([ p.typeName for p in method.parameters ])
+
     def parameter(p, defaultValue=False):
         r = "%s %s" % (p.typeName, p.camelCase)
         if defaultValue:
             r += default_value(p)
         return r
 
+    def returns_as_list():
+        return ", ".join([ r.typeName for r in method.returns ])
+
     def returns_as_tuple_index(tuple):
         return ", ".join([ "std::move(std::get<%d>(%s))" % (i,tuple) \
                 for i in range(len(method.returns))])
@@ -68,6 +74,16 @@
         static int _callback_${ method.CamelCase }(
             sd_bus_message*, void*, sd_bus_error*);
 ###
+### Emit 'vtable'
+###
+    % elif ptype == 'vtable':
+    vtable::method("${method.name}",
+                   details::${interface_name()}::_param_${ method.CamelCase }
+                        .data(),
+                   details::${interface_name()}::_return_${ method.CamelCase }
+                        .data(),
+                   _callback_${ method.CamelCase }),
+###
 ### Emit 'callback-cpp'
 ###
     % elif ptype == 'callback-cpp':
@@ -102,4 +118,25 @@
 
     return 0;
 }
+
+namespace details
+{
+namespace ${interface_name()}
+{
+static const auto _param_${ method.CamelCase } =
+    % if len(method.parameters) == 0:
+        utility::tuple_to_array(std::make_tuple('\0'));
+    % else:
+        utility::tuple_to_array(message::types::type_id<
+                ${ parameters_types_as_list() }>());
+    % endif
+static const auto _return_${ method.CamelCase } =
+    % if len(method.parameters) == 0:
+        utility::tuple_to_array(std::make_tuple('\0'));
+    % else:
+        utility::tuple_to_array(message::types::type_id<
+                ${ returns_as_list() }>());
+    % endif
+}
+}
     % endif