作者:朱金灿

来源:http://blog.csdn.net/clever101

STL的泛型数组是vetor,com的泛型数组类型是VARIANT。二者怎样能相互转化呢?就是说怎么把一个vector对象封装进VARIANT对象,又怎么将VARIANT对象封装进vector对象。经过一番研究,找到了办法。需要注意的是,数值数组和字符串数组是需要单独处理的。首先谈谈数组类型的数组如何转换,比如std::vector<int>转换为一个VARIANT对象。需要一个模板类来实现,代码如下:

template<class T>
class CVariantPack
{
private: CVariantPack(void){}; ~CVariantPack(void){}; public: static bool SetTPtrVariant(VARENUM ElementType,const std::vector<T>& vecData,VARIANT &vdata)
{
try
{
if(vecData.empty())
{
return false;
}
SAFEARRAYBOUND rgsabound[1];
rgsabound[0].lLbound = 0;
rgsabound[0].cElements = (ULONG)vecData.size(); SAFEARRAY *psa = SafeArrayCreate(ElementType,1, rgsabound );
if( psa )
{
for( long i=0; i<(long)vecData.size(); i++ )
{
SafeArrayPutElement( psa, &i, (void *)(&vecData[i]));
}
vdata.vt = VT_ARRAY|ElementType;
vdata.parray = psa;
SafeArrayUnaccessData( psa );
return true;
}
else
{
return false;
}
}
catch(...)
{
return false;
}
} static int GetTPtrVariant (VARENUM ElementType,std::vector<T>& vecData,const VARIANT vdata)
{
try
{
if( vdata.vt==VT_NULL || vdata.vt==VT_EMPTY )
{
return -1;
}
if( !(vdata.vt & VT_ARRAY) )
{
return -2;
}
SAFEARRAY *psa = vdata.parray;
UINT nDims = SafeArrayGetDim( psa );
if( nDims != 1 )
{
return -3;
}
//检查数组元素类型
VARTYPE vt = 0;
SafeArrayGetVartype( psa, &vt );
if( vt != ElementType )
{
return -4;
}
//检查数组上下限和元素个数是否为偶数个
LONG lUBound =0, lLBound = 0;
SafeArrayGetUBound( psa, 1, &lUBound );
SafeArrayGetLBound( psa, 1, &lLBound );
int lElements = lUBound - lLBound + 1;
if( lElements <= 0 )
{
return -5;
}
T *pTmp = NULL;
SafeArrayAccessData( psa, (void **)&pTmp );
if( NULL == pTmp )
{
return -6;
}
for (int i = 0;i<lElements;i++)
{
vecData.push_back(*(pTmp+i));
} SafeArrayUnaccessData( psa );
return lElements;
}
catch(...)
{
return -1;
};
} };

测试函数如下:

bool TestVariantPack1(void)
{
std::vector<long> a;
a.push_back(1);
a.push_back(2);
a.push_back(3);
VARIANT vdata;
//long 数组封装到variant
if( !CVariantPack<long>::packtptrvariant(v_long,a,3,vdata))
{
return false;
}
std::vector<long> b;
//从variant获取long数组数据
int num= CVariantPack<long>::GetTPtrVariant(VT_I4,b,vdata);
if( num<=0 )
{
return false;
}
}

下面再谈谈字符串数组的相互转换。

