sdbus++: generate header for server bindings
Add a 'server-header' command to sdbus++ that generates a class
definition for the server bindings. This class defines static
functions for registering as sd-bus callbacks and virtual C++
functions to implement the method behavior.
It is expected that a server implementation will create a class,
which inherits from this generated class, and implement all of
the method behaviors. Instances of the class will then register
on construction with sd-bus.
Signals and properties are not yet supported.
Change-Id: If0ec37b2acb6f8d528358004ec91dbe979644df7
Signed-off-by: Patrick Williams <patrick@stwcx.xyz>
diff --git a/tools/sdbus++ b/tools/sdbus++
index e68685d..6606d07 100755
--- a/tools/sdbus++
+++ b/tools/sdbus++
@@ -5,7 +5,8 @@
def main():
valid_types = { 'interface': sdbusplus.Interface }
- valid_processes = { 'markdown' : "markdown" }
+ valid_processes = { 'markdown' : "markdown",
+ 'server-header' : "server_header" }
parser = argparse.ArgumentParser(description='Process sdbus++ YAML files.')
diff --git a/tools/sdbusplus/interface.py b/tools/sdbusplus/interface.py
index 0cdb1a0..fa56eb9 100644
--- a/tools/sdbusplus/interface.py
+++ b/tools/sdbusplus/interface.py
@@ -30,3 +30,6 @@
def markdown(self, loader):
return self.render(loader, "interface.mako.md", interface=self)
+
+ def server_header(self, loader):
+ return self.render(loader, "interface.mako.server.hpp", interface=self)
diff --git a/tools/sdbusplus/method.py b/tools/sdbusplus/method.py
index f8e2efd..84d6095 100644
--- a/tools/sdbusplus/method.py
+++ b/tools/sdbusplus/method.py
@@ -14,3 +14,7 @@
def markdown(self, loader):
return self.render(loader, "method.mako.md", method=self)
+
+ def cpp_prototype(self, loader, interface, ptype):
+ return self.render(loader, "method.mako.prototype.hpp", method=self,
+ interface=interface, ptype=ptype, post=str.rstrip)
diff --git a/tools/templates/interface.mako.server.hpp b/tools/templates/interface.mako.server.hpp
new file mode 100644
index 0000000..ff18548
--- /dev/null
+++ b/tools/templates/interface.mako.server.hpp
@@ -0,0 +1,37 @@
+#pragma once
+#include <tuple>
+#include <systemd/sd-bus.h>
+#include <sdbusplus/vtable.hpp>
+ <%
+ namespaces = interface.name.split('.')
+ classname = namespaces.pop()
+ %>
+namespace sdbusplus
+{
+namespace server
+{
+ % for s in namespaces:
+namespace ${s}
+{
+ % endfor
+
+class ${classname}
+{
+ public:
+ % for m in interface.methods:
+${ m.cpp_prototype(loader, interface=interface, ptype='header') }
+ % endfor
+
+ private:
+ % for m in interface.methods:
+${ m.cpp_prototype(loader, interface=interface, ptype='callback-header') }
+ % endfor
+
+ static const sdbusplus::vtable::vtable_t _vtable[];
+};
+
+ % for s in namespaces:
+} // namespace ${s}
+ % endfor
+} // namespace server
+} // namespace sdbusplus
diff --git a/tools/templates/method.mako.prototype.hpp b/tools/templates/method.mako.prototype.hpp
new file mode 100644
index 0000000..5055dbb
--- /dev/null
+++ b/tools/templates/method.mako.prototype.hpp
@@ -0,0 +1,57 @@
+<%
+ def cpp_return_type():
+ if len(method.returns) == 0:
+ return "void"
+ elif len(method.returns) == 1:
+ return method.returns[0].typeName
+ else:
+ return "std::tuple<" + \
+ ", ".join([ r.typeName for r in method.returns ]) + \
+ ">"
+
+ def parameters(defaultValue=False):
+ return ",\n ".\
+ join([ parameter(p, defaultValue) for p in method.parameters ])
+
+ def parameter(p, defaultValue=False):
+ r = "%s %s" % (p.typeName, p.name)
+ if defaultValue:
+ r += default_value(p)
+ return r
+
+ def default_value(p):
+ if p.defaultValue != None:
+ return " = " + str(p.defaultValue)
+ else:
+ return ""
+%>
+###
+### Emit 'header'
+###
+ % if ptype == 'header':
+ /** @brief Implementation for ${ method.name }
+ * ${ method.description.strip() }
+ % if len(method.parameters) != 0:
+ *
+ % for p in method.parameters:
+ * @param[in] ${p.name} - ${p.description.strip()}
+ % endfor
+ % endif
+ % if len(method.returns) != 0:
+ *
+ % for r in method.returns:
+ * @return ${r.name}[${r.typeName}] - ${r.description.strip()}
+ % endfor
+ % endif
+ */
+ virtual ${cpp_return_type()} ${ method.name }(
+ ${ parameters() }) = 0;
+###
+### Emit 'callback-header'
+###
+ % elif ptype == 'callback-header':
+ /** @brief sd-bus callback for ${ method.name }
+ */
+ static int _callback_${ method.name }(
+ sd_bus_message*, void*, sd_bus_error*);
+ % endif