7a706b90c3
clang 2.8 compiles SyncEvolution + Synthesis faster than g++ 4.4.5 (3:40min instead of 4:10min on my laptop) and produces more useful error reports. This patch fixes the code so that it compiles cleanly with clang when using "-Wall -Werror -Wno-unknown-pragmas". Note that clang 2.6 (Debian Squeeze) goes into an infinite recursion compiling code using gdbus-cxx-bridge.h and dies eventually with a stack overflow - can't be used. Changes necessary for clang: - eptr pointer referencing ambiguous, use *x.get() instead - boost::intrusive_ptr* must be defined before code using it - two-phase template checking requires explicitly specifying members in base classes - name clashes with plain C structs (DBusServer, DBusWatch) are an error and need to be avoided (done with namespaces GDBusCXX and SyncEvo) - floats cannot be inline constants - unused methods in local classes are warned about (left() in SyncML.cpp)
290 lines
7.8 KiB
C++
290 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::auto_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(DBusConnection *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[])
|
|
{
|
|
DBusConnection *conn;
|
|
DBusError 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);
|
|
|
|
dbus_error_init(&err);
|
|
|
|
conn = b_dbus_setup_bus(DBUS_BUS_SESSION, "org.example", false, &err);
|
|
if (conn == NULL) {
|
|
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::auto_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();
|
|
|
|
b_dbus_cleanup_connection(conn);
|
|
|
|
g_main_loop_unref(main_loop);
|
|
|
|
return 0;
|
|
}
|