问题的提出:
近期在编程时,需要将数组表示的数据通过ActiveX或COM控件接口传入到控件的内部,由于ActiveX或COM控件接口是跨语言的,故不能将ActiveX或COM控件接口的参数简单地定义为指针。为了支持跨语言访问,必须将ActiveX或COM控件接口的参数定义为变体类型,即VARIANT。代码如下:
调用方:
// 组织数据
m_plDataBuf = new LONG[nDataCnt]; auto_ptr<LONG> ptrDataBuf(m_plDataBuf);
// 给数组赋值 for(vector<int>::size_type i = 0; i < nDataCnt; ++i) { m_plDataBuf[i] = vtData[i]; } // 将数据通过VARIANT的SAFEARRAY数组传入。其中m_varBuffer为VARIANT类型 m_pArray = NULL; // m_pArray 为SAFEARRAY* 类型 HRESULT hr = SafeArrayAllocDescriptor(1, &m_pArray);//创建SAFEARRAY结构的对象 m_pArray->cDims = 1; // 数组维数 m_pArray->cbElements = sizeof(LONG); // 每个元素占用的字节数 m_pArray->rgsabound[0].cElements = nDataCnt; // 第0维的元素个数 m_pArray->rgsabound[0].lLbound = 0; // 第0维数组起始下标 m_pArray->pvData = m_plDataBuf; // 真实的数据 m_pArray->fFeatures =FADF_AUTO|FADF_FIXEDSIZE; //FADF_AUTO指定在栈上分配数据,并且大小不可以改变 m_varBuffer.vt = (VT_ARRAY | VT_VARIANT); // 注意:SAFEARRAY的类型格式必须是这样 m_varBuffer.parray = m_pArray; // 将普通数据赋值给SAFEARRAY数组。
// 设置数据源。m_spMeSampleCE为ActiveX或COM控件接口类,SetDataSource为接口类方法 m_spMeSampleCE->SetDataSource(m_varBuffer);
被调用方:ActiveX或COM控件接口函数设计:
VARIANT_BOOL CECGView::SetDataSource(VARIANT &varDataBuf) { AFX_MANAGE_STATE(AfxGetStaticModuleState()); if(varDataBuf.vt != ((VT_ARRAY | VT_VARIANT))) // 数据类型不是SAFEARRAY类型 return VARIANT_FALSE;
ClearDataSource(); LONG uHighBound = 0, uLowBound = 0;
// 获取数据个数 ::SafeArrayGetLBound(varDataBuf.parray, 1, &uLowBound); ::SafeArrayGetUBound(varDataBuf.parray, 1, &uHighBound); m_nBufLen = uHighBound - uLowBound + 1;
// m_pDataBuf不能自己new出来。SafeArrayAccessData函数内部会new出一个,所以下句注释的代码是不能要的,否则出错。
// m_pDataBuf = new LONG [m_nBufLen ]; HRESULT hr = SafeArrayAccessData(varDataBuf.parray, (void**)&m_pDataBuf); if(FAILED(hr)) return VARIANT_FALSE;
// 注意:只有取出来的数据m_pDataBuf 用完后才能调用这个函数,该函数调用后会使m_pDataBuf 缓冲区无效。
// SafeArrayUnaccessData(m_parray);
return VARIANT_TRUE; }
|