VARIANT结构体主要是使用在COM(组件对象模型)中用于传递参数使用,它的存在主要是为了保持一个在COM参数传递方法的统一性,它几乎包含了所有普通常用类型的数据类型的传递,如整型,浮点型,布尔型等等,以及相应类型的指针类型,如整型指针。它的使用也比较方便。先来看看这个结构体它的结构:

typedef struct tagVARIANT {
  union {
    struct __tagVARIANT {
      VARTYPE vt;
      WORD    wReserved1;
      WORD    wReserved2;
      WORD    wReserved3;
      union {
        LONGLONG            llVal;
        LONG                lVal;
        BYTE                bVal;
        SHORT               iVal;
        FLOAT               fltVal;
        DOUBLE              dblVal;
        VARIANT_BOOL        boolVal;
        _VARIANT_BOOL       bool;
        SCODE               scode;
        CY                  cyVal;
        DATE                date;
        BSTR                bstrVal;
        IUnknown            *punkVal;
        IDispatch           *pdispVal;
        SAFEARRAY           *parray;
        BYTE                *pbVal;
        SHORT               *piVal;
        LONG                *plVal;
        LONGLONG            *pllVal;
        FLOAT               *pfltVal;
        DOUBLE              *pdblVal;
        VARIANT_BOOL        *pboolVal;
        _VARIANT_BOOL       *pbool;
        SCODE               *pscode;
        CY                  *pcyVal;
        DATE                *pdate;
        BSTR                *pbstrVal;
        IUnknown            **ppunkVal;
        IDispatch           **ppdispVal;
        SAFEARRAY           **pparray;
        VARIANT             *pvarVal;
        PVOID               byref;
        CHAR                cVal;
        USHORT              uiVal;
        ULONG               ulVal;
        ULONGLONG           ullVal;
        INT                 intVal;
        UINT                uintVal;
        DECIMAL             *pdecVal;
        CHAR                *pcVal;
        USHORT              *puiVal;
        ULONG               *pulVal;
        ULONGLONG           *pullVal;
        INT                 *pintVal;
        UINT                *puintVal;
        struct __tagBRECORD {
          PVOID       pvRecord;
          IRecordInfo *pRecInfo;
        } __VARIANT_NAME_4;
      } __VARIANT_NAME_3;
    } __VARIANT_NAME_2;
    DECIMAL             decVal;
  } __VARIANT_NAME_1;
} VARIANT, *LPVARIANT, VARIANTARG, *LPVARIANTARG;

这个结构体呢,有5个成员,分别是VARTYPE vt ,WORD wReserved1,WORD wReserved2,WORD wReserved3,和最后一个共用体。其中vt用以指明最后一个共用体中哪一个成员有效,wReserved1,wReserved2,wReserved3,这三个我们使用的时候不用管,系统保留,最后一个共用体根据vt的提示,对相应的成员进行值的存储。我们从两个不同的角度来理解,首先是使用VARIANT来存储参数,首先是声明一个这个结构体的对象,然后对对象的vt进行赋值,它可接受的值是一个枚举值,也就说只能在枚举这个范围内取值,比如我要用VARIANT传递一个整数,现在我对vt的赋值为VT_INT,这样就说明了我要使用这个结构体中共用体的整型变量,接着对INT变量进行赋值,赋我们要传递的值。这样就完成VARIANT的传递。现在我们从另外一个角度来理解VARIANT,刚才是我们对VARIANT对象进行赋值传递,现在我们是这个VARIANT对象的接收者,我们从参数中获得这个对象之后,我们首先检查这个结构体的vt成员,看它哪个类型的变量有效,比如就这个例子而言,检查到vt的值是VT_INT,因此,我直接去获取这个结构体中VT_INT所对应的变量,获取它的值。这样,我们从传递到使用两个角度来理解了VARIANT结构体,概括起来说,就是vt指明了我要传递的变量的类型,结构体中共用体的成员用来存储vt指明的类型的值。

下面来看看具体VARIANT结构体是如何使用赋值的,首先是第一种方法:

