浅析dbus_message_new_signal()函数内部具体实现
/** The object path used in local/in-process-generated messages. */
#define DBUS_PATH_LOCAL "/org/freedesktop/DBus/Local"
/** This is a special interface whose methods can only be invoked
* by the local implementation (messages from remote apps aren't
* allowed to specify this interface).
*/
#define DBUS_INTERFACE_LOCAL "org.freedesktop.DBus.Local"
DBusMessage*
dbus_message_new_signal (const char *path,
const char *interface,
const char *name)
{
DBusMessage *message;
_dbus_return_val_if_fail (path != NULL, NULL);
_dbus_return_val_if_fail (interface != NULL, NULL);
_dbus_return_val_if_fail (name != NULL, NULL);
_dbus_return_val_if_fail (_dbus_check_is_valid_path (path), NULL);
_dbus_return_val_if_fail (_dbus_check_is_valid_interface (interface), NULL);
_dbus_return_val_if_fail (_dbus_check_is_valid_member (name), NULL);
message = dbus_message_new_empty_header (); // 如果message cache缓冲区有释放的message内存,返回
// cache中的内存,否则调用message = dbus_new (DBusMessage, 1);申请一块内存,初始化完message内存之后
// 进一步清空&message->header[luther.gliethttp]
// 1.为&header->data申请32字节的数据存储保证空间.
// 2.设置&header->data有效数据长度为0
// 3.header->byte_order = byte_order; // 占用2字节空间以上数据对应的大小端模式
// 4.header->padding = 0; // padding被强制初始化成0
// 5.header->fields[i].value_pos = _DBUS_HEADER_FIELD_VALUE_UNKNOWN; // 所有fileds域置无效值
// 6.为&message->body申请32字节的数据存储保证空间.
// 好了,一个全新的message空间申请完成了,同时message->header也完成了他应有的初始化工作.[lutehr.gliethttp]
if (message == NULL)
return NULL;
if (!_dbus_header_create (&message->header, // 为空的message->header.data[]空间填入有效数据
DBUS_MESSAGE_TYPE_SIGNAL,
NULL, path, interface, name, NULL))
{
dbus_message_unref (message);
return NULL;
}
dbus_message_set_no_reply (message, TRUE);
return message;
}
==>_dbus_header_create
==>reserve_header_padding (header)
// 为header->data[]空间预留7字节padding,执行完reserve_header_padding(header)之后
// #define MAX_POSSIBLE_HEADER_PADDING 7
// header->data长度将等于MAX_POSSIBLE_HEADER_PADDING
// header->padding也将等于MAX_POSSIBLE_HEADER_PADDING
// #define HEADER_END_BEFORE_PADDING(header) \
(_dbus_string_get_length (&(header)->data) - (header)->padding)
// header->data长度减去header->padding为header位于padding之前的结尾.
==>_dbus_type_writer_init_values_only (&writer, header->byte_order, // 初始化writer
&_dbus_header_signature_str, 0,
&header->data,
HEADER_END_BEFORE_PADDING (header));
// _DBUS_STRING_DEFINE_STATIC(_dbus_header_signature_str, DBUS_HEADER_SIGNATURE);
/** Header format is defined as a signature:
* byte byte order
* byte message type ID
* byte flags
* byte protocol version
* uint32 body length
* uint32 serial
* array of struct (byte,variant) (field name, value)
*
* The length of the header can be computed as the
* fixed size of the initial data, plus the length of
* the array at the end, plus padding to an 8-boundary.
*/
#define DBUS_HEADER_SIGNATURE \
DBUS_TYPE_BYTE_AS_STRING \
DBUS_TYPE_BYTE_AS_STRING \
DBUS_TYPE_BYTE_AS_STRING \
DBUS_TYPE_BYTE_AS_STRING \
DBUS_TYPE_UINT32_AS_STRING \
DBUS_TYPE_UINT32_AS_STRING \
DBUS_TYPE_ARRAY_AS_STRING \
DBUS_STRUCT_BEGIN_CHAR_AS_STRING \
DBUS_TYPE_BYTE_AS_STRING \
DBUS_TYPE_VARIANT_AS_STRING \
DBUS_STRUCT_END_CHAR_AS_STRING
==>_dbus_type_writer_init_values_only (DBusTypeWriter *writer,
int byte_order,
const DBusString *type_str, // "yyyyuua(yv)"
int type_pos, // 从0开始
DBusString *value_str, // 数据字符串
int value_pos) // 起始pos等于0
==*>writer->type_str = &_dbus_header_signature_str;// 所以writer->type_str指向同一个"yyyyuua(yv)"
writer->type_pos = 0; // 从0开始
writer->value_str = &header->data;
writer->value_pos = 0; // 起始pos等于0
writer->type_pos_is_expectation = TRUE; // type是自定义的,不需要追加
==>v_BYTE = header->byte_order;
_dbus_type_writer_write_basic (&writer, DBUS_TYPE_BYTE, &v_BYTE)
==*>_dbus_type_writer_write_basic_no_typecode (writer, type, value)
==**>_dbus_marshal_write_basic (writer->value_str, // &header->data
writer->value_pos, // 0
type,
value,
writer->byte_order,
&writer->value_pos);
==**>_dbus_marshal_write_basic (DBusString *str,// &header->data
int insert_at,
int type,
const void *value,
int byte_order,
int *pos_after);
这样header->data[0] = v_BYTE;
writer->value_pos = writer->value_pos + 1;
所以writer->value_pos = 1;
==*>write_or_verify_typecode (writer, type)
==**>if (writer->container_type != DBUS_TYPE_ARRAY)
writer->type_pos += 1; // 这时writer->type_pos等于1
此时header->data[0]等于header->byte_order
writer->value_pos等于1
writer->type_pos等于1
writer->type_str指向"yyyyuua(yv)"
==>v_BYTE = message_type;
_dbus_type_writer_write_basic (&writer, DBUS_TYPE_BYTE, &v_BYTE)
此时header->data[1]等于message_type
writer->value_pos等于2
writer->type_pos等于2
==>v_BYTE = 0;
_dbus_type_writer_write_basic (&writer, DBUS_TYPE_BYTE, &v_BYTE)
此时header->data[2]等于0
writer->value_pos等于3
writer->type_pos等于3
==>v_BYTE = DBUS_MAJOR_PROTOCOL_VERSION;
_dbus_type_writer_write_basic (&writer, DBUS_TYPE_BYTE, &v_BYTE)
此时header->data[3]等于DBUS_MAJOR_PROTOCOL_VERSION
writer->value_pos等于4
writer->type_pos等于4
==>v_UINT32 = 0; /* body length */
_dbus_type_writer_write_basic (&writer, DBUS_TYPE_UINT32, &v_UINT32)
此时header->data[4字节对齐调整后位置]等于0
writer->value_pos等于4字节对齐调整后位置+4后的数值
writer->type_pos等于5
==>v_UINT32 = 0; /* serial */
_dbus_type_writer_write_basic (&writer, DBUS_TYPE_UINT32, &v_UINT32)
此时header->data[4字节对齐调整后位置]等于0
writer->value_pos等于4字节对齐调整后位置+4后的数值
writer->type_pos等于6
/** Offset from start of _dbus_header_signature_str to the signature of the fields array */
#define FIELDS_ARRAY_SIGNATURE_OFFSET 6
下面创建展开一个新的container,该container的array->value_pos等于writer的value_pos,这样
array这个container将继续向writer->value_str数据区,即header->data内存区,存放这个新的
container对应的数据们,其实这个展开了的新的container,就是将一个独立的具有自身运算规则
的实体,将这个实体从writer->type_pos中抠出来独立进行数据填充运算,运算得到的数据最终还是
存放到header->data数据区中,这是一个很高明的做法[luther.gliethttp]
==>_dbus_type_writer_recurse (&writer, DBUS_TYPE_ARRAY,
&_dbus_header_signature_str, // 其值为"yyyyuua(yv)"
FIELDS_ARRAY_SIGNATURE_OFFSET, // 'a'位于第6个偏移
&array) // 将"a(yv)"作为一个独立的container展开,然后按格式继续存放数据
dbus_bool_t
_dbus_type_writer_recurse (DBusTypeWriter *writer,
int container_type,
const DBusString *contained_type,
int contained_type_start,
DBusTypeWriter *sub)
{
int contained_type_len;
if (contained_type)
contained_type_len = find_len_of_complete_type (contained_type, contained_type_start);
// contained_type其值为"yyyyuua(yv)"
// contained_type_start为6
// find_len_of_complete_type就是计算a(yv)这个数组小括号部分包含字节数(包括小括号)
// 即计算"(yv)"字符串长度,很明显为4
// 所以contained_type_len等于4
else
contained_type_len = 0;
// 展开"a(yv)"成立一个新的container,作为后续数据处理的基writer.[luther.gliethttp]
return _dbus_type_writer_recurse_contained_len (writer, container_type,
contained_type,
contained_type_start,
contained_type_len,
sub,
FALSE);
}
==*>_dbus_type_writer_recurse_contained_len
==**>writer_recurse_init_and_check (writer, container_type, sub);
==***>_dbus_type_writer_init (sub,
writer->byte_order,
writer->type_str,
// 上面已经分析了writer->type_str = &_dbus_header_signature_str;
// 他们的对应的字符串为"yyyyuua(yv)"
writer->type_pos, // 现在writer->type_pos等于6
writer->value_str,// writer->value_str仍然等于&header->data;
writer->value_pos)// writer->value_pos等于上面存入writer->type_str
// 指定数据"yyyyuu"类型对应的数据之后最终align了的数值.
// 至少存放了1+1+1+1+4+4+align_bytes=12+align_bytes字节数据.
这样
sub->type_str = writer->type_str;对应的字符串为"yyyyuua(yv)"
sub->type_pos = writer->type_pos;等于6
sub->value_str= writer->value_str;等于&header->data
sub->value_pos= writer->value_pos;等于当前存入writer->value_str空间实际数据个数.
sub->container_type = DBUS_TYPE_ARRAY; // 数组
......
if (writer->type_pos_is_expectation ||
(sub->container_type == DBUS_TYPE_ARRAY || sub->container_type == DBUS_TYPE_VARIANT))
sub->type_pos_is_expectation = TRUE; // 不需要将type数值存入writer->type_pos所在处
else
sub->type_pos_is_expectation = FALSE; // 需要将type数值存入writer->type_pos所在处
......
==***>_dbus_first_type_in_signature (writer->type_str, writer->type_pos);// 检查"yyyyuua(yv)"第6个偏移是否为数组关键字
==**>writer_recurse_array (writer, contained_type, contained_type_start, contained_type_len,
sub, is_array_append);
static dbus_bool_t
writer_recurse_array (DBusTypeWriter *writer,
const DBusString *contained_type,
int contained_type_start,
int contained_type_len,
DBusTypeWriter *sub,
dbus_bool_t is_array_append)
{
dbus_uint32_t value = 0;
int alignment;
int aligned;
#ifndef DBUS_DISABLE_CHECKS
if (writer->container_type == DBUS_TYPE_ARRAY &&
// 这时我们的writer->container_type等于DBUS_TYPE_INVALID;
writer->type_str)
{
if (!_dbus_string_equal_substring (contained_type,
contained_type_start,
contained_type_len,
writer->type_str,
writer->u.array.element_type_pos + 1))
{
_dbus_warn_check_failed ("Writing an array of '%s' but this is incompatible with the expected type of elements in the parent array\n",
_dbus_string_get_const_data_len (contained_type,
contained_type_start,
contained_type_len));
_dbus_assert_not_reached ("incompatible type for child array");
}
}
#endif /* DBUS_DISABLE_CHECKS */
if (writer->enabled && !is_array_append)
{
/* 3 pad + 4 bytes for the array length, and 4 bytes possible padding
* before array values
*/
if (!_dbus_string_alloc_space (sub->value_str, 3 + 4 + 4)) // 提前申请4字节空间存放array长度,以保证空间足够
return FALSE;
}
if (writer->type_str != NULL)
{
sub->type_pos += 1; /* move to point to the element type, since type_pos
* should be the expected type for further writes
*/
// 这时sub->type_pos指向"(yv)"字符串
sub->u.array.element_type_pos = sub->type_pos; // 记录type_pos到array专用空间[luther.gliethttp]
}
if (!writer->type_pos_is_expectation)
{
// 如果type是不存在的,那么需要这里动态的将该type数值添加到writer->type_str[type_pos]处
/* sub is a toplevel/outermost array so we need to write the type data */
/* alloc space for array typecode, element signature */
if (!_dbus_string_alloc_space (writer->type_str, 1 + contained_type_len))
return FALSE;
if (!_dbus_string_insert_byte (writer->type_str,
writer->type_pos,
DBUS_TYPE_ARRAY)) // 因为这是array,所以追加类型值
_dbus_assert_not_reached ("failed to insert array typecode after prealloc");
if (!_dbus_string_copy_len (contained_type,
// 将contained_type[contained_type_start]开始contained_type_len个字节长度数据拷贝到
// sub->type_str类型字符串sub->u.array.element_type_pos开始处.
contained_type_start, contained_type_len,
sub->type_str,
sub->u.array.element_type_pos))
_dbus_assert_not_reached ("should not have failed to insert array element typecodes");
}
if (writer->type_str != NULL)
{
/* If the parent is an array, we hold type_pos pointing at the array element type;
* otherwise advance it to reflect the array value we just recursed into
*/
if (writer->container_type != DBUS_TYPE_ARRAY) // 如果writer不是array,那么
// writer的type_pos需要跳过该结构体类型所占字节数,
// 这里writer->type_pos将指向"yyyyuua(yv)"该字符串的结尾'\0'数据.
writer->type_pos += 1 + contained_type_len;
else
_dbus_assert (writer->type_pos_is_expectation); /* because it's an array */
}
if (writer->enabled)
{
/* Write (or jump over, if is_array_append) the length */
// 将sub->value_pos对齐下一个4字节边界,以备后面存放array数据长度[luther.gliethttp]
sub->u.array.len_pos = _DBUS_ALIGN_VALUE (sub->value_pos, 4);
if (is_array_append)
{
sub->value_pos += 4;
}
else
{
// 向sub->u.array.len_pos偏移处存放array数据长度初始值0
// 之后sub->value_pos将调整到4字节边界,之后再加4,指向
// array数据长度存储空间的下一个有效数据存储空间[luther.gliethtp].
// 这时的sub->value_pos一定在4字节边界.
if (!_dbus_type_writer_write_basic_no_typecode (sub, DBUS_TYPE_UINT32,
&value))
_dbus_assert_not_reached ("should not have failed to insert array len");
}
// 这时的sub->value_pos一定在4字节边界.
_dbus_assert (sub->u.array.len_pos == sub->value_pos - 4);
/* Write alignment padding for array elements
* Note that we write the padding *even for empty arrays*
* to avoid wonky special cases
*/
alignment = element_type_get_alignment (contained_type, contained_type_start);
// array是4字节对齐的
aligned = _DBUS_ALIGN_VALUE (sub->value_pos, alignment);
if (aligned != sub->value_pos)
{
if (!is_array_append)
{
if (!_dbus_string_insert_bytes (sub->value_str, // 将未4字节对齐的间隙填入'\0'数据
sub->value_pos,
aligned - sub->value_pos,
'\0'))
_dbus_assert_not_reached ("should not have failed to insert alignment padding");
}
sub->value_pos = aligned; // 新位置应该是对齐后的位置[luther.gliethtp]
}
sub->u.array.start_pos = sub->value_pos; // 这个已经位于4字节边界上的位置,就是
// array做数据存放的起始位置 |array_len|sub->value_pos
if (is_array_append)
{
dbus_uint32_t len;
_dbus_assert (_DBUS_ALIGN_VALUE (sub->u.array.len_pos, 4) ==
(unsigned) sub->u.array.len_pos);
// 需要将类型追加到
len = _dbus_unpack_uint32 (sub->byte_order,
_dbus_string_get_const_data_len (sub->value_str,
sub->u.array.len_pos,
4));
sub->value_pos += len;
}
}
else
{
/* not enabled, so we won't write the len_pos; set it to -1 to so indicate */
sub->u.array.len_pos = -1; // 置成非法值,因为我们不能写
sub->u.array.start_pos = sub->value_pos;
}
_dbus_assert (sub->u.array.len_pos < sub->u.array.start_pos);
_dbus_assert (is_array_append || sub->u.array.start_pos == sub->value_pos);
#if RECURSIVE_MARSHAL_WRITE_TRACE
_dbus_verbose (" type writer %p recurse array done remaining sig '%s' array start_pos = %d len_pos = %d value_pos = %d\n", sub,
sub->type_str ?
_dbus_string_get_const_data_len (sub->type_str, sub->type_pos, 0) :
"unknown",
sub->u.array.start_pos, sub->u.array.len_pos, sub->value_pos);
#endif
return TRUE;
}
至此_dbus_type_writer_recurse()函数已经为我们创建展开了一个新的container,
该container的array->value_pos等于writer的value_pos,这样
array这个container将继续向writer->value_str数据区,即header->data内存区,存放这个新的
container对应的数据们,其实这个展开了的新的container,就是将一个独立的具有自身运算规则
的实体,将这个实体从writer->type_pos中抠出来独立进行数据填充运算,运算得到的数据最终还是
存放到header->data数据区中,这是一个很高明的做法[luther.gliethttp]
下面就是以array为基writer,根据array标识的type_pos和value_pos进行数据填充了.
==>write_basic_field (&array,
DBUS_HEADER_FIELD_PATH,
DBUS_TYPE_OBJECT_PATH,
&path);
static dbus_bool_t
write_basic_field (DBusTypeWriter *writer,
int field,
int type,
const void *value)
{
DBusTypeWriter sub;
DBusTypeWriter variant;
int start;
int padding;
unsigned char field_byte;
DBusString contained_type;
char buf[2];
start = writer->value_pos; // 就是array的value_pos,就是指向&header->data[value_pos]内存.
padding = _dbus_string_get_length (writer->value_str) - start;
// 现在array的type_pos指向"(yv)"字符串,
// 所以继续抠出DBUS_TYPE_STRUCT即'('结构体.
// [注意这次执行_dbus_type_writer_recurse操作,writer就是array,
// 这里writer->container_type即array.container_type等于DBUS_TYPE_ARRAY]
// _dbus_type_writer_recurse==>writer_recurse_struct_or_dict_entry该函数完成之后
// sub->type_pos指向"yv)"字符串[luther.gliethttp].
if (!_dbus_type_writer_recurse (writer, DBUS_TYPE_STRUCT,
NULL, 0, &sub))
goto append_failed;
field_byte = field;
// 写入"yv)"字符串的"y"数据
if (!_dbus_type_writer_write_basic (&sub, DBUS_TYPE_BYTE,
&field_byte))
goto append_failed;
buf[0] = type;
buf[1] = '\0';
_dbus_string_init_const_len (&contained_type, buf, 1);
// 在"v)"中抠出variant
if (!_dbus_type_writer_recurse (&sub, DBUS_TYPE_VARIANT,
&contained_type, 0, &variant))
goto append_failed;
if (!_dbus_type_writer_write_basic (&variant, type, value))
goto append_failed;
if (!_dbus_type_writer_unrecurse (&sub, &variant))
goto append_failed;
if (!_dbus_type_writer_unrecurse (writer, &sub))
goto append_failed;
return TRUE;
append_failed:
_dbus_string_delete (writer->value_str,
start,
_dbus_string_get_length (writer->value_str) - start - padding);
return FALSE;
}
_dbus_type_writer_recurse (&sub, DBUS_TYPE_VARIANT,
&contained_type, 0, &variant)
==>writer_recurse_variant
static dbus_bool_t
writer_recurse_variant (DBusTypeWriter *writer,
const DBusString *contained_type,
int contained_type_start,
int contained_type_len,
DBusTypeWriter *sub)
{
int contained_alignment;
if (writer->enabled)
{
/* Allocate space for the worst case, which is 1 byte sig
* length, nul byte at end of sig, and 7 bytes padding to
* 8-boundary.
*/
// 用来存放sig的空间
if (!_dbus_string_alloc_space (sub->value_str, contained_type_len + 9))
return FALSE;
}
/* write VARIANT typecode to the parent's type string */
// 这时type_pos指向"v)"字符串
if (!write_or_verify_typecode (writer, DBUS_TYPE_VARIANT))
return FALSE;
/* If not enabled, mark that we have no type_str anymore ... */
if (!writer->enabled)
{
sub->type_str = NULL;
sub->type_pos = -1;
return TRUE;
}
/* If we're enabled then continue ... */
// 向&header->data[value_pos]插入type类型字符串长度,variant对应的长度为1
if (!_dbus_string_insert_byte (sub->value_str,
sub->value_pos,
contained_type_len))
_dbus_assert_not_reached ("should not have failed to insert variant type sig len");
sub->value_pos += 1; // 数据偏移指针后移
/* Here we switch over to the expected type sig we're about to write */
sub->type_str = sub->value_str;
sub->type_pos = sub->value_pos;
// ok,type类型长度填完之后,紧跟的内存空间就是存放contained_type_len长度的type类型控制数据
// 我们这里很简单就一个"o",即:DBUS_TYPE_OBJECT_PATH
if (!_dbus_string_copy_len (contained_type, contained_type_start, contained_type_len,
sub->value_str, sub->value_pos))
// 将type类型数据拷贝到header->data[]空间
_dbus_assert_not_reached ("should not have failed to insert variant type sig");
sub->value_pos += contained_type_len; // header->data[]空间偏移指针调整
if (!_dbus_string_insert_byte (sub->value_str,
// 追加DBUS_TYPE_INVALID数据,表示该variant类型控制结构结束[luther.gliethttp]
sub->value_pos,
DBUS_TYPE_INVALID))
_dbus_assert_not_reached ("should not have failed to insert variant type nul termination");
sub->value_pos += 1;
contained_alignment = _dbus_type_get_alignment (_dbus_first_type_in_signature (contained_type, contained_type_start)); // 调整value_pos到第1个type数据对齐边界上
if (!_dbus_string_insert_bytes (sub->value_str, // 填充'\0'数据到调整发生的gaps间隙.
sub->value_pos,
_DBUS_ALIGN_VALUE (sub->value_pos, contained_alignment) - sub->value_pos,
'\0'))
_dbus_assert_not_reached ("should not have failed to insert alignment padding for variant body");
sub->value_pos = _DBUS_ALIGN_VALUE (sub->value_pos, contained_alignment);
return TRUE;
}
_dbus_type_writer_write_basic (&variant, type, value) // 将数据写入到header->data[]内存空间.
即_dbus_type_writer_write_basic (&variant, DBUS_HEADER_FIELD_PATH,DBUS_TYPE_OBJECT_PATH)
_dbus_type_writer_write_basic
==*>_dbus_type_writer_write_basic_no_typecode
==**>_dbus_marshal_write_basic
==***>marshal_string (str, insert_at, vp->str, byte_order, pos_after);
==****>marshal_len_followed_by_bytes // 插入字符串
static dbus_bool_t
marshal_len_followed_by_bytes (int marshal_as,
DBusString *str,
int insert_at,
const unsigned char *value,
int data_len, /* doesn't include nul if any */
int byte_order,
int *pos_after)
{
int pos;
DBusString value_str;
int value_len;
_dbus_assert (byte_order == DBUS_LITTLE_ENDIAN || byte_order == DBUS_BIG_ENDIAN);
if (insert_at > _dbus_string_get_length (str))
_dbus_warn ("insert_at = %d string len = %d data_len = %d\n",
insert_at, _dbus_string_get_length (str), data_len);
if (marshal_as == MARSHAL_AS_BYTE_ARRAY)
value_len = data_len;
else
value_len = data_len + 1; /* value has a nul */ // 我们这里插入的就是字符串"org.freedesktop.DBus"
_dbus_string_init_const_len (&value_str, value, value_len);
pos = insert_at;
if (marshal_as == MARSHAL_AS_SIGNATURE)
{
_dbus_assert (data_len <= DBUS_MAXIMUM_SIGNATURE_LENGTH);
_dbus_assert (data_len <= 255); /* same as max sig len right now */
if (!_dbus_string_insert_byte (str, pos, data_len))
goto oom;
pos += 1;
}
else
{
if (!marshal_4_octets (str, pos, data_len,
// 将字符串"org.freedesktop.DBus"长度写入header->data[]空间
byte_order, &pos))
goto oom;
}
if (!_dbus_string_copy_len (&value_str, 0, value_len, // 拷贝数据
str, pos))
goto oom;
#if 0
/* too expensive */
_dbus_assert (_dbus_string_equal_substring (&value_str, 0, value_len,
str, pos));
_dbus_verbose_bytes_of_string (str, pos, value_len);
#endif
pos += value_len;
if (pos_after)
*pos_after = pos; // 最新空闲header->data[]空间偏移[luther.gliethttp]
return TRUE;
oom:
/* Delete what we've inserted */
_dbus_string_delete (str, insert_at, pos - insert_at);
return FALSE;
}
type内容为"a(yv)",那么header->data[]中对应的区段数据为:
1. array_len |
2. field_byte[即DBUS_HEADER_FIELD_PATH] |
3. (variant)插入type类型字符串长度contained_type_len这里为1
[即只有'o'一个控制类型DBUS_TYPE_OBJECT_PATH] |
4. (variant)插入type类型字符串'o'[即DBUS_TYPE_OBJECT_PATH]
5. 写入字符串"org.freedesktop.DBus"长度21(包含字符串结尾0数据)
6. 写入字符串"org.freedesktop.DBus"+'\0'
好了,"a(yv)"这个arry的arry[0]已经填充完毕了,之后重复上面的操作填充arry[1]...即可[luther.gliethttp]
|