3

この質問が少し焦点が合っていない場合はお詫び申し上げます。私は COM を使用して、Windows 10 の下で Visual Studio 2015 Community を使用していくつかの単純な COM サーバーとオブジェクトを作成しています。すべての COM オブジェクトは IUnknown インターフェイスを実装する必要があります。VS2015 の IDE は、スーパークラスの仮想関数の実装を提供します。したがって、これらの内容で「Example.h」を作成すると:

#include <Unknwn.h>

class MyClass : public IUnknown
{
};

次に、右クリック メニューから [Quick Actions and Refactorings.../Implement all Pure Virtuals for class 'MyClass'] を選択すると、生成されたコードが .h ファイルに表示されます。

#include <Unknwn.h>

class MyClass : public IUnknown
{
    // Inherited via IUnknown
    virtual HRESULT QueryInterface(REFIID riid, void ** ppvObject) override;
    virtual ULONG AddRef(void) override;
    virtual ULONG Release(void) override;
};

また、VS2015 はスタブ実装も提供してくれます。

#include "stdafx.h"
#include "Example.h"

HRESULT MyClass::QueryInterface(REFIID riid, void ** ppvObject)
{
    return E_NOTIMPL;
}

ULONG MyClass::AddRef(void)
{
    return 0;
}

ULONG MyClass::Release(void)
{
    return 0;
}

それは素晴らしいことですが、コンパイルされません。次のエラー メッセージが表示されます。

エラー C2695: 'CFactory3::QueryInterface': 仮想関数のオーバーライドは、呼び出し規約のみが 'IUnknown::QueryInterface' と異なります

3 つの方法すべてでそのエラー メッセージが表示されます。__stdcallこれらの各メソッドの実際の宣言は呼び出し規約を指定するため、これは理にかなっています。MyClassこれで、次のように の宣言に追加できます。

virtual HRESULT __stdcall QueryInterface(REFIID riid, void ** ppvObject) override;
virtual ULONG __stdcall AddRef(void) override;
virtual ULONG __stdcall Release(void) override;

それはうまくコンパイルされます。

まず、"Peek Definition" を使用すると、次のように表示されるため、使用する呼び出し規約がわかっています。

virtual HRESULT STDMETHODCALLTYPE QueryInterface( 
            /* [in] */ REFIID riid,
            /* [iid_is][out] */ _COM_Outptr_ void __RPC_FAR *__RPC_FAR *ppvObject) = 0;

もう 1 レベル掘り下げると、それSTDMETHODCALLTYPEは単純に として定義されたマクロであることがわかり__stdcallます。第二に、私が持っているチュートリアル資料のほとんどは、IUnknown メソッドをSTDMETHODIMPマクロで実装することを推奨しています (これは に展開されHRESULT STDMETHODCALLTYPEます)。

ただし、 IUnknown メソッドに関するMSDN ページを見ると、特定の呼び出し規約が必要であるとは言及されていません。

したがって__stdcall、IUnknown メソッドの MSDN ページで規則が言及されていない理由と、VS2015 IDE がサブクラスの IUnknown のスタブ実装にそれを含めなかった理由を疑問に思っています。

一般に、COM または Windows の他の部分によって呼び出されるメソッドまたは関数に必要な呼び出し規約を調べるにはどうすればよいでしょうか。

4

1 に答える 1