首先我们声明一个VARIANT结构体的对象vr1,然后使用VariantInit函数对其进行初始化,它的作用就是对vt赋VT_EMPTY,对别的变量值附空,否则就是一个随机值,这个过程和我们声明一个int变量一样,如果声明的时候不初始化,就是一个随机值。编程过程中,不管是指针还是什么变量,都应该在声明之后对其进行初始化。接着就是我赋VT_INT给vt,这里的V_VT就是代表要对vr1结构体中的vt成员进行幅值,接着对vr1中的INT成员赋值,这里的V_INT就是表示要对INT赋值,因此这里有一个规律,就是V_,它的后面加成员类型就可以对相应的成员赋值,而这里的成员类型有一个对照表,在文章的最后给出,比如,我要对BSTR成员赋值,我就用V_BSTR。这时候,就可以使用vr1了,使用完成之后,我们应该调用VariantClear函数,这个函数的作用就是将vt赋值为VT_EMPTY,以及释放使用这个结构体中的内存中的内容,如果是com对象,该函数是不会进行对象的release操作的,不管怎么样,我们都应该在使用完了VARIANT结构体之后,调用这个函数。

下面是第二种方法,原理和过程和地中方法类似,有一点微小的区别,就是VARIANT结构体的赋值上面来说,有点不同,如下:

接下来是字符串的操作,BSTR,我们不能直接将字符串传递一个VARIANT结构体对象,而是要用到函数SysAllocString,它的返回值就是一个BSTR,由它分配一个字符串,供VARIANT,对于为什么要这么做,可以自己查看MSDN COM的Automation那部分:

完成之后,我们还应该调用SysFreeString来释放由SysAllocString分配的内存。

另外,我们可以在类型与变量的对照表中发现,同一类型,对应了两种不同的变量,如,INT对应了变量有intVal和pintVal,其实这很简单,后者是指针性,如果要使用,说明我们赋值的对象是一个指针,如下:

最后给出类型与变量的对照表,如果是使用地中方法用V_加类型,就直接使用下表中VT_后的名称就可以了:

Member name Description
  VT_EMPTY Indicates that a value was not specified.
  VT_NULL Indicates a null value, similar to a null value in SQL.
  VT_I2 Indicates a short integer.
  VT_I4 Indicates a long integer.
  VT_R4 Indicates a float value.
  VT_R8 Indicates a double value.
  VT_CY Indicates a currency value.
  VT_DATE Indicates a DATE value.
  VT_BSTR Indicates a BSTR string.
  VT_DISPATCH Indicates an IDispatch pointer.
  VT_ERROR Indicates an SCODE.
  VT_BOOL Indicates a Boolean value.
  VT_VARIANT Indicates a VARIANT far pointer.
  VT_UNKNOWN Indicates an IUnknown pointer.
  VT_DECIMAL Indicates a decimal value.
  VT_I1 Indicates a char value.
  VT_UI1 Indicates a byte.
  VT_UI2 Indicates an unsignedshort.
  VT_UI4 Indicates an unsignedlong.
  VT_I8 Indicates a 64-bit integer.
  VT_UI8 Indicates an 64-bit unsigned integer.
  VT_INT Indicates an integer value.
  VT_UINT Indicates an unsigned integer value.
  VT_VOID Indicates a C style void.
  VT_HRESULT Indicates an HRESULT.
  VT_PTR Indicates a pointer type.
  VT_SAFEARRAY Indicates a SAFEARRAY. Not valid in a VARIANT.
  VT_CARRAY Indicates a C style array.
  VT_USERDEFINED Indicates a user defined type.
  VT_LPSTR Indicates a null-terminated string.
  VT_LPWSTR Indicates a wide string terminated by nullNothingnullptra null reference (Nothing in Visual Basic).
  VT_RECORD Indicates a user defined type.
  VT_FILETIME Indicates a FILETIME value.
  VT_BLOB Indicates length prefixed bytes.
  VT_STREAM Indicates that the name of a stream follows.
  VT_STORAGE Indicates that the name of a storage follows.
  VT_STREAMED_OBJECT Indicates that a stream contains an object.
  VT_STORED_OBJECT Indicates that a storage contains an object.
  VT_BLOB_OBJECT Indicates that a blob contains an object.
  VT_CF Indicates the clipboard format.
  VT_CLSID Indicates a class ID.
  VT_VECTOR Indicates a simple, counted array.
  VT_ARRAY Indicates a SAFEARRAY pointer.
  VT_BYREF Indicates that a value is a reference.

