一、简介

DBus的出现,使得Linux进程间通信更加便捷,不仅可以和用户空间应用程序进行通信,而且还可以和内核的程序进行通信,DBus使得Linux变得更加智能,更加具有交互性。
        DBus分为两种类型:system bus(系统总线),用于系统(Linux)和用户程序之间进行通信和消息的传递;session bus(回话总线),用于桌面(GNOME, KDE等)用户程序之间进行通信。

二、详解之Qt代码

1、代码一

(1)test.h

  1. #ifndef  TEST_H
  2. #define  TEST_H
  3. #include  <QtCore>
  4. #include  <QTimer>
  5. class Test : public QObject
  6. {
  7. Q_OBJECT
  8. public:
  9. Test();
  10. public slots:
  11. QString testStart();
  12. void changeTest();
  13. signals:
  14. void stateChange(QString str);
  15. private:
  16. QTimer *timer;
  17. };
  18. #endif  /*TEST_H*/

(2)test.cpp

  1. #include "test.h"
  2. Test::Test()
  3. {
  4. qDebug() << "===========test init===========";
  5. timer = new QTimer;
  6. connect(timer, SIGNAL(timeout()), this, SLOT(changeTest()));
  7. }
  8. QString Test::testStart()
  9. {
  10. qDebug() << "+++++++QtDBus test++++++++++";
  11. QString tmp;
  12. tmp = QString("OFF");
  13. qDebug() << tmp;
  14. if (timer->isActive()) {
  15. timer->stop();
  16. }
  17. timer->start(2000);
  18. return tmp;
  19. }
  20. void Test::changeTest()
  21. {
  22. QString tmp;
  23. tmp = QString("ON");
  24. qDebug() << "+++++++++++++++++++" << tmp;
  25. emit stateChange(tmp);
  26. }

(3)test_adaptor.h

  1. #include    "test_adaptor.h"
  2. #include    <QtCore>
  3. TestInterfaceAdaptor::TestInterfaceAdaptor(QObject *parent)
  4. :QDBusAbstractAdaptor(parent)
  5. {
  6. qDebug() << "***************TestInterfaceAdaptor::TestInterfaceAdaptor**************";
  7. setAutoRelaySignals(true);  //connection of the signals on the parent
  8. }
  9. TestInterfaceAdaptor::~TestInterfaceAdaptor()
  10. {
  11. }
  12. QString TestInterfaceAdaptor::test()
  13. {
  14. QString out;
  15. QMetaObject::invokeMethod(parent(), "testStart",Q_RETURN_ARG(QString, out));
  16. qDebug() << "==========" << out;
  17. return out;
  18. }

(4)test_adaptor.cpp

  1. #ifndef  TEST_ADAPTOR_H
  2. #define  TEST_ADAPTOR_H
  3. #include  <QtCore/QObject>
  4. #include  <QtDBus/QtDBus>
  5. /****
  6. **dbus-send --session --print-reply --dest=com.asianux.btagent /  com.asianux.btagent.adaptor.test
  7. **dbus-monitor --session \ "type='signal',interface='com.asianux.btagent.adaptor',member='stateChange'"
  8. *****/
  9. class TestInterfaceAdaptor : public QDBusAbstractAdaptor
  10. {
  11. Q_OBJECT
  12. Q_CLASSINFO("D-Bus Interface", "com.asianux.btagent.adaptor")
  13. Q_CLASSINFO("D-Bus Introspection", ""
  14. "  <interface name=\"com.asianux.btagent.adaptor\">\n"
  15. "    <method name=\"test\">\n"
  16. "      <arg name=\"state\" type=\"s\" direction=\"out\"/>\n"
  17. "    </method> \n"
  18. "    <signal name=\"stateChange\"> \n"
  19. "       <arg type=\"s\" direction=\"out\"/>\n"
  20. "    </signal> \n"
  21. "  </interface>\n"
  22. "")
  23. public:
  24. TestInterfaceAdaptor(QObject *parent);
  25. virtual ~TestInterfaceAdaptor();
  26. public:
  27. public slots:
  28. QString test();
  29. signals:
  30. void stateChange(QString str);
  31. };
  32. #endif  /*TEST_ADAPTOR_H*/

