example: create calculator server app

Change-Id: Ie2ad4ff00208056c48c0d596053b20b82f1fb3a1
Signed-off-by: Patrick Williams <patrick@stwcx.xyz>
diff --git a/Makefile.am b/Makefile.am
index 2a24517..288b0a8 100644
--- a/Makefile.am
+++ b/Makefile.am
@@ -43,4 +43,4 @@
 pkgconfiglib_DATA = sdbusplus.pc
 
 endif
-SUBDIRS = test tools
+SUBDIRS = . tools example test
diff --git a/configure.ac b/configure.ac
index 493ca4f..d2156ab 100644
--- a/configure.ac
+++ b/configure.ac
@@ -86,6 +86,7 @@
 
 # Create configured output
 AC_CONFIG_FILES([Makefile test/Makefile tools/Makefile tools/setup.py])
+AC_CONFIG_FILES([example/Makefile])
 AC_CONFIG_FILES([sdbusplus.pc])
 AC_CONFIG_FILES([sdbusplus/bus.hpp])
 AC_CONFIG_FILES([sdbusplus/server.hpp])
diff --git a/example/Makefile.am b/example/Makefile.am
new file mode 100644
index 0000000..c9fb907
--- /dev/null
+++ b/example/Makefile.am
@@ -0,0 +1,44 @@
+noinst_PROGRAMS = calculator-server
+
+calculator_server_generated_files = \
+	net/poettering/Calculator/server.hpp \
+	net/poettering/Calculator/server.cpp \
+	net/poettering/Calculator/error.hpp \
+	net/poettering/Calculator/error.cpp
+
+calculator_markdown_generated_files = \
+	calculator.md
+
+calculator_server_SOURCES = \
+	calculator-server.cpp $(calculator_server_generated_files)
+calculator_server_CXXFLAGS = $(SYSTEMD_CFLAGS)
+calculator_server_LDADD = $(SYSTEMD_LIBS) ../libsdbusplus.la
+
+BUILT_SOURCES = \
+	$(calculator_server_generated_files) \
+	$(calculator_markdown_generated_files)
+CLEANFILES = \
+	$(calculator_server_generated_files) \
+	$(calculator_markdown_generated_files)
+
+net/poettering/Calculator/server.hpp:
+	@top_srcdir@/tools/sdbus++ -r . \
+	    interface server-header net.poettering.Calculator > $@
+
+net/poettering/Calculator/server.cpp:
+	@top_srcdir@/tools/sdbus++ -r . \
+	    interface server-cpp net.poettering.Calculator > $@
+
+net/poettering/Calculator/error.hpp:
+	@top_srcdir@/tools/sdbus++ -r . \
+	    error exception-header net.poettering.Calculator > $@
+
+net/poettering/Calculator/error.cpp:
+	@top_srcdir@/tools/sdbus++ -r . \
+	    error exception-cpp net.poettering.Calculator > $@
+
+calculator.md:
+	@top_srcdir@/tools/sdbus++ -r . \
+	    interface markdown net.poettering.Calculator > $@
+	@top_srcdir@/tools/sdbus++ -r . \
+	    error markdown net.poettering.Calculator >> $@
diff --git a/example/calculator-server.cpp b/example/calculator-server.cpp
new file mode 100644
index 0000000..e72c493
--- /dev/null
+++ b/example/calculator-server.cpp
@@ -0,0 +1,72 @@
+#include <iostream>
+#include <sdbusplus/server.hpp>
+#include <net/poettering/Calculator/server.hpp>
+#include <net/poettering/Calculator/error.hpp>
+
+using Calculator_inherit = sdbusplus::server::object_t<
+        sdbusplus::net::poettering::server::Calculator>;
+
+/** Example implementation of net.poettering.Calculator */
+struct Calculator : Calculator_inherit
+{
+    /** Constructor */
+    Calculator(sdbusplus::bus::bus& bus, const char* path) :
+        Calculator_inherit(bus, path) { }
+
+    /** Multiply (x*y), update lastResult */
+    int64_t multiply(int64_t x, int64_t y) override
+    {
+        return lastResult(x*y);
+    }
+
+    /** Divide (x/y), update lastResult
+     *
+     *  Throws DivisionByZero on error.
+     */
+    int64_t divide(int64_t x, int64_t y) override
+    {
+        using sdbusplus::net::poettering::Calculator::Error::DivisionByZero;
+        if (y == 0)
+        {
+            status(State::Error);
+            throw DivisionByZero();
+        }
+
+        return lastResult(x/y);
+    }
+
+    /** Clear lastResult, broadcast 'Cleared' signal */
+    void clear() override
+    {
+        auto v = lastResult();
+        lastResult(0);
+        cleared(v);
+        return;
+    }
+};
+
+int main()
+{
+    // Define a dbus path location to place the object.
+    constexpr auto path = "/net/poettering/calculator";
+
+    // Create a new bus and affix an object manager for the subtree path we
+    // intend to place objects at..
+    auto b = sdbusplus::bus::new_default();
+    sdbusplus::server::manager_t m{b, path};
+
+    // Reserve the dbus service name : net.poettering.Calculator
+    b.request_name("net.poettering.Calculator");
+
+    // Create a calculator object at /net/poettering/calculator
+    Calculator c1{b, path};
+
+    // Handle dbus processing forever.
+    while(1)
+    {
+        b.process_discard(); // discard any unhandled messages
+        b.wait();
+    }
+
+    return 0;
+}