• [转] DBus学习(六):Method的收发小例子


    From: http://blog.csdn.net/flowingflying/article/details/5455327

      我们继续学习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 ( db us_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 ( db us_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;
    }

  • 相关阅读:
    【转】EditText获取焦点不自动弹出键盘设置--失去焦点的方法,不错
    【转】eclipse android 设置及修改生成apk的签名文件 -- custom debug keystore
    【转】Adnroid4.0 签名混淆打包(conversion to dalvik format failed with error 1)
    【转】Android Fragment 基本介绍--不错
    【转】java代码中实现android背景选择的selector-StateListDrawable的应用
    【转】android官方侧滑菜单DrawerLayout详解
    【转】微信Android SDK示例代码及运行方法
    【转】Eclipse中设置ButterKnife进行注解式开发步骤 -- 不错
    【转】ButterKnife基本使用--不错
    python 命令行:help(),'more'不是内部或外部命令,也不是可运行的程序或批处理文件
  • 原文地址:https://www.cnblogs.com/cnland/p/3049650.html
Copyright © 2020-2023  润新知