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 クラスの領域が自動的に確保されるし、メンバの初期化はコンストラクタで行えばいい。
問題となるのは仮想テーブルの初期化だけろう。
そもそも仮想テーブルとは何なのだろうか。それを考えてみる。