一区二区三区日韩精品-日韩经典一区二区三区-五月激情综合丁香婷婷-欧美精品中文字幕专区

分享

Qt淺談之二十七進程間通信之QtDBus good

 昵稱52164085 2018-01-18

一、簡介

        DBus的出現(xiàn),使得Linux進程間通信更加便捷,不僅可以和用戶空間應用程序進行通信,而且還可以和內(nèi)核的程序進行通信,DBus使得Linux變得更加智能,更加具有交互性。
        DBus分為兩種類型:system bus(系統(tǒng)總線),用于系統(tǒng)(Linux)和用戶程序之間進行通信和消息的傳遞;session bus(回話總線),用于桌面(GNOME, KDE等)用戶程序之間進行通信。       

二、詳解之Qt代碼

1、代碼一

(1)test.h

[html] view plain copy  在CODE上查看代碼片派生到我的代碼片
  1. #ifndef  TEST_H  
  2. #define  TEST_H  
  3.   
  4. #include  <QtCore>  
  5. #include  <QTimer>  
  6.   
  7. class Test : public QObject  
  8. {  
  9.     Q_OBJECT  
  10. public:  
  11.     Test();  
  12.   
  13. public slots:  
  14.     QString testStart();  
  15.     void changeTest();  
  16.   
  17. signals:  
  18.     void stateChange(QString str);  
  19.   
  20. private:  
  21.     QTimer *timer;  
  22. };  
  23. #endif  /*TEST_H*/  

(2)test.cpp

[html] view plain copy  在CODE上查看代碼片派生到我的代碼片
  1. #include "test.h"  
  2.   
  3. Test::Test()  
  4. {  
  5.     qDebug() << "===========test init===========";  
  6.     timer = new QTimer;  
  7.     connect(timer, SIGNAL(timeout()), this, SLOT(changeTest()));  
  8. }  
  9.   
  10. QString Test::testStart()  
  11. {  
  12.     qDebug() << "+++++++QtDBus test++++++++++";  
  13.     QString tmp;  
  14.     tmp = QString("OFF");  
  15.     qDebug() << tmp;  
  16.     if (timer->isActive()) {  
  17.         timer->stop();  
  18.     }  
  19.     timer->start(2000);  
  20.     return tmp;  
  21. }  
  22.   
  23. void Test::changeTest()  
  24. {  
  25.     QString tmp;  
  26.     tmp = QString("ON");  
  27.     qDebug() << "+++++++++++++++++++" << tmp;  
  28.     emit stateChange(tmp);  
  29. }  

(3)test_adaptor.h

[html] view plain copy  在CODE上查看代碼片派生到我的代碼片
  1. #include    "test_adaptor.h"  
  2. #include    <QtCore>  
  3.   
  4. TestInterfaceAdaptor::TestInterfaceAdaptor(QObject *parent)  
  5.     :QDBusAbstractAdaptor(parent)  
  6. {  
  7.     qDebug() << "***************TestInterfaceAdaptor::TestInterfaceAdaptor**************";  
  8.     setAutoRelaySignals(true);  //connection of the signals on the parent  
  9. }  
  10.   
  11. TestInterfaceAdaptor::~TestInterfaceAdaptor()  
  12. {  
  13. }  
  14.   
  15. QString TestInterfaceAdaptor::test()  
  16. {  
  17.     QString out;  
  18.     QMetaObject::invokeMethod(parent(), "testStart",Q_RETURN_ARG(QString, out));  
  19.     qDebug() << "==========" << out;  
  20.     return out;  
  21. }  

(4)test_adaptor.cpp

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

(5)main.cpp

[html] view plain copy  在CODE上查看代碼片派生到我的代碼片
  1. #include  <QApplication>  
  2. #include  <QtDBus>  
  3. #include <QDebug>  
  4. #include  "test_adaptor.h"  
  5. #include  "test.h"  
  6.   
  7. int main(int argc,char *argv[])  
  8. {  
  9.     QApplication app(argc,argv);  
  10.   
  11.     Test *test = new Test();  
  12.   
  13.     new TestInterfaceAdaptor(test);  
  14.     QDBusConnection conn = QDBusConnection::sessionBus();  
  15.     conn.registerObject("/",test);  
  16.     conn.registerService("com.asianux.btagent");  
  17.   
  18.     return app.exec();  
  19. }  

