Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

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

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:

  • _variant_t or CComVariant for POD types
  • _bstr_t, CComBSTR, or BSTR for strings
  • CComSafeArray or SAFEARRAY for arrays

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:

  • CComVariant vs. _variant_t, CComBSTR vs. _bstr_t
  • Convert VARIANT to...?
  • How to best convert VARIANT_BOOL to C++ bool?
like image 319
Nate Kohl Avatar asked Mar 01 '10 21:03

Nate Kohl


1 Answers

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.

like image 193
Luke Avatar answered Nov 02 '22 10:11

Luke