将 VARIANT 转换为字节,反之亦然? [复制]
Posted
技术标签:
【中文标题】将 VARIANT 转换为字节,反之亦然? [复制]【英文标题】:Convert VARIANT to bytes and vise versa? [duplicate] 【发布时间】:2014-05-05 04:49:17 【问题描述】:我需要能够在系统注册表中保存VARIANT(用于 COM 自动化),然后再从那里读回。
我认为最简单的方法是将其转换为字节数组,然后保存(并以相反的方式反转该过程。)问题是我不想开始为所有VARIANT 可能包含的数据类型(包括对象和数组)。
所以我很好奇是否有办法做到这一点? (即序列化一个 VARIANT。)
【问题讨论】:
我认为使用一些带有 RPC 支持功能的工具,包括VARIANT_UserSize
、VARIANT_UserMarshal
和 VARIANT_UserUnmarshal
可能做你想做的事,但它是一个很久,因为我开始使用它们。祝你好运。
谢谢大家。似乎没有完美的解决方案,每个人都在按照自己的方式做。
【参考方案1】:
找到了这个解决方案in here。它并没有覆盖所有角落,但它是迄今为止我见过的最接近的:
STDMETHODIMP CVarToByteArrayCvt::CvtVariantToByteArray(VARIANT srcVariant, VARIANT *retval)
CComVariant vSrcData(srcVariant); // any VARIANT type
IStream *pStream;
HRESULT hRes;
STATSTG statstg;
LPBYTE buf;
ULONG cbRead, ulStreamSize;
USHORT i;
VariantClear(retval);
hRes = CreateStreamOnHGlobal(NULL, TRUE, &pStream); // IStream based on memory handler
if(hRes==S_OK)
if((vSrcData.vt & VT_ARRAY)==0) // not an array
hRes = vSrcData.WriteToStream(pStream); // writes VARIANT to a stream (array of bytes)
else // special array handling
hRes = pStream->Write(&srcVariant.vt, sizeof(VARTYPE), NULL); // stores element type
hRes = pStream->Write(&srcVariant.parray->rgsabound[0].lLbound, sizeof(LONG), NULL); // stores lower boundary
hRes = pStream->Write(&srcVariant.parray->rgsabound[0].cElements, sizeof(ULONG), NULL); // stores number of elements
LPVOID ptr;
hRes = SafeArrayAccessData(vSrcData.parray, (LPVOID *)&ptr);
switch (vSrcData.vt & (~VT_ARRAY))
case VT_UNKNOWN:
case VT_DISPATCH:
LPUNKNOWN *punkValArr = (LPUNKNOWN *)ptr;
for(i = 0; i < srcVariant.parray->rgsabound[0].cElements; i++)
CComPtr<IPersistStream> spStream;
if(punkValArr[i] != NULL)
hRes = punkValArr[i]->QueryInterface(IID_IPersistStream, (void**)&spStream);
if(spStream != NULL)
OleSaveToStream(spStream, pStream);
else
WriteClassStm(pStream, CLSID_NULL);
case VT_UI1:
case VT_I1:
BYTE *pbyteValArr = (BYTE *)ptr;
for(i = 0; i < srcVariant.parray->rgsabound[0].cElements; i++)
hRes = pStream->Write((void *)&pbyteValArr[i], sizeof(BYTE), NULL);
break;
case VT_I2:
case VT_UI2:
case VT_BOOL:
short *pshortValArr = (short *)ptr;
for(i = 0; i < srcVariant.parray->rgsabound[0].cElements; i++)
hRes = pStream->Write((void *)&pshortValArr[i], sizeof(short), NULL);
break;
case VT_I4:
case VT_UI4:
case VT_R4:
case VT_INT:
case VT_UINT:
case VT_ERROR:
long *plongValArr = (long *)ptr;
for(i = 0; i < srcVariant.parray->rgsabound[0].cElements; i++)
hRes = pStream->Write((void *)&plongValArr[i], sizeof(long), NULL);
break;
case VT_R8:
case VT_CY:
case VT_DATE:
double *pdoubleValArr = (double *)ptr;
for(i = 0; i < srcVariant.parray->rgsabound[0].cElements; i++)
hRes = pStream->Write((void *)&pdoubleValArr[i], sizeof(double), NULL);
break;
case VT_BSTR:
BSTR *pbstrValArr = (BSTR *)ptr;
for(i = 0; i < srcVariant.parray->rgsabound[0].cElements; i++)
CComBSTR bstrVal = pbstrValArr[i];
hRes = bstrVal.WriteToStream(pStream);
break;
case VT_VARIANT:
VARIANT *pvariantValArr = (VARIANT *)ptr;
for(i = 0; i < srcVariant.parray->rgsabound[0].cElements; i++)
CComVariant varVal = pvariantValArr[i];
hRes = varVal.WriteToStream(pStream);
break;
SafeArrayUnaccessData(vSrcData.parray);
;
if(hRes==S_OK)
hRes = pStream->Stat(&statstg, STATFLAG_NONAME);
if(hRes==S_OK)
ulStreamSize = (ULONG)statstg.cbSize.QuadPart;
retval->vt=VT_ARRAY|VT_UI1;
retval->parray = SafeArrayCreateVector(VT_UI1, 0, ulStreamSize);
if(retval->parray!=NULL)
hRes = SafeArrayAccessData(retval->parray, (LPVOID *)&buf);
if(hRes==S_OK)
_LARGE_INTEGER pos;
pos.QuadPart = 0;
hRes = pStream->Seek(pos, STREAM_SEEK_SET, NULL);
hRes = pStream->Read(buf, ulStreamSize, &cbRead);
SafeArrayUnaccessData(retval->parray);
;
;
;
;
pStream->Release();
;
return hRes;
STDMETHODIMP CVarToByteArrayCvt::CvtByteArrayToVariant(VARIANT srcByteArray, VARIANT *retval)
HRESULT hRes = S_OK;
LPBYTE buf;
IStream *pStream;
ULONG cbWritten;
CComVariant destVariant;
USHORT i;
VariantClear(retval);
if(srcByteArray.vt==(VT_ARRAY|VT_UI1)) // is it really a byte array
hRes = SafeArrayAccessData(srcByteArray.parray, (LPVOID *)&buf);
if(hRes==S_OK)
hRes = CreateStreamOnHGlobal(NULL, TRUE, &pStream); // IStream based on memory handler
if(hRes==S_OK)
_LARGE_INTEGER pos;
pos.QuadPart = 0;
hRes = pStream->Seek(pos, STREAM_SEEK_SET, NULL);
hRes = pStream->Write(buf, retval->parray->rgsabound[0].cElements, &cbWritten);
if(hRes==S_OK)
hRes = pStream->Seek(pos, STREAM_SEEK_SET, NULL);
VARTYPE vt;
hRes = pStream->Read((LPVOID)&vt, sizeof(VARTYPE), NULL);
if((vt & VT_ARRAY)==0) // not an array
hRes = pStream->Seek(pos, STREAM_SEEK_SET, NULL);
hRes = destVariant.ReadFromStream(pStream);
if(hRes==S_OK) VariantCopy(retval, &destVariant);
else // handling an array
retval->vt = vt;
LONG lBound;
ULONG cElems;
LPVOID ptr;
hRes = pStream->Read((LPVOID)&lBound, sizeof(LONG), NULL);
hRes = pStream->Read((LPVOID)&cElems, sizeof(ULONG), NULL);
retval->parray = SafeArrayCreateVector(vt & ~VT_ARRAY, lBound, cElems);
hRes = SafeArrayAccessData(retval->parray, &ptr);
switch (vt & (~VT_ARRAY))
case VT_UNKNOWN:
case VT_DISPATCH:
LPUNKNOWN *punkArr = (LPUNKNOWN *)ptr;
for(i = 0; i < retval->parray->rgsabound[0].cElements; i++)
punkArr[i] = NULL;
OleLoadFromStream(pStream,
((vt & VT_UNKNOWN)!=0) ? IID_IUnknown : IID_IDispatch,
(void**)&punkArr[i]);
case VT_UI1:
case VT_I1:
BYTE *pbyteValArr = (BYTE *)ptr;
for(i = 0; i < retval->parray->rgsabound[0].cElements; i++)
hRes = pStream->Read((void *)&pbyteValArr[i], sizeof(BYTE), NULL);
break;
case VT_I2:
case VT_UI2:
case VT_BOOL:
short *pshortValArr = (short *)ptr;
for(i = 0; i < retval->parray->rgsabound[0].cElements; i++)
hRes = pStream->Read((void *)&pshortValArr[i], sizeof(short), NULL);
break;
case VT_I4:
case VT_UI4:
case VT_R4:
case VT_INT:
case VT_UINT:
case VT_ERROR:
long *plongValArr = (long *)ptr;
for(i = 0; i < retval->parray->rgsabound[0].cElements; i++)
hRes = pStream->Read((void *)&plongValArr[i], sizeof(long), NULL);
break;
case VT_R8:
case VT_CY:
case VT_DATE:
double *pdoubleValArr = (double *)ptr;
for(i = 0; i < retval->parray->rgsabound[0].cElements; i++)
hRes = pStream->Read((void *)&pdoubleValArr[i], sizeof(double), NULL);
break;
case VT_BSTR:
BSTR *pbstrValArr = (BSTR *)ptr;
for(i = 0; i < retval->parray->rgsabound[0].cElements; i++)
CComBSTR bstrVal;
pbstrValArr[i] = NULL;
hRes = bstrVal.ReadFromStream(pStream);
pbstrValArr[i] = ::SysAllocString((wchar_t *)bstrVal);
break;
case VT_VARIANT:
VARIANT *pvariantValArr = (VARIANT *)ptr;
for(i = 0; i < retval->parray->rgsabound[0].cElements; i++)
CComVariant varVal;
hRes = varVal.ReadFromStream(pStream);
VariantCopy(&pvariantValArr[i], &varVal);
break;
SafeArrayUnaccessData(retval->parray);
;
;
pStream->Release();
;
SafeArrayUnaccessData(srcByteArray.parray);
;
;
return hRes;
【讨论】:
以上是关于将 VARIANT 转换为字节,反之亦然? [复制]的主要内容,如果未能解决你的问题,请参考以下文章