STL数组和com数组相互转换的做法
作者:朱金灿
来源: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数组相互转换的做法的更多相关文章
- hdu5438 Ponds[DFS,STL vector二维数组]
目录 题目地址 题干 代码和解释 参考 题目地址 hdu5438 题干 代码和解释 解答本题时参考了一篇代码较短的博客,比较有意思,使用了STL vector二维数组. 可以结合下面的示例代码理解: ...
- 关于数组和List之间相互转换的方法
1.List转换成为数组:返回数组的运行时类型.如果列表能放入指定的数组.否则,将根据指定数组.如果指定的数组的元素比列表的多),那么会将存储列表元素的数组. 返回:包含列表元素的list.add(& ...
- C语言数组:C语言数组定义、二维数组、动态数组、字符串数组
1.C语言数组的概念 在<更加优美的C语言输出>一节中我们举了一个例子,是输出一个 4×4 的整数矩阵,代码如下: #include <stdio.h> #include &l ...
- 【嵌入式开发】C语言 指针数组 多维数组
. 作者 : 万境绝尘 转载请注明出处 : http://blog.csdn.net/shulianghan/article/details/21402047 . 1. 地址算数运算示例 指针算数运算 ...
- 数组转集合、集合转数组、字符串数组与int型、long型数组等的转换
在项目中经常会遇到数组转集合.集合转数组.数组之间类型转换等操作 1.数组转集合 为了实现把一个数组转换成一个ArrayList,很多Java程序员会使用如下的代码: String str[] = { ...
- C语言 指针数组 多维数组
. 作者 : 万境绝尘 转载请注明出处 : http://blog.csdn.net/shulianghan/article/details/21402047 . 1. 地址算数运算示例 指针算数运算 ...
- PHP如何判断一个数组是一维数组或者是二维数组?用什么函数?
如题:如何判断一个数组是一维数组或者是二维数组?用什么函数? 判断数量即可 <?php if (count($array) == count($array, 1)) { echo '是一维数组' ...
- 数组去重及数组的prototype原型
Array.prototype.check= function(){ for(var i=0;i<this.length;i++){ for(var j=i+1;j<this.length ...
- PChar,PAnsiChar,String,AnsiString,Char数组,AnsiChar数组转换
PChar,PAnsiChar,String,AnsiString,Char数组,AnsiChar数组之间的转换关系见下图 通过转换链,可以实现任意两个类型之间的互转.如PChar转PAnsiChar ...
随机推荐
- python一行代码实现9x9乘法表
for i in range(1,10): for j in range(1,i+1): print('%s * %s = %s ' %(i,j,i*j),end="") prin ...
- Python笔记(五)
# -*- coding:utf-8 -*- # 函数 # python中定义函数的规则如下:以def开头,接函数名称和(),传入的参数和变量放在圆括号中间,函数以:起始,并且缩进,return选择性 ...
- dozer初探
简介 Dozer是一款javaBean的映射工具,用于解决一个类到另外一个类的自动适配功能,它即支持简单的映射,也支持复杂类型的双向递归映射(官网). 示例 举个例子,假设说我们现在有User(用户) ...
- 通过配置host,自定义域名让本地访问
最近服务器这块一直由我来维护,我们开发的项目很多域名根本没有解析,而是仅仅配置了host,就可以本地访问服务器了.感觉很有意思,于是乎,打算试一试.结果弄了许久,最后第二天才解决了.把这个艰辛的旅程记 ...
- C#---爬虫抓取系列
以前就尝试过研究了一些爬虫程序,也找过一些爬虫抓取软件,效果不是很好. 今天正好一个培训的网友给了我一个视频,正好研究下,收获颇丰.感谢那位哥们~ 1.首先讨论一下抓取一个页面 这里我写了模仿写了一个 ...
- IBM 总架构师:话说程序员的职业生涯
作者:IBM 软件集团大中华区总架构师 寇卫东 有一些年轻的程序员向我咨询,将来的路应该怎么走?俗话说,条条大路通罗马.不同的路都能走向成功.到底选哪条路,取决于自己的兴趣.可能有程序员会问:如果还没 ...
- 又一个设计工具 Framer X Preview
又一个设计工具 Framer X Preview 所说比 Sketch 和 Figma 都要好用,不知道是不是真的 ~~ To give you a little background, I've b ...
- 跨域-jsonp、cors、iframe、document.domain、postMessage()
同源策略 概念:同源: 协议.域名.端口号 完全相同 同源策略是浏览器的一种安全策略:且浏览器不会将违反同源策略的响应信息返回 http://127.0.0.1:3000/index.html ...
- CentOS 7.1 下载,安装,配置
CentOS(全称 Community Enterprise Operating System)是 RHEL 源代码再编译的产物. 2014年初,CentOS 宣布加入 Red Hat. CentOS ...
- Codeforces Round #499 (Div. 2) D. Rocket_交互题_二分
第一次作交互题,有点不习惯. 由于序列是循环的,我们可以将一半的机会用于判断当前是否是在说谎,另一半的机会用于二分的判断. 对于判断是否实在说谎,用1判断即可.因为不可能有比1还小的数. 本题虽然非常 ...