轉載:http://blog.csdn.net/shanzhizi/article/details/7710692
DBus是進程間通信的工具。網上的資料不太多,大都又是基於GLib或python的。在windows下如果要用純c/c++語言,似乎只能用原始的DBus庫來編寫程序。倘若不親自寫寫,還真不知道到底是怎樣的。
DBus的數據都要綁定在消息上:
消息: DBusMessage
數據: DBusMessageIter
從數據結構的命名上看,與其稱之爲消息的數據,不如稱爲消息數據的迭代器。
事實上其數據的操作過程,就是個迭代過程。
I 傳輸單獨一個變量
如bool類型,有:
DBusMessage *msg; // DBus消息
DBusMessageIter datatoSentIter; // DBus數據迭代器
dbus_bool_t singleData = true; // DBus的內建bool型
// 每條語句都需要返回值bool判斷是否成功,爲方便清晰略去
dbus_message_iter_init_append(msg, &datatoSentIter); // 將迭代器綁定至消息
dbus_message_iter_append_basic(&datatoSentIter, DBUS_TYPE_BOOLEAN, &singleData);
// TODO: 向連接發送並flush
以上是發送,接收此單個bool數據也很簡單:
DBusMessageIter dataRecievedIter; // 接收數據迭代器
dbus_bool_t singleData; // 保存傳送過來的bool變量
dbus_message_iter_init(&msg, &dataRecievedIter); // 生成msg消息的數據迭代器
if (dbus_message_iter_get_arg_type(&dataRecievedIter) == DBUS_TYPE_BOOLEAN)
{
dbus_message_iter_get_basic(&dataRecievedIter, &singleData);
}
II 傳輸數個變量或數組
如傳輸一個bool變量,一個char*字符串和一個int數組
對於發送有:
DBusMessage msg;
DBusMessageIter datatoSendIter;
dbus_bool_t boolArg = true; // 要傳送的bool變量
char strArg[] = "I am a string"; // 要傳送的字符串
int *intArrayArg = GetIntArray(); // 要傳送的int數組,GetIntArray()給intArrayArg初始化賦值
由於要傳輸的數據包含這三種數據類型,該數據實際上是一個由這三組數據組成的結構
在Windows DBus中需以專門的代碼來處理
DBusMessageIter subStructIter;
dbus_message_iter_open_container(&msg,
DBUS_TYPE_STRUCT, // 開啓子迭代的類型
NULL,
&subStructIter); // 要被初始化爲子迭代的迭代器
// 開啓後關閉前對子迭代的操作有效
dbus_message_iter_append_basic(&subStructIter, DBUS_TYPE_BOOLEAN, &boolArg); // 將bool變量append爲第一個
char *buff = strArg; // 對於一些編譯器,聲名爲char strArg[]的strArg無法通過DBus,故需要這一步
dbus_message_iter_append_basic(&subStructIter, DBUS_TYPE_STRING, &buff); // 將字符串append爲第二個
由於數組不是基本類型,無法用*_append_basic函數來append,需開啓新的子迭代
char buf[2];
buf[0] = DBUS_TYPE_INT;
buf[1] = '/0';
DBusMessageIter subArrayIter;
dbus_message_iter_open_container(&subStructIter, // 從前一子迭代開啓新的子迭代
DBUS_TYPE_ARRAY, // 開啓的子迭代是數組
buf, // 表示數組的數據類型,注意特殊的表示方法
&subArrayIter); // 初始化子迭代
int elementNum = GetIntArrayCount(); // 獲得int數組的元素個數
dbus_message_iter_append_fixed_array(&subArrayIter,
DBUS_TYPE_INT, // 數組元素數據類型
&intArrayArg, // 數組地址的地址
elementNum); // 數組元素個數
最後要關閉子迭代,實際上是將子迭代的數據加載到了父迭代器上
dbus_message_iter_close_container(&subStructIter, &subArrayIter);
dbus_message_iter_close_container(&datatoSendIter, &subStructIter);
對於接收有:
DBusMessageIter dataRecievedIter;
// 聲明用於接受數據的變量
dbus_bool_t boolArg;
char *strArg;
int *intArrayArg;
dbus_message_iter_init(msg, &dataRecievedIter); // 用msg數據初始化數據迭代器
pan class="comment">// 對於迭代中的每一層,都需專門解開處理
DBusMessageIter subStructIter;
dbus_message_iter_recurse(&dataRecievedIter, &subStructIter); // 將迭代器中打包的數據解開給子迭代
// 以下每步都需判斷數據類型,爲清晰略去
dbus_message_iter_get_basic(&subStructIter,&boolArg);
dbus_message_iter_next(&subStructIter); // 步進,相當於指針指向下個數據
dbus_message_iter_get_basic(&subStructIter, &strArg);
dbus_message_iter_next(&subStructIter);
DBusMessageIter subArrayIter;
dbus_message_iter_recurse(&subStructIter, &subArrayIter); //解開下層迭代
int elementNum;
dbus_message_iter_get_fixed_array(&subArrayIter, &intArrayIter, &elementNum); // 獲得數組指針以及元素個數
由上代碼可知,無論做否數據類型的判斷,傳輸數據的格式發送與接收雙方應該定義好。Linux上的DBus-GLib支持對於xml定義的解析自動生成頭文件,方便的解決了這個問題。
對於傳輸數據的內存釋放,除了傳送的具體數據外,迭代器不需專門釋放,但是消息需要解引用。
另外,對於成分十分複雜的數據,實際上可以事先定義一個足夠大的結構,將所有要傳輸的數據都放在裏面,比如:
typedef struct
{
bool a;
char str[3];
...
}LargeStruct;
然後用如下代碼來發送:
LargeStruct data;
// 初始化...
// ...
// 轉換成BYTE數組append
BYTE *byteLargeStruct = (BYTE*)(&data);
dbus_message_iter_append_fixed_array(&iter,
DBUS_TYPE_BYTE,
buf,
&byteLargeStruct,
sizeof(LargeStruct));
然後用同樣方法來接收
這種方法的很方便,不用進行層層迭代,缺點是結構中不能含有指針類型的成員,數組必須是靜態聲明的定長數組