导航:[首页]->[network]->[DBUS学习笔记之 DBusMessage]

生命周期

创建

// Constructs a new message of the given message type. 
DBusMessage *   dbus_message_new (int message_type)

// Constructs a new message representing a signal emission. 
DBusMessage *   dbus_message_new_signal (const char *path, const char *interface, const char *name)

// Constructs a new message to invoke a method on a remote object. 
DBusMessage *   dbus_message_new_method_call (const char *destination, 
    const char *path, const char *interface, const char *method)

// Constructs a message that is a reply to a method call. 
DBusMessage *   dbus_message_new_method_return (DBusMessage *method_call)
// Creates a new message that is an error reply to another message.

DBusMessage *   dbus_message_new_error (DBusMessage *reply_to, 
    const char *error_name, const char *error_message)

// Creates a new message that is an error reply to another message, 
// allowing you to use printf formatting.
DBusMessage *   dbus_message_new_error_printf (DBusMessage *reply_to, 
    const char *error_name, const char *error_format,...)

从DBusConnection中获取

通常对于发送的DBusMessage,我们需要明确的创建并设置适当的属性,对于接收的消息,直接使用DBusConnection的方法就可以了。例如

DBusMessage * msg;
DBusConnection * connection;
while (1) {
    dbus_connection_read_write(connection, 0);
    msg = dbus_connection_pop_message(connection);
}

引用技术

DBUS中很多对象都使用应用技术来管理,DBusMessage也不例外。当dbus_message_unref之后,引用技术变成0,那么该对象就被销毁。

// Increments the reference count of a DBusMessage. 
DBusMessage *   dbus_message_ref (DBusMessage *message)

// Decrements the reference count of a DBusMessage, freeing the message if the count reaches 0. 
void    dbus_message_unref (DBusMessage *message)

其他

// 拷贝消息
DBusMessage *   dbus_message_copy (const DBusMessage *message)

消息类型

  1. DBUS_MESSAGE_TYPE_SIGNAL : 事件
  2. DBUS_MESSAGE_TYPE_METHOD_CALL : 方法调用
  3. DBUS_MESSAGE_TYPE_METHOD_RETURN : 方法返回
  4. DBUS_MESSAGE_TYPE_ERROR : 错误

前面提到,消息只有两种,实际上,DBUS_MESSAGE_TYPE_METHOD_RETURNDBUS_MESSAGE_TYPE_ERROR是可以和DBUS_MESSAGE_TYPE_METHOD_CALL归为一大类的。

// 获得消息类型 
int     dbus_message_get_type (DBusMessage *message)、

// Checks whether the message is a method call with the given interface and member fields.
dbus_bool_t     dbus_message_is_method_call (DBusMessage *message, 
    const char *interface, const char *method)

// Checks whether the message is a signal with the given interface and member fields.
dbus_bool_t     dbus_message_is_signal (DBusMessage *message, 
    const char *interface, const char *signal_name)

// Checks whether the message is an error reply with the given error name. 
dbus_bool_t     dbus_message_is_error (DBusMessage *message, const char *error_name)

基本属性

Path

// Sets the object path this message is being sent to (for DBUS_MESSAGE_TYPE_METHOD_CALL)
// the one a signal is being emitted from (for DBUS_MESSAGE_TYPE_SIGNAL). 
dbus_bool_t     dbus_message_set_path (DBusMessage *message, const char *object_path)

// Gets the object path this message is being sent to (for DBUS_MESSAGE_TYPE_METHOD_CALL)
// being emitted from (for DBUS_MESSAGE_TYPE_SIGNAL). 
char *  dbus_message_get_path (DBusMessage *message)

// Checks if the message has a particular object path. 
dbus_bool_t     dbus_message_has_path (DBusMessage *message, const char *path)

// Gets the object path this message is being sent to (for DBUS_MESSAGE_TYPE_METHOD_CALL)
// being emitted from (for DBUS_MESSAGE_TYPE_SIGNAL) in a decomposed format (one array element per path component). 
dbus_bool_t     dbus_message_get_path_decomposed (DBusMessage *message, char ***path)

Interface

