COM IDL定义中[in,out]和[out,retval]之间的差异

COM IDL定义中[in,out]和[out,retval]之间的差异,com,idl,notation,Com,Idl,Notation,在我使用的一些IDL中,我注意到在方法中标记返回值有两种约定-[In,out]和[out,retval] 当存在多个返回值时,似乎会使用[in,out],例如: HRESULT MyMethod( [in] long InputParam, [in, out] long* OutputParam1, [in, out] long* OutputParam2 ); HRESULT MyMethod2( [in] long InputParam, [o

在我使用的一些IDL中,我注意到在方法中标记返回值有两种约定-
[In,out]
[out,retval]

当存在多个返回值时,似乎会使用
[in,out]
,例如:

HRESULT MyMethod(
    [in] long InputParam, 
    [in, out] long* OutputParam1, 
    [in, out] long* OutputParam2
);
HRESULT MyMethod2(
    [in] long InputParam, 
    [out, retval] long* OutputParam1
);
当只有一个返回值时,似乎会使用
[out,retval]
,例如:

HRESULT MyMethod(
    [in] long InputParam, 
    [in, out] long* OutputParam1, 
    [in, out] long* OutputParam2
);
HRESULT MyMethod2(
    [in] long InputParam, 
    [out, retval] long* OutputParam1
);
这是一个COM IDL约定还是我正在使用的代码中的约定


从这两个符号生成的代码是否存在功能差异,或者它们是否完全可以互换?

[in,out]
表示调用方法时传递有效值,方法返回成功时存在有效值(指针指向的位置)
[out]
表示在调用方法时指向的值可以是任何值,但在方法返回成功时它将有效。
[out]
[in,out]
参数都必须是指针-它们的值不变且有效,有效性要求仅适用于它们所指向的变量

[out,retval]
是一种语法糖,用于指示在创建本机COM支持包装器时,此参数应转换为返回值。比如说

HRESULT MyMethod( [out] long* OutParam1, [out, retval] long* OutParam2 );
变成

long IWrappedInterface::MyMethod( long* OutParam1 );
如果未标记它,则包装器将包含具有原始签名的方法:

HRESULT IWrappedInterface::MyMethod( long* OutParam1, long* OutParam2 );

只有最后一个
[out]
参数可以标记为
[out,retval]
<代码>[in,out]参数不能标记为
[retval]

另一个区别是.NET代码中PIA的显示方式

[out,ret]将在.NET中显示为返回值


[out]将在.NET中显示一个有关该方法的参数。

感谢您的有益解释。我想补充一点,
[in,out]
可能不是所有语言都能正确处理的(更具体地说,是老式的Visual Basic,对.NET不太确定)。我想知道[out,retval]定义COM接口是违反最佳实践的,因为如果执行失败,无法获取错误代码(HRESULT)?@dave:如果执行失败,将返回相应的HRESULT。如果您通过“原始接口”调用该方法,则签名将返回
HRESULT
,您可以对其进行检查。如果您正在调用一个本机COM支持包装器,该包装器返回的不是
HRESULT
,那么该包装器将在其内部进行检查,并调用
\u COM\u issue\u error()
,该包装器将映射到引发异常的某个函数上。所以这不是问题。详细说明@KimGräsman的评论:Visual Basic(“经典”)不支持
[in,out]
。一个
[in,out]
参数将由实现该方法的Visual Basic代码处理,就像它是
[out]
一样。这意味着调用方法时参数指向的任何值都将被丢弃并覆盖,而无需进行检查,可能会导致泄漏。有时不重要(例如,参数指向本地int),有时重要(参数指向BSTR)