天天看點

《XPCOM元件開發》筆記(二)

前面的例子是一個簡單的無狀态工廠版本,但實際中工廠應該存儲狀态。至少要儲存它所建立的對象的資訊。當一個工廠對動态共享庫中的類的執行個體進行管理時,它應當知道何時可以解除安裝掉庫。如果工廠儲存了狀态,那麼你就可以檢視是否有顯示的引用并判斷是否工廠建立過任何對象。

      工廠能儲存的另外一種狀态是對象是否是單例的。若是,則以後對工廠的調用應當傳回一個對象。(這可以通過IServiceManager簡化),

      用類來實作工廠,你可以讓工廠類從ISupports接口繼承,也就可以管理工廠對象自身的生命周期。當你将工廠集合成組時,若需要判斷他們是否可以解除安裝掉時很有用。通過IClassInfo,工廠支援對其底層實作的資訊查詢,比如對象使用什麼語言寫的,對象支援的接口等。

      在跨平台的環境中定義接口應該使用接口定義語言(IDL),XPCOM使用了它的一個變種XPIDL,讓你能指明一個給定接口的方法,屬性和常量,也可以定義接口層次關系。

      它也有一些缺陷,它不支援多繼承,方法名稱也必須唯一。但它允許你産生類型庫(typelib,字尾為.xpt的檔案)。它是接口的二進制表現形式,提供了對接口程式級的控制和通路,而這對于在非C++環境中使用接口至關重要。當元件從其他語言通路,就使用二進制類型庫來通路接口,進而得知它支援的方法,調用這些方法。實作這個功能的XPCOM的子集叫XPConnect。它是XPCOM中的一層,提供了從javascript等語言通路XPCOM元件的功能。每一個要映射到javascript的接口都應該有一個對應的類型庫。從IDL檔案可以産生類型庫和C++頭檔案,使用的工具是xpidl編譯器。

      有一種對象名為服務對象,一般隻有一份拷貝(當然同時可以有多種服務)。客戶都是與同一個服務對象打交道。在XPCOM中有許多服務用來幫助開發者編寫跨平台元件。包括跨平台檔案抽象(提供了對檔案,目錄服務的統一形式的通路,確定每個使用者使用相同的記憶體配置設定者的記憶體管理,允許傳遞簡單消息的事件通知系統)。

JavaScript版本:

 // xpconnect to cookiemanager

// get the cookie manager component in JavaScript

var cookiemanager = Components.classes["@mozilla.org/

cookiemanager;1"].getService();

cookiemanager = cookiemanager.QueryInterface

(Components.interfaces.nsICookieManager);

// called as part of a largerDeleteAllCookies() function

function FinalizeCookieDeletions() {

for (var c=0; c<deletedCookies.length; c++) {

cookiemanager.remove(deletedCookies[c].host,

deletedCookies[c].name,

deletedCookies[c].path);

}

deletedCookies.length = 0;

C++版本:

nsCOMPtr<nsIServiceManager> servMan;

nsresult rv = NS_GetServiceManager(getter_AddRefs(servMan));

if (NS_FAILED(rv))

    return -1;

nsCOMPtr<nsICookieManager> cookieManager;

rv = servMan->GetServiceByContractID("@mozilla.org/cookiemanager",

NS_GET_IID(nsICookieManager), getter_AddRefs(cookieManager));

PRUint32 len;

deletedCookies->GetLength(&len);

for (int c=0; c<len; c++)

{

    cookiemanager->Remove(deletedCookies[c].host,deletedCookies[c].name,deletedCookies[c].path);

示例:

cookiemanager = cookiemanager

.QueryInterface(Components.interfaces.nsICookieManager);

function loadCookies() {

// load cookies into a table

var enumerator = cookiemanager.enumerator;

var count = 0;

var showPolicyField = false;

while (enumerator.hasMoreElements()) {

var nextCookie = enumerator.getNext();

nextCookie = nextCookie.QueryInterface

(Components.interfaces.nsICookie);

.

deletedCookies[c].path,

      當開發完一個元件并編譯成庫後,它必須導出一個名為NSGetModule的方法,這個函數是通路庫的入口點。它在元件的注冊和登出,以及XPCOM想知道子產品/庫實作了哪些接口或類時被調用。nsIModule和nsIFactory接口控制元件的實際建立,還有字元串和XPCOM膠水部分。這些實用工具提供了像智能指針等功能。

      通過傳遞參數,你可以對XPCOM的初始化過程進行某些配置,包括特定目錄的自定義位置。

      XPCOM啟動步驟:1)應用程式啟動XPCOM,2)XPCOM發出一個通知表明它開始啟動了。3)XPCOM發現并處理元件清單。4)XPCOM發現并處理類型庫清單。5)若有新元件,XPCOM就注冊他們:a)調用自動注冊 b)注冊新元件  c)調用自動注冊結束

6)完成啟動過程,XPCOM發出通知表明它已經啟動完畢。

      XPCOM使用了名為清單的特殊檔案來跟蹤和持久化元件的資訊到本地系統中。有兩類清單:1)元件清單。2)類型庫清單。

      元件清單列出了所有注冊元件,并儲存了每個元件能做什麼的詳細資訊,XPCOM将這個檔案讀入到一個駐記憶體資料庫中。檔案中主要有三種資訊:1)注冊元件在磁盤上的位置及其大小。2)類ID到位置的映射。3)契約ID到類ID的映射。

      注冊就是讓XPCOM知道你的元件的存在的過程。可以在安裝的過程中顯示注冊元件,或使用regxpcom,或使用Service Manager的自動注冊方法來在一個指定的元件目錄中查找和注冊元件:

1)XPInstall API 2)regxpcom指令行工具 3)Service Manage的nsIComponetRegistrar API

      目前面說的清單檔案被讀入後,XPCOM會檢檢視是否有元件需要被注冊,有兩種方法來注冊。一種使用XPInstall,它提供了在安裝過程中注冊你的元件的接口。另一種是使用regxpcom,它會在預設的元件系統資料庫中注冊你的元件。當注冊過程開始時,XPCOM會給所有的注冊過的監聽者廣播一個通知,表明XPCOM已經開始注冊新元件了。當所有元件注冊完畢,另一個通知會被廣播,表明XPCOM已經完成了注冊過程。

      當應用程式準備關閉XPCOM時,它調用NS_ShutdownXPCOM,接下來:

1)              XPCOM廣播一個關閉通知給所有注冊過的監聽者

2)              XPCOM關閉元件管理器,服務管理器和相關的服務

3)              XPCOM釋放所有全局服務

      4)NS_ShutdownXPCOM   傳回,應用程式退出。

      注意關閉過程是不可逆的。

本文轉自Phinecos(洞庭散人)部落格園部落格,原文連結:http://www.cnblogs.com/phinecos/archive/2008/06/02/1212027.html,如需轉載請自行聯系原作者