(6)運行

        可以在linux終端發(fā)送(dbus-send)和監(jiān)控dbus(dbus-monitor)的信息。 dbus-send調(diào)用遠程方法的一般形式是:$ dbus-send [--system | --session] --type=method_call --print-reply --dest=連接名 對象路徑 接口名.方法名 參數(shù)類型:參數(shù)值 參數(shù)類型:參數(shù)值,dbus-send支持的參數(shù)類型包括:string, int32, uint32, double, byte, boolean。
       啟動程序后,先執(zhí)行:dbus-send --session --print-reply --dest=com.asianux.btagent /  com.asianux.btagent.adaptor.test,發(fā)送dbus信號,得到輸出結(jié)果:

       然后輸入:dbus-monitor --session \ "type='signal',interface='com.asianux.btagent.adaptor',member='stateChange'",監(jiān)控,從應用程序發(fā)出的DBus信號:

        也可以通過qt自帶的工具qdbusviewer查看和操作相應的DBus信號:

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

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

makefile:

[html] view plain copy  在CODE上查看代碼片派生到我的代碼片
  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  

運行結(jié)果(先啟動最上的服務器qt程序):

2、代碼二

(1)qdbus.h

[html] view plain copy  在CODE上查看代碼片派生到我的代碼片
  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.   
  10. public:  
  11. //     DeviceManager(){}  
  12. //     ~DeviceManager(){}  
  13. public slots:  
  14.     void slotInterface(QString);  
  15. };  
  16. #endif // QDBUS  

(2)main.cpp

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

運行結(jié)果:

3、其他網(wǎng)上代碼

D-Bus的QT4綁定

       下面,我們通過一個實例來介紹D-Bus的QT4綁定。(參見hotel.pro)
在Session bus上創(chuàng)建一個"com.test.hotel" service,通過這個service可以執(zhí)行check in,check out和query三個動作。

創(chuàng)建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,參數(shù)為房間數(shù),返回成功拿到的房間數(shù)
    int checkIn(int num_room);
    // Check out,參數(shù)為房間數(shù),返回成功退回的房間數(shù)
    int checkOut(int num_room);
    // Query,用于查詢目前還剩下的房間數(shù) 
    int query();
private:
    int m_rooms;
    QReadWriteLock m_lock;
};

運行這個程序,我們可以使用qdbusviewer查看和操作這個Object。

