DBus glib 各数据类型接收与发送详解—C语言(3)
DBus glib 各數(shù)據(jù)類(lèi)型接收與發(fā)送詳解—C語(yǔ)言(3)
動(dòng)機(jī) 前置知識(shí) 正文動(dòng)機(jī)
說(shuō)到 DBus 用過(guò)的人大概都能明白其工作的流程。典型的使用流程是,向 DBus 服務(wù)進(jìn)程發(fā)送數(shù)據(jù),然后接收其返回的數(shù)據(jù)。簡(jiǎn)單的說(shuō),就像調(diào)用函數(shù)一樣,向服務(wù)進(jìn)程發(fā)送數(shù)據(jù)就相當(dāng)于函數(shù)的參數(shù),其返回的數(shù)據(jù)就相當(dāng)于函數(shù)返回的結(jié)果。雖然明白了流程,但想要使用 C語(yǔ)言 通過(guò)已有的 DBus 服務(wù)進(jìn)行操作,仍然是一項(xiàng)不太容易的工作(對(duì)像我這樣的菜鳥(niǎo)^_^),因?yàn)閿?shù)據(jù)的類(lèi)型真是太多了, 使用 Python 會(huì)簡(jiǎn)單一點(diǎn)。簡(jiǎn)單點(diǎn)的有 Boolean, Byte, Int32, Int64, String, ObjectPath, Signature 等; 復(fù)雜一點(diǎn)的有 Array, Struct, Dict 等。如果不能弄清楚它們之間的聯(lián)系,那么將是一件非常頭痛的事。為了使我研究的結(jié)果不被淡忘,于是有了這篇文章。
前置知識(shí)
- 能夠熟練使用 C語(yǔ)言;
- 了解 DBus 各數(shù)據(jù)類(lèi)型的表示, 參考 D-Bus Specification
- 對(duì) DBus-glib 有基本的了解,能夠與 DBus 服務(wù)進(jìn)程進(jìn)行簡(jiǎn)單的交互。
- 簡(jiǎn)單使用 d-feet, 參考 D-Bus 實(shí)例講解
- 大概對(duì) Python 有些了解(只是為了說(shuō)明我的分析思路,如果你只想找 C 的解決方法,那完全可以不了解);
- 簡(jiǎn)單了解 python dbus
正文
上一篇討論了高級(jí)數(shù)據(jù)類(lèi)型的傳遞,這次我們就討論更難一點(diǎn)的, 復(fù)雜數(shù)據(jù)類(lèi)型 的傳遞。為什么說(shuō)復(fù)雜呢?因?yàn)樗歉呒?jí)數(shù)據(jù)類(lèi)型的雜揉,本來(lái)高級(jí)數(shù)據(jù)類(lèi)型就挺難的了,再雜揉一下,不用活了。
同樣先給出 Python 編寫(xiě)的服務(wù)與測(cè)試
Python DBus 服務(wù)進(jìn)程
?
more_advanced_data_deliver_service.py
#!/usr/bin/env pythonimport gobjectimport dbus import dbus.service import dbus.mainloop.glibclass AdvancedData(dbus.service.Object):def __init__(self, bus, object_path):dbus.service.Object.__init__(self, bus, object_path)self._last_input = None@dbus.service.method('airead.fan.MoreAdvancedDataType', in_signature='a(si)', out_signature='a(si)')def StructArrayPrint(self, struct_array):print "receive struct array:"for st in struct_array:for value in st:print value, ",",print '\n' + '-' * 28print '=' * 33ret = [('li', 21), ('wen', 22), ('feng', 23)]return ret@dbus.service.method('airead.fan.MoreAdvancedDataType', in_signature='a{sv}', out_signature='a{sv}')def DictDictPrint(self, dictdict):print "receive dict{sv}:"for subdict in dictdict:print "subdict:", subdictfor key in dictdict[subdict]:print " ", key, ":", dictdict[subdict][key]print '-' * 33print '=' * 33ret = {};ret['fanrenhao'] = {'name':'renhao', 'age':'24', 'gender': 'male'}ret['liwenfeng'] = {'name':'wenfeng', 'age':'22', 'gender': 'female'}return ret@dbus.service.method('airead.fan.MoreAdvancedDataType', in_signature='a(oa{sv})', out_signature='a(oa{sv})')def ObjectPathDictStructArrayPrint(self, complex_array):print "receive a(oa{sv}):"for struct in complex_array:for mem in struct:if type(mem) == dbus.Dictionary:for key in mem:print key, ":", mem[key]else:print memprint '-' * 33print '=' * 33# o for objectpatho1 = dbus.ObjectPath("/path1")o2 = dbus.ObjectPath("/path2")# d for dictionaryd1 = {'name':'renhao', 'age':24, 'gender': 'male'}d2 = {'name':'wenfeng', 'age':22, 'gender': 'female'}# s for structs1 = (o1, d1)s2 = (o2, d2)ret = [s1, s2]return retif __name__ == '__main__':dbus.mainloop.glib.DBusGMainLoop(set_as_default=True)session_bus = dbus.SessionBus()name = dbus.service.BusName("airead.fan.MoreAdvancedDataType", session_bus)object = AdvancedData(session_bus, '/airead/fan/MoreAdvancedDataType')mainloop = gobject.MainLoop()print "Running example service."mainloop.run()Python 測(cè)試服務(wù)
more_advanced_data_deliver_test_py.py
#!/usr/bin/pythonimport sys import dbus from traceback import print_excdef main():bus = dbus.SessionBus()try:remote_object = bus.get_object("airead.fan.MoreAdvancedDataType", "/airead/fan/MoreAdvancedDataType")dbus_interface = dbus.Interface(remote_object, "airead.fan.MoreAdvancedDataType")#test a(si)astruct = [('apple', 1), ('banana', 2), ('cherry', 5)]ret = dbus_interface.StructArrayPrint(astruct)print "receive struct array:"for struct in ret:for value in struct:print valueprint '-' * 28print '=' * 33 + "\n"#test a{sv}dic = {}dic['fanrenhao'] = {'name':'renhao', 'age':'24', 'gender': 'male'}dic['liwenfeng'] = {'name':'wenfeng', 'age':'22', 'gender': 'female'}ret = dbus_interface.DictDictPrint(dic)print "receive dict{sv}:"for subdict in ret:print "subdict:", subdictfor key in ret[subdict]:print " ", key, ":", ret[subdict][key]print '-' * 33print '=' * 33 + "\n"#test a(oa{sv})# o for objectpatho1 = dbus.ObjectPath("/p1")o2 = dbus.ObjectPath("/p2")# d for dictionaryd1 = {'a':'apple', 'b': 'banana'}d2 = {'c': 'cherry', 'd': 88}complex_array = [(o1, d1), (o2, d2)]ret = dbus_interface.ObjectPathDictStructArrayPrint(complex_array)print "receive a(oa{sv}):"for struct in ret:for mem in struct:if type(mem) == dbus.Dictionary:for key in mem:print key, ":", mem[key]else:print memprint '-' * 33print '=' * 33 + "\n"except dbus.DBusException:print_exc()sys.exit(1)main()使用 C 實(shí)現(xiàn)復(fù)雜數(shù)據(jù)類(lèi)型的傳遞
以下代碼僅僅為了演示數(shù)據(jù)類(lèi)型的傳遞,不保證沒(méi)有內(nèi)存泄漏,請(qǐng)仔細(xì)檢查后再使用。
STRUCT_ARRAY
?
這次我們要傳遞的是結(jié)構(gòu)體數(shù)組 "a(si)"。
因?yàn)闆](méi)有 "(si)" 類(lèi)型,所以我們自己定義。同樣因?yàn)闆](méi)有 "a(si)",所以我們也自己定義。那么接下來(lái)如代碼所示,就可以進(jìn)行傳遞了。
只要知道哪種數(shù)據(jù)與哪種類(lèi)型對(duì)應(yīng)后,就不難了。難就難在不知道該與哪種數(shù)據(jù)類(lèi)型對(duì)應(yīng),同時(shí)又對(duì) dbus-glib 與 glib 不熟,這樣的話,真的是比較頭痛的一件事。
#define DBUS_STRUCT_STRING_INT ( \dbus_g_type_get_struct ( "GValueArray", G_TYPE_STRING, \G_TYPE_INT, G_TYPE_INVALID)) #define DBUS_ARRAY_STRUCT_STRING_INT ( \dbus_g_type_get_collection("GPtrArray", DBUS_STRUCT_STRING_INT) )int send_recv_struct_array(DBusGProxy *proxy) {gchar *method;GError *error = NULL;GPtrArray *gparray, *ret;GValueArray *garray[3], *tmp_garray;GValue gval[3][2] = {`0`};GValue *tmp_gval;gchar *str[3] = {"apple", "banana", "cherry"};gint num[3] = {1, 2, 5};int i, j;for (i = 0; i < 3; i++) {g_value_init (&gval[i][0], G_TYPE_STRING);g_value_set_string(&gval[i][0], str[i]);g_value_init (&gval[i][1], G_TYPE_INT);g_value_set_int(&gval[i][1], num[i]);}gparray = g_ptr_array_new();for (i = 0; i < 3; i++) {garray[i] = g_value_array_new(0);for (j = 0; j < 2 ; j++) {g_value_array_append(garray[i], &gval[i][j]);}g_ptr_array_add(gparray, garray[i]);}method = "StructArrayPrint";if (!dbus_g_proxy_call(proxy, method, &error,DBUS_ARRAY_STRUCT_STRING_INT, gparray,G_TYPE_INVALID,DBUS_ARRAY_STRUCT_STRING_INT, &ret,G_TYPE_INVALID)) {g_printerr("call %s failed: %s\n", method, error->message);g_error_free(error);error = NULL;return -1;}for (i = 0; i < ret->len; i++) {tmp_garray = g_ptr_array_index(ret, i);tmp_gval = g_value_array_get_nth(tmp_garray, 0);g_print("%s: ", g_value_get_string(tmp_gval));tmp_gval = g_value_array_get_nth(tmp_garray, 1);g_print("%d\n", g_value_get_int(tmp_gval));}g_print("=================================\n\n");return 0; }DICT_DICT
下面演示的是一個(gè) "a{sv}" 的數(shù)據(jù)類(lèi)型,特別的是這里的 "v" 我們用它再來(lái)容納一個(gè) "a{ss}" 數(shù)據(jù)類(lèi)型。這樣的話是不是有點(diǎn)復(fù)雜了哇?
源代碼如下,俗話說(shuō),源代碼上沒(méi)有任何能夠隱藏的秘密,有這句話吧?
#define DBUS_TYPE_G_STRING_VALUE_HASHTABLE \dbus_g_type_get_map ( "GHashTable", G_TYPE_STRING, G_TYPE_VALUE)int send_recv_dictdict(DBusGProxy *proxy) {int i;char *method;GHashTable *table, *ret, *subtable;GHashTableIter iter, subiter;gpointer key, value, subkey, subvalue;GError *error = NULL;GValue gval[2] = `0`;gchar *table_value[2][3] = {{"renhao", "24", "male"},{"wenfeng", "22", "female"}};table = g_hash_table_new(NULL, NULL);for (i = 0; i < 2; i++) {g_value_init(&gval[i], DBUS_TYPE_G_STRING_STRING_HASHTABLE);g_value_take_boxed(&gval[i],dbus_g_type_specialized_construct(DBUS_TYPE_G_STRING_STRING_HASHTABLE));subtable = g_value_get_boxed(&gval[i]);g_hash_table_insert(subtable, "name", table_value[i][0]);g_hash_table_insert(subtable, "age", table_value[i][1]);g_hash_table_insert(subtable, "gender", table_value[i][2]);}g_hash_table_insert(table, "fanrenhao", &gval[0]);g_hash_table_insert(table, "liwenfeng", &gval[1]);method = "DictDictPrint";if (!dbus_g_proxy_call(proxy, method, &error,DBUS_TYPE_G_STRING_VALUE_HASHTABLE, table,G_TYPE_INVALID,DBUS_TYPE_G_STRING_VALUE_HASHTABLE, &ret,G_TYPE_INVALID)) {g_printerr("call %s failed: %s\n", method, error->message);g_error_free(error);error = NULL;return -1;}g_print("receive: dictionary\n");g_hash_table_iter_init(&iter, ret);while (g_hash_table_iter_next(&iter, &key, &value)) {g_print("%s:\n", (char *)key);subtable = g_value_get_boxed(value);g_hash_table_iter_init(&subiter, subtable);while (g_hash_table_iter_next(&subiter, &subkey, &subvalue)) {g_print("%s, %s\n", (char *)subkey, (char *)subvalue);}g_print("---------------------------------\n");}g_print("=================================\n\n");return 0; }ObjectPath_Dict_Struct_Array
這是一個(gè) "a(oa{sv})" 的數(shù)據(jù)類(lèi)型。也就是說(shuō)首先要定義一個(gè) "a{sv}" 的數(shù)據(jù)類(lèi)型, 再由 "a{sv}" 定義一個(gè) "(oa{sv})",最后再定義 "a(oa{sv})" 的數(shù)據(jù)類(lèi)型。這很復(fù)雜吧,現(xiàn)實(shí)中真的傳遞過(guò)這樣復(fù)雜的數(shù)據(jù)嗎? 真的出現(xiàn)過(guò),就在 connman (connect manager 類(lèi)似 network-manager 的東東) 的服務(wù)進(jìn)程中! 我就是因?yàn)樗沤佑|到了 D-Bus, 它的 "a(oa{sv})" 真的是害得我不淺,所以才有了這篇文章。
具體代碼如下:
int send_recv_objectpath_dict_struct_array(DBusGProxy *proxy) {//這個(gè)當(dāng)成是期末考試的試題吧 ^_^//好吧,我承認(rèn)是我懶了return 0; }C D-Bus 測(cè)試完整代碼
/*** @file more_advanced_data_deliver_test_c.c* @brief* @author Airead Fan <fgh1987168@gmail.com>* @date 2012/03/23 17:55:41*/#include <stdio.h> #include <stdlib.h> #include <string.h> #include <dbus/dbus-glib.h>#define METHOD_STRLEN 128/** a{sv}* dic = {}* dic['fanrenhao'] = {'name':'renhao', 'age':'24', 'gender': 'male'}* dic['liwenfeng'] = {'name':'wenfeng', 'age':'22', 'gender': 'female'}*/#define DBUS_TYPE_G_STRING_VALUE_HASHTABLE \dbus_g_type_get_map ( "GHashTable", G_TYPE_STRING, G_TYPE_VALUE)int send_recv_dictdict(DBusGProxy *proxy) {int i;char *method;GHashTable *table, *ret, *subtable;GHashTableIter iter, subiter;gpointer key, value, subkey, subvalue;GError *error = NULL;GValue gval[2] = `0`;gchar *table_value[2][3] = {{"renhao", "24", "male"},{"wenfeng", "22", "female"}};table = g_hash_table_new(NULL, NULL);for (i = 0; i < 2; i++) {g_value_init(&gval[i], DBUS_TYPE_G_STRING_STRING_HASHTABLE);g_value_take_boxed(&gval[i],dbus_g_type_specialized_construct(DBUS_TYPE_G_STRING_STRING_HASHTABLE));subtable = g_value_get_boxed(&gval[i]);g_hash_table_insert(subtable, "name", table_value[i][0]);g_hash_table_insert(subtable, "age", table_value[i][1]);g_hash_table_insert(subtable, "gender", table_value[i][2]);}g_hash_table_insert(table, "fanrenhao", &gval[0]);g_hash_table_insert(table, "liwenfeng", &gval[1]);method = "DictDictPrint";if (!dbus_g_proxy_call(proxy, method, &error,DBUS_TYPE_G_STRING_VALUE_HASHTABLE, table,G_TYPE_INVALID,DBUS_TYPE_G_STRING_VALUE_HASHTABLE, &ret,G_TYPE_INVALID)) {g_printerr("call %s failed: %s\n", method, error->message);g_error_free(error);error = NULL;return -1;}g_print("receive: dictionary\n");g_hash_table_iter_init(&iter, ret);while (g_hash_table_iter_next(&iter, &key, &value)) {g_print("%s:\n", (char *)key);subtable = g_value_get_boxed(value);g_hash_table_iter_init(&subiter, subtable);while (g_hash_table_iter_next(&subiter, &subkey, &subvalue)) {g_print("%s, %s\n", (char *)subkey, (char *)subvalue);}g_print("---------------------------------\n");}g_print("=================================\n\n");return 0; }/** a(si)* astruct = [('apple', 1), ('banana', 2), ('cherry', 5)]*/#define DBUS_STRUCT_STRING_INT ( \dbus_g_type_get_struct ( "GValueArray", G_TYPE_STRING, \G_TYPE_INT, G_TYPE_INVALID)) #define DBUS_ARRAY_STRUCT_STRING_INT ( \dbus_g_type_get_collection("GPtrArray", DBUS_STRUCT_STRING_INT) )int send_recv_struct_array(DBusGProxy *proxy) {gchar *method;GError *error = NULL;GPtrArray *gparray, *ret;GValueArray *garray[3], *tmp_garray;GValue gval[3][2] = {`0`};GValue *tmp_gval;gchar *str[3] = {"apple", "banana", "cherry"};gint num[3] = {1, 2, 5};int i, j;for (i = 0; i < 3; i++) {g_value_init (&gval[i][0], G_TYPE_STRING);g_value_set_string(&gval[i][0], str[i]);g_value_init (&gval[i][1], G_TYPE_INT);g_value_set_int(&gval[i][1], num[i]);}gparray = g_ptr_array_new();for (i = 0; i < 3; i++) {garray[i] = g_value_array_new(0);for (j = 0; j < 2 ; j++) {g_value_array_append(garray[i], &gval[i][j]);}g_ptr_array_add(gparray, garray[i]);}method = "StructArrayPrint";if (!dbus_g_proxy_call(proxy, method, &error,DBUS_ARRAY_STRUCT_STRING_INT, gparray,G_TYPE_INVALID,DBUS_ARRAY_STRUCT_STRING_INT, &ret,G_TYPE_INVALID)) {g_printerr("call %s failed: %s\n", method, error->message);g_error_free(error);error = NULL;return -1;}for (i = 0; i < ret->len; i++) {tmp_garray = g_ptr_array_index(ret, i);tmp_gval = g_value_array_get_nth(tmp_garray, 0);g_print("%s: ", g_value_get_string(tmp_gval));tmp_gval = g_value_array_get_nth(tmp_garray, 1);g_print("%d\n", g_value_get_int(tmp_gval));}g_print("=================================\n\n");return 0; }int send_recv_objectpath_dict_struct_array(DBusGProxy *proxy) {return 0; }int main(int argc, char *argv[]) {DBusGConnection *connection;GError *error = NULL;DBusGProxy *proxy;g_type_init();/* conect system connection and get proxy */connection = dbus_g_bus_get(DBUS_BUS_SESSION, &error);if (connection == NULL) {g_printerr("get system bus failed: %s\n", error->message);g_error_free(error);return -1;}/* get proxy */proxy = dbus_g_proxy_new_for_name(connection,"airead.fan.MoreAdvancedDataType","/airead/fan/MoreAdvancedDataType","airead.fan.MoreAdvancedDataType");send_recv_dictdict(proxy);send_recv_struct_array(proxy);send_recv_objectpath_dict_struct_array(proxy);return 0; }Makefile
有些東西實(shí)際上沒(méi)用,我也懶得去了。
CC = gccCFLAGS = -Wall -g CFLAGS += $(shell pkg-config --cflags glib-2.0 ) CFLAGS += $(shell pkg-config --cflags dbus-glib-1) #CFLAGS += $(shell pkg-config --cflags gtk+-2.0)LDFLAGS = LDFLAGS += $(shell pkg-config --libs glib-2.0) LDFLAGS += $(shell pkg-config --libs dbus-glib-1) #LDFLAGS += $(shell pkg-config --libs gtk+-2.0)SOURCE = $(wildcard *.c) TARGETS := $(patsubst %.c, %, $(SOURCE)) TARGETS_OUT = common_marshaler basic_data TARGETS := $(filter-out $(TARGETS_OUT), $(TARGETS)) TARGETS := $(addsuffix .out, $(TARGETS))%.out: %.c@echo CC $< -o $@@$(CC) $< common_marshaler.c basic_data.c $(CFLAGS) -o $@ $(LDFLAGS).PHONY: all clean test marshalerall: $(TARGETS)marshaler:glib-genmarshal --prefix _common_marshal --header common_marshaler.list > common_marshaler.hglib-genmarshal --prefix _common_marshal --body common_marshaler.list > common_marshaler.cdbus-binding-tool --prefix=airead_fan --mode=glib-server all_basic_data_deliver_server.xml > all_basic_data_deliver_server.hclean:rm -f *~ a.out *.o $(TARGETS) core.*test:@echo TARGETS: $(TARGETS)轉(zhuǎn)載于:https://blog.51cto.com/fanrenhao/817627
總結(jié)
以上是生活随笔為你收集整理的DBus glib 各数据类型接收与发送详解—C语言(3)的全部?jī)?nèi)容,希望文章能夠幫你解決所遇到的問(wèn)題。
- 上一篇: ASP.NET温故而知新学习系列之ASP
- 下一篇: 活动目录域结构和域信任关系建立实验