トップ 一覧 検索 ヘルプ RSS ログイン

【C++】 DA のエントリ関数に関する注意点の変更点

  • 追加された行はこのように表示されます。
  • 削除された行はこのように表示されます。
{{category 開発情報}}
{{category 陰郎の書いた記事,nolink}}

!!概要
 DA の使用では、ID=1000 であるようなコードリソースの先頭に DA のエントリポイントなる関数(引数も復帰値もなし)が存在していなければなりません。しかし、C++ においてクラスやテンプレートを使用する場合、コンパイラによって別の関数が先頭に配置される結果として DA が正常に起動できなくなる場合があります。
 DA の使用では、ID=1000 であるようなコードリソースの先頭に DA のエントリポイントとなる関数(引数も復帰値もなし)が存在していなければなりません。しかし、C++ においてクラスやテンプレートを使用する場合、コンパイラによって別の関数が先頭に配置される結果として DA が正常に起動できなくなる場合があります。
 
!!説明
 まず、以下のコードをご覧ください。DA のエントリポイント関数である DAMain よりも手前で[[汎用リソースクラステンプレート|【C++】 リソースのための汎用クラステンプレート]]のヘッダファイルをインクルードし、それを DAMain 関数内で使用しています。

 #include "Resource.hxx"
 
 void DAMain( ) {
 
     :
     :
 
     // 親フォームのフィールドを取得する。
     FieldType* pField = GetParentField( );
     if( !pField ) {
         Resource<'tSTR', const char*> msg( TSTR_NO_ACTIVE_FIELD );
         ::FrmCustomAlert( GENERIC_ERROR_ALERT, msg, "", "" );
         return;
     }

 
 DAMain 関数はたしかにこのソースファイルの先頭に存在しますが、これを PODS でビルドしたところ、DA を起動することはできませんでした。これは、Resource テンプレートに含まれるメンバ関数がコンパイラによって DAMain 関数よりも手前に配置されてしまったために発生する問題です。
 
 Codewarrior では、エントリポイントとなる関数名を明示的に指定できるため、上記のようなコードでも問題なく DA は動作します。しかし、PODS ではできないため(あるいは筆者がやり方を知らないだけかもしれませんが)、上記の問題が発生することになります。すべて試したわけではありませんが、エントリポイントとなる関数よりも手前に以下の条件を満たしている論理構成体が存在していると発生するはずです。

*クラス定義内の非インラインメンバ関数
*大域関数テンプレート
*クラステンプレート内のメンバ関数

 これらはすべてコンパイラによって配置される位置が決定される(と思われる)ため、DA のエントリポイント関数よりも前に存在しないように気をつけてください。また、インライン関数でもコンパイラの判断によりインライン展開されなければ同様の問題が発生し得ますので注意が必要です。

 
!!注意事項
 この情報は、筆者が PODS を使用した際に発生した事象と、手探りで原因を調査した結果を書き記したものです。そのため、他の開発環境には当てはまらない可能性があります。

!!コメント
{{comment multi}}