// Sets the interface this message is being sent to (for DBUS_MESSAGE_TYPE_METHOD_CALL)
// the interface a signal is being emitted from (for DBUS_MESSAGE_TYPE_SIGNAL). 
dbus_bool_t     dbus_message_set_interface (DBusMessage *message, const char *interface)

// Gets the interface this message is being sent to (for DBUS_MESSAGE_TYPE_METHOD_CALL)
// being emitted from (for DBUS_MESSAGE_TYPE_SIGNAL). 
const char *    dbus_message_get_interface (DBusMessage *message)

// Checks if the message has an interface. 
dbus_bool_t     dbus_message_has_interface (DBusMessage *message, const char *interface)

Member

// Sets the interface member being invoked (DBUS_MESSAGE_TYPE_METHOD_CALL)
// emitted (DBUS_MESSAGE_TYPE_SIGNAL). 
dbus_bool_t     dbus_message_set_member (DBusMessage *message, const char *member)

// Gets the interface member being invoked (DBUS_MESSAGE_TYPE_METHOD_CALL)
// emitted (DBUS_MESSAGE_TYPE_SIGNAL). 
const char *    dbus_message_get_member (DBusMessage *message)

// Checks if the message has an interface member. 
dbus_bool_t     dbus_message_has_member (DBusMessage *message, const char *member)

发送接收方

对于方法调用,需要明确地指定发送接收方

// Checks whether the message has the given unique name as its sender. 
dbus_bool_t     dbus_message_has_sender (DBusMessage *message, const char *name)

// Sets the message sender. 
dbus_bool_t     dbus_message_set_sender (DBusMessage *message, const char *sender)

// Gets the unique name of the connection which originated this message, or NULL if unknown or inapplicable. 
const char *    dbus_message_get_sender (DBusMessage *message)

// Checks whether the message was sent to the given name. 
dbus_bool_t     dbus_message_has_destination (DBusMessage *message, const char *name)

dbus_bool_t     dbus_message_set_destination (DBusMessage *message, const char *destination)
// Sets the message's destination. 

// Gets the destination of a message or NULL if there is none set. 
const char *    dbus_message_get_destination (DBusMessage *message)

dbus_message_new函数很少用,不过在使用它创建DBusMessage之后,在配合上述属性设置的方法,也可以实现dbus_message_new_signal等函数相同的效果。

私有数据

