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

  • 相关阅读:
    002-数据库命名开发规范
    006-多线程-基础-同步解决 概述【ReentrantLock、Semaphore、CyclicBarrier、CountDownLatch】
    005-多线程-基础-sleep、join、yield、wait、notify、notifyAll、run、start、synchronized
    004-多线程-基础-同步问题引出、同步问题解决、死锁、生产者与消费者
    003-多线程-基础-其他【命名和取得、休眠、优先级、线程状态、线程中断】
    002-多线程-基础-实现方式【thread、runnable、callale、thread和runnable对比】
    001-多线程-基础-进程线程、线程状态、优先级、用户线程和守护线程
    001-Spring在代码中获取bean的几种方式
    004-mysql explain详解
    java-序列化-001-原生介绍
  • 原文地址:https://www.cnblogs.com/lanzhi/p/6470090.html
Copyright © 2020-2023  润新知