作者:朱金灿

来源: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控件中传入字符串数组的有关问题

STL数组和com数组相互转换的做法的更多相关文章

  1. hdu5438 Ponds[DFS,STL vector二维数组]

    目录 题目地址 题干 代码和解释 参考 题目地址 hdu5438 题干 代码和解释 解答本题时参考了一篇代码较短的博客,比较有意思,使用了STL vector二维数组. 可以结合下面的示例代码理解: ...

  2. 关于数组和List之间相互转换的方法

    1.List转换成为数组:返回数组的运行时类型.如果列表能放入指定的数组.否则,将根据指定数组.如果指定的数组的元素比列表的多),那么会将存储列表元素的数组. 返回:包含列表元素的list.add(& ...

  3. C语言数组:C语言数组定义、二维数组、动态数组、字符串数组

    1.C语言数组的概念 在<更加优美的C语言输出>一节中我们举了一个例子,是输出一个 4×4 的整数矩阵,代码如下: #include <stdio.h> #include &l ...

  4. 【嵌入式开发】C语言 指针数组 多维数组

    . 作者 : 万境绝尘 转载请注明出处 : http://blog.csdn.net/shulianghan/article/details/21402047 . 1. 地址算数运算示例 指针算数运算 ...

  5. 数组转集合、集合转数组、字符串数组与int型、long型数组等的转换

    在项目中经常会遇到数组转集合.集合转数组.数组之间类型转换等操作 1.数组转集合 为了实现把一个数组转换成一个ArrayList,很多Java程序员会使用如下的代码: String str[] = { ...

  6. C语言 指针数组 多维数组

    . 作者 : 万境绝尘 转载请注明出处 : http://blog.csdn.net/shulianghan/article/details/21402047 . 1. 地址算数运算示例 指针算数运算 ...

  7. PHP如何判断一个数组是一维数组或者是二维数组?用什么函数?

    如题:如何判断一个数组是一维数组或者是二维数组?用什么函数? 判断数量即可 <?php if (count($array) == count($array, 1)) { echo '是一维数组' ...

  8. 数组去重及数组的prototype原型

    Array.prototype.check= function(){ for(var i=0;i<this.length;i++){ for(var j=i+1;j<this.length ...

  9. PChar,PAnsiChar,String,AnsiString,Char数组,AnsiChar数组转换

    PChar,PAnsiChar,String,AnsiString,Char数组,AnsiChar数组之间的转换关系见下图 通过转换链,可以实现任意两个类型之间的互转.如PChar转PAnsiChar ...

随机推荐

  1. BZOJ 3667 Pollard-rho &Miller-Rabin

    论O(1)快速乘和O(logn)快速乘的差距-. //By SiriusRen #include <cstdio> #include <algorithm> using nam ...

  2. POJ 1543 暴搜

    题意:输出a^3=b^3+c^3+d^3的所有a,b,c,d的值. b,c,d由小到大且b,c,d都大于1. 思路: 按照题意写就好.... // by SiriusRen #include < ...

  3. node-express项目的搭建并通过mongoose操作MongoDB实现增删改查分页排序(四)

    最近写了一个用node来操作MongoDB完成增.删.改.查.排序.分页功能的示例,并且已经放在了服务器上地址:http://39.105.32.180:3333. Mongoose是在node.js ...

  4. 基于mysql主从同步的proxy读写分离

    mysql-proxy 简介 MySQL Proxy是一个处于你的client端和MySQL server端之间的简单程序,它可以监测.分析或改变它们的通信.它使用灵活,没有限制,常见的用途包括:负载 ...

  5. eclipse 启动程序时错误弹窗:multiple problems have occurred

    .log内容如下: !ENTRY org.eclipse.ui 4 4 2017-04-14 09:31:05.341!MESSAGE An internal error has occurred.! ...

  6. css3动画机制原理和实战

    这段时间喜欢上css3动画效果了,关于这个每个人都有不同的看法,在我个人看来css3在做一些小页面的动画效果还是很好用的,一些简单的小动画要是用js的话,未免浪费. 要是做大一点的话最好js+css3 ...

  7. Eclipse安装不了AXIS2 Tool插件,总是找不到axis2 wizards的问题找到解决答案(转载)

    http://blog.csdn.net/downmoon/article/details/7309485 最近在学习axis2工作需要,google一搜,网上到处都是装axis2插件的.根据网上的直 ...

  8. jq——html,text,val和对象访问

    html代码 1.html():获取的是对象内的html代码,类似于innerHTML 2.html(代码):设置html的内容,替换 $("div").html("hh ...

  9. Django路由中的include

    include(module,namespace = None,app_name = None)[source] include(pattern_list) include((pattern_list ...

  10. DRF lazy Serializer

    class LazySerializer: def __init__(self, cls_name, **kwargs): self.cls_name = cls_name self.kwargs = ...