在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 Modules CreateInstance function
?pMe->pfnModCrInst = pfnMC;
?
?// Store Address of Modules 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自身的創建函數
不論是 AEEClsCreateInstance還是pme->pfnModCrInst其實都是類似的,通過AEEApplet_New(除extension 外通常都是調用該函數)來最終創建應用,AEEApplet_New無非是具體分配applet內存,初始化applet的vtbl(這里最重要的是實例化applet_handleevent)并返回Iapplet指針,供運行時使用 。