2011年3月29日 星期二

如何用dbus傳送array of struct (2)

 


上一篇文章中提到,可以利用array of array of byte來傳送struct的陣列。


除了將struct轉成array of byte之外,還有另一個方法能做到這件事,


就是把struct轉成GValueArray


一個struct裡面可能會有很多變數,型態各不同,有的是string,有的是int,


對應到GValueArray,就是裡面會有很多個GValue,每個GValue有它自己的GType (G_TYPE_STRING、G_TYPE_INT、G_TYPE_UINT等等)。


 


首先,xml檔要定義這個array of struct,例如你的struct是長這樣:


typedef struct{
        gchar *title;
        gint price;
}BookInfo;


那麼xml裡就可以這樣寫:


<?xml version="1.0" encoding="UTF-8" ?>
<node name="/">
  <interface name="myInterface">
    <method name="myMethod">
        <arg name="myData" type="a(si)" />
    </method>
  </interface>
</node>



其中a(si)就是array of struct,而且這個struct有兩個變數,第一個是string,第二個是int。


 


在client端,首先要定義這個struct:


#define G_BOOK_STRUCT (dbus_g_type_get_struct("GValueArray",G_TYPE_STRING,G_TYPE_INT,G_TYPE_INVALID))


在這裡定義一個G_BOOK_STRUCT,說明它是一個GValueArray,裡面的變數型態分別是G_TYPE_STRING跟G_TYPE_INT


 


然後建立一個GPtrArray,用來裝許多個G_BOOK_STRUCT,


GPtrArray *book_array = g_ptr_array_new();


 


接著定義第一本書的資訊,並把它加入到book_array裡面:



GValueArray
*book1;


book1 = g_value_array_new(2);


GValue title = {0}, price = {0};


g_value_init(&title, G_TYPE_STRING); 


g_value_init(&price, G_TYPE_INT);


g_value_set_static_string(&title, "Harry Poter");


g_value_set_int(&price, 199);


g_valu_array_append(book1, &title);


g_valu_array_append(book1, &price);


g_ptr_array_add(book_array, book1);


這邊所做的事,就是產生一個GValueArray,裡面可以放兩個GValue,第一個的態型是G_TYPE_STRING,第二個是G_TYPE_INT,


然後把值寫進GValue,附加到GValueArray裡面。


最後一行再把GValueArray加到GPtrArray裡面,如果有很多本書,就一直重覆這一段即可。


 


之後client要送出dbus:


dbus_g_proxy_call (proxy, "myMethod", &error,
  dbus_g_type_get_collection ("GPtrArray", G_BOOK_STRUCT), book_array,
G_TYPE_INVALID,
G_TYPE_INVALID)


這邊需要用dbus_g_type_get_collection的函式來指定book_array的型態。


 


而在server端要接收的function:


gboolean test_obj_my_method (TestObj *obj, GPtrArray *array, GError **error)
{
gint i;
        for(i=0 ; i<array->len ; i++){
                GValueArray *book = (GValueArray *)g_ptr_array_index(array, i);
GValue *title = g_value_array_get_nth(book, 0);
GValue *price = g_value_array_get_nth(book, 1); 
                printf("title=%s, price=%d\n", g_value_dup_string(title), g_value_get_int(price));


        }

        return TRUE;
}


當Server端收到GPtrArray之後,一樣透過g_ptr_array_index來取出第i個GValueArray,


g_value_array_get_nth函式,把GValueArray的第一個元素(title,型態是string)取出來,存在GValue;


接著把GValueArray的第二個元素(price,型態是int)取出來,存在GValue;


最後再透過g_value_dup_stringg_value_get_int的函式,轉成string或int。


沒有留言:

張貼留言