(5)main.cpp

  1. #include  <QApplication>
  2. #include  <QtDBus>
  3. #include <QDebug>
  4. #include  "test_adaptor.h"
  5. #include  "test.h"
  6. int main(int argc,char *argv[])
  7. {
  8. QApplication app(argc,argv);
  9. Test *test = new Test();
  10. new TestInterfaceAdaptor(test);
  11. QDBusConnection conn = QDBusConnection::sessionBus();
  12. conn.registerObject("/",test);
  13. conn.registerService("com.asianux.btagent");
  14. return app.exec();
  15. }

(6)运行

可以在linux终端发送(dbus-send)和监控dbus(dbus-monitor)的信息。 dbus-send调用远程方法的一般形式是:$ dbus-send [--system | --session] --type=method_call --print-reply --dest=连接名 对象路径 接口名.方法名 参数类型:参数值 参数类型:参数值,dbus-send支持的参数类型包括:string, int32, uint32, double, byte, boolean。
       启动程序后,先执行:dbus-send --session --print-reply --dest=com.asianux.btagent /  com.asianux.btagent.adaptor.test,发送dbus信号,得到输出结果:

       然后输入:dbus-monitor --session \ "type='signal',interface='com.asianux.btagent.adaptor',member='stateChange'",监控,从应用程序发出的DBus信号:

        也可以通过qt自带的工具qdbusviewer查看和操作相应的DBus信号:

(7)除了上述方法,也可以使用glib的程序进行DBus通信。
main.c:

  1. #include <stdio.h>
  2. #include <stdlib.h>
  3. #include <glib.h>
  4. #include <dbus/dbus-glib.h>
  5. #include <dbus/dbus.h>
  6. static void bt_manager_changed_cb (DBusGProxy *proxy,
  7. const gchar *state,
  8. gpointer user_data)
  9. {
  10. printf("state = %s\n",state);
  11. }
  12. int main(int argc,char *argv[])
  13. {
  14. GMainLoop *loop = g_main_loop_new(NULL,TRUE);
  15. g_type_init();
  16. GError * error = NULL;
  17. DBusGConnection *gconn = dbus_g_bus_get(DBUS_BUS_SESSION, NULL);
  18. DBusGProxy *m_proxy = dbus_g_proxy_new_for_name(gconn, "com.asianux.btagent","/","com.asianux.btagent.adaptor");
  19. char *str = NULL;
  20. dbus_g_proxy_call(m_proxy, "test", &error,
  21. G_TYPE_INVALID,
  22. G_TYPE_STRING,&str,
  23. G_TYPE_INVALID);
  24. dbus_g_proxy_add_signal (m_proxy,
  25. "stateChange",
  26. G_TYPE_STRING,
  27. G_TYPE_INVALID);
  28. dbus_g_proxy_connect_signal (m_proxy,
  29. "stateChange",
  30. G_CALLBACK (bt_manager_changed_cb),
  31. NULL,
  32. NULL);
  33. printf("str = %s\n",str);
  34. g_main_loop_run(loop);
  35. }

makefile:

  1. all:
  2. gcc -g main.c -o test `pkg-config --cflags --libs dbus-1 gthread-2.0 glib-2.0 dbus-glib-1`
  3. clean:
  4. rm -rf *.o test

运行结果(先启动最上的服务器qt程序):

2、代码二

(1)qdbus.h

  1. #ifndef QDBUS
  2. #define QDBUS
  3. #include <QtCore>
  4. /*dbus-send --session --print-reply --dest=com.asianux.btagent2 / com.asianux.btagent2.interface.slotInterface string:"helloworld"*/
  5. class DeviceManager : public QObject
  6. {
  7. Q_OBJECT
  8. Q_CLASSINFO("D-Bus Interface", "com.asianux.btagent2.interface")
  9. public:
  10. //     DeviceManager(){}
  11. //     ~DeviceManager(){}
  12. public slots:
  13. void slotInterface(QString);
  14. };
  15. #endif // QDBUS