通過QDBusMessage訪問Service
在QT4中,用QDBusMessage表示在D-Bus上發(fā)送和接收的Message。(參見checkin.pro)

       // 用來構(gòu)造一個在D-Bus上傳遞的Message
        QDBusMessage m = QDBusMessage::createMethodCall("com.test.hotel",
                                                      "/hotel/registry",
                                                      "com.test.hotel.registry",
                                                      "checkIn");
        if (argc== 2){
                // 給QDBusMessage增加一個參數(shù);
                // 這是一種比較友好的寫法,也可以用setArguments來實現(xiàn)
                m << QString(argv[1]).toInt();
        }

       // 發(fā)送Message
        QDBusMessage response = QDBusConnection::sessionBus().call(m);
        // 判斷Method是否被正確返回
        if (response.type()== QDBusMessage::ReplyMessage){
                // QDBusMessage的arguments不僅可以用來存儲發(fā)送的參數(shù),也用來存儲返回值;
                // 這里取得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)

       // 創(chuàng)建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,參數(shù)為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已經(jīng)非常方便了,但還不夠直觀。還有沒有更直觀的方法,就像訪問本地類成員變量的方式訪問遠程的method?答案是Proxy。 
Proxy Object提供了一種更加直觀的方式來訪問Service,就好像調(diào)用本地對象的方法一樣。 
概括的說,達成上述目標需要分三步走:
(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)調(diào)用(2)生成的類來訪問Service。
下面是舉例(參見checkin3.pro ):

       // 初始化自動生成的Proxy類com::test::hotel::registry
        com::test::hotel::registry myHotel("com.test.hotel",
                                           "/hotel/registry",
                                           QDBusConnection::sessionBus());
        // 調(diào)用checkIn
        QDBusPendingReply<int> reply= myHotel.checkIn(num_room);
        // qdbusxml2cpp生成的Proxy類是采用異步的方式來傳遞Message,
        // 所以在此需要調(diào)用waitForFinished來等到Message執(zhí)行完成
        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。
很多情況下,我們可能只需要把我們定義的類里的方法有選擇的發(fā)布到Message Bus上,使用Adapter可以很方便的實現(xiàn)這種意圖。
以前文中的Hotel為例,假設我們只需要把checkIn和checkOut發(fā)布到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)調(diào)用(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被發(fā)布。

自動啟動Service
D-Bus系統(tǒng)提供了一種機制可以在訪問某個service時,自動把該程序運行起來。
我們需要在/usr/share/dbus-1/services下面建立com.test.hotel.service文件,文件的內(nèi)容如下:
[D-BUS Service]
Name=com.test.hotel
Exec=/path/to/your/hotel
這樣,我們在訪問Hotel的method之前,就不必手動運行該應用程序了。

4、其他細節(jié)

(1)如果想使用system bus(自啟動服務參考上述),需要在/etc/dbus-1/system.d/目錄下創(chuàng)建一個配置文件my.conf:

[html] view plain copy  在CODE上查看代碼片派生到我的代碼片
  1. <!DOCTYPE busconfig PUBLIC  
  2.  "-//freedesktop//DTD D-BUS Bus Configuration 1.0//EN"  
  3.  "http://www./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實現(xiàn)的Qt檢測U盤的例子:http://download.csdn.net/detail/taiyang1987912/8686677
(3)除了DBus,也可使用SIGHUP信號用于進程間通信,比如重寫了配置文件,又不想重啟程序就讓配置生效,可以往該程序的進程發(fā)送一個SIGHUP信號:killall -HUP <進程名稱>或kill -HUP <進程號>,可能因以前的系統(tǒng)沒有提供用戶自定義信號 SIGUSR1 和 SIGUSR1 ,而對于一個沒有終端的守護進程來說是不可能收到 SIGHUP 信號的,所以就把 SIGHUP 當用戶自定義信號使用。

[html] view plain copy  在CODE上查看代碼片派生到我的代碼片
  1. #include<stdio.h>  
  2. #include <stdlib.h>  
  3. #include<signal.h>  
  4. char**args;  
  5.   
  6. void exithandle(int sig)  
  7. {  
  8.     printf("%s:(%d)sighup received\n", args[0], sig);  
  9.     exit(0);  
  10. }  
  11.   
  12. int main(int argc,char **argv)  
  13. {  
  14.     args = argv;  
  15.     signal(SIGHUP,exithandle);  
  16.     while(1) sleep(1);  
  17.     return 0;  
  18. }  

運行程序,打開另終端發(fā)送killall -HUP ./sighupcode,則會處理SIGHUP信號:

 

 

三、詳解之C代碼

1、代碼

      使用C語言調(diào)用dbus的底層函數(shù)編寫一個遠程調(diào)用的示例代碼,代碼很簡單,沒使用GObject等一些復雜的庫。
(1)method_send.c

[html] view plain copy  在CODE上查看代碼片派生到我的代碼片
  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.        
  17.     //從msg中讀取參數(shù),這個在上一次學習中學過    
  18.    if(!dbus_message_iter_init(msg,&arg))    
  19.         printf("Message has noargs\n");    
  20.     else if(dbus_message_iter_get_arg_type(&arg)!= DBUS_TYPE_STRING)    
  21.         printf("Arg is notstring!\n");    
  22.     else    
  23.        dbus_message_iter_get_basic(&arg,& param);    
  24.     if(param == NULL) return;  
  25.     //創(chuàng)建返回消息reply    
  26.     reply = dbus_message_new_method_return(msg);    
  27.     //在返回消息中填入兩個參數(shù),和信號加入?yún)?shù)的方式是一樣的。這次我們將加入兩個參數(shù)。    
  28.     dbus_message_iter_init_append(reply,&arg);    
  29.     if(!dbus_message_iter_append_basic(&arg,DBUS_TYPE_BOOLEAN,&stat)){    
  30.         printf("Out ofMemory!\n");    
  31.         exit(1);    
  32.     }    
  33.     if(!dbus_message_iter_append_basic(&arg,DBUS_TYPE_UINT32,&level)){    
  34.         printf("Out ofMemory!\n");    
  35.         exit(1);    
  36.     }  
  37.     //發(fā)送返回消息  
  38.     if( !dbus_connection_send(conn, reply,&serial)){    
  39.         printf("Out of Memory\n");    
  40.         exit(1);    
  41.     }    
  42.     dbus_connection_flush (conn);    
  43.     dbus_message_unref (reply);  
  44. }  
  45.   
  46. void listen_dbus()  
  47. {  
  48.     DBusMessage * msg;  
  49.     DBusMessageIter arg;  
  50.     DBusConnection * connection;  
  51.     DBusError err;  
  52.     int ret;  
  53.     char * sigvalue;  
  54.     dbus_error_init(&err);  
  55.     //創(chuàng)建于session D-Bus的連接  
  56.     connection =dbus_bus_get(DBUS_BUS_SESSION, &err);  
  57.     if(dbus_error_is_set(&err)){  
  58.         fprintf(stderr,"ConnectionError %s\n",err.message);  
  59.         dbus_error_free(&err);  
  60.     }  
  61.     if(connection == NULL)    
  62.         return;    
  63.     //設置一個BUS name:test.wei.dest    
  64.     ret =dbus_bus_request_name(connection,"test.wei.dest",DBUS_NAME_FLAG_REPLACE_EXISTING,&err);    
  65.     if(dbus_error_is_set(&err)){    
  66.         fprintf(stderr,"Name Error%s\n",err.message);    
  67.         dbus_error_free(&err);    
  68.     }    
  69.     if(ret !=DBUS_REQUEST_NAME_REPLY_PRIMARY_OWNER)    
  70.         return;  
  71.     //要求監(jiān)聽某個singal:來自接口test.signal.Type的信號  
  72.     dbus_bus_add_match(connection,"type='signal',interface='test.signal.Type'",&err);    
  73.     dbus_connection_flush(connection);    
  74.     if(dbus_error_is_set(&err)){    
  75.         fprintf(stderr,"Match Error%s\n",err.message);    
  76.         dbus_error_free(&err);    
  77.     }   
  78.      while(1){    
  79.         dbus_connection_read_write(connection,0);    
  80.         msg =dbus_connection_pop_message (connection);    
  81.     
  82.         if(msg == NULL){    
  83.             sleep(1);    
  84.             continue;    
  85.         }    
  86.     
  87.         if(dbus_message_is_signal(msg,"test.signal.Type","Test")){    
  88.             if(!dbus_message_iter_init(msg,&arg))    
  89.                fprintf(stderr,"Message Has no Param");    
  90.             else if(dbus_message_iter_get_arg_type(&arg) != DBUS_TYPE_STRING)    
  91.                 g_printerr("Param isnot string");    
  92.             else    
  93.                dbus_message_iter_get_basic(&arg,&sigvalue);    
  94.         }else if(dbus_message_is_method_call(msg,"test.method.Type","Method")){    
  95.             //我們這里面先比較了接口名字和方法名字,實際上應當現(xiàn)比較路徑    
  96.             if(strcmp(dbus_message_get_path(msg),"/test/method/Object") == 0)    
  97.                reply_to_method_call(msg,connection);    
  98.         }    
  99.         dbus_message_unref(msg);    
  100.     }  
  101. }  
  102.   
  103. int main( int argc , char ** argv)  
  104. {  
  105.     listen_dbus();  
  106.     return 0;  
  107. }  

