将VARIANT转换为字节,反之亦然
Convert VARIANT to bytes and vise versa?
我需要能够在系统注册表中保存一个VARIANT(用于COM自动化),然后稍后从那里读取它。
我认为最简单的方法是将其转换为字节数组,然后保存它(并反过来处理)。问题是我不想开始实现VARIANT可能包含的所有数据类型(包括对象和数组)的所有可能性。
所以我很好奇是否有办法做到这一点?(即序列化一个VARIANT)
在这里找到了这个解决方案。它没有覆盖所有的角落,但它是目前为止我见过的最接近的:
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;
}
相关文章:
- 从不同线程使用int64的不同字节安全吗
- 在C++中,是否可以基于给定的标识符创建基类的新实例,反之亦然
- 将Integer转换为4字节的unsined字符矢量(按大端字节顺序)
- 在UNIX系统中使用DIR查找文件的字节大小
- 如何使用Crypto++并为RSA返回可打印的字节/字符数组
- std::当在256字节边界上写入整数时,流的奇怪行为
- 当比特(而不是字节)的顺序至关重要时的持久性
- 从文件中读取多个字节,并将它们存储在C++中进行比较
- 如何在文件中查找字节序列
- luaL_dofile在已知良好的字节码上失败,可以使用未编译的版本
- 字节到位运算符重载C++
- 在java中读取c++字节的位字段
- 在C++中,将int值赋给enum,反之亦然
- 使用 std::vector::reverse_iterator 将 int 序列化为字节向量?
- 将 char[] 数组转换为字节,然后将字节转换为 int,反之亦然
- 将字节数组 (uint8_t) 转换为单词数组 (uint16_t),反之亦然
- Qt是否有一种将字节转换为int的方法,反之亦然
- C++-独立于平台的函数,用于将字节数组转换为值,反之亦然
- 将字节数转换为灰度,反之亦然
- 将VARIANT转换为字节,反之亦然