Search code examples
c++boost

How to convert Windows GUID to boost::uuid?


I tried to get string for Windows GUID, but failed by using boost::uuid. The result is exact as this post Boost uuid + boost endian said, byte order wrong.

void foo(GUID& g)
{
  boost::uuids::uuid * u = reinterpret_cast<boost::uuids::uuid*>(&g);
  std::string ustr = boost::lexical_cast<std::string>(*u);
}

Finally, I used this post Convert GUID structure to LPCSTR to complete my convert.

But I am still curious,

  1. Is there some elegant methods to convert any types to boost's ?
  2. If there is, is there out-of-shelf libs for Windows' ?

Solution

  • u = reinterpret_cast<boost::uuids::uuid*>(g);
    

    I believe you should take the address of g in the reinterpret_cast:

    u = reinterpret_cast<boost::uuids::uuid*>(&g);
    

    Even if you do take the address, I think you have other troubles. Microsoft uses double words and words in their GUID structure, while Boost uses bytes.

    Microsoft:

    typedef struct _GUID {
        DWORD Data1;  WORD Data2;  WORD Data3;  BYTE Data4[8];
    } GUID;
    

    Boost:

    struct uuid
    {
        ...
    public:
        // or should it be array<uint8_t, 16>
        uint8_t data[16];
    };
    

    I believe you need to perform an explicit conversion with something like:

    void MsToBoostUuid(const GUID& ms, boost::uuids::uuid& bst)
    {
        bst.data[0] = static_cast<uint8_t>(ms.Data1 >> 24);
        bst.data[1] = static_cast<uint8_t>(ms.Data1 >> 16);
        bst.data[2] = static_cast<uint8_t>(ms.Data1 >>  8);
        bst.data[3] = static_cast<uint8_t>(ms.Data1 >>  0);
    
        bst.data[4] = static_cast<uint8_t>(ms.Data2 >> 8);
        bst.data[5] = static_cast<uint8_t>(ms.Data2 >> 0);
    
        bst.data[6] = static_cast<uint8_t>(ms.Data3 >> 8);
        bst.data[7] = static_cast<uint8_t>(ms.Data3 >> 0);
    
        bst.data[8] = ms.Data4[0];
        bst.data[9] = ms.Data4[1];
        ...
        bst.data[14] = ms.Data4[6];
        bst.data[15] = ms.Data4[7];
    }
    
    void foo(const GUID& g)
    {
      boost::uuids::uuid u;
      MsToBoostUuid(g, u);
    
      std::string ustr = boost::lexical_cast<std::string>(*u);
    }
    

    You can also add operators, like:

    inline bool operator==(const& uuid lhs, const GUID& rhs)
    {
        boost::uuids::uuid t;
        MsToBoostUuid(rhs, t);
        return std::equal(lhs.begin(), lhs.end(), t.begin());
    }
    
    inline bool operator==(const GUID& lhs, const& uuid rhs)
    {
        boost::uuids::uuid t;
        MsToBoostUuid(lhs, t);
        return std::equal(t.begin(), t.end(), rhs.begin());
    }
    

    ... the result is exact as this post Boost uuid + boost endian said, byte order wrong.

    I believe the currently accepted answer is incorrect. I believe Dutton's answer is correct, but it does not show you a typical conversion between UUID types.