コンパイラエラー

C言語におけるC3136エラーの原因とCOMインターフェース継承の修正方法について解説

このエラーC3136は、COMインターフェイス用の属性が付いたインターフェイスが、正しいCOMインターフェイス(通常はIUnknown)から継承されていない場合に発生します。

たとえば、__interfaceを使用してインターフェイス宣言を行った際、継承元がCOMインターフェイスでないとC3136エラーが発生します。

正しい継承関係に修正することで解決できます。

エラーC3136の概要

このエラーは、COMインターフェースに対して正しい継承関係が構築されていない場合に発生します。

COMインターフェースは、すべて最終的に IUnknown から継承される必要がありますが、これに反する継承方法をとると、コンパイラがエラーC3136を出力します。

エラー発生の背景

COMコンポーネントを利用する際、インターフェースはCOMの規約に則って定義されなければなりません。

具体的には、__interface 属性を使用して定義されたインターフェースは、自動的にCOMインターフェースとして扱われ、最終的に IUnknown から継承する必要があります。

しかし、誤ってCOMインターフェース以外を継承した場合に、コンパイラは「COM インターフェースは他の COM インターフェースからのみ継承できます」というエラーを発生させます。

エラーメッセージの内容

エラーメッセージは次のような内容です。

「’interface’ : COM インターフェイスは他の COM インターフェイスからのみ継承できます、’interface’ は COM インターフェイスではありません。」

このメッセージは、COMインターフェース属性が指定されたインターフェースが、正しいCOM継承を行っていない場合に表示されます。

C3136エラーの原因詳細

COMインターフェースには、特有の属性や継承規則が存在します。

エラーC3136は、これらの規則に違反している際に発生します。

COMインターフェース属性の説明

__interface 属性は、インターフェースをCOMインターフェースとして定義するためのMicrosoft独自のキーワードです。

この属性を使用することで、インターフェースが自動的にCOMインターフェースとして認識され、IUnknown から継承しているとみなされます。

そのため、継承先がCOMインターフェースでない場合、ルールに反してエラーが発生します。

継承階層の誤設定による問題

COMインターフェースのルールにおいて、すべてのCOMインターフェースは最終的に IUnknown から継承される必要があります。

継承階層が正しく設定されていない場合、たとえばCOMインターフェース属性が付いたインターフェースが、COMインターフェースではないインターフェースを継承すると、エラーC3136が発生します。

__interfaceとIUnknownの関係

IUnknown はCOMの基本インターフェースであり、ここから派生して各COMインターフェースが定義されます。

__interface で定義されたインターフェースは、明示的に IUnknown を継承するか、COMインターフェースとして定義された別のインターフェースから継承する必要があります。

もし、直接的または間接的に IUnknown との関係が構築されていない場合、コンパイラは継承関係が正しくないと判断します。

例示コードから見る具体的原因

次のコードは、エラーC3136 が発生する例です。

#include "unknwn.h"
// COMインターフェース属性が付いたインターフェースがIUnknownから継承していないためエラーが発生する例
__interface A   // エラーC3136が発生する
{
    int a();
};
[object]
// インターフェースBがインターフェースAを継承しているが、AがCOMインターフェースではないためエラーとなる
__interface B : A {
    int aa();
};
int main()
{
    return 0;
}

このコードでは、__interface AIUnknown から継承していない状態で定義されているため、エラーが発生します。

COMインターフェース継承の正しい方法

COMインターフェースを正しく定義するためには、すべてのインターフェースが IUnknown から派生することを保証する必要があります。

ここでは正しい継承方法と、その書き方について説明します。

IUnknownからの継承の必要性

COMの設計において、IUnknown は基本となるインターフェースであり、全てのCOMインターフェースは必ず IUnknown を継承します。

これにより、COMインターフェースは共通のインターフェースQueryInterfaceAddRefReleaseを持つことが保証され、COMオブジェクト間の相互運用性が確保されます。

したがって、インターフェース定義時には明示的に IUnknown からの継承を指定する必要があります。

正しいインターフェース宣言の書き方

以下は、正しいCOMインターフェースの定義例です。

正しくは、_interface キーワードを使用して IUnknown から継承する必要があります。

#include <unknwn.h>
// 正しいCOMインターフェース定義の例:IUnknownから継承する
_interface A : IUnknown {
    int a();
};
[object]
// インターフェースBは正しくAを継承している
__interface B : A {
    int aa();
};
int main()
{
    return 0;
}

この例では、インターフェース A が明示的に IUnknown から継承されているため、COMインターフェースとして適切に定義されています。

__interfaceと_interfaceの違い

__interface_interface は、どちらもCOMインターフェースを定義する際に使用されるキーワードですが、以下の点で違いがあります。

  • __interface

COMインターフェース属性を前に付与することで、あたかもCOMインターフェースとして振る舞うように指定されます。

ただし、継承関係が正しく構築されない場合にエラーが発生するため、注意が必要です。

  • _interface

明示的に IUnknown から継承する形式でインターフェースを定義します。

この方法を用いると、継承関係が明確になり、C3136エラーを回避できます。

修正方法の実践手順

正しい継承関係が構築されるようにコードを修正するための手順とポイントについて説明します。

コード修正のポイント

エラーC3136を解消するためには、COMインターフェースを定義する際に、必ず IUnknown から継承するように修正します。

具体的には、__interface を直接使用するのではなく、_interface キーワードを用いて、明示的に IUnknown を継承するようにします。

修正前後の比較例

以下は、修正前と修正後のコードの比較です。

修正前修正後
c |c
#include “unknwn.h”#include <unknwn.h>
// COMインターフェースがIUnknownを継承していない// 正しくIUnknownから継承するCOMインターフェース定義例
__interface A {_interface A : IUnknown {
int a();int a();
};};
[object][object]
__interface B : A { int aa(); };__interface B : A { int aa(); };
int main() {int main() {
return 0;return 0;
}}
|

この比較表から分かるように、__interface A の宣言を _interface A : IUnknown と修正することで、COMインターフェースとしての継承関係が正しく構築されます。

テスト実施時の注意点

コード修正後は、以下の点に注意してテストを実施してください。

  • 修正後のインターフェースが正しく定義されているか、コンパイルエラーが解消されているかを確認する。
  • COMオブジェクト同士のインターフェース呼び出しが正しく動作するか、特に QueryInterfaceAddRefRelease の動作を確認する。
  • 既存のCOMコンポーネントとの互換性が保持されているかテストする。

このように、正しい継承関係を構築し、テストを通して動作確認を行うことで、安定したCOMインターフェースの実装が可能になります。

まとめ

この記事では、COMインターフェースにおけるエラーC3136の原因と対策について解説しています。

COMインターフェースは必ずIUnknownから継承する必要があり、属性の誤用や継承関係の不備によりエラーが発生することを説明しました。

また、正しいインターフェース宣言方法として_interfaceを使用し、具体例を用いて修正方法を示しました。

これにより、COM開発でのエラー解消と正しい設計が理解できる内容となっています。

関連記事

Back to top button
目次へ