In Borland C++ Builder 6, the code generated to import COM objects slightly differs from the one generated by previous versions of C++ Builder.
Specifically, the VARIANT date type is used instead of TVariant. Giving up its TVariant
“smart wrapper” was a good move from Borland, but it broke backward compatibility with output parameters of some COM methods, which don’t receive a value anymore.
For example, below is the code generated by C++ Builer 4 for the FarPoint TfpSpread COM object (from file FPSpreadADO_TLB.h) :
[code lang=cpp]
VARIANT_BOOL __fastcall GetText(long Col, long Row, TVariant* Var)
{
_TDispID _dispid(/* GetText */ DISPID(252));
TAutoArgs<3> _args;
_args[1] = Col /*[VT_I4:0]*/;
_args[2] = Row /*[VT_I4:0]*/;
_args[3] = Var /*[VT_VARIANT:1]*/;
OleFunction(_dispid, _args);
return _args.GetRetVariant();
}
[/code]
When generated using C++ Builder 6, the code becomes :
[code lang=cpp]
VARIANT_BOOL __fastcall GetText(long Col, long Row, VARIANT* Var)
{
_TDispID _dispid(/* GetText */ DISPID(252));
TAutoArgs<3> _args;
_args[1] = Col /*[VT_I4:0]*/;
_args[2] = Row /*[VT_I4:0]*/;
_args[3] = Var /*[VT_VARIANT:1]*/;
OleFunction(_dispid, _args);
return _args.GetRetVariant();
}
[/code]
Notice the Var
parameter, whose type was changed from TVariant* to VARIANT* : that’s the source of the problem.
The issue comes from the TAutoArgs
class, more specifically from its array of Variant
.
The Variant
assignment operator (=) behaves differently depending if its RHS is a TVariant*
or a VARIANT*
:
Variant = TVariant*
: TheVariant
is initialized with a reference to theTVariant*
object (vt = VT_BYREF|VT_VARIANT
, andpvarVal
receives a pointer to theTVariant*
Variant = VARIANT*
: theVariant
‘=’ operator assumes theVARIANT*
is aVT_BOOL
. Changes to theVariant
are not reflected on theVARIANT*
To fix the problem, one must explicitly set the Variant
as a reference to the VARIANT*
. For example, the previous example must be changed to :
[code lang=cpp]
VARIANT_BOOL __fastcall GetText(long Col, long Row, VARIANT* Var)
{
_TDispID _dispid(/* GetText */ DISPID(252));
TAutoArgs<3> _args;
_args[1] = Col /*[VT_I4:0]*/;
_args[2] = Row /*[VT_I4:0]*/;
_args[3].vt = VT_BYREF|VT_VARIANT /*[VT_VARIANT:1]*/;
_args[3].pvarVal = Var;
OleFunction(_dispid, _args);
return _args.GetRetVariant();
}
[/code]
Omg!
Thank you so much!
I had been getting crazy for a few days, before I found your post. At last my code works the right way, thank you!
Hi Martha,
I wasted so much time with this issue, I’m really glad this post was helpful to you 🙂