syncevolution/src/gdbus/test/example.cpp

287 lines
7.8 KiB
C++

/*
*
* Library for simple D-Bus integration with GLib
*
* Copyright (C) 2009 Intel Corporation. All rights reserved.
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License version 2 as
* published by the Free Software Foundation.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
*
*/
#ifdef HAVE_CONFIG_H
#include <config.h>
#endif
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <stdint.h>
#include <sys/signal.h>
#include "gdbus-cxx-bridge.h"
#include <memory>
#include <iostream>
namespace GDBusCXX {
struct args {
int a;
std::string b;
std::map<std::string, std::string> c;
};
static void hello_global() {}
class Test {
typedef boost::shared_ptr< Result1<const std::string&> > string_result;
struct async
{
async(const boost::shared_ptr<Watch> &watch, Watch *watch2, const string_result &result):
m_watch(watch),
m_watch2(watch2),
m_result(result)
{}
~async()
{
delete m_watch2;
}
boost::shared_ptr<Watch> m_watch;
Watch *m_watch2;
string_result m_result;
};
static gboolean method_idle(gpointer data)
{
std::unique_ptr<async> mydata(static_cast<async *>(data));
std::cout << "replying to method_async" << std::endl;
mydata->m_result->done("Hello World, asynchronous and delayed");
return false;
}
static void disconnect(const std::string &id, const std::string &peer)
{
std::cout << id << ": " << peer << " has disconnected." << std::endl;
}
public:
static void hello_static() {}
void hello_const() const {}
static void hello_world(const char *msg) { puts(msg); }
void hello_base() {}
void method(std::string &text)
{
text = "Hello World";
}
void method_async(const Caller_t &caller,
const boost::shared_ptr<Watch> &watch,
int32_t secs,
const string_result &r)
{
watch->setCallback(boost::bind(disconnect, "watch1", caller));
Watch *watch2 = r->createWatch(boost::bind(disconnect, "watch2", caller));
std::cout << "method_async called by " << caller << " delay " << secs << std::endl;
g_timeout_add_seconds(secs, method_idle, new async(watch, watch2, r));
}
void method2(int32_t arg, int32_t &ret)
{
ret = arg * 2;
}
int32_t method3(int32_t arg)
{
return arg * 3;
}
void method8_simple(int32_t a1, int32_t a2, int32_t a3, int32_t a4, int32_t a5,
int32_t a6, int32_t a7, int32_t a8)
{
}
void method9_async(Result9<int32_t, int32_t, int32_t, int32_t, int32_t,
int32_t, int32_t, int32_t, int32_t> *r)
{
r->done(1, 2, 3, 4, 5, 6, 7, 8, 9);
delete r;
}
int32_t method9(int32_t a1, int32_t a2, int32_t a3, int32_t a4, int32_t a5,
int32_t a6, int32_t a7, int32_t a8, int32_t a9)
{
return 0;
}
void hash(const std::map<int8_t, int32_t> &in, std::map<int16_t, int32_t> &out)
{
for (std::map<int8_t, int32_t>::const_iterator it = in.begin();
it != in.end();
++it) {
out.insert(std::make_pair((int16_t)it->first, it->second * it->second));
}
}
void array(const std::vector<int32_t> &in, std::vector<int32_t> &out)
{
for (std::vector<int32_t>::const_iterator it = in.begin();
it != in.end();
++it) {
out.push_back(*it * *it);
}
}
void error()
{
throw dbus_error("org.example.error.Invalid", "error");
}
void argtest(const args &in, args &out)
{
out = in;
out.a = in.a + 1;
}
};
class Test2
{
public:
void test2() {}
};
template<> struct dbus_traits<args> :
public dbus_struct_traits<args, dbus_member<args, int, &args::a,
dbus_member<args, std::string, &args::b,
dbus_member_single<args, std::map<std::string, std::string>, &args::c> > > >
{};
class DBusTest : public Test, private Test2
{
DBusObjectHelper m_object;
DBusObjectHelper m_secondary;
public:
DBusTest(const DBusConnectionPtr conn) :
m_object(conn, "/test", "org.example.Test"),
// same path!
m_secondary(conn, m_object.getPath(), "org.example.Secondary"),
signal(m_object, "Signal")
{
m_object.add(this, &Test::method8_simple, "Method8Simple");
// m_object.add(this, &Test::method10_async, "Method10Async", G_DBUS_METHOD_FLAG_ASYNC);
// m_object.add(this, &Test::method9, "Method9");
m_object.add(this, &Test::method2, "Method2");
m_object.add(this, &Test::method3, "Method3");
m_object.add(this, &Test::method, "Test");
m_object.add(this, &Test::method_async, "TestAsync");
m_object.add(this, &Test::argtest, "ArgTest");
m_object.add(this, &Test::hash, "Hash");
m_object.add(this, &Test::array, "Array");
m_object.add(this, &Test::error, "Error");
m_object.add(&hello_global, "Global");
m_object.add(&DBusTest::hello_static, "Static");
m_object.add(static_cast<Test2 *>(this), &Test2::test2, "Private");
// The hello_const() method cannot be registered
// because there is no matching MakeMethodEntry<>
// specialization for it or DBusObjectHelper::add()
// fails to determine the right function type,
// depending how one wants to interpret the problem.
// m_object.add2(this, &DBusTest::hello_const, "Const");
m_object.add(signal);
m_secondary.add(this, &DBusTest::hello, "Hello");
}
~DBusTest()
{
}
EmitSignal3<int32_t, const std::string &, const std::map<int32_t, int32_t> &>signal;
void hello() {}
static void hello_static() {}
void hello_const() const {}
void activate()
{
m_secondary.activate();
m_object.activate();
}
void deactivate()
{
m_object.deactivate();
m_secondary.deactivate();
}
};
static GMainLoop *main_loop = NULL;
static void sig_term(int sig)
{
g_main_loop_quit(main_loop);
}
} // namespace GDBusCXX
using namespace GDBusCXX;
int main(int argc, char *argv[])
{
DBusConnectionPtr conn;
DBusErrorCXX err;
struct sigaction sa;
memset(&sa, 0, sizeof(sa));
sa.sa_handler = sig_term;
sigaction(SIGINT, &sa, NULL);
sigaction(SIGTERM, &sa, NULL);
sa.sa_handler = SIG_IGN;
sigaction(SIGCHLD, &sa, NULL);
sigaction(SIGPIPE, &sa, NULL);
main_loop = g_main_loop_new(NULL, FALSE);
conn = dbus_get_bus_connection("SESSION", "org.example", false, &err);
if (!conn) {
if (dbus_error_is_set(&err) == TRUE) {
fprintf(stderr, "%s\n", err.message);
dbus_error_free(&err);
} else
fprintf(stderr, "Can't register with session bus\n");
exit(1);
}
std::unique_ptr<DBusTest> test(new DBusTest(conn));
test->activate();
test->signal(42, "hello world", std::map<int32_t, int32_t>());
test->deactivate();
test->activate();
test->signal(123, "here I am again", std::map<int32_t, int32_t>());
g_main_loop_run(main_loop);
test.reset();
g_main_loop_unref(main_loop);
return 0;
}