在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自身的創建函數