花园分享 http://blog.sciencenet.cn/u/zxczxc0417

博文

VARIANT类型 详解

已有 9104 次阅读 2012-10-11 02:18 |个人分类:乱七八糟|系统分类:海外观察| 化学, 诺贝尔, 人人, 终结者

MFC+类型转换

http://wenku.baidu.com/view/23091600b52acfc789ebc9ca.html

 

 

关于VARIANT类型和BSTR

2008-01-03 16:30 by Mainz, 334 visits, 网摘, 收藏, 编辑

在进行COM编程的时候常常用到VARIANT类型的变量, 其中的字符串分量为bstrVal即双字节的BSTR, 如果需要将其转换为字符串STRING我以前使用强制类型转换:
(const char*)bsVal;
在看了潘爱民老师的<<COM编程原理>>偶尔发现如下函数(例子摘自MSDN)

//compile options needed: /Gr or /Gz
#include <comutil.h>
int main()
{
char sz[]="hello";
_bstr_t b;
b = _com_util::ConvertStringToBSTR(sz);
char * p = _com_util::ConvertBSTRToString(b);
return 1;
}


注意: 上述代码编译时候出现如下错误

error LNK2001: unresolved external symbol "char * __fastcall _com_util::ConvertBSTRToString(unsigned short *)"
(?ConvertBSTRToString@_com_util@@YIPADPAG@Z)

error LNK2001: unresolved external symbol "unsigned short * __fastcall
_com_util::ConvertStringToBS
TR(char const *)" (?ConvertStringToBSTR@_com_util@@YIPAGPBD@Z)

解决: 在Link页加入comsupp.lib就可以了, 不过我的程序编译的时候没有上述错误, 但是在同事的机器上出现了.

我的用法 -- _com_util::ConvertStringToBSTR();

char* pTemp;
CString csTemp;

pTemp = _com_util::ConvertBSTRToString(bsVal);
csTemp = pTemp;
delete pTemp;
pTemp = NULL;

// 这是我们公司的一位高手的最安全的用法
// 对于ConvertStringToBSTR不需要

另:

char * 转换到 BSTR 可以这样:

BSTR b=_com_util::ConvertStringToBSTR("数据");///使用前需要加上#include "comutil.h"和在Project - settings - link - general, Object/library modules - 加上comsupp.lib

SysFreeString(bstrValue);

反之可以使用

char *p=_com_util::ConvertBSTRToString(b);
delete p;

 

这几天,一直为一个以前没见过的类型头痛不已,网上找解决方法又不贴切,着实让我难受了一阵子.今天终于把问题解决,在这里跟大家分..

    VARIANT,变体类型,在VB中是一个可以容纳很多常用类型的超级类型,所以,如果不知道它的里面到底存了些什么数据,对着它就像对着一个从未见过面的朋友一样,不知该怎么交流.在这种情况下,我们可以通过取得VARIANT类型变量的vt值,得以确认:
      enum VARENUM
    { VT_EMPTY = 0,
 VT_NULL = 1,
 VT_I2 = 2,
 VT_I4 = 3,
 VT_R4 = 4,
 VT_R8 = 5,
 VT_CY = 6,
 VT_DATE = 7,
 VT_BSTR = 8,
 VT_DISPATCH = 9,
 VT_ERROR = 10,
 VT_BOOL = 11,
 VT_VARIANT = 12,
 VT_UNKNOWN = 13,
 VT_DECIMAL = 14,
 VT_I1 = 16,
 VT_UI1 = 17,
 VT_UI2 = 18,
 VT_UI4 = 19,
 VT_I8 = 20,
 VT_UI8 = 21,
 VT_INT = 22,
 VT_UINT = 23,
 VT_VOID = 24,
 VT_HRESULT = 25,
 VT_PTR = 26,
 VT_SAFEARRAY = 27,
 VT_CARRAY = 28,
 VT_USERDEFINED = 29,
 VT_LPSTR = 30,
 VT_LPWSTR = 31,
 VT_RECORD = 36,
 VT_FILETIME = 64,
 VT_BLOB = 65,
 VT_STREAM = 66,
 VT_STORAGE = 67,
 VT_STREAMED_OBJECT = 68,
 VT_STORED_OBJECT = 69,
 VT_BLOB_OBJECT = 70,
 VT_CF = 71,
 VT_CLSID = 72,
 VT_BSTR_BLOB = 0xfff,
 VT_VECTOR = 0x1000,
 VT_ARRAY = 0x2000,
 VT_BYREF = 0x4000,
 VT_RESERVED = 0x8000,
 VT_ILLEGAL = 0xffff,
 VT_ILLEGALMASKED = 0xfff,
 VT_TYPEMASK = 0xfff
    };

    这个枚举结构里,存着vt值的宏定义,假如m_DataA为VARIANT类型变量,m_DataA .vt = 4,则这个变量里的就是存的一个单精度数据(以上宏在MSDN均可查到所代表的类型),当然,上面的宏可以叠加使用,比如说m_DataA.vt = 8204,转化成十六进制数为0x200C,VT_ARRAY = 0x2000,VT_VARIANT = 12(12的十六进制为:C),变量里存的数据是一个 变体数组类型(VT_ARRAY |VT_VARIANT ).

