为什么 MSDN 或 VS2015 不使用 __stdcall 约定声明 IUnknown 方法?
Why Doesn't MSDN or VS2015 Declare IUnknown Methods with __stdcall convention?
如果这个问题有点不集中,我们深表歉意。我正在使用 COM,使用 Visual Studio 2015 Community,在 Windows 10 下编写一些简单的 COM 服务器和对象。所有 COM 对象都必须实现 IUnknown 接口。 VS2015的IDE将提供实现superclass的虚函数。所以,如果我用这些内容创建 "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;
}
很好,但无法编译。我收到此错误消息:
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 方法。
但是,当我查看 IUnknown 方法的 MSDN Page 时,没有提到需要任何特定的调用约定。
所以我想知道为什么 IUnknown 方法的 MSDN 页面上没有提到 __stdcall
约定,以及为什么 VS2015 IDE 没有将它包含在 IUnknown 的存根实现中对于我的子class.
一般来说,如何查找将由 COM 或 Windows 的任何其他部分调用的方法或函数的必要调用约定?
...from the right-click menu, I get some generated code in my .h file:
您遇到的问题是 Visual Studio IDE 不遵守现有接口声明的调用约定,并为默认调用约定而不是 __stdcall
生成代码。
所以你基本上应该编辑到 STDMETHOD
,你可以从那里开始。也希望下一个Visual Studio在代码生成和重构工具中考虑调用约定。
The __stdcall
calling convention is used to call Win32 API functions.
基本上这个调用约定是所有 COM 方法的标准(通常通过宏 STDMETHOD
、STDMETHOD_
、STDMETHODCALLTYPE
等)以及其他 API声明:CALLBACK
、WINAPI
解析为 __stdcall
。
MSDN 应该更清楚 __stdcall
而不是假设它 goes without saying:
... Certain necessary calling convention details, such as __stdcall
are left out for this illustration...
如果您对用于与 Windows API 通信的约定有疑问,请从 __stdcall
开始,因为这是您最好的选择。
如果这个问题有点不集中,我们深表歉意。我正在使用 COM,使用 Visual Studio 2015 Community,在 Windows 10 下编写一些简单的 COM 服务器和对象。所有 COM 对象都必须实现 IUnknown 接口。 VS2015的IDE将提供实现superclass的虚函数。所以,如果我用这些内容创建 "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;
}
很好,但无法编译。我收到此错误消息:
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 方法。
但是,当我查看 IUnknown 方法的 MSDN Page 时,没有提到需要任何特定的调用约定。
所以我想知道为什么 IUnknown 方法的 MSDN 页面上没有提到 __stdcall
约定,以及为什么 VS2015 IDE 没有将它包含在 IUnknown 的存根实现中对于我的子class.
一般来说,如何查找将由 COM 或 Windows 的任何其他部分调用的方法或函数的必要调用约定?
...from the right-click menu, I get some generated code in my .h file:
您遇到的问题是 Visual Studio IDE 不遵守现有接口声明的调用约定,并为默认调用约定而不是 __stdcall
生成代码。
所以你基本上应该编辑到 STDMETHOD
,你可以从那里开始。也希望下一个Visual Studio在代码生成和重构工具中考虑调用约定。
The
__stdcall
calling convention is used to call Win32 API functions.
基本上这个调用约定是所有 COM 方法的标准(通常通过宏 STDMETHOD
、STDMETHOD_
、STDMETHODCALLTYPE
等)以及其他 API声明:CALLBACK
、WINAPI
解析为 __stdcall
。
MSDN 应该更清楚 __stdcall
而不是假设它 goes without saying:
... Certain necessary calling convention details, such as
__stdcall
are left out for this illustration...
如果您对用于与 Windows API 通信的约定有疑问,请从 __stdcall
开始,因为这是您最好的选择。