C言語で発生するコンパイラエラー C3708 について解説
コンパイラ エラー C3708は、__interfaceキーワードの使い方に問題がある場合に発生します。
イベントとしてinterfaceを宣言する際、対象のイベントソースのメンバーが正しく指定されていないとエラーとなります。
C/C++の開発環境で正しい記述に修正することで解消できます。
C3708エラーの基本情報
エラーの意味と背景
C3708エラーは、Microsoftのコンパイラで発生するもので、「__interface
」や「__event
」キーワードの使用方法に誤りがある際に表示されるエラーです。
具体的には、イベント宣言において対象となるイベント ソースが正しく指定されていない場合に発生します。
エラーメッセージ自体は「’interface’: ‘keyword’ の使用法が正しくありません。
互換性のあるイベント ソースのメンバーでなければなりません」という内容となり、利用者に対して正しいイベント宣言の方法を促すものです。
発生状況とその特徴
C3708エラーは主に、イベントを定義する際に発生します。
事件となるケースとしては、グローバルなスコープで直接「__event __interface
」を宣言したり、イベント ソースに含まれない場所でイベント宣言を行った場合などです。
たとえば、コンポーネントやオブジェクトの定義と混同してしまうとエラーが生じやすくなります。
C++におけるCOMプログラミングやATL(Active Template Library)での開発環境下で特に目立つエラーであり、エラー発生箇所を確認することで、宣言の順序や正しいイベント ソースの使用方法を導き出す手がかりとなります。
原因の詳細解析
__interfaceキーワードの誤用
イベント宣言における不備
本エラーの大きな原因は、イベント宣言において「__interface
」キーワードを誤った場所で利用している点にあります。
イベントとしてインターフェイスを宣言する場合、対象となるイベントはイベント ソースとして定義されたクラス(または構造体)の一部である必要があります。
グローバルなスコープや、イベント ソースと関連付けられていない場所で「__event __interface
」を宣言すると、コンパイラは正しい宣言方法でないと判断し、エラーを発生させます。
正しい記述方法との比較
正しい記述方法としては、イベント宣言を行う際に、まずイベント ソース自体を定義し、その中でイベントとしてインターフェイスを宣言します。
たとえば、次のようなコードは正しい形式で記述されます。
#define _ATL_ATTRIBUTES 1
#include "atlbase.h"
#include "atlcom.h"
[module(name="MyLibrary")];
[object, uuid("00000000-0000-0000-0000-000000000001")]
__interface I {
HRESULT func();
};
[coclass, event_source(com), uuid("00000000-0000-0000-0000-000000000003")]
struct EventSource {
// 正しいイベント宣言
__event __interface I;
};
int main(void) {
printf("正しいイベント宣言のサンプルです\n");
return 0;
}
上記の例では、EventSource
というイベント ソースの中にイベントが正しく宣言されているため、C3708エラーは発生しません。
正しい書き方は、イベントの宣言が必ずイベント ソースに含まれている必要があるという点に注意してください。
コード記述の問題事例
発生箇所の特定と原因分析
コード記述の問題事例としては、たとえば次のようなケースが挙げられます。
コンパイラがC3708エラーを報告する行は、通常、グローバルやイベント ソース外に「__event __interface
」が記述されている箇所です。
原因分析の際は、まずどのインターフェイスがイベントとして使用されるべきかを確認し、そのイベント宣言が正しいクラスや構造体内に記述されているかをチェックしてください。
イベントソースの指定漏れや不適切な宣言は、すぐにコードレビューで発見できる場合が多いです。
コード例による検証
エラー発生コードの解説
エラー箇所の詳細解説
次に示すコードは、C3708エラーが発生する典型例です。
以下のコードでは、グローバルなスコープでイベントを宣言してしまっており、適切なイベント ソースとの関連付けがなされていません。
そのため、コンパイラが「C3708エラー」を報告します。
#define _ATL_ATTRIBUTES 1
#include "atlbase.h"
#include "atlcom.h"
// ATLモジュールの宣言
[module(name="MyLibrary")];
// インターフェイスIの宣言
[object, uuid("00000000-0000-0000-0000-000000000001")]
__interface I {
HRESULT func();
};
// インターフェイスIIの宣言
[object, uuid("00000000-0000-0000-0000-000000000002")]
__interface II {
HRESULT func();
};
// 以下の行がエラー発生箇所です。グローバルな位置でイベントを宣言しているため、C3708エラーが発生します。
__event __interface I;
// イベント ソース内でのイベント宣言(こちらは正しい)
[coclass, event_source(com), uuid("00000000-0000-0000-0000-000000000003")]
struct E : II {
__event __interface II;
};
int main(void) {
printf("エラー発生サンプルコードです\n");
return 0;
}
エラー発生サンプルコードです
上記コードのうち、グローバルな位置に記述された「__event __interface I;
」が問題であることを理解することが大切です。
修正後コードの解説
修正ポイントの明確化
エラーを解消するためには、イベント宣言を必ずイベント ソースに含める必要があります。
以下のコード例では、全てのイベント宣言をイベント ソースである構造体内に移動し、正しい書き方を実現しています。
これにより、C3708エラーが回避され、正しくコンパイルされるようになります。
#define _ATL_ATTRIBUTES 1
#include "atlbase.h"
#include "atlcom.h"
// ATLモジュールの宣言
[module(name="MyLibrary")];
// インターフェイスIの宣言
[object, uuid("00000000-0000-0000-0000-000000000001")]
__interface I {
HRESULT func();
};
// インターフェイスIIの宣言
[object, uuid("00000000-0000-0000-0000-000000000002")]
__interface II {
HRESULT func();
};
// イベントの宣言はイベント ソース内で行います。
[coclass, event_source(com), uuid("00000000-0000-0000-0000-000000000003")]
struct E : II {
// 修正箇所:グローバルではなく、イベント ソース内に正しく宣言しています。
__event __interface I;
};
int main(void) {
printf("エラー修正後のサンプルコードです\n");
return 0;
}
エラー修正後のサンプルコードです
この修正例では、イベント宣言が必ずイベント ソース内に含まれるようになっているため、コンパイラは正しく解釈し、エラーが発生しなくなります。
修正ポイントは宣言位置の変更にあることがわかります。
エラー修正時の注意事項
修正ポイントの確認項目
エラー修正に際しては、以下の点を確認してください。
- イベントとして使用するインターフェイスが、正しくイベント ソース内で宣言されているか
- グローバルなスコープでイベント宣言していないか
- イベント ソースの属性(例:
event_source(com)
)が正しく設定されているか
これらのポイントを確認することで、C3708エラーの原因箇所を迅速に特定することができます。
コンパイラ動作の留意点
コンパイラは、イベント宣言に関して非常に厳格なチェックを行います。
正しいイベント ソースの構成が維持されていない場合、エラーメッセージが示す対象箇所をしっかりと確認する必要があります。
特に、複数のインターフェイスやイベントを取り扱う場合、宣言順序やイベントソースとの関連付けに注意を払うとともに、コンパイラのエラーメッセージをヒントにして適切な修正を行ってください。
まとめ
この記事では、C3708エラーの基本情報や、エラーがどのような状況で発生するかについて解説しています。
エラー原因の解析として、イベント宣言時の「__interface
」誤用や、グローバルスコープでの不適切な記述の問題点を提示しました。
また、エラー発生コードと修正後コードの例を通じて、正しいイベントソース内での宣言方法を理解できる内容となっています。