SafeArray是VB中的数组存储方式。通过SafeArray,可以在VC++和VB间相互调用。

SafeArrayGetLBound(SAFEARRAY * psa, UINT nDim, LONG * plLbound);

SafeArrayGetUBound(SAFEARRAY * psa, UINT nDim, LONG * plUbound);
假如变量里存的是数组数据,这两个API函数是用来得到该数组下标的起始和结束位置.

SafeArrayAccessData(SAFEARRAY * psa, void HUGEP** ppvData);

     这个函数用于获取SafeArray的数据指针,并锁定SafeArray数组的数据。在取得了数据指针之后,就可以直接访问SafeArray数组中的数据了。

     如果数组类型是Type,那么所取得的数据指针实际上就是Type类型的数组的地址。在多维数组的情况下,必须把多个维度的下标转换成一维下标进行访问。

SafeArrayUnaccessData(SAFEARRAY * psa);

这个函数的作用是对SafeArray数据解锁,解锁后,就不应该继续对数据指针进行读写访问。如果要访问,必须重新获取并锁定数据。

示例:

VARIANT INMR::GetDataA()
{
 VARIANT result;
 InvokeHelper(0x1a, DISPATCH_PROPERTYGET, VT_VARIANT, (void*)&result, NULL);
 return result;
}

void CNMR02View::GetNMRDataA()
{
 VARIANT m_nVarA = iRiNMR.GetDataA();
 
 if(m_nVarA.vt = VT_ARRAY|VT_VARIANT)
 {
  long upBoundA,lowBoundA;
  SAFEARRAY *pDataA = m_nVarA.parray;
  SafeArrayGetUBound(pDataA,1,&upBoundA);
  SafeArrayGetLBound(pDataA,1,&lowBoundA);
  VARIANT *pTmp = 0;
  SafeArrayAccessData(pDataA,(void**)&pTmp);
  for(int i = lowBoundA; i < upBoundA ; i++)
  {
   m_DataA.push_back(pTmp[i].dblVal);
 
 
  }
  SafeArrayUnaccessData(pDataA);
  SafeArrayDestroy(pDataA);
 }
 

}

尽供参考.

 

本文来自CSDN博客,转载请标明出处:http://blog.csdn.net/seabob/archive/2009/05/14/4184292.aspx

 

 

 

在OLE、ActiveX和COM中,VARIANT数据类型提供了一种非常有效的机制,由于它既包含了数据本身,也包含了数据的类型,因而它可以实现各种不同的自动化数据的传输。下面让我们来看看OAIDL.H文件中VARIANT定义的一个简化版:

struct tagVARIANT {
  VARTYPE vt;
  union {
   short iVal; // VT_I2.
   long lVal; // VT_I4.
   float fltVal; // VT_R4.
   double dblVal; // VT_R8.
   DATE date; // VT_DATE.
   BSTR bstrVal; // VT_BSTR.
   …
   short * piVal; // VT_BYREF|VT_I2.
   long * plVal; // VT_BYREF|VT_I4.
   float * pfltVal; // VT_BYREF|VT_R4.
   double * pdblVal; // VT_BYREF|VT_R8.
   DATE * pdate; // VT_BYREF|VT_DATE.
   BSTR * pbstrVal; // VT_BYREF|VT_BSTR.
  };
};

  显然,VARIANT类型是一个C结构,它包含了一个类型成员vt、一些保留字节以及一个大的union类型。例如,如果vt为VT_I2,那么我们可以从iVal中读出VARIANT的值。同样,当给一个VARIANT变量赋值时,也要先指明其类型。例如:

VARIANT va;
:: VariantInit(&va); // 初始化
int a = 2002;
va.vt = VT_I4; // 指明long数据类型
va.lVal = a; // 赋值

  为了方便处理VARIANT类型的变量,Windows还提供了这样一些非常有用的函数:

  VariantInit —— 将变量初始化为VT_EMPTY;

  VariantClear —— 消除并初始化VARIANT;

  VariantChangeType —— 改变VARIANT的类型;

  VariantCopy —— 释放与目标VARIANT相连的内存并复制源VARIANT。



https://wap.sciencenet.cn/blog-236430-621288.html

上一篇:VC++ 学习笔记
下一篇:小小迷你review:甲酸低温分解制氢的昨天,今天和明天
收藏 IP: 221.224.90.*| 热度|

3 刘红义 许培扬 吕喆

该博文允许注册用户评论 请点击登录 评论 (11 个评论)

数据加载中...
扫一扫,分享此博文

Archiver|手机版|科学网 ( 京ICP备07017567号-12 )

GMT+8, 2024-6-6 19:15

Powered by ScienceNet.cn

Copyright © 2007- 中国科学报社

返回顶部