将 VARIANT 转换为字节,反之亦然? [复制]

Posted

技术标签:

【中文标题】将 VARIANT 转换为字节,反之亦然? [复制]【英文标题】:Convert VARIANT to bytes and vise versa? [duplicate] 【发布时间】:2014-05-05 04:49:17 【问题描述】:

我需要能够在系统注册表中保存VARIANT(用于 COM 自动化),然后再从那里读回。

我认为最简单的方法是将其转换为字节数组,然后保存(并以相反的方式反转该过程。)问题是我不想开始为所有VARIANT 可能包含的数据类型(包括对象和数组)。

所以我很好奇是否有办法做到这一点? (即序列化一个 VARIANT。)

【问题讨论】:

我认为使用一些带有 RPC 支持功能的工具,包括 VARIANT_UserSizeVARIANT_UserMarshalVARIANT_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 转换为字节,反之亦然? [复制]的主要内容,如果未能解决你的问题,请参考以下文章

将字节转换为 dart 中的位,反之亦然

图像到字节数组到字符串(反之亦然)

将字节数组转换为 tagVARIANT 数组

将字节数组放入 JSON,反之亦然

如何在 Swift 5 中将“日期”转换为“数据”,反之亦然? [复制]

将音频、mp3 文件转换为字符串,反之亦然