3

I have an existing Interface API, which has an OUT, RETVAL parameter like below

HRESULT Test([out, retval] VARIANT_BOOL *pVal);

I was asked to add an optional IN parameter, hence I tried the below, since RETVAL parameter by rule should be the last parameter I was forced to put the optional IN parameter as a first parameter

HRESULT Test([in, optional, defaultvalue(VARIANT_FALSE)] VARIANT_BOOL optFlag, [out, retval] VARIANT_BOOL *pVal);

When I tried to call this API like below, with only the mandatory OUT parameter from a C++ component compiler errors out saying two parameters are required for this call

VARIANT_BOOL outFlag;
pInterface->Test(&outFlag);

Please let me know what I am missing here to achieve this combination.

Roman R.
  • 68,205
  • 6
  • 94
  • 158
Titus
  • 907
  • 8
  • 18
  • The [optional] attribute is useful when a compiler uses the type library to import declarations. They typically also rewrite the function so the [retval] becomes the return value and a failure HRESULT code turns into an exception. You are not using that feature, looks like you use the generated .h file. And ignore the HRESULT, bad idea. Consider the #import directive. – Hans Passant Oct 21 '16 at 10:34

2 Answers2

3

MSDN on optional IDL attribute:

The [optional] attribute is valid only if the parameter is of type VARIANT or VARIANTÂ *.

You are trying to apply it to VARIANT_BOOL.

There is also a hint there on the order of parameters with such attributes:

The MIDL compiler accepts the following parameter ordering (from left-to-right):

  • Required parameters (parameters that do not have the [defaultvalue] or [optional] attributes),
  • Optional parameters with or without the [defaultvalue] attribute,
  • Parameters with the [optional] attribute and without the [defaultvalue] attribute,
  • [lcid] parameter, if any,
  • [retval] parameter

IDL compiler issues a warning when compiling such method:

warning MIDL2401: [defaultvalue] is applied to a non-VARIANT and [optional]. Please remove [optional] : [ Parameter 'optFlag' of Procedure 'Test' ...

Nevertheless, attributes are compiled into type library and are available for importers. For instance, C# imports the method as:

bool Test(bool optFlag = false);

which should match your expectations. However this goes rather as a free bonus since type library importers are free to interpret the flags (esp. exceeding the documented limitations) at their discretion. C++ #import does not generate a method with an optional parameter.

Roman R.
  • 68,205
  • 6
  • 94
  • 158
  • That isn't actually correct. Have a look-see at wincodec.idl for example, note the optional ULONG. Afaik it is entirely up to a compiler to interpret it the way it wants to. – Hans Passant Oct 21 '16 at 12:17
  • @HansPassant: Such optional attribute is reflected as some flag in the type library, because import sees it back. Importers are free to interpret this the way they want, right, but they don't have to go beyond the documented statement limiting that to variants only. Also, in this specific scenario mentioned in question there is an IDL compiler warning explaining the problem: "warning MIDL2401: [defaultvalue] is applied to a non-VARIANT and [optional]. Please remove [optional]..." – Roman R. Oct 21 '16 at 12:35
  • This is mostly true for higher level (Automation/IDispatch) languages (VB/VBA/VBScript, .NET), where there is the notion of a "Missing" VARIANT value (technically represented by VT_ERROR / DISP_E_PARAMNOTFOUND) https://support.microsoft.com/en-us/kb/154039 – Simon Mourier Oct 21 '16 at 12:37
1

The C++ bindings generated by microsofts IDL compiler do not support the optional and/or default value feature.

Try it from C# or similar.

Yakk - Adam Nevraumont
  • 262,606
  • 27
  • 330
  • 524