1. 程式人生 > >D-Bus學習(六) Method的收發小例子

D-Bus學習(六) Method的收發小例子

分享一下我老師大神的人工智慧教程!零基礎,通俗易懂!http://blog.csdn.net/jiangjunshow

也歡迎大家轉載本篇文章。分享知識,造福人民,實現我們中華民族偉大復興!

               

  我們繼續學習D-Bus,參考http://dbus.freedesktop.org/doc/dbus/libdbus-tutorial.html,相關的API介面reference參考http://dbus.freedesktop.org/doc/dbus/api/html/modules.html

。從底層,即libdbus學習如何傳送Method以及如何等待應答,在上上次學習中,給出了同步的方式,這是更為高層的處理方式,建議使用。監聽method和監聽signal的方式非常相似。在給出例子之前,我希望和上次學習一樣給出一個示意圖,更好地瞭解D-Bus的各個概念。


監聽Method call訊息,並返回Method reply訊息

  Method的監聽和signal的監聽的處理時一樣,但是訊號是不需要答覆,而Method需要。在下面的例子中,我們將學習如何在訊息中加入多個引數(在D-Bus學習(四)中,我們加入了一個引數)的情況。

#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <dbus/dbus-glib.h>
#include <dbus/dbus.h>
#include <unistd.h>


/*讀取訊息的引數,並且返回兩個引數,一個是bool值stat,一個是整數level*/
void reply_to_method_call(DBusMessage * msg, DBusConnection * conn){
    DBusMessage * reply;
    DBusMessageIter arg;
    char * param = NULL;
    dbus_bool_t stat = TRUE;
    dbus_uint32_t level = 2010;
    dbus_uint32_t serial = 0;

   
    //從msg中讀取引數,這個在上一次學習中學過
    if(!dbus_message_iter_init(msg,&arg))
        printf("Message has no args/n");
    else if(dbus_message_iter_get_arg_type(&arg) != DBUS_TYPE_STRING)
        printf("Arg is not string!/n");
    else
        dbus_message_iter_get_basic(&arg,& param);
   if(param == NULL) return;


    //建立返回訊息reply
    reply = dbus_message_new_method_return(msg);
    //在返回訊息中填入兩個引數,和訊號加入引數的方式是一樣的。這次我們將加入兩個引數。
    dbus_message_iter_init_append(reply,&arg);
    if(!dbus_message_iter_append_basic(&arg,DBUS_TYPE_BOOLEAN,&stat)){
        printf("Out of Memory!/n");
        exit(1);
    }
    if(!dbus_message_iter_append_basic(&arg,DBUS_TYPE_UINT32,&level)){
        printf("Out of Memory!/n");
        exit(1);
    }

  //傳送返回訊息
      if( !dbus_connection_send(conn, reply, &serial)){
        printf("Out of Memory/n");
        exit(1);
    }
    dbus_connection_flush(conn);
    dbus_message_unref(reply);
}

/* 監聽D-Bus訊息,我們在上次的例子中進行修改 */
void listen_dbus()
{
    DBusMessage * msg;
    DBusMessageIter arg;
    DBusConnection * connection;
    DBusError err;
    int ret;
    char * sigvalue;

    dbus_error_init(&err);
    //創建於session D-Bus的連線
    connection = dbus_bus_get(DBUS_BUS_SESSION, &err);
    if(dbus_error_is_set(&err)){
        fprintf(stderr,"Connection Error %s/n",err.message);
        dbus_error_free(&err);
    }
    if(connection == NULL)
        return;
    //設定一個BUS name:test.wei.dest
    ret = dbus_bus_request_name(connection,"test.wei.dest",DBUS_NAME_FLAG_REPLACE_EXISTING,&err);
    if(dbus_error_is_set(&err)){
        fprintf(stderr,"Name Error %s/n",err.message);
        dbus_error_free(&err);
    }
    if(ret != DBUS_REQUEST_NAME_REPLY_PRIMARY_OWNER)
        return;

    //要求監聽某個singal:來自介面test.signal.Type的訊號
    dbus_bus_add_match(connection,"type='signal',interface='test.signal.Type'",&err);
    dbus_connection_flush(connection);
    if(dbus_error_is_set(&err)){
        fprintf(stderr,"Match Error %s/n",err.message);
        dbus_error_free(&err);
    }


    while(true){
        dbus_connection_read_write(connection,0);
        msg = dbus_connection_pop_message(connection);

        if(msg == NULL){
            sleep(1);
            continue;
        }


        if(dbus_message_is_signal(msg,"test.signal.Type","Test")){
            if(!dbus_message_iter_init(msg,&arg))
                fprintf(stderr,"Message Has no Param");
            else if(dbus_message_iter_get_arg_type(&arg) != DBUS_TYPE_STRING)
                g_printerr("Param is not string");
            else
                dbus_message_iter_get_basic(&arg,&sigvalue);

        }else if(dbus_message_is_method_call(msg,"test.method.Type","Method")){
           //我們這裡面先比較了介面名字和方法名字,實際上應當現比較路徑
           if(strcmp(dbus_message_get_path(msg),"/test/method/Object") == NULL)
               reply_to_method_call(msg, connection);
        }
        dbus_message_unref(msg);
    }
   
   
}
int main( int argc , char ** argv){
    listen_dbus();
    return 0;
}

