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”的不同之处仅在于调用约定

我收到所有三种方法的错误消息。这是有道理的,因为每个方法的实际声明都指定了__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 页面时,没有提到需要任何特定的调用约定。

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

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

4

1 回答 1

0

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

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

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

__stdcall调用约定用于调用 Win32 API 函数。

基本上,这种调用约定是所有 COM 方法(通常通过宏STDMETHODSTDMETHOD_等使用STDMETHODCALLTYPE)以及其他 API 声明的标准:CALLBACKWINAPI解析为__stdcall.

MSDN 应该更清楚,__stdcall而不是假设它是不言而喻的

...某些必要的调用约定详细信息,例如__stdcall在此插图中省略...

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

于 2016-07-05T06:47:47.347 回答