__uuidof 可以用作 C 字符串常量吗?

问题描述 投票:0回答:2

如果我在源代码中的某处定义了 UUID:

class DECLSPEC_UUID("31A0884B-2B2F-4243-B4A0-2AEFE11FDD68") MyGuidClass;

有没有办法将它用于 static const C 字符串声明? (Microsoft 特定。)

以这种形式:

static LPCWSTR kstrKeys[] =
{
    __uuidof(MyGuidClass),    //instead of this: L"31A0884B-2B2F-4243-B4A0-2AEFE11FDD68",
};
c++ visual-studio-2012 uuid
2个回答
0
投票

__uuidof 不返回字符串,而是返回 GUID。但可以在编译时将此 guid 转换为字符串。我使用 std::array 来存储字符串数据,因为这是 constexpr (即使在 C++17 中)

#include <Windows.h>
#include <array>
#include <iostream>
#include <string_view>

// compile time function to convert uuid to an array holding the string data
template<typename char_t, typename coclass_t>
static constexpr auto from_guid()
{
    // __uuidof doesn't return a string buit a GUID class
    const GUID guid{ __uuidof(coclass_t)};
    
    // conversion table from decimal values to hex characters
    std::array<char_t,16> output{'0','1','2','3','4','5','6','7','8','9','A','B','C','D','E','F'};
    std::array<char_t,39> guid_str{};
    
    // unrolled loop, it is not allowed to do type punning in constexpr
    // so I cannot have a std::uint8_t* to the start of the memory
    // of the guid. Then again it are easy byte mask operations
    guid_str[0] = '{';
    guid_str[1] = output[(guid.Data1 >> 28) & 0x0f];
    guid_str[2] = output[(guid.Data1 >> 24) & 0x0f];
    guid_str[3] = output[(guid.Data1 >> 20) & 0x0f];
    guid_str[4] = output[(guid.Data1 >> 16) & 0x0f];
    guid_str[5] = output[(guid.Data1 >> 12) & 0x0f];
    guid_str[6] = output[(guid.Data1 >>  8) & 0x0f];
    guid_str[7] = output[(guid.Data1 >>  4) & 0x0f];
    guid_str[8] = output[guid.Data1 & 0x0f];
    guid_str[9] = '-';
    guid_str[10] = output[(guid.Data2 >> 12) & 0x0f];
    guid_str[11] = output[(guid.Data2 >>  8) & 0x0f];
    guid_str[12] = output[(guid.Data2 >>  4) & 0x0f];
    guid_str[13] = output[guid.Data2 & 0x0f];
    guid_str[14] = '-';
    guid_str[15] = output[(guid.Data3 >> 12) & 0x0f];
    guid_str[16] = output[(guid.Data3 >>  8) & 0x0f];
    guid_str[17] = output[(guid.Data3 >>  4) & 0x0f];
    guid_str[18] = output[guid.Data3 & 0x0f];
    guid_str[19] = '-';
    
    std::size_t offset{20ul};
    for(std::size_t i=0; i < 8; ++i)
    {
        auto hi = guid.Data4[i] >> 4;
        auto lo = guid.Data4[i] & 0xF;

        if ( i==2 ) 
        {
            guid_str[offset++] = '-';
        }

        guid_str[offset++] = output[hi];
        guid_str[offset++] = output[lo];
    }

    guid_str[offset] = '}';

    return guid_str;
}

class __declspec(uuid("{6B8FF54A-BE2C-41A3-B9A1-5C443A1E14BB}")) MyGuidClass1 {};
class __declspec(uuid("{EA86CFEF-606C-4F9D-9EBA-9F4B40728153}")) MyGuidClass2 {};

// Let compiler create data in memory to refer to 
static constexpr auto guid1_str{ from_guid<WCHAR,MyGuidClass1>() };
static constexpr auto guid2_str{ from_guid<WCHAR,MyGuidClass2>() };

// now you can refer to the compile time string buffers.
static std::array<const WCHAR*,2> kstrKeys
{
    guid1_str.data(),
    guid2_str.data()
};

// And here is the test output
int main()
{
    std::wcout << kstrKeys[0] << L"\n";
    std::wcout << kstrKeys[1] << L"\n";

    // or just use the compile time constants directly
    std::wcout << guid1_str.data() << L"\n";
    std::wcout << guid2_str.data() << L"\n";

    return 0;
}

0
投票
can define next macros:

#define CC(m)  ((m) < 10 ? '0' + (m) : 'A' + ((m)-10))
#define UV(m) CC(((m) >> 4) & 15), CC((m) & 15)

#define DECLARE_STRING_UUID(MyClass)\
enum { \
    e0 = __uuidof(MyClass).Data1 & 0xff,\
    e1 = (__uuidof(MyClass).Data1 >> 8 ) & 0xff,\
    e2 = (__uuidof(MyClass).Data1 >> 16 ) & 0xff,\
    e3 = (__uuidof(MyClass).Data1 >> 24 ) & 0xff,\
    e4 = __uuidof(MyClass).Data2 & 0xff,\
    e5 = (__uuidof(MyClass).Data2 >> 8 ) & 0xff,\
    e6 = __uuidof(MyClass).Data3 & 0xff,\
    e7 = (__uuidof(MyClass).Data3 >> 8 ) & 0xff,\
    e8 = __uuidof(MyClass).Data4[0],\
    e9 = __uuidof(MyClass).Data4[1],\
    ea = __uuidof(MyClass).Data4[2],\
    eb = __uuidof(MyClass).Data4[3],\
    ec = __uuidof(MyClass).Data4[4],\
    ed = __uuidof(MyClass).Data4[5],\
    ee = __uuidof(MyClass).Data4[6],\
    ef = __uuidof(MyClass).Data4[7],\
};\
public:\
    inline static wchar_t szUUID[39] = {\
        '{',\
        UV(e3),\
        UV(e2),\
        UV(e1),\
        UV(e0),\
        '-',\
        UV(e5),\
        UV(e4),\
        '-',\
        UV(e7),\
        UV(e6),\
        '-',\
        UV(e8),\
        UV(e9),\
        '-',\
        UV(ea),\
        UV(eb),\
        UV(ec),\
        UV(ed),\
        UV(ee),\
        UV(ef),\
        '}',\
        0\
    };

并将其用于您的课堂:

class DECLSPEC_UUID("31A0884B-2B2F-4243-B4A0-2AEFE11FDD68") MyGuidClass
{
    DECLARE_STRING_UUID(MyGuidClass);
};

测试用:

OutputDebugStringW(MyGuidClass::szUUID);
© www.soinside.com 2019 - 2024. All rights reserved.