DBus如何使用原始DBus庫傳送和接收數據

轉載: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));
然後用同樣方法來接收
這種方法的很方便,不用進行層層迭代,缺點是結構中不能含有指針類型的成員,數組必須是靜態聲明的定長數組

http://blog.csdn.net/shanzhizi

發佈了22 篇原創文章 · 獲贊 21 · 訪問量 30萬+
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章