傳送Method call訊息,並等待Method reply訊息

  下面的例子在上次學習訊號傳送的例子上進行修改。如下:

#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <dbus/dbus-glib.h>
#include <dbus/dbus.h>
#include <unistd.h>

//建立與session D-Bus daemo的連線,並設定連線的名字,相關的程式碼已經多次使用過了
DBusConnection *  connect_dbus(){
    DBusError err;
    DBusConnection * connection;
    int ret;

    //Step 1: connecting session bus
    /* initialise the erroes */
    dbus_error_init(&err);
    /* Connect to Bus*/
    connection = dbus_bus_get(DBUS_BUS_SESSION, &err);
    if(dbus_error_is_set(&err)){
        fprintf(stderr,"Connection Err : %s/n",err.message);
        dbus_error_free(&err);
    }
    if(connection == NULL)
        return NULL;

    //step 2: 設定BUS name,也即連線的名字。
    ret = dbus_bus_request_name(connection,"test.wei.source",DBUS_NAME_FLAG_REPLACE_EXISTING,&err);
    if(dbus_error_is_set(&err)){
        fprintf(stderr,"Name Err : %s/n",err.message);
        dbus_error_free(&err);
    }
    if(ret != DBUS_REQUEST_NAME_REPLY_PRIMARY_OWNER)
        return NULL;

    return connection;   
}


void send_a_method_call(DBusConnection * connection,char * param)
{
    DBusError err;
    DBusMessage * msg;
    DBusMessageIter    arg;
    DBusPendingCall * pending;
    dbus_bool_t * stat;
    dbus_uint32_t * level;   
   
    dbus_error_init(&err);


    //針對目的地地址,請參考圖,建立一個method call訊息Constructs a new message to invoke a method on a remote object. 
    msg = dbus_message_new_method_call("test.wei.dest","/test/method/Object","test.method.Type","Method");
    if(msg == NULL){
        g_printerr("Message NULL");
        return;
    }


    //為訊息新增引數。Append arguments
    dbus_message_iter_init_append(msg, &arg);
    if(!dbus_message_iter_append_basic(&arg, DBUS_TYPE_STRING,&param)){
        g_printerr("Out of Memory!");
        exit(1);

    }

    //傳送訊息並獲得reply的handle。Queues a message to send, as with dbus_connection_send(), but also returns a DBusPendingCall used to receive a reply to the message.
    if(!dbus_connection_send_with_reply(connection, msg,&pending, -1)){
        g_printerr("Out of Memory!");
        exit(1);
    }     

    if(pending == NULL){
        g_printerr("Pending Call NULL: connection is disconnected ");
        dbus_message_unref(msg);
        return;
    }


    dbus_connection_flush(connection);
    dbus_message_unref(msg);

 
    //waiting a reply,在傳送的時候,已經獲取了method reply的handle,型別為DBusPendingCall。
    // block until we recieve a reply,
Block until the pending call is completed. 
    dbus_pending_call_block(pending);
    // get the reply message,Gets the reply, or returns NULL if none has been received yet.
    msg = dbus_pending_call_steal_reply(pending);
    if (msg == NULL) {
        fprintf(stderr, "Reply Null/n");
         exit(1);
    }
     // free the pending message handle
     dbus_pending_call_unref(pending);
    // read the parameters
    if (!dbus_message_iter_init(msg, &arg))
        fprintf(stderr, "Message has no arguments!/n");
    else if ( dbus_message_iter_get_arg_type(&arg) != DBUS_TYPE_BOOLEAN)
        fprintf(stderr, "Argument is not boolean!/n");
    else
        dbus_message_iter_get_basic(&arg, &stat);
 
    if (!dbus_message_iter_next(&arg))
        fprintf(stderr, "Message has too few arguments!/n");
    else if ( dbus_message_iter_get_arg_type(&arg) != DBUS_TYPE_UINT32 )
        fprintf(stderr, "Argument is not int!/n");
    else
        dbus_message_iter_get_basic(&arg, &level);

    printf("Got Reply: %d, %d/n", stat, level);
    dbus_message_unref(msg);
}

int main( int argc , char ** argv){
    DBusConnection * connection;
    connection = connect_dbus();
    if(connection == NULL)
        return -1;

    send_a_method_call(connection,"Hello, D-Bus");
    return 0;
}

相關連結: 我的D-Bus相關文章

           

給我老師的人工智慧教程打call!http://blog.csdn.net/jiangjunshow

這裡寫圖片描述