Will Perone

Getting C++ to work in BREW can be confusing at first. Lets take a look at how it's done. The first thing we need to do is define the new and delete operators because they are not defined by default in the BREW api. We'll end up with a new.h like the following:
#ifndef __NEW__ 
#define __NEW__ 

#include "AEEStdlib.h" 

void* operator new(size_t size) throw();
void* operator new [](size_t size) throw();
void operator delete(void* address) throw();
void operator delete [](void* address) throw();
#endif 

And a corresponding new.cpp:
#include "new.h" 

void* operator new( size_t size ) throw()
{     return MALLOC( size );    }

void operator delete( void * ptr ) throw()
{     FREE(ptr);                 }

void* operator new[]( size_t size ) throw()
{     return MALLOC(size);      }

void operator delete[]( void * ptr ) throw()
{     FREE(ptr);                 }
We're basically just wrapping the BREW MALLOC and FREE functions but these wrappers internally will also call the constructors and destructors of any classes using them. We will have to include new.h in any source file we are using new/delete in.

Next we will create a basic Applet class that be responsible for the instantiation and destruction of our actual App class where all of the data will reside.
#ifndef __APPLET__ 
#define __APPLET__ 


#include "App.h" 
#include "AEEAppGen.h" 

// this structure is never newed or deleted because it's initialized in AEEApplet_New
struct Applet: public AEEApplet {

        App  *app; // make a pointer to our actual App stuff so we can new and delete it
        
        static Applet *Get()
        {   return (Applet *)GETAPPINSTANCE();  }

        static bool Init()               // This is called before sending EVT_APP_START to the HandleEvent function
        {   return (Get()->app= new App())!=NULL;   }

        static void Free(Applet *applet) // This is called after sending EVT_APP_STOP to the HandleEvent function   
        {   delete applet->app;       }

        static bool HandleEvent(Applet* applet, AEEEvent eCode, uint16 wParam, uint32 dwParam)
        {   return applet->app->HandleEvent(eCode, wParam, dwParam);    }
};
#endif 
The main.cpp file is pretty straighforward now and looks a lot nicer with our Applet abstraction. The only weird thing is that the ARM compiler (version 3) will make you define a main function for some reason even though it doesn't use it.
#include "Applet.h" 
#include "yourclassid.bid" 

int AEEClsCreateInstance(AEECLSID ClsId, IShell *pIShell, IModule *po, void **ppObj)
{
        *ppObj = NULL;
        if (ClsId == AEECLSID_YOURCLASSID && 
                AEEApplet_New(sizeof(Applet), ClsId, pIShell, po, (IApplet**)ppObj,
                              (AEEHANDLER)Applet::HandleEvent, (PFNFREEAPPDATA)Applet::Free) )                           
        {       
                if (Applet::Init()) return AEE_SUCCESS;
                IAPPLET_Release((IApplet*)*ppObj); 
    }
        return EFAILED;
}

int main() { return 0; } // ARM compiler will complain if you don't have this
Now all we have to do is create our actual App class that will be the actual interface of everything in the application.
#ifndef __APP__ 
#define __APP__ 

#include "new.h" 

class App {
public:
    AEEDeviceInfo  DeviceInfo; 

    bool           suspended; // whether the app is paused or not
        
    // put all your stuff here

    App();
    ~App();
    bool HandleEvent(AEEEvent eCode, uint16 wParam, uint32 dwParam);
};
#endif 
The corresponding App.cpp would be something like the following:
#include "Applet.h" 

App::App()
{
    DeviceInfo.wStructSize = sizeof(DeviceInfo);
    ISHELL_GetDeviceInfo(Applet::Get()->m_pIShell,&DeviceInfo);                 
}

App::~App()
{
    // any final removal / Release / destruction here
}

bool App::HandleEvent(AEEEvent eCode, uint16 wParam, uint32 dwParam)
{
    switch (eCode) 
    {        
        case EVT_APP_START:     
            suspended= false;
            // your init stuff
            return(TRUE);
        
        case EVT_APP_STOP:
            // app is closing, do your destruction / free stuff
            return(TRUE);
        
        case EVT_APP_SUSPEND:
            suspended= true; // app has paused / gone to the background
            return(TRUE);

        case EVT_APP_RESUME:
            suspended= false; // app has resumed / come to the foreground
            return(TRUE);

        // An brew directed SMS message has arrived for this app
        // sender simply uses this format "//BREW:ClassId:Message", example //BREW:0x00000001:Hello World
        case EVT_APP_MESSAGE:         
            // message is stored in (char *)dwParam
            if (suspended || !Applet::Get()->app) { 
                // app is suspended / not running if you get here
            } else {
                // do something else here
            }
            return(TRUE);        

        case EVT_KEY:
            // key is stored in wParam
            if (!suspended) {                
                if (wParam==AVK_SELECT) { // example to quit the app
                    ISHELL_CloseApplet(Applet::Get()->m_pIShell, FALSE);
                } 
            }
            return(TRUE);
   }
   return FALSE;
}
Vuala, one working C++ BREW application.

No Comments yet, be the first!
<- for private contact