DBusMessage可以携带一些私有数据在各个程序逻辑中传递,方便管理(注意和参数相区分,后者会被发送到连接对端

// Allocates an integer ID to be used for storing application-specific data on any DBusMessage. 
dbus_bool_t     dbus_message_allocate_data_slot (dbus_int32_t *slot_p)

// Deallocates a global ID for message data slots. 
void    dbus_message_free_data_slot (dbus_int32_t *slot_p)

// Stores a pointer on a DBusMessage, along with an optional function to be used 
// for freeing the data when the data is set again, or when the message is finalized. 
dbus_bool_t     dbus_message_set_data (DBusMessage *message, 
    dbus_int32_t slot, void *data, DBusFreeFunction free_data_func)

// Retrieves data previously set with dbus_message_set_data(). 
void *  dbus_message_get_data (DBusMessage *message, dbus_int32_t slot)

参数

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

int main()
{
    DBusMessage * msg;
    msg = dbus_message_new_signal(
                "/test/signal/Object1fasdf",
                "test.signal.Type", "Test");


    //给这个信号(messge)具体的内容
    {
        DBusMessageIter iter;
        DBusMessageIter subiter;
        dbus_message_iter_init_append(msg, &iter);
        // 基本类型,字符串
        const char * msg_ = "hello world";
        dbus_message_iter_append_basic(&iter, DBUS_TYPE_STRING, &msg_);

        // 结构
        dbus_message_iter_open_container(
                &iter,
                DBUS_TYPE_STRUCT,
                NULL,
                &subiter);
        dbus_message_iter_append_basic(&subiter, DBUS_TYPE_STRING, &msg_);
        dbus_message_iter_append_basic(&subiter, DBUS_TYPE_STRING, &msg_);
        dbus_message_iter_close_container(&iter,&subiter);

        // 基本类型 int
        int intval_ = 123456;
        dbus_message_iter_append_basic(&iter, DBUS_TYPE_INT32, &intval_);

        // 数组
        /**
         * For variants, the contained_signature should be the type of
         * the single value inside the variant. For structs and dict entries,
         *  contained_signature should be NULL;
         *  it will be set to whatever types you write into the struct.
         *   For arrays, contained_signature should be the type
         *    of the array elements.
         */
        dbus_message_iter_open_container(&iter,
                DBUS_TYPE_ARRAY,
                "i", // i 对应 DBUS_TYPE_INT32
                &subiter);
        int array[] = { 1, 2, 3 ,4 ,5};
        int* fuck_ = array;
        dbus_message_iter_append_fixed_array (
                &subiter,
                DBUS_TYPE_INT32,
                &fuck_,
                sizeof(array)/sizeof(array[0]));
        dbus_message_iter_close_container(&iter,&subiter);

        // 基本类型 浮点
        double doubleval_ = 1.234567;
        dbus_message_iter_append_basic(&iter, DBUS_TYPE_DOUBLE, &doubleval_);
    }
    {
        // 遍历参数
        DBusMessageIter iter;
        dbus_message_iter_init(msg, &iter);
        int current_type;
        int cnt_ = 1;
        while ((current_type = dbus_message_iter_get_arg_type(&iter))
                != DBUS_TYPE_INVALID)
        {
            // 基本类型
            if(DBUS_TYPE_STRING == current_type)
            {
                char* value_;
                dbus_message_iter_get_basic(&iter, &value_);
                printf("iter %d string '%s'\n",cnt_,value_);
            }
            else if(DBUS_TYPE_INT32 == current_type)
            {
                int value_;
                dbus_message_iter_get_basic(&iter, &value_);
                printf("iter %d int32 '%d'\n",cnt_,value_);
            }
            else if(DBUS_TYPE_DOUBLE == current_type)
            {
                double value_;
                dbus_message_iter_get_basic(&iter, &value_);
                printf("iter %d int32 '%f'\n",cnt_,value_);
            }
            // 数组类型
            else if(DBUS_TYPE_ARRAY == current_type)
            {
                // 先获取数组元素的类型
                if(DBUS_TYPE_INT32 == dbus_message_iter_get_element_type(&iter))
                {
                    // 跳进去
                    DBusMessageIter subiter;
                    dbus_message_iter_recurse(&iter, &subiter);
                    int* array_;
                    int array_len_;
                    // 获得地址和数组长度
                    dbus_message_iter_get_fixed_array(&subiter, &array_,&array_len_);
                    printf("iter %d array len '%d' type\n",
                            cnt_,
                            array_len_);
                    int index = 0;
                    for(;index < array_len_;index++)
                    {
                        printf("iter %d array [%d] = '%d'\n",
                                cnt_,
                                index,
                                array_[index]);
                    }
                }
                else
                {
                    printf("iter %d array type\n");
                }
            }
            // 结构类型
            else if(DBUS_TYPE_STRUCT == current_type)
            {
                printf("iter %d struct type\n");

                // 跳进去
                DBusMessageIter subiter;
                int subcnt_ = 0;
                dbus_message_iter_recurse(&iter, &subiter);

                // 遍历,同上
                int sub_current_type;
                while ((sub_current_type = dbus_message_iter_get_arg_type(&subiter))
                        != DBUS_TYPE_INVALID)
                {
                    printf("sub iter %d struct type\n",subcnt_);
                    dbus_message_iter_next(&subiter);
                    subcnt_ ++;
                }
            }
            else
            {
                printf("iter %d unknown type\n");
            }
            dbus_message_iter_next(&iter);
            cnt_ ++;
        }
    }

    return 0;
}

参考

  1. http://dbus.freedesktop.org/doc/api/html/group__DBusMessage.html
  2. http://hi.baidu.com/9562512/item/f93cac0be4849cdcdce5b076
  3. http://dbus.freedesktop.org/doc/api/html/group__DBusProtocol.html#ga7eb77066dadf5415896b44c56d93acce