(2)main.cpp

  1. #include <QCoreApplication>
  2. #include <QObject>
  3. #include <QtDBus>
  4. #include "qdbus.h"
  5. void DeviceManager::slotInterface(QString str)
  6. {
  7. qDebug() << "D-Bus Interface(com.asianux.btagent2.interface):" << str;
  8. }
  9. int main(int argc, char *argv[])
  10. {
  11. QCoreApplication a(argc, argv);
  12. QDBusConnection bus = QDBusConnection::sessionBus();
  13. if(!bus.registerService("com.asianux.btagent2")){
  14. qDebug() << bus.lastError().message();
  15. exit(1);
  16. }
  17. DeviceManager *deviceManager = new DeviceManager();
  18. bus.registerObject("/", deviceManager, QDBusConnection::ExportAllSlots);
  19. return a.exec();
  20. }

运行结果:

3、其他网上代码

D-Bus的QT4绑定

       下面,我们通过一个实例来介绍D-Bus的QT4绑定。(参见hotel.pro)
在Session bus上创建一个"com.test.hotel" service,通过这个service可以执行check in,check out和query三个动作。

创建Service并且注册Object:

// 用于建立到session bus的连接
    QDBusConnection bus = QDBusConnection::sessionBus();

// 在session bus上注册名为"com.test.hotel"的service
    if (!bus.registerService("com.test.hotel")){
            qDebug()<< bus.lastError().message();
            exit(1);
    }
    Hotel my_hotel;

// 注册名为"/hotel/registry"的object。
    // "QDBusConnection::ExportAllSlots"

// 表示把类Hotel的所有Slot都导出为这个Object的method
    bus.registerObject("/hotel/registry",&my_hotel,
                       QDBusConnection::ExportAllSlots);
    return a.exec();
}

再看一下Hotel类的定义。

class Hotel:public QObject
{
    Q_OBJECT

// 定义Interface名称为"com.test.hotel.registry"
    Q_CLASSINFO("D-Bus Interface","com.test.hotel.registry")
public:
    Hotel() { m_rooms = MAX_ROOMS;}
public slots:
    // Check in,参数为房间数,返回成功拿到的房间数
    int checkIn(int num_room);
    // Check out,参数为房间数,返回成功退回的房间数
    int checkOut(int num_room);
    // Query,用于查询目前还剩下的房间数 
    int query();
private:
    int m_rooms;
    QReadWriteLock m_lock;
};

运行这个程序,我们可以使用qdbusviewer查看和操作这个Object。

通过QDBusMessage访问Service

在QT4中,用QDBusMessage表示在D-Bus上发送和接收的Message。(参见checkin.pro)

// 用来构造一个在D-Bus上传递的Message
        QDBusMessage m = QDBusMessage::createMethodCall("com.test.hotel",
                                                      "/hotel/registry",
                                                      "com.test.hotel.registry",
                                                      "checkIn");
        if (argc== 2){
                // 给QDBusMessage增加一个参数;
                // 这是一种比较友好的写法,也可以用setArguments来实现
                m << QString(argv[1]).toInt();
        }

// 发送Message
        QDBusMessage response = QDBusConnection::sessionBus().call(m);
        // 判断Method是否被正确返回
        if (response.type()== QDBusMessage::ReplyMessage){
                // QDBusMessage的arguments不仅可以用来存储发送的参数,也用来存储返回值;
                // 这里取得checkIn的返回值
                int num_room = response.arguments().takeFirst().toInt();
                printf("Got %d %s\n", num_room,(num_room> 1)?"rooms": "room");
        } else {
                fprintf(stderr,"Check In fail!\n");
        }

通过QDBusInterface 访问Service

在QT4中,QDBusInterface可以更加方便的访问Service。(参见checkin2.pro)

// 创建QDBusInterface
        QDBusInterface iface( "com.test.hotel", "/hotel/registry",
                              "com.test.hotel.registry",

QDBusConnection::sessionBus());
        if (!iface.isValid()){
                qDebug()<<

qPrintable(QDBusConnection::sessionBus(). lastError().message());
                exit(1);
        }

// 呼叫远程的checkIn,参数为num_room
        QDBusReply<int> reply= iface.call("checkIn", num_room);
        if (reply.isValid()){
                num_room = reply.value();
                printf("Got %d %s\n", num_room,(num_room> 1)?"rooms": "room");
        } else {
                fprintf(stderr,"Check In fail!\n");
        }

看,用QDBusInterface来访问Service是不是更加方便?

