IDL文件和C ++头文件中的defaultvalue和retval参数排序

时间:2014-10-03 15:32:42

标签: c++ com idl

我正在尝试更新现有的COM API以包含新的可选输出参数,并且遇到了IDL文件和相关C ++头文件中参数类型的强制排序问题。

以前我有一个像这样的IDL文件(名称已更改以保护无辜者):

HRESULT CreateSomething(
    [in] BSTR base_uri,
    [in] ISomethingDescription* something_description,
    [out, retval] BSTR* something_uri
);

和关联的C ++标题看起来像:

HRESULT __stdcall CreateSomething(
    /* [in] */ BSTR study_uri,
    /* [in] */ ISomethingDescription* something_description,
    /* [out, retval] */ BSTR* something_uri
);

这需要更新以添加可选的输出参数,该参数可以为一些客户端提供额外的错误报告信息,遵循现有模式与内部SDK的其余部分。

为此,我计划将IDL文件更新为:

HRESULT CreateSomething(
    [in] BSTR base_uri,
    [in] ISomethingDescription* something_description,
    [out, defaultvalue(0)] ErrorCode* error_code,
    [out, retval] BSTR* something_uri
);

其中ErrorCode是在单独的IDL文件中定义的枚举。这遵循我在网上看到的关于如何排序带有defaultvalue和retval属性的参数的指导。但是,当我尝试更新C ++头文件时,我遇到的问题是默认参数不在参数列表的末尾,即

HRESULT __stdcall CreateSomething(
    /* [in] */ BSTR study_uri,
    /* [in] */ ISomethingDescription* something_description,
    /* [out, defaultvalue(0)] */ ErrorCode* error_code = 0,   // this is clearly wrong
    /* [out, retval] */ BSTR* something_uri
);

我在MSDN上看到的文档似乎表明你可以在同一个函数定义中使用defaultvalue和retval属性的参数,我已经看到了包含这些定义的IDL文件的一些例子,但我无法弄清楚它是怎么回事可以编写等效的C ++定义。

某些客户端(以及我们自己的测试代码)直接使用MIDL生成的头文件,因此如果省略原始C ++头文件中的默认值,则MIDL生成的文件中生成的函数不包含默认值条目,即它看起来像这样:

virtual HRESULT STDMETHODCALLTYPE CreateSomething( 
            /* [in] */ BSTR base_uri,
            /* [in] */ ISomethingDescription *something_description,
            /* [defaultvalue][out] */ ErrorCode *error_code,
            /* [retval][out] */ BSTR *something_uri) = 0;

我们SDK中的类似函数包括IDL文件和C ++标题中的默认值 - 并不是说​​整个方法都不值得怀疑。

对此有任何帮助/建议将不胜感激。

1 个答案:

答案 0 :(得分:3)

MSDN is pretty clear about the parameters

  

MIDL编译器接受以下参数排序(从左到右):

     
      
  1. 必需参数(没有[defaultvalue]或[optional]属性的参数),
  2.   
  3. 带或不带[defaultvalue]属性的可选参数
  4.   
  5. 具有[optional]属性且没有[defaultvalue]属性的参数
  6.   
  7. [lcid]参数,如果有的话,
  8.   
  9. [retval]参数
  10.   

请注意,没有提及“not optional default value”参数。这是因为默认值仅适用于可选 - 这是有意义的,因为非可选参数始终具有显式值,没有适用的默认值。

因此,您的默认值参数必须是可选的,然后新约束适用:"The [optional] attribute is valid only if the parameter is of type VARIANT or VARIANT *.",这意味着您的可选枚举参数基本上无效。可能会发生这种情况,MIDL编译器会接受这个并将相应的标志放在类型库上,但最终这并不是预期它在第一位工作的方式:默认值仅适用于变体。

然后,当您从IDL生成C ++标头时,您会发现可选参数只是一个标记。诸如脚本语言之类的开发环境可能会检测它以分别更新此COM方法的语法,但在C ++端,参数始终存在且基本上是必需的。您基本上只有一个特殊约定,即看到调用者没有默认值的可选参数的值,在这种情况下,您在相应的变量参数中有VT_ERRORDISP_E_PARAMNOTFOUND