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

标签 visual-studio com stdcall

如果这个问题有点不集中,我们深表歉意。我正在使用 COM,在 Windows 10 下使用 Visual Studio 2015 Community 编写一些简单的 COM 服务器和对象。所有 COM 对象都必须实现 IUnknown 接口(interface)。 VS2015 的 IDE 将提供实现父类(super class)的虚函数。所以,如果我用这些内容创建“Example.h”:

#include <Unknwn.h>

class MyClass : public IUnknown
{
};

然后我从右键单击菜单中选择快速操作和重构.../为类“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 还为我提供了一个 stub 实现:

#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;
}

这很好,但它无法编译。我收到此错误消息:

error C2695: 'CFactory3::QueryInterface': overriding virtual function differs from 'IUnknown::QueryInterface' only by calling convention

我收到了所有三种方法的错误消息。这是有道理的,因为每个方法的实际声明都指定了 __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 的宏。其次,我的大部分教程 Material 都建议使用 STDMETHODIMP 宏(扩展为 HRESULT STDMETHODCALLTYPE)实现 IUnknown 方法。

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

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

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

最佳答案

...from the right-click menu, I get some generated code in my .h file:

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

所以您基本上应该编辑为 STDMETHOD 并且您可以从那里开始。也希望下一个Visual Studio在代码生成和重构工具中考虑调用约定。

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

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

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

... Certain necessary calling convention details, such as __stdcall are left out for this illustration...

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

关于visual-studio - 为什么 MSDN 或 VS2015 不使用 __stdcall 约定声明 IUnknown 方法?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/38190178/

相关文章:

visual-studio - 如何在同一解决方案中添加对另一个项目的引用?

c# - 调试符号未加载

c++ - 将 COM 事件公开给 VBScript (ATL)

C++-生成器 : convert into stdcall type

visual-studio - VSHost崩溃,REGDB_E_INVALIDVALUE加载特定项目

c++ - MFC CWinApp 程序中的输入框?

.net - 注册 .NET dll 以在 VB6 应用程序中使用

python - 如何隐藏从 Python 调度的 COM 对象

.net - 为什么在违反调用约定的情况下 PInvoke 不会崩溃(在 .NET 3.5 中)?

windows - stdcall 可以有可变参数吗?