我先前在「PHP DBus client」一文中,只粗略地提到某些 DBus 方法或信號傳回的資料項目,要調用其方法 getData() 取值。
沒有說明為什麼,因此其他人在使用時,經常又再問我如何取用某某 DBus 方法的回傳值。
那些不能直接取值的資料項目,其實都是被封箱的(boxed)。
Variant, Struct, Dict, Array 等型態,在 DBus 規格中皆歸類為封箱型態 (Boxed type)。
封箱型態的意義可參考 Boxing and Unboxing (C# Programming Guide) 之解釋。
PHP DBus 模組從遠端個體取得封箱型態的內容時,會將它們配置為 DbusVariant, DbusStruct, DbusDict, DbusArray 等類別個體。
這些被封箱在冠上 Dbus 之名的型態裡的內容,需要先拆封 (unboxing) 為 PHP 基本型態後,才能得其值。
拆封方法便是 $obj->getData()
。
範例一是一個簡單的拆封範例。我向 Linux 桌面環境上常用的 NetworkManager 調用 GetAll() 方法查詢其目前屬性狀態。
回傳的屬性狀態是一個封箱資料,所以要先對目標拆封才能得值。
上述範例所得到的封箱資料,像是個俄羅斯娃娃,資料內容被層層包裝。
當我們需要多次從這個 DBus 封箱資料中取值時,就要重複上述拆封工作,這實在是件煩事。
所幸要把它完全拆封倒也不是難事,一個遞迴函數就可以解決。
範例二是 DBus 封箱資料的泛用拆封函數,它會將所有封箱資料全部拆封。
比對範例一與範例二的 var_dump 結果,可以看出這個拆封函數會遺失型態資訊 (例如 dbus signature)。目前還看不出有無副作用。
此外,「Boxing and Unboxing (C# Programming Guide)」提到了拆封工作的效能問題。
雖然我們此處談的是 PHP ,但基本道理是一樣的。
從 dbus_unboxing() 的程式碼中,應該也可想像拆封一個有多層封箱的資料時,將會發生多次資料內容配置工作。
因此從效能面考量,若你只需要向一個封箱資料取其中一筆內容時,你應先考慮用範例一的方式取值,而不建議直接調用本文所寫的 dbus_unboxing() 函數將其全部拆封。
相關文章
樂多舊網址: http://blog.roodo.com/rocksaying/archives/16404035.html