为什么MSDN或VS2015不使用__stdcall约定声明IUnknown方法?

时间:2016-07-04 18:03:55

标签: visual-studio com stdcall

如果这个问题有点不重要,请道歉。我正在使用COM,在Windows 10下使用Visual Studio 2015社区编写一些简单的COM服务器和对象。所有COM对象都必须实现IUnknown接口。 VS2015的IDE将提供实现超类的虚函数。所以,如果我用这些内容创建“Example.h”:

#include <Unknwn.h>

class MyClass : public IUnknown
{
};

然后我选择Quick Actions and Refactorings ... /为'MyClass'类实现所有Pure Virtuals,从右键菜单中,我在.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'的区别仅在于调用约定

我收到所有三种方法的错误消息。这是有道理的,因为每个方法的实际声明都指定了__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;

向下钻取一个级别,我发现STDMETHODCALLTYPE只是一个定义为__stdcall的宏。其次,我建议的大多数教程材料都是使用STDMETHODIMP宏(扩展为HRESULT STDMETHODCALLTYPE)来实现IUnknown方法。

但是,当我查看IUnknown方法的MSDN Page时,没有提到需要任何特定的调用约定。

所以我想知道为什么在MSDN页面上没有提到IUnknown方法的__stdcall约定,以及为什么VS2015 IDE没有将它包含在我的子类的IUnknown的存根实现中。

一般来说,如何查找将由COM或Windows的任何其他部分调用的方法或函数的必要调用约定?

1 个答案:

答案 0 :(得分:0)

  

...从右键菜单中,我在我的.h文件中获取一些生成的代码

您遇到的问题是Visual Studio IDE不支持现有接口声明的调用约定,并为默认调用约定而不是__stdcall生成代码。

所以你基本上应该编辑到STDMETHOD,你很高兴从那里开始。并且还希望下一代Visual Studio能够在代码生成和重构工具中考虑调用约定。

  

The __stdcall calling convention is used to call Win32 API functions.

基本上,此调用约定是所有COM方法的标准(通常通过宏STDMETHODSTDMETHOD_STDMETHODCALLTYPE等)以及其他API声明使用:{{1} },CALLBACK解析为WINAPI

MSDN应该更清楚__stdcall而不是假设goes without saying

  

...某些必要的呼叫约定详细信息,例如__stdcall,这些插图仅供参考......

如果您对与Windows API通信使用的约定有疑问,请从__stdcall开始,因为这是您最好的选择。