从D-Bus XML自动生成Proxy类

用QDB usInterface访问Service已经非常方便了,但还不够直观。还有没有更直观的方法,就像访问本地类成员变量的方式访问远程的method?答案是Proxy。 
Proxy Object提供了一种更加直观的方式来访问Service,就好像调用本地对象的方法一样。 
概括的说,达成上述目标需要分三步走:
(1)使用工具qdbuscpp2xml从hotel.h生成XML文件;
            qdbuscpp2xml -M hotel.h -o com.test.hotel.xml
(2)使用工具qdbusxml2cpp从XML文件生成继承自QDBusInterface的类;
            qdbusxml2cpp com.test.hotel.xml -i hotel.h -p hotelInterface
       这条命令会生成两个文件:hotelInterface.cpp和hotelInterface.h
(3)调用(2)生成的类来访问Service。
下面是举例(参见checkin3.pro ):

// 初始化自动生成的Proxy类com::test::hotel::registry
        com::test::hotel::registry myHotel("com.test.hotel",
                                           "/hotel/registry",
                                           QDBusConnection::sessionBus());
        // 调用checkIn
        QDBusPendingReply<int> reply= myHotel.checkIn(num_room);
        // qdbusxml2cpp生成的Proxy类是采用异步的方式来传递Message,
        // 所以在此需要调用waitForFinished来等到Message执行完成
        reply.waitForFinished();
        if (reply.isValid()){
                num_room = reply.value();
                printf("Got %d %s\n", num_room,(num_room> 1)?"rooms": "room");
        } else {
                fprintf(stderr,"Check In fail!\n");
        };

使用Adapter注册Object

如前文所述,我们可以直接把class Hotel注册为Message Bus上的一个Object,但这种方式并不是QT4所推荐的。QT4推荐使用Adapter来注册Object。
很多情况下,我们可能只需要把我们定义的类里的方法有选择的发布到Message Bus上,使用Adapter可以很方便的实现这种意图。
以前文中的Hotel为例,假设我们只需要把checkIn和checkOut发布到Message Bus上,应该怎么办?
(1)使用工具 qdbuscpp2xml从hotel.h生成XML文件;
            qdbuscpp2xml -M hotel.h -o com.test.hotel.xml 
(2)编辑com.test.hotel.xml,把其中的query部分去掉;
        即去掉以下三条语句:
        <method name="query">
               <arg type="i" direction="out"/>
        </method>
(3)使用工具qdbusxml2cpp从XML文件生成继承自QDBusInterface的类;
            qdbusxml2cpp com.test.hotel.xml -i hotel.h -a hotelAdaptor
       这条命令会生成两个文件:hotelAdaptor.cpp和hotelAdaptor.h
(4)调用(3)生成的类来注册Object。(参见hotel2.pro)

int main(int argc,char*argv[])
{
    QCoreApplication a(argc, argv);
    QDBusConnection bus = QDBusConnection::sessionBus();
    Hotel myHotel;
    // RegistryAdaptor是qdbusxml2cpp生成的Adaptor类
    RegistryAdaptor myAdaptor(&myHotel);
    if (!bus.registerService("com.test.hotel")){
            qDebug()<< bus.lastError().message();
            exit(1);
    }
    bus.registerObject("/hotel/registry",&myHotel);
    return a.exec();
}

运行这个应用程序,我们从qdbusviewer上可以看到,只有checkIn和checkOut两个method被发布。

自动启动Service

D-Bus系统提供了一种机制可以在访问某个service时,自动把该程序运行起来。
我们需要在/usr/share/dbus-1/services下面建立com.test.hotel.service文件,文件的内容如下:
[D-BUS Service]
Name=com.test.hotel
Exec=/path/to/your/hotel
这样,我们在访问Hotel的method之前,就不必手动运行该应用程序了。

4、其他细节

(1)如果想使用system bus(自启动服务参考上述),需要在/etc/dbus-1/system.d/目录下创建一个配置文件my.conf:

  1. <!DOCTYPE busconfig PUBLIC
  2. "-//freedesktop//DTD D-BUS Bus Configuration 1.0//EN"
  3. "http://www.freedesktop.org/standards/dbus/1.0/busconfig.dtd">
  4. <busconfig>
  5. <policy context="default">
  6. <allow own="com.asianux.btagent2"/>
  7. <allow send_destination="com.asianux.btagent2"/>
  8. <allow receive_sender="com.asianux.btagent2"/>
  9. </policy>
  10. </busconfig>

