李歡歡
上海同濟大學(xué)軟件學(xué)院嵌入式系統(tǒng)實驗室,上海 201804
Widget 是小工具的意思。Widget的設(shè)計理念就是使在我們桌面,手機,網(wǎng)頁等平臺運行的任何工具都能更換皮膚,擁有個性化的外觀。Widget應(yīng)用廣泛,目前在PC桌面上常見的有vista,Win7的側(cè)邊工具欄,在手機上比如蘋果的iphone、Google的Android、Nokia的S60等主流手機系統(tǒng)都已經(jīng)添加了很多Widget應(yīng)用。
需要安裝Widget引擎才能夠運行Widget工具。我們的Widget引擎是在WinCE上實現(xiàn)的一個基于JavaScript的應(yīng)用程序平臺,主要是參考Yahoo!Widget Engine設(shè)計的,它能夠支持大部分的Yahoo Widgets。我們的Widget引擎主要由以下部分組成:XML解析器,JavaScript引擎,cairo圖像庫等。
每個Widget都是作為單獨的程序執(zhí)行,Widget一般都是一個壓縮包(其實就是.zip格式),運行時,引擎負責(zé)解析壓縮包中的內(nèi)容。壓縮包里面有一個.kon文件,.kon文件是Yahoo!Widget的文件格式,它是采用XML格式來定義的。.kon文件中有很多XML標簽,比如<window>、<image>、<action>,這幾種標簽標識的內(nèi)容分別是窗口、圖片和動作,他們都是屬于引擎中的CoreDOM,當(dāng)然CoreDOM還有很多種,比如Text,Frame等。CoreDOM主要描述組成一個widget的對象和這些對象的屬性。而另外有些標簽如:<screen> 、<system>、<filesystem>等這些是標識系統(tǒng)方面的東西,它們是屬于System DOM。System DOM主要是指一些系統(tǒng)的屬性和函數(shù),它們用來幫助JavaScript腳本來訪問系統(tǒng)的信息,或者底層硬件信息。
我們采用的JavaScript引擎是SpiderMonkey,它是FireFox瀏覽器的JavaScript引擎。通過System DOM的設(shè)計,在C++程序中執(zhí)行JavaScript 腳本,并讓JavaScript腳本訪問C++對象的數(shù)據(jù)和執(zhí)行操作,這樣也就能達到SystemDOM訪問系統(tǒng)屬性和底層硬件信息的要求。
為了能運行JavaScript腳本首先得建立JavaScript運行環(huán)境,主要是JavaScript Runtime、Context和全局對象。這里不詳細介紹。建立好運行環(huán)境后,就需要添加System DOM。我們以cpu這個System DOM作為例子。
首先需要定義一個C++類,這個類主要實現(xiàn)C++對象的方法,比如我們的System DOM 中有一個cpu,我們在JavaScript代碼中執(zhí)行cpu. activity,就能得到cpu的利用率,這時,我們需要建立一個C++類Cpu,然后在類中實現(xiàn)一個getCpuUsage()方法,來獲取cpu的利用率。有的情況比較簡單,可以不用實現(xiàn)添加C++類也行,比如screen,system.memory等這些System DOM。
定義完C++使用的類后,需要再定義一個C++類給JavaScript類使用,這里我們?nèi)∶麨镴SCpu。雖然這個類也是C++類,但是它內(nèi)部需要添加SpiderMonkey定義的結(jié)構(gòu)類型JSClass和回調(diào)函數(shù)等方法,我們?yōu)榱撕米R別類名前面添加JS,我們相應(yīng)的稱這個類為JSCpu。
在JSClass結(jié)構(gòu)體類型中,包含有JavaScript類的名字、標志位以及給腳本引擎用的回調(diào)函數(shù)的名字。這里的回調(diào)函數(shù)的作用包括設(shè)置屬性數(shù)據(jù)、獲取屬性數(shù)據(jù)、類的析構(gòu)等,可以根據(jù)自己的需要在JSCpu類中定義?;卣{(diào)函數(shù)在類中都是以靜態(tài)成員函數(shù)存在,之所以JSClass結(jié)構(gòu)體對象和回調(diào)函數(shù)都是靜態(tài)的,是因為我們需要在沒有對象的情況下調(diào)用這些函數(shù)。
回調(diào)函數(shù)主要包括以下幾種:JSSetProperty,JSGetProperty,JSConstructor,JSDestructor。
JSGetProperty和JSSetProperty就是get和set方法,用來訪問和設(shè)置屬性。在JSGetProperty中,首先通過函數(shù)獲取在JSConstructor中附加在JSObject上的指針,通過這個指針獲得JSObject內(nèi)置的C++對象的指針。由于可能有多個屬性,所以調(diào)用JSGetProperty時會傳入一個jsval的參數(shù),通過這個參數(shù)能夠區(qū)分不同的屬性。Jsval是JSAPI中定義的JavaScript類型,能夠保存C++類型的值。然后對不同的屬性,通過C++對象的指針調(diào)用不同的方法,就可以得到需要的值。最后設(shè)置JSGetProperty的還回參數(shù),還回參數(shù)是一個jsval類型的指針。
JSSetProperty的實現(xiàn)跟JSGetProperty相似。得到JSObject指針后,針對不同的屬性,將jsval指針類型的參數(shù)中的值設(shè)置到C++類型對象中去。有的System DOM不需要實現(xiàn)JSSetProperty,比如memory和cpu,因為它們只需要訪問屬性。
有的System DOM,比如filesystem. createDirectory (),這時我們需要通過添加方法來實現(xiàn)。首先需要創(chuàng)建一個JSFunctionSpec類型的數(shù)組作為JSClass類靜態(tài)數(shù)組成員,然后在實現(xiàn)文件中,對數(shù)組進行初始化,最后一個元素必須為空。
方法的實現(xiàn),主要看具體的需要。方法可以傳入?yún)?shù),調(diào)用JS_ConvertArguments,通過這個JSAPI能直接獲取到此方法傳入的參數(shù)。同時可以通過前面的方法獲得JSObject中的指針,然后再進行操作。
完成JSClass結(jié)構(gòu)體和回調(diào)函數(shù)后,還需要初始化JSObject,需要調(diào)用JSAPI,JS_InitClass來初始化JSObject。
本文詳細描述了System DOM的設(shè)計原理和實現(xiàn)方法,通過我們設(shè)計的System DOM,所以能方便Widget工具訪問系統(tǒng)信息和底層硬件信息。