Question

The following code is from MSDN source-code examples and I have one question.

Why we need to use multiple VARIANT result; definitions to define different variables? Can we initialize VARIANT variables of different types (mostly integer and strings) in a shorter way? Concise and safe method.

Also, can VariantInit(&result) be replaced by result.vt = VT_EMPTY to just mark the VARIANT as empty?

int main()
{
    //blahblahbla
    {
        VARIANT x;
        x.vt = VT_R4;   // 4-byte real. 
        x.fltVal = 1.2f;
        wprintf(L"Set FloatProperty = %.2f\n", x.fltVal);
        hr = AutoWrap(DISPATCH_PROPERTYPUT, NULL, pSimpleObj, L"FloatProperty", 1, x);
    }
    {
        VARIANT result;
        VariantInit(&result);
        hr = AutoWrap(DISPATCH_PROPERTYGET, &result, pSimpleObj, L"FloatProperty", 0);
        wprintf(L"Get FloatProperty = %.2f\n", result.fltVal);
    }

    {
        VARIANT result;
        VariantInit(&result);
        hr = AutoWrap(DISPATCH_METHOD, &result, pSimpleObj, L"HelloWorld", 0);
        wprintf(L"Call HelloWorld => %s\n", result.bstrVal);
        VariantClear(&result);
    }
}
Était-ce utile?

La solution

Why we need to use different "VARIANT result" variables?

You don't have to, it is just the way the sample was written. Do be careful when you re-use VARIANT variables, just calling VariantInit() or assigning result.vt = VT_EMPTY is dangerous. A variant can store resources that need to be released. As was done in the snippet, note the call to VariantClear(), required to release the BSTR. Which is different from VariantInit(), VariantClear releases the resources first before initializing the variant again.

Also note how it was omitted after the DISPATCH_PROPERTYGET call. That's okay but you have to know what you are doing. Okay in this case because a VARIANT can store a floating point value without having to allocate memory for it. Calling VariantClear() anyway is certainly not wrong.

And keep in mind that MSDN source code is often written to compile with a C compiler. If you write COM code then you'd almost always favor using C++. Which can certainly to a better job, you can now use the _variant_t class. A wrapper class that avoids silly mistakes and makes the syntax cleaner as well, what you asked for. You no longer have to use VariantInit or VariantClear, the wrapper does it for you and never gets it wrong.

Autres conseils

An alternative to using VARIANT directly is to instead use one of the wrapper classes available with C++. There are several alternatives depending on whether you are using MFC or ATL or just native C++.

For a simple wrapper there is the _variant_t class which provides some of the basic amenities especially for simple data such as integers and strings. The class does not have direct support for SAFEARRAY type VARIANTS.

See the Microsoft Developer Network topic _variant_t Class which provides an overview of the wrapper class and the methods available.

A _variant_t object encapsulates the VARIANT data type. The class manages resource allocation and deallocation and makes function calls to VariantInit and VariantClear as appropriate.

There are several variations of the constructor taking different parameter types and creating the appropriate kind of VARIANT object. It looks like for the standard Windows API UNICODE or wchar_t string, you will need to use a BSTR object.

ATL offers the CComVariant and MFC offers the COleVariant classes for wrapping VARIANT. These three wrapper classes (_variant_t, CComVariant, and COleVariant all seem to be derived from struct tagVARIANT, the underlying data structure for VARIANT, so all of these seem to be usable for any interface that uses VARIANT.

This note for CComVariant from Microsoft Developer Network CComVariant Class

CComVariant wraps the VARIANT and VARIANTARG type, which consists of a union and a member indicating the type of the data stored in the union. VARIANTs are typically used in Automation.

CComVariant derives from the VARIANT type so it can be used wherever a VARIANT can be used. You can, for example, use the V_VT macro to extract the type of a CComVariant or you can access the vt member directly just as you can with a VARIANT.

And this note for COleVariant from Microsoft Developer Network COleVariant Class:

This class is derived from the VARIANT structure. This means you can pass a COleVariant in a parameter that calls for a VARIANT and that the data members of the VARIANT structure are accessible data members of COleVariant.

Licencié sous: CC-BY-SA avec attribution
Non affilié à StackOverflow
scroll top