数据类型
其实DBUS的数据类型在 bluetoothctl client tool 中的dbus数据模型就有记录和说明过。通过基本类型数据进行嵌套可以组合成复杂数据类型,一般可以用简称表示,例如 a{sv}
。如何将数据进行构造和解析才是难点和重点。
Numeric
数字的数据类型涉及: b
, y
, n
, q
, i
, u
, x
, t
, h
, d
Character |
Equivalent C type |
b |
gboolean |
y |
guchar |
n |
gint16 |
q |
guint16 |
i |
gint32 |
u |
guint32 |
x |
gint64 |
t |
guint64 |
h |
gint32 (handle) |
d |
gdouble |
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45
|
#include <stdio.h> #include <stdlib.h> #include <string.h> #include <stdbool.h>
#include <glib.h> #include <gio/gio.h> #include <glib/gprintf.h>
int main(int argc, char *argv[]) { GVariant *value1, *value2, *value3, *value4; value1 = g_variant_new ("y", 200); value2 = g_variant_new ("b", TRUE); value3 = g_variant_new ("d", 37.5); value4 = g_variant_new ("x", G_GINT64_CONSTANT (998877665544332211));
guchar byte; gdouble floating; gboolean truth; gint64 bignum; g_variant_get (value1, "y", &byte); g_variant_get (value2, "b", &truth); g_variant_get (value3, "d", &floating); g_variant_get (value4, "x", &bignum);
g_printf("value1(y): %u\n", byte); g_printf("value2(b): %s\n", truth ? "ture":"false"); g_printf("value3(d): %.1f\n", floating); g_printf("value4(x): %ld\n", bignum); g_variant_unref(value1); g_variant_unref(value2); g_variant_unref(value3); g_variant_unref(value4);
return 0; }
|
String
字符串涉及:s
, o
, g
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41
|
#include <stdio.h> #include <stdlib.h> #include <string.h> #include <stdbool.h>
#include <glib.h> #include <gio/gio.h> #include <glib/gprintf.h>
int main(int argc, char *argv[]) { GVariant *value1, *value2, *value3;
value1 = g_variant_new ("s", "hello world!"); value2 = g_variant_new ("o", "/must/be/a/valid/path"); value3 = g_variant_new ("g", "iias");
gchar *str, *object_path, *signature;
g_variant_get (value1, "s", &str); g_variant_get (value2, "o", &object_path); g_variant_get (value3, "g", &signature);
g_printf("value1(s): %s'\n", str); g_printf("value1(s): %s'\n", object_path); g_printf("value1(s): %s'\n", signature); g_free (str); g_free (object_path); g_free (signature); g_variant_unref(value1); g_variant_unref(value2); g_variant_unref(value3);
return 0; }
|
注意:当g_variant_get() 遇到 ‘s’ ,’o’, ‘g’ 时,会创建一块新的内容,然后把要返回的字符串拷贝到这个内容中,这块内存返回给给一个指向gchar *
的指针,所以传入函数参数类型是 gchar **
,最后使用完后,需要用户使用g_free() 进行释放。
Array
数组:a
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40
|
#include <stdio.h> #include <stdlib.h> #include <string.h> #include <stdbool.h>
#include <glib.h> #include <gio/gio.h> #include <glib/gprintf.h>
int main(int argc, char *argv[]) { GVariantBuilder *builder; GVariant *value;
builder = g_variant_builder_new(G_VARIANT_TYPE("as")); g_variant_builder_add(builder, "s", "when"); g_variant_builder_add(builder, "s", "in"); g_variant_builder_add(builder, "s", "the"); g_variant_builder_add(builder, "s", "course"); value = g_variant_new("as", builder); g_variant_builder_unref(builder);
GVariantIter *iter; gchar *str;
g_variant_get(value, "as", &iter); while (g_variant_iter_loop(iter, "s", &str)) g_print("%s\n", str); g_variant_iter_free(iter);
g_variant_unref(value);
return 0; }
|
Tuple
元组:()
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28
|
#include <stdio.h> #include <stdlib.h> #include <string.h> #include <stdbool.h>
#include <glib.h> #include <gio/gio.h> #include <glib/gprintf.h>
int main(int argc, char *argv[]) { GVariant *value1, *value2;
value1 = g_variant_new("(s(ii))", "Hello", 55, 77);
gchar *string; gint x, y;
g_variant_get(value1, "(s(ii))", &string, &x, &y); g_printf("%s, %d, %d\n", string, x, y); g_free(string);
return 0; }
|
Dictionary
字典:{}
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53
|
#include <stdio.h> #include <stdlib.h> #include <string.h> #include <stdbool.h>
#include <glib.h> #include <gio/gio.h> #include <glib/gprintf.h>
int main(int argc, char *argv[]) { GVariantBuilder *b; GVariant *dict;
b = g_variant_builder_new(G_VARIANT_TYPE("a{sv}")); g_variant_builder_add(b, "{sv}", "name", g_variant_new_string("foo")); g_variant_builder_add(b, "{sv}", "timeout", g_variant_new_int32(10)); dict = g_variant_builder_end(b); g_variant_builder_unref(b);
GVariantIter iter; GVariant *value; gchar *key; g_variant_iter_init(&iter, dict); while (g_variant_iter_next (&iter, "{sv}", &key, &value)) { const gchar *type = g_variant_get_type_string(value); switch (*type) { case 's': g_printf("%s(%s): %s\n", key, type, g_variant_get_string(value, NULL)); break; case 'i': g_printf("%s(%s): %d\n", key, type, g_variant_get_int32(value)); break; default: break; } g_variant_unref(value); g_free(key); } g_variant_unref(dict);
return 0; }
|
注意:通过g_variant_iter_next() 获取的key和value,在while循环内部使用完后,需要用户进行释放。通过g_variant_iter_init() 获取的dict,在使用完后,也需要用户进行释放。但是有特殊的地方,若第二个参数是{&sv},那么对应的key就无需用户释放。
Multiple
复合类型,即不同类型的嵌套,例如:(a{sv})
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55
|
#include <stdio.h> #include <stdlib.h> #include <string.h> #include <stdbool.h>
#include <glib.h> #include <gio/gio.h> #include <glib/gprintf.h>
int main(int argc, char *argv[]) { GVariantBuilder *b; GVariant *dict, *tuple;
b = g_variant_builder_new(G_VARIANT_TYPE("a{sv}")); g_variant_builder_add(b, "{sv}", "name", g_variant_new_string("foo")); g_variant_builder_add(b, "{sv}", "timeout", g_variant_new_int32(10)); dict = g_variant_builder_end(b); g_variant_builder_unref(b); tuple = g_variant_new_tuple(&dict, 1);
GVariantIter *iter; GVariant *value; gchar *key; g_variant_get(tuple, "(a{sv})", &iter); while (g_variant_iter_next (iter, "{sv}", &key, &value)) { const gchar *type = g_variant_get_type_string(value); switch (*type) { case 's': g_printf("%s(%s): %s\n", key, type, g_variant_get_string(value, NULL)); break; case 'i': g_printf("%s(%s): %d\n", key, type, g_variant_get_int32(value)); break; default: break; } g_variant_unref(value); g_free(key); } g_variant_unref(tuple);
return 0; }
|
内存释放
g_variant_iter_free()
g_variant_iter_free() 可以释放由这两个函数返回的变量的内存:g_variant_iter_new()
or g_variant_iter_copy()
1 2 3 4
| void g_variant_iter_free ( GVariantIter* iter )
|
参考来源
1、BlueZ Part 3: Understanding DBUS – Container type system – (2)
2、BlueZ Part 2: Understanding DBUS – Basic type system – (1)
3、GVariant 格式字符串
4、Dbus-glib
5、dbus介绍与例子