C++ による BREW 開発(4)

AEEApplet_New() は、エラー処理を省けば次のようになっている。

boolean AEEApplet_New(int16 nIn,
                      AEECLSID clsID
                      IShell * pIShell,
                      IModule * pIModule,
                      IApplet **ppObj,
                      AEEHANDLER pAppHandleEvent,
                      PFNFREEAPPDATA pFreeAppData)
{
    AEEApplet*       pMe = NULL;
    VTBL(IApplet)*   appFuncs;
    int              nSize;
    
    nSize = (int)nIn;
    
    (*ppObj) = NULL;
    
    // 1.領域の確保
    pMe = (AEEApplet*)MALLOC( nSize + sizeof( IAppletVtbl ) );
    
    // 2.仮想テーブルの初期化
    appFuncs = (IAppletVtbl*)((byte*)pMe + nSize);
    
    appFuncs->AddRef      = AEEApplet_AddRef;
    appFuncs->Release     = AEEApplet_Release;
    appFuncs->HandleEvent = AEEApplet_HandleEvent;
    
    INIT_VTBL( pMe , IApplet , *appFuncs );
    
    // 3.メンバ変数の初期化
    pMe->m_nRefs      = 1;
    pMe->m_pIShell    = pIShell;
    pMe->m_pIModule   = pIModule;
    pMe->m_pIDisplay  = NULL;
    
    pMe->clsID        = clsID;
    
    pme->pAppHandleEvent = pAppHandleEvent;
    pme->pFreeAppData = pFreeAppData;
    
    ISHELL_CreateInstance( pIShell , AEECLSID_DISPLAY , (void**)&pMe->m_pIDisplay );
    
    ISHELL_AddRef( pIShell );
    IMODULE_AddRef( pIModule );
    
    *ppObj = (IApplet*)pMe;
    
    return TRUE;
}

まずは領域の確保だ。
注目すべき点は、メインアプレット構造体のサイズだけでなく、sizeof( IAppletVtbl ) の大きさ分だけ余分に取っていることだ。これは、次に行われる仮想テーブルの初期化で使用される。


次に行われるのは仮想テーブルの初期化だ。
この部分は C++ で書くときに、一番頭を悩ませる部分だ。
これは後日詳しく書くことにする。


最後に行われるのは、メンバの初期化だ。
ここで説明することはあまりない。C++ で言えば、コンストラクタでメンバを初期化している部分だ。



この AEEApplet_New() をどのように C++ で書けばいいのか。
new をすれば MyApplet クラスの領域が自動的に確保されるし、メンバの初期化はコンストラクタで行えばいい。
問題となるのは仮想テーブルの初期化だけろう。
そもそも仮想テーブルとは何なのだろうか。それを考えてみる。