A simple way to convert to/from VARIANT types in C++

Nate Kohl picture Nate Kohl · Mar 1, 2010 · Viewed 22.7k times · Source

Are there any easy-to-use, high-level classes or libraries that let you interact with VARIANTs in Visual C++?

More specifically, I'd like to convert between POD types (e.g. double, long), strings (e.g. CString), and containers (e.g. std::vector) and VARIANTs. For example:

long val = 42;
VARIANT var;
if (ToVariant(val, var)) ...     // tries to convert long -> VARIANT
comObjPtr->someFunc(var);

std::vector<double> vec;
VARIANT var = comObjPtr->otherFunc();
if (FromVariant(var, vec)) ...   // tries VARIANT -> std::vector<double>

I (naively?) assumed that people working with COM do this all the time, so there would most likely be a single convenient library that handles all sorts of conversions. But all that I've been able to find is a motley assortment of wrapper classes that each convert a few types:

Is there any simple way -- short of switching to Visual Basic -- to avoid this nightmare of awkward memory management and bitwise VT_ARRAY | VT_I4 code?

Related questions:

Answer

Luke picture Luke · Mar 7, 2010

Well, most of the hard work is already done for you with the various wrapper classes. I prefer _variant_t and _bstr_t as they are more suited for conversion to/from POD types and strings. For simple arrays, all you really need is template conversion function. Something like the following:

// parameter validation and error checking omitted for clarity
template<typename T>
void FromVariant(VARIANT Var, std::vector<T>& Vec)
{
    CComSafeArray<T> SafeArray;
    SafeArray.Attach(Var.parray);
    ULONG Count = SafeArray.GetCount();
    Vec.resize(Count);
    for(ULONG Index = 0; Index < Count; Index++)
    {
        Vec[Index] = SafeArray[Index];
    }
}
....
std::vector<double> Vec;
VARIANT Var = ...;
FromVariant(Var, Vec);
...

Of course things get hairy (in regards to memory / lifetime management) if the array contains non-POD types, but it is still doable.