Please read this post for context before moving on.
Creation of IMcbXML.c
The IMcbXML.c is the main source file for our extension, it is equivalent to AEEAppGen.c and AEEModGen.c in case of BREW Applets. This file implements instantiation of the extension, setting up of VTBL and reference counting.
We need to create a class structure to hold our instance specific information such as our reference count, shell and module pointer.
typedef struct McbXML{Lets create the entry point for our extension, the all important AEEClsCreateInstance function.
DECLARE_VTBL(IMcbXML)
uint32 m_nRefs;
IShell *m_pIShell;
IModule *m_pIModule;
};
int AEEClsCreateInstance(AEECLSID ClsId,IShell * pIShell,IModule * po, void ** ppObj)The AEEClsCreateInstance is the entry point for the extension.
{
*ppObj = NULL;
if( ClsId == AEECLSID_MCBXML )
{
if( McbXML_New(sizeof(McbXML_t), pIShell, po, (IModule **)ppObj) == SUCCESS )
return AEE_SUCCESS;
}
return EFAILED;
}
The McbXML_New is the constructor function for our extension. It allocates the memory for the class structure and VTBL, sets up the VTBL with the function pointers and stores the IShell and IModule pointers.
int McbXML_New(int16 nSize, IShell *pIShell, IModule* pIModule, IModule ** ppMod)Now, to manage our references we need to create the AddRef and Release functions.
{
McbXML_t *pMe = NULL;
VTBL(IMcbXML) * modFuncs;
if( !ppMod !pIShell !pIModule )
return EFAILED;
*ppMod = NULL;
// Allocate memory for the IMcbXML object
if( nSize < sizeof(McbXML_t) )
nSize += sizeof(McbXML_t);
if( (pMe = (McbXML_t*)MALLOC(nSize + sizeof(IMcbXMLVtbl))) == NULL )
return ENOMEMORY;
// Allocate the vtbl and assign each function pointer to the correct
// function address
modFuncs = (IMcbXMLVtbl *)((byte *)pMe + nSize);
modFuncs->AddRef = McbXML_AddRef;
modFuncs->Release = McbXML_Release;
modFuncs->ParseXML = McbXML_ParseXML;
modFuncs->FindElement= McbXML_FindElement;
modFuncs->DeleteRoot = McbXML_DeleteRoot;
//initialize the vtable
INIT_VTBL(pMe, IModule, *modFuncs);
//We've got one reference since this class is allocated
pMe->m_nRefs = 1;
// initialize our internal member variables
pMe->m_pIShell = pIShell;
pMe->m_pIModule = pIModule;
//Add References to the interfaces we're using
ISHELL_AddRef(pIShell);
IMODULE_AddRef(pIModule);
*ppMod = (IModule*)pMe;
return AEE_SUCCESS;
}
static uint32 McbXML_AddRef(IMcbXML * po)As you can see the AddRef function increments the m_nRefs variable, the release function will Free up the memory when the reference count reaches zero. This reference counting mechanism prevents the release of an extension when it is still used by someone.
{
return (++((McbXML_t *)po)->m_nRefs);
}
static uint32 McbXML_Release(IMcbXML * po)
{
McbXML_t *pMe = (McbXML_t *)po;
//Decrease the number of references. If we still
//have some references to this object, return
//and do not free resources
if(-pMe->m_nRefs != 0)
return pMe->m_nRefs;
// Release interfaces
ISHELL_Release(pMe->m_pIShell);
IMODULE_Release(pMe->m_pIModule);
//Free the object
FREE_VTBL(pMe, IModule);
FREE(pMe);
return 0;
}
Now, we need to create the wrapper function to call the actuan McbXML API's.
static McbXMLElement* McbXML_ParseXML(IMcbXML *po, LPCTSTR lpszXML, McbXMLResults *pResults)In the next post we will create the supporting BID and MIF file and see how to use our extension.
{
return McbParseXML(lpszXML, pResults);
}
static McbXMLElement* McbXML_FindElement(IMcbXML *po, McbXMLElement *pHead, LPCTSTR lpszName)
{
return McbFindElement(pHead, lpszName);
}
static void McbXML_DeleteRoot(IMcbXML *po, McbXMLElement * pElement)
{
McbDeleteRoot(pElement);
}
0 Responses to "BREW Extensions Demystified - Part III"
Post a Comment