更多详细信息,请参考msdn

或是有任何编程问题,到http://www.panshy.com提问或是查阅。

VARIANT的使用方法相关推荐

  1. java uuid静态方法_Java UUID的variant()方法和示例

    java uuid静态方法 UUID类variant()方法 (UUID Class variant() method) variant() method is available in java.u ...

  2. Delphi 变体类型(Variant)的介绍(流与变体类型的相互转换、变体类型常用的函数)...

    来源:http://blog.csdn.net/xiongmao000738/article/details/6863988 一.变体类型常用的函数介绍: Variant: 一种可以拥有各种数据类型: ...

  3. API ‘variant.getAssemble()‘ is obsolete and has been replaced with ‘variant.getAssembleProvider()‘

    Warning 日志 最近在做Android工程的架构升级,每次同步工程()都会报下面的告警信息: API 'variant.getAssemble()' is obsolete and has be ...

  4. 导出各种类型的文件的简单方法(暂时)

    把html导出为excel或者word文档 [b]1.jsp页面简单导出[/b] 导出为excel: <% response.setContentType("application/v ...

  5. boost使用学习总结

    boost常用库案例 http://www.cnblogs.com/wangkangluo1/archive/2011/07/19/2110746.html 1.boost::any boost::a ...

  6. ADO学习(九)如何阅读ADO文档

      <ADO API参考>用VB的语法描述了ADO API的内容.但ADO程序员却使用着不同的编程语言,比如VB,VC++,VJ++.对此<ADO for VC++的语法索引> ...

  7. 在MFC中使用Cstring

    此文介绍了关于MFC使用CString的资料,可一参考一下. 转自于VC知识库:http://www.vckbase.com/index.php/wv/829 通过阅读本文你可以学习如何有效地使用 C ...

  8. [转载]VC++程序员应当如何阅读ADO文档

    <ADO API参考>用VB的语法描述了ADO API的内容.但ADO程序员却使用着不同的编程语言,比如VB,VC++,VJ++.对此<ADO for VC++的语法索引>提供 ...

  9. CString 操作指南

    原著:Joseph M. Newcomer 翻译:littleloach 原文出处:codeproject:CString Management 通过阅读本文你可以学习如何有效地使用 CString. ...

最新文章

  1. 使用多个推理芯片需要仔细规划
  2. 在Python中实现SVM分类
  3. Oracle 11 密码永不过期
  4. 打分排序系统漫谈1 - 时间衰减
  5. [转载]matlab中控制mesh或者surf的颜色
  6. 今晚8点不见不散!余承东Vlog如此夸赞华为Mate30系列新机
  7. 大数据在智慧社区的作用有哪些
  8. 制作网页先写html还是css,制作网页是先学html还是css
  9. stl_algorithm算法之排序算法
  10. 错排公式的推导及应用
  11. 计算机网络技术与实验清华大学,清华大学计算机网络实验指示书.doc
  12. 《WinHex》误使用Ghost恢复系统恢复数据图文教程
  13. IB网卡驱动安装以及Infiniband连接带宽测试
  14. AdventureWorks 安装和配置[转自 微软msdn]
  15. lenovo启动热键_联想电脑如何进入U盘启动,按哪个快捷键?
  16. matlab centralize,智课雅思词汇---二十三、动词性后缀-ate-fy-ish-ize
  17. u盘工作表在计算机上打不开,U盘中无法打开的excel的解决办法
  18. linux中怎么连接wifi密码,Linux终端中连接WiFi的方法
  19. 【Windows系统】产品ID、设备ID等系统参数
  20. 软测(三)测试用例基本介绍

热门文章

  1. github + jekyll 建自己的博客
  2. 12864液晶8x16ascii点阵_Arduino基础入门篇31—LCD1602液晶显示
  3. 关于编程风格--静态常量前置(一)
  4. 【转载】一文彻底搞定哈希表!
  5. 格莱富笔记本电脑教你轻松打开笔记本电脑隐藏文件夹
  6. 监狱犯人腕带定位解决方案
  7. 有赞零售小票打印跨平台解决方案 1
  8. 实现golang中memset函数
  9. 从网瘾少年逆袭拿到微软 、字节等offer(下)
  10. 双指针算法(更新中....)