(2)method_recv.c

[html] view plain copy  在CODE上查看代碼片派生到我的代碼片
  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的連接,并設定連接的名字,相關的代碼已經(jīng)多次使用過了  
  9. DBusConnection * connect_dbus()  
  10. {  
  11.     DBusError err;  
  12.     DBusConnection * connection;  
  13.     int ret;  
  14.   
  15.     //Step 1: connecting session bus  
  16.     dbus_error_init(&err);  
  17.        
  18.     connection =dbus_bus_get(DBUS_BUS_SESSION, &err);  
  19.     if(dbus_error_is_set(&err)){  
  20.         fprintf(stderr,"ConnectionErr : %s\n",err.message);  
  21.         dbus_error_free(&err);  
  22.     }  
  23.     if(connection == NULL)  
  24.         return NULL;  
  25.     //step 2: 設置BUS name,也即連接的名字。  
  26.     ret =dbus_bus_request_name(connection,"test.wei.source",DBUS_NAME_FLAG_REPLACE_EXISTING,&err);  
  27.     if(dbus_error_is_set(&err)){  
  28.         fprintf(stderr,"Name Err :%s\n",err.message);  
  29.         dbus_error_free(&err);  
  30.     }  
  31.     if(ret !=DBUS_REQUEST_NAME_REPLY_PRIMARY_OWNER)  
  32.         return NULL;  
  33.   
  34.     return connection;     
  35. }  
  36.   
  37. void send_a_method_call(DBusConnection * connection,char * param)  
  38. {  
  39.     DBusError err;  
  40.     DBusMessage * msg;  
  41.     DBusMessageIter    arg;  
  42.     DBusPendingCall * pending;  
  43.     dbus_bool_t * stat;  
  44.     dbus_uint32_t * level;     
  45.      
  46.     dbus_error_init(&err);  
  47.     //針對目的地地址,請參考圖,創(chuàng)建一個method call消息。Constructs a new message to invoke a method on a remote object.  
  48.     msg =dbus_message_new_method_call ("test.wei.dest","/test/method/Object","test.method.Type","Method");  
  49.     if(msg == NULL){  
  50.         g_printerr("MessageNULL");  
  51.         return;  
  52.     }  
  53.   
  54.     //為消息添加參數(shù)。Appendarguments  
  55.     dbus_message_iter_init_append(msg, &arg);  
  56.     if(!dbus_message_iter_append_basic(&arg, DBUS_TYPE_STRING,&stat)){  
  57.        g_printerr("Out of Memory!");  
  58.         exit(1);  
  59.     }  
  60.   
  61.     //發(fā)送消息并獲得reply的handle。Queues amessage to send, as withdbus_connection_send() , but also returns aDBusPendingCall used to receive a reply to the message.  
  62.     if(!dbus_connection_send_with_reply (connection, msg,&pending, -1)){  
  63.        g_printerr("Out of Memory!");  
  64.         exit(1);  
  65.     }       
  66.   
  67.     if(pending == NULL){  
  68.         g_printerr("Pending CallNULL: connection is disconnected ");  
  69.         dbus_message_unref(msg);  
  70.         return;  
  71.     }  
  72.   
  73.     dbus_connection_flush(connection);  
  74.     dbus_message_unref(msg);  
  75.    
  76.    //waiting a reply,在發(fā)送的時候,已經(jīng)獲取了methodreply的handle,類型為DBusPendingCall。  
  77.     // block until we recieve a reply, Block until the pendingcall is completed.  
  78.    dbus_pending_call_block (pending);  
  79.     //get the reply message,Gets thereply, or returns NULL if none has been received yet.  
  80.     msg =dbus_pending_call_steal_reply (pending);  
  81.     if (msg == NULL) {  
  82.         fprintf(stderr, "ReplyNull\n");  
  83.          exit(1);  
  84.     }  
  85.      // free the pendingmessage handle  
  86.      dbus_pending_call_unref(pending);  
  87.     // read the parameters  
  88.     if(!dbus_message_iter_init(msg, &arg))  
  89.         fprintf(stderr, "Message hasno arguments!\n");  
  90.     else if (dbus_message_iter_get_arg_type(&arg) != DBUS_TYPE_BOOLEAN)  
  91.         fprintf(stderr, "Argument isnot boolean!\n");  
  92.     else  
  93.         dbus_message_iter_get_basic(&arg, &stat);  
  94.    
  95.     if (!dbus_message_iter_next(&arg))  
  96.         fprintf(stderr, "Message hastoo few arguments!\n");  
  97.     else if (dbus_message_iter_get_arg_type(&arg) != DBUS_TYPE_UINT32 )  
  98.         fprintf(stderr, "Argument isnot int!\n");  
  99.     else  
  100.         dbus_message_iter_get_basic(&arg, &level);  
  101.   
  102.     printf("Got Reply: %d,%d\n", stat, level);  
  103.     dbus_message_unref(msg);  
  104. }  
  105. int main( int argc , char ** argv)  
  106. {  
  107.    DBusConnection * connection;  
  108.     connection = connect_dbus();  
  109.     if(connection == NULL)  
  110.         return -1;  
  111.   
  112.    send_a_method_call(connection,"Hello, D-Bus");  
  113.     return 0;  
  114. }  