(2)可以参考通过QDbus实现的Qt检测U盘的例子:http://download.csdn.net/detail/taiyang1987912/8686677
(3)除了DBus,也可使用SIGHUP信号用于进程间通信,比如重写了配置文件,又不想重启程序就让配置生效,可以往该程序的进程发送一个SIGHUP信号:killall -HUP <进程名称>或kill -HUP <进程号>,可能因以前的系统没有提供用户自定义信号 SIGUSR1 和 SIGUSR1 ,而对于一个没有终端的守护进程来说是不可能收到 SIGHUP 信号的,所以就把 SIGHUP 当用户自定义信号使用。

  1. #include<stdio.h>
  2. #include <stdlib.h>
  3. #include<signal.h>
  4. char**args;
  5. void exithandle(int sig)
  6. {
  7. printf("%s:(%d)sighup received\n", args[0], sig);
  8. exit(0);
  9. }
  10. int main(int argc,char **argv)
  11. {
  12. args = argv;
  13. signal(SIGHUP,exithandle);
  14. while(1) sleep(1);
  15. return 0;
  16. }

运行程序,打开另终端发送killall -HUP ./sighupcode,则会处理SIGHUP信号:

三、详解之C代码

1、代码

使用C语言调用dbus的底层函数编写一个远程调用的示例代码,代码很简单,没使用GObject等一些复杂的库。
(1)method_send.c

  1. #include <stdio.h>
  2. #include <stdlib.h>
  3. #include <string.h>
  4. #include <dbus/dbus-glib.h>
  5. #include <dbus/dbus.h>
  6. #include <unistd.h>
  7. /*gcc -o method_send method_send.c -I/usr/include/glib-2.0 -I/usr/include/dbus-1.0 -I/usr/lib64/glib-2.0/include -I/usr/lib64/dbus-1.0/include -lglib-2.0 -ldbus-glib-1*/
  8. void reply_to_method_call(DBusMessage * msg, DBusConnection * conn)
  9. {
  10. DBusMessage * reply;
  11. DBusMessageIter arg;
  12. char * param = NULL;
  13. dbus_bool_t stat = TRUE;
  14. dbus_uint32_t level = 2010;
  15. dbus_uint32_t serial = 0;
  16. //从msg中读取参数,这个在上一次学习中学过
  17. if(!dbus_message_iter_init(msg,&arg))
  18. printf("Message has noargs\n");
  19. else if(dbus_message_iter_get_arg_type(&arg)!= DBUS_TYPE_STRING)
  20. printf("Arg is notstring!\n");
  21. else
  22. dbus_message_iter_get_basic(&arg,& param);
  23. if(param == NULL) return;
  24. //创建返回消息reply
  25. reply = dbus_message_new_method_return(msg);
  26. //在返回消息中填入两个参数,和信号加入参数的方式是一样的。这次我们将加入两个参数。
  27. dbus_message_iter_init_append(reply,&arg);
  28. if(!dbus_message_iter_append_basic(&arg,DBUS_TYPE_BOOLEAN,&stat)){
  29. printf("Out ofMemory!\n");
  30. exit(1);
  31. }
  32. if(!dbus_message_iter_append_basic(&arg,DBUS_TYPE_UINT32,&level)){
  33. printf("Out ofMemory!\n");
  34. exit(1);
  35. }
  36. //发送返回消息
  37. if( !dbus_connection_send(conn, reply,&serial)){
  38. printf("Out of Memory\n");
  39. exit(1);
  40. }
  41. dbus_connection_flush (conn);
  42. dbus_message_unref (reply);
  43. }
  44. void listen_dbus()
  45. {
  46. DBusMessage * msg;
  47. DBusMessageIter arg;
  48. DBusConnection * connection;
  49. DBusError err;
  50. int ret;
  51. char * sigvalue;
  52. dbus_error_init(&err);
  53. //创建于session D-Bus的连接
  54. connection =dbus_bus_get(DBUS_BUS_SESSION, &err);
  55. if(dbus_error_is_set(&err)){
  56. fprintf(stderr,"ConnectionError %s\n",err.message);
  57. dbus_error_free(&err);
  58. }
  59. if(connection == NULL)
  60. return;
  61. //设置一个BUS name:test.wei.dest
  62. ret =dbus_bus_request_name(connection,"test.wei.dest",DBUS_NAME_FLAG_REPLACE_EXISTING,&err);
  63. if(dbus_error_is_set(&err)){
  64. fprintf(stderr,"Name Error%s\n",err.message);
  65. dbus_error_free(&err);
  66. }
  67. if(ret !=DBUS_REQUEST_NAME_REPLY_PRIMARY_OWNER)
  68. return;
  69. //要求监听某个singal:来自接口test.signal.Type的信号
  70. dbus_bus_add_match(connection,"type='signal',interface='test.signal.Type'",&err);
  71. dbus_connection_flush(connection);
  72. if(dbus_error_is_set(&err)){
  73. fprintf(stderr,"Match Error%s\n",err.message);
  74. dbus_error_free(&err);
  75. }
  76. while(1){
  77. dbus_connection_read_write(connection,0);
  78. msg =dbus_connection_pop_message (connection);
  79. if(msg == NULL){
  80. sleep(1);
  81. continue;
  82. }
  83. if(dbus_message_is_signal(msg,"test.signal.Type","Test")){
  84. if(!dbus_message_iter_init(msg,&arg))
  85. fprintf(stderr,"Message Has no Param");
  86. else if(dbus_message_iter_get_arg_type(&arg) != DBUS_TYPE_STRING)
  87. g_printerr("Param isnot string");
  88. else
  89. dbus_message_iter_get_basic(&arg,&sigvalue);
  90. }else if(dbus_message_is_method_call(msg,"test.method.Type","Method")){
  91. //我们这里面先比较了接口名字和方法名字,实际上应当现比较路径
  92. if(strcmp(dbus_message_get_path(msg),"/test/method/Object") == 0)
  93. reply_to_method_call(msg,connection);
  94. }
  95. dbus_message_unref(msg);
  96. }
  97. }
  98. int main( int argc , char ** argv)
  99. {
  100. listen_dbus();
  101. return 0;
  102. }

