BREW中的應用加載機制

在BREW中,module是基本的執行單位,在手機上體現爲.mod文件,在仿真器中體現爲.dll文件。一個module可以包含一個或多個applet,或一個或多個擴展類(關於擴展類有單獨的章節進行闡述)。凡是在手機上與其他代碼一同編譯完成的叫做靜態模塊,凡是通過下載方式(無線下載或者數據線下載)存於文件系統中的叫動態模塊。

每個module都需要有標識自身的MIF文件,從BREW 3.1開始即使是靜態module也需要有相應的MIF。而在BREW3.1之前,對於靜態module是沒有單獨的MIF文件的,需要通過AEEAppInfo的結構體來表示module的信息,裏面主要包括clsid,應用類型,圖標等信息,每個靜態 module都需要有一個實例化的AEEAppInfo結構體,AEE從此數據結構中獲得必要的module信息。在環境初始化(AEE_init)的時候AEE通過枚舉每個MIF文件來獲得各個module的必要信息,比如clsid等。

針對BREW3.1以前的版本,由於靜態module不存在MIF文件,所以過程有所不同。每個靜態module的實現必須提供一個XXX_getmodinfo(),在該函數中返回特定於該module的Mod_Load()函數指針,通常形式爲 XXXMod_Load,同時返回特定於該module的AEEAppInfo結構數據。所有的這些XXX_getmodinfo函數指針構成了一個staticmodinfo的數組。初始化時AEE通過檢索該數組(猜測執行其中的每一個函數)來獲得每個static module的相關模塊信息(比如clsid)以及加載函數。

Module的加載是在運行時才進行的。對於動態應用,加載是通過通用函數AEEMod_Load實現的,而AEEMod_Load實際是調用AEEStaticMod_New,在AeeModGen.c中可以看到該函數的聲明。

int AEEStaticMod_New(int16 nSize, IShell *pIShell, void *ph, IModule **ppMod,

PFNMODCREATEINST pfnMC,PFNFREEMODDATA pfnMF)

{

AEEMod *pMe = NULL;

VTBL(IModule) *modFuncs;

if (!ppMod || !pIShell) {

return EFAILED;

}

*ppMod = NULL;

#ifdef AEE_SIMULATOR

if (!ph) {

return EFAILED;

} else {

g_pvtAEEStdLibEntry = (AEEHelperFuncs *)ph;

}

#endif

//Allocate memory for the AEEMod object

if (nSize < sizeof(AEEMod)) {

nSize += sizeof(AEEMod);

}

if (NULL == (pMe = (AEEMod *)MALLOC(nSize + sizeof(IModuleVtbl)))) {

return ENOMEMORY;

}

modFuncs = (IModuleVtbl *)((byte *)pMe + nSize);

 

// Initialize individual entries in the VTBL

modFuncs->AddRef = AEEMod_AddRef;

modFuncs->Release = AEEMod_Release;

modFuncs->CreateInstance = AEEMod_CreateInstance;

modFuncs->FreeResources = AEEMod_FreeResources;

 

// initialize the vtable

INIT_VTBL(pMe, IModule, *modFuncs);

 

// initialize the data members

 

// Store address of Module's CreateInstance function

pMe->pfnModCrInst = pfnMC;

 

// Store Address of Module's FreeData function

pMe->pfnModFreeData = pfnMF;

pMe->m_nRefs = 1;

pMe->m_pIShell = pIShell;

 

// Set the pointer in the parameter

*ppMod = (IModule*)pMe;

return SUCCESS;

}

上述代碼在sdk中的AeeModGen.c可以找到,概括起來,就是在爲module分配內存,並且實例化vtbl表,其中有兩行代碼值得注意:

modFuncs->CreateInstance = AEEMod_CreateInstance;

pMe->pfnModCrInst = pfnMC;

第一行是指定module的創建函數爲AEEMod_CreateInstance,而第二行是指定該module具有自身特殊的創建函數,該函數即爲參數pfnMC指定的函數。而在AEEMod_Load中調用AEEStaticMod_New時該參數爲NULL,即所有動態 module採用通用的createinstance 函數(該函數實際上即爲AEEClsCreateInstance), 對於靜態module,其實其自身的XXXMod_Load加載函數和通用的AEEMod_Load具體實現幾乎一樣,最主要的區別在於其調用AEEStaticMod_New時指定了pfnMC參數,即靜態 module需要指定自身的創建函數。這是通過在AEEStaticMod_New中代碼modFuncs->CreateInstance = AEEMod_CreateInstance 來指定,由AEEMod_CreateInstance函數來創建的。

static int AEEMod_CreateInstance(IModule *pIModule,IShell *pIShell, AEECLSID ClsId, void **ppObj) {

AEEMod *pme = (AEEMod *)pIModule;

int nErr = 0;

// For a dynamic module, they must supply the AEEClsCreateInstance()

// function. Hence, invoke it. For a static app, they will have

if (pme->pfnModCrInst) {

nErr = pme->pfnModCrInst(ClsId, pIShell, pIModule, ppObj);

#if !defined(AEE_STATIC)

} else {

nErr = AEEClsCreateInstance(ClsId, pIShell, pIModule, ppObj);

#endif

return nErr;

}

對於動態 module,由於pme->pfnModCrInst爲NULL,所以調用通用的創建函數AEEClsCreateInstance(ClsId, pIShell, pIModule, ppObj)來進行創建。AEEClsCreatelnstance通過調用AEEAppGen.c的AEEApplet_New()方法來完成空間分配、虛函數表構造、初始化等一系列工作。而對於靜態module,因爲指定了自身的創建函數,所以pme->pfnModCrInst不爲NULL,從而執行特定於該module自身的創建函數

 

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章