版權聲明:本文為半吊子子全棧工匠(wireless_com,同公衆号)原創文章,未經允許不得轉載。 https://blog.csdn.net/wireless_com/article/details/5914184
在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) {
} 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)
nErr = AEEClsCreateInstance(ClsId, pIShell, pIModule, ppObj);
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指針,供運作時使用 。