(2)method_recv.c

  1. #include <stdio.h>
  2. #include <stdlib.h>
  3. #include <string.h>
  4. #include <dbus/dbus-glib.h>
  5. #include <dbus/dbus.h>
  6. #include <unistd.h>
  7. /*gcc -o method_recv method_recv.c -I/usr/include/glib-2.0 -I/usr/include/dbus-1.0 -I/usr/lib64/glib-2.0/include -I/usr/lib64/dbus-1.0/include -lglib-2.0 -ldbus-glib-1*/
  8. //建立与session D-Bus daemo的连接,并设定连接的名字,相关的代码已经多次使用过了
  9. DBusConnection * connect_dbus()
  10. {
  11. DBusError err;
  12. DBusConnection * connection;
  13. int ret;
  14. //Step 1: connecting session bus
  15. dbus_error_init(&err);
  16. connection =dbus_bus_get(DBUS_BUS_SESSION, &err);
  17. if(dbus_error_is_set(&err)){
  18. fprintf(stderr,"ConnectionErr : %s\n",err.message);
  19. dbus_error_free(&err);
  20. }
  21. if(connection == NULL)
  22. return NULL;
  23. //step 2: 设置BUS name,也即连接的名字。
  24. ret =dbus_bus_request_name(connection,"test.wei.source",DBUS_NAME_FLAG_REPLACE_EXISTING,&err);
  25. if(dbus_error_is_set(&err)){
  26. fprintf(stderr,"Name Err :%s\n",err.message);
  27. dbus_error_free(&err);
  28. }
  29. if(ret !=DBUS_REQUEST_NAME_REPLY_PRIMARY_OWNER)
  30. return NULL;
  31. return connection;
  32. }
  33. void send_a_method_call(DBusConnection * connection,char * param)
  34. {
  35. DBusError err;
  36. DBusMessage * msg;
  37. DBusMessageIter    arg;
  38. DBusPendingCall * pending;
  39. dbus_bool_t * stat;
  40. dbus_uint32_t * level;
  41. dbus_error_init(&err);
  42. //针对目的地地址,请参考图,创建一个method call消息。Constructs a new message to invoke a method on a remote object.
  43. msg =dbus_message_new_method_call ("test.wei.dest","/test/method/Object","test.method.Type","Method");
  44. if(msg == NULL){
  45. g_printerr("MessageNULL");
  46. return;
  47. }
  48. //为消息添加参数。Appendarguments
  49. dbus_message_iter_init_append(msg, &arg);
  50. if(!dbus_message_iter_append_basic(&arg, DBUS_TYPE_STRING,&stat)){
  51. g_printerr("Out of Memory!");
  52. exit(1);
  53. }
  54. //发送消息并获得reply的handle。Queues amessage to send, as withdbus_connection_send() , but also returns aDBusPendingCall used to receive a reply to the message.
  55. if(!dbus_connection_send_with_reply (connection, msg,&pending, -1)){
  56. g_printerr("Out of Memory!");
  57. exit(1);
  58. }
  59. if(pending == NULL){
  60. g_printerr("Pending CallNULL: connection is disconnected ");
  61. dbus_message_unref(msg);
  62. return;
  63. }
  64. dbus_connection_flush(connection);
  65. dbus_message_unref(msg);
  66. //waiting a reply,在发送的时候,已经获取了methodreply的handle,类型为DBusPendingCall。
  67. // block until we recieve a reply, Block until the pendingcall is completed.
  68. dbus_pending_call_block (pending);
  69. //get the reply message,Gets thereply, or returns NULL if none has been received yet.
  70. msg =dbus_pending_call_steal_reply (pending);
  71. if (msg == NULL) {
  72. fprintf(stderr, "ReplyNull\n");
  73. exit(1);
  74. }
  75. // free the pendingmessage handle
  76. dbus_pending_call_unref(pending);
  77. // read the parameters
  78. if(!dbus_message_iter_init(msg, &arg))
  79. fprintf(stderr, "Message hasno arguments!\n");
  80. else if (dbus_message_iter_get_arg_type(&arg) != DBUS_TYPE_BOOLEAN)
  81. fprintf(stderr, "Argument isnot boolean!\n");
  82. else
  83. dbus_message_iter_get_basic(&arg, &stat);
  84. if (!dbus_message_iter_next(&arg))
  85. fprintf(stderr, "Message hastoo few arguments!\n");
  86. else if (dbus_message_iter_get_arg_type(&arg) != DBUS_TYPE_UINT32 )
  87. fprintf(stderr, "Argument isnot int!\n");
  88. else
  89. dbus_message_iter_get_basic(&arg, &level);
  90. printf("Got Reply: %d,%d\n", stat, level);
  91. dbus_message_unref(msg);
  92. }
  93. int main( int argc , char ** argv)
  94. {
  95. DBusConnection * connection;
  96. connection = connect_dbus();
  97. if(connection == NULL)
  98. return -1;
  99. send_a_method_call(connection,"Hello, D-Bus");
  100. return 0;
  101. }