// std::vector< std::wstring>转换为一个VARIANT对象
bool StringArrayToVariant(const std::vector< std::wstring >& vecData,VARIANT& vdata)
{
if(vecData.empty())
{
return false;
} SAFEARRAY *psa;
SAFEARRAYBOUND rgsabound;
rgsabound.cElements = (ULONG)vecData.size();
rgsabound.lLbound = 0;
psa = SafeArrayCreate(VT_BSTR, 1, &rgsabound);//设置为一位BSTR数组
if( psa )
{
BSTR* bstrArray;
::SafeArrayAccessData(psa,(void**)&bstrArray);//将数据引出进行操作,并加锁
for (int i = 0 ; i < vecData.size(); ++i)
{
// bstrArray[i] = arExport[i].AllocSysString(); // 如果是std::vector<CString>,请用这句代码
bstrArray[i] = const_cast<TCHAR*>(vecData[i].c_str());
} vdata.vt = VT_ARRAY|VT_BSTR;
vdata.parray = psa;
::SafeArrayUnaccessData(psa);
return true;
}
return false;
} //VARIANT对象转换为std::vector< std::wstring>
int VariantToStringArray(const VARIANT& vdata,std::vector<std::wstring >& vecData)
{
if( vdata.vt==VT_NULL || vdata.vt==VT_EMPTY )
{
return -1;
}
if( !(vdata.vt & VT_ARRAY) )
{
return -2;
}
SAFEARRAY *psa = vdata.parray;
UINT nDims = SafeArrayGetDim( psa );
if( nDims != 1 )
{
return -3;
}
//检查数组元素类型
VARTYPE vt = 0;
SafeArrayGetVartype( psa, &vt );
if( vt != VT_BSTR )
{
return -4;
}
//检查数组上下限和元素个数是否为偶数个
LONG lUBound =0, lLBound = 0;
SafeArrayGetUBound( psa, 1, &lUBound );
SafeArrayGetLBound( psa, 1, &lLBound );
int lElements = lUBound - lLBound + 1;
if( lElements <= 0 )
{
return -5;
}
BSTR* pTmp = NULL;
SafeArrayAccessData( psa, (void **)&pTmp );
if( NULL == pTmp )
{
return -6;
}
for (int i = 0;i<lElements;i++)
{
vecData.push_back(*(pTmp+i));
} SafeArrayUnaccessData( psa );
return lElements;
}

这里需要注意的是,com只支持unicode字符,所以对应的stl字符串数组类型为std::vector<std::wstring>。

测试函数如下:

bool TestVariantPack(void)
{
std::vector<std::wstring> vecString;
vecString.push_back(_T("HelloWorld"));
vecString.push_back(_T(","));
vecString.push_back(_T("I am from China!")); VARIANT vdata;
// std::vector<std::wstring> 数组封装到variant
if( !SysUtility::StringArrayToVariant(vecString,vdata))
{
return false;
}
std::vector<std::wstring> vecString2;
//从variant获取std::vector<std::wstring>数组数据
int num= SysUtility::VariantToStringArray(vdata,vecString2);
if( num<=0 )
{
return false;
}
return true;
}

参考文献:

1. 关于在C#中调用MFC编写Activex控件中传入字符串数组的有关问题

最新文章

  1. js 连续赋值。。理解不了,先占坑
  2. vs2012中使用Icenium开发应用
  3. windows下安装git &amp; 在git@OSC上推送代码
  4. C# 通过后台获取浏览器域名
  5. 解决play framework play控制台乱码问题
  6. centos7虚拟机无法上网的解决办法
  7. SQL中查询优化的主要策略
  8. HTML5之 离线数据存储
  9. SQL Server 2008导入、导出数据库
  10. JavaScript 中的正常任务与微任务
  11. 在sql server中怎样获得正在执行的Sql查询
  12. 移动平台Unity3D 应用性能优化
  13. vue 路由参数
  14. es6 promise对象
  15. centos7 安装redis服务及phpredis扩展
  16. vue.js安装问题
  17. IIS错误提示:另一个程序正在使用此文件 进程无法访问
  18. 我的WAF Bypass实战系列
  19. mfc 动态分配内存
  20. Python加密模块-pycryptodome

热门文章

  1. Redis学习笔记(四) 基本命令:String操作
  2. POJ 3628 01背包 OR 状压
  3. 最简单的启动并连接一个redis的docker容器
  4. onmouse事件与mouse事件
  5. struts2中各个jar包的具体作用
  6. Guitar Pro中文版下载,你想要的,都在这啦!
  7. docker mysql pxc集群(percona-xtradb-cluster)
  8. POJ 2774 Long Long Message (后缀数组+二分)
  9. shell 测试命令
  10. Opencv 视频转为图像序列