(3)編譯運行(先運行method_send)
編譯method_send.c:

編譯method_recv.c(得到運行結(jié)果):

四、總結(jié)

(1)本文僅提供代碼的測試,其他的具體函數(shù)的意義請查閱相應的幫助文檔。
(2)源碼已經(jīng)打包上傳到csdn上,可登錄下載(http://download.csdn.net/detail/taiyang1987912/8687183)。
(3)若有建議,請留言,在此先感謝!

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

    本站是提供個人知識管理的網(wǎng)絡存儲空間,所有內(nèi)容均由用戶發(fā)布,不代表本站觀點。請注意甄別內(nèi)容中的聯(lián)系方式、誘導購買等信息,謹防詐騙。如發(fā)現(xiàn)有害或侵權內(nèi)容,請點擊一鍵舉報。
    轉(zhuǎn)藏 分享 獻花(0

    0條評論

    發(fā)表

    請遵守用戶 評論公約

    類似文章 更多

    欧美人与动牲交a精品| 自拍偷拍一区二区三区| 中文字幕在线区中文色| 欧美日韩国产精品黄片| 日本三区不卡高清更新二区| 正在播放玩弄漂亮少妇高潮| 夫妻性生活动态图视频| 精品人妻av区波多野结依| 亚洲国产成人精品福利| 熟妇人妻av中文字幕老熟妇| 果冻传媒精选麻豆白晶晶| 毛片在线观看免费日韩| 日韩一本不卡在线观看| 国产成人精品在线播放| 色丁香一区二区黑人巨大| 不卡免费成人日韩精品| 久久女同精品一区二区| 久久精品国产亚洲熟女| 国产原创中文av在线播放| 人妻久久这里只有精品| 丰满少妇高潮一区二区| 开心五月激情综合婷婷色| 欧美日韩三区在线观看| 国产在线不卡中文字幕| 91爽人人爽人人插人人爽| 日韩人妻欧美一区二区久久| 冬爱琴音一区二区中文字幕| 国产一区二区不卡在线视频| 亚洲综合天堂一二三区| 一区二区三区亚洲国产| 国产精品香蕉在线的人| 日本人妻中出在线观看| 日本男人女人干逼视频| 丰满人妻熟妇乱又乱精品古代| 国产欧美日韩精品自拍| 好吊妞视频免费在线观看| 国产日韩欧美专区一区| 日韩在线欧美一区二区| 日韩精品一区二区三区含羞含羞草 | 中文字幕熟女人妻视频| 在线免费国产一区二区|