(3)编译运行(先运行method_send)
编译method_send.c:

编译method_recv.c(得到运行结果):

四、总结

(1)本文仅提供代码的测试,其他的具体函数的意义请查阅相应的帮助文档。
(2)源码已经打包上传到csdn上,可登录下载(http://download.csdn.net/detail/taiyang1987912/8687183)。
(3)若有建议,请留言,在此先感谢!

http://blog.csdn.net/taiyang1987912/article/details/45642079

Qt浅谈之二十七进程间通信之QtDBus的更多相关文章

  1. Qt浅谈之二十七进程间通信之QtDBus good

    一.简介 DBus的出现,使得Linux进程间通信更加便捷,不仅可以和用户空间应用程序进行通信,而且还可以和内核的程序进行通信,DBus使得Linux变得更加智能,更加具有交互性.        DB ...

  2. Qt浅谈之二十App自动重启及关闭子窗口

    一.简介 最近因项目需求,Qt程序一旦检测到错误,要重新启动,自己是每次关闭主窗口的所有子窗口但有些模态框会出现问题,因此从网上总结了一些知识点,以备以后的应用. 二.详解 1.Qt结构 int ma ...

  3. Qt浅谈之二十App自动重启及关闭子窗口(六种方法)

    一.简介 最近因项目需求,Qt程序一旦检测到错误,要重新启动,自己是每次关闭主窗口的所有子窗口但有些模态框会出现问题,因此从网上总结了一些知识点,以备以后的应用. 二.详解 1.Qt结构 int ma ...

  4. Qt浅谈之二十六图片滑动效果

    一.简介 博客中发现有作者写的仿360的代码,觉得其中图片滑动的效果很有意思,特提取其中的代码.并加上类似mac的画面移动的动画效果. 二.详解 1.代码一:界面滑动(QWidget) (1)slid ...

  5. Qt浅谈之二十一log调试日志

    一.简单介绍 近期因调试code时,想了解程序的流程,但苦于没有一个简易的日志记录,不停使用qDebug打印输出,而终于提交代码时得去多次删除信息打印,有时还会出现新改动的代码分不清是哪些部分.而使用 ...

  6. Qt浅谈之二:钟表(时分秒针)

    一.简介 QT编写的模拟时钟,demo里的时钟只有时针和分针,在其基础上添加了秒针,构成了一个完整的时钟.能对2D绘图中坐标系统.平移变换(translate).比例变换(scale).旋转变换(ro ...

  7. Qt浅谈内存泄露(总结)

    Qt浅谈内存泄露(总结) 来源 http://blog.csdn.net/taiyang1987912/article/details/29271549 一.简介 Qt内存管理机制:Qt 在内部能够维 ...

  8. Qt浅谈之总结(整理)

    Qt浅谈之总结(整理) 来源 http://blog.csdn.net/taiyang1987912/article/details/32713781 一.简介 QT的一些知识点总结,方便以后查阅. ...

  9. Android开发-浅谈架构(二)

    写在前面的话 我记得有一期罗胖的<罗辑思维>中他提到 我们在这个碎片化 充满焦虑的时代该怎么学习--用30%的时间 了解70%该领域的知识然后迅速转移芳草鲜美的地方 像游牧民族那样.原话应 ...

随机推荐

  1. BZOJ3479: [Usaco2014 Mar]Watering the Fields

    3479: [Usaco2014 Mar]Watering the Fields Time Limit: 10 Sec  Memory Limit: 128 MBSubmit: 81  Solved: ...

  2. POJ_3009——冰球,IDS迭代加深搜索

    Description On Planet MM-21, after their Olympic games this year, curling is getting popular. But th ...

  3. How to Read an Engineering Research Paper

    How to Read an Engineering Research Paper William G. Griswold Department of Computer Science & E ...

  4. tomcat+redis实现session共享缓存

    一:linux下redis安装 1.wget http://download.redis.io/releases/redis-3.2.4.tar.gz 2.tar xzf redis-3.2.4.ta ...

  5. selenium page object model

    Page Object Model (POM) & Page Factory in Selenium: Ultimate Guide 来源:http://www.guru99.com/page ...

  6. iOS打电话、发邮件、发短信、打开浏览器

    //1.调用 自带mail [[UIApplication sharedApplication] openURL:[NSURL URLWithString:@"mailto://163@16 ...

  7. Android adb

    查看原文:http://blog.csdn.net/u010818425/article/details/52266593 (一)基础操作 安装app adb install -r xxx.apk / ...

  8. Android软键盘强制弹出,隐藏输入法.

    本文实例讲述了Android实现弹出键盘代码,是一个非常实用的功能.代码非常简洁.分享给大家供大家参考. 具体功能代码如下: ? 1 2 3 4 5 6 7 8 Timer timer = new T ...

  9. Oracle11g完全卸载步骤

    Oracle11g完全卸载步骤:1. 开始->设置->控制面板->管理工具->服务 停止所有Oracle服务.2. 开始->程序->Oracle - OraHome ...

  10. Use GraceNote SDK in iOS(一)通过序列化GDO查询专辑封面

    于Use MusicBrainz in iOS之后,因为MusicBrainz找出专辑封面,它只能转移到其他网站提供的音乐信息搜索服务,领导给出GraceNote.(有压力.. .) 需求类似:通过一 ...