在IDL中声明接口时,至少有两种方法可以从接口返回值:[out]
和[out, retval]
。
当使用[out, retval]
时,COM包装器使标记的参数成为返回值,并且不再从该方法返回HRESULT
。问题是如何获得HRESULT
以测试COM调用是否成功?而且,从COM服务器设计的角度来看,在COM方法调用中不返回HRESULT
通常被认为是不好的做法吗?
答案 0 :(得分:2)
有一个重要的区别,它取决于客户端代码中的语言运行时支持。其中许多(如.NET或脚本语言)将修改函数的签名,并使其看起来像是一个函数,它返回您使用[retval]注释的值。并将隐藏HRESULT,在您返回失败代码时自动触发异常。这可以使客户端代码看起来更自然。
是的,你应该总是实现STDMETHOD,这样的语言运行时往往需要它。当客户端代码想要使用后期绑定以及函数调用需要遍历公寓边界(即从一个线程编组到另一个线程或跨过一个进程或机器边界)时,这也是一个很难的要求,这是你无法控制的事情。 / p>
答案 1 :(得分:1)
无论参数是声明为[out]
还是[out, retval]
,HRESULT
都将返回给调用方。接下来发生的事情在很大程度上取决于实际调用者代码和COM之间的中间件。
如果它是.NET代码,那么HRESULT
将由.NET生成的包装器检查,并且将抛出异常并且唯一的解决方案是捕获和解释可能很多痛苦的异常,因为{{ 3}}
如果它是更老的学校,例如Visual C ++ Native COM支持,那么你有选择。默认情况下,Native COM Support为每个带有[out, retval]
参数的方法生成一个包装器,该参数现在返回该参数的类型,并在包装器中检查HRESULT
,并且可能调用_com_issue_error()
异常并将原始HRESULT
传递给_com_issue_error()
以及可以从中检索它的异常对象。可能是每个COM方法调用的处理异常会给代码添加混乱,然后您可以使用raw_interfaces_only
和#import
指令,然后生成包装器 - 您将为您呈现原始界面。这取决于您选择的内容 - HRESULT
检查内包装或没有包装。
无论如何,你将有办法知道有错误。使用[out, retval]
绝不是一种不好的做法。