C+中的GUID常量+;(在特定的奥威尔开发-C+;+;) < >我把很多插件从Delphi翻译成C++,每个插件都用GUID识别。

C+中的GUID常量+;(在特定的奥威尔开发-C+;+;) < >我把很多插件从Delphi翻译成C++,每个插件都用GUID识别。,c++,guid,C++,Guid,在Delphi中,这个常量看起来非常好: const GUID_PLUGIN_ABC_V1: TGUID = '{6C26245E-F79A-416C-8C73-BEA3EC18BB6E}'; P>在我的C++翻译中,我需要做如下: static const GUID GUID_PLUGIN_ABC_V1 = {0x6C26245E, 0xF79A, 0x416C, { 0x8C, 0x73, 0xBE, 0xA3, 0xEC, 0x18, 0xBB, 0x6E} }; 这很烦人,

在Delphi中,这个常量看起来非常好:

const
  GUID_PLUGIN_ABC_V1: TGUID = '{6C26245E-F79A-416C-8C73-BEA3EC18BB6E}';
<> P>在我的C++翻译中,我需要做如下:

static const GUID GUID_PLUGIN_ABC_V1 =
  {0x6C26245E, 0xF79A, 0x416C, { 0x8C, 0x73, 0xBE, 0xA3, 0xEC, 0x18, 0xBB, 0x6E} };
这很烦人,因为有两件事:

  • 这对我来说很难翻译,因为我需要手动拆分我的GUID,并且存在出错的风险(因此提供了错误的GUID)

  • 由于源代码是公共的,我确实希望人们使用人类可读的GUID,例如用于web上的研究等。 因此,我需要在常量上方添加注释:

    // {6C26245E-F79A-416C-8C73-BEA3EC18BB6E}
    static const GUID GUID_PLUGIN_ABC_V1 =
      {0x6C26245E, 0xF79A, 0x416C, { 0x8C, 0x73, 0xBE, 0xA3, 0xEC, 0x18, 0xBB, 0x6E} };
    
  • 现在我有以下问题:

  • 对于这个任务(对于现有的guid),是否有一个好的转换器
  • 有没有一个工具可以用这个常量符号创建新的guid
  • 有没有可能使用宏,比如

    static const GUID GUID_PLUGIN_ABC_V1 =
      GUIDMACRO('{6C26245E-F79A-416C-8C73-BEA3EC18BB6E}')
    
    ?


  • GUID与COM无关。

    您可以使用用户定义的文字:

    #include <array>
    #include <cstring>
    #include <iostream>
    
    struct Guid
    {
        uint32_t a = 0;
        uint16_t b = 0;
        uint16_t c = 0;
        uint16_t d = 0;
        std::array<uint8_t, 6> e;
    };
    
    Guid operator "" _guid (const char* s, std::size_t n)
    {
        if(n == 38)
        {
            // Parse and consider byte order (endian).              
            // Provide something reasonable to replace this:
            if(std::strncmp(s, "{6C26245E-F79A-416C-8C73-BEA3EC18BB6E}", 36) == 0)
            {
                Guid result;
                result.a = 0x6C26245E;
                result.b = 0xF79A;
                result.c = 0x416C;
                result.d = 0x8C73;
                result.e = { 0xBE, 0xA3, 0xEC, 0x18, 0xBB, 0x6E };
                return result;
            }
        }
        // Invalid
        return Guid();
    }
    
    int main()
    {
        Guid guid = "{6C26245E-F79A-416C-8C73-BEA3EC18BB6E}"_guid;
        std::cout << std::hex
            << guid.a << "-"
            << guid.b << "-"
            << guid.c << "-"
            << guid.d << "-"
            << "array\n";
    }
    
    #包括

    编辑:解析

    #include <array>
    #include <cctype>
    #include <cstdint>
    #include <cstdlib>
    #include <cstring>
    
    #pragma pack(push, 0)
    struct Guid
    {
      std::uint32_t data1;
      std::uint16_t data2;
      std::uint16_t data3;
      std::array<uint8_t, 8> data4;
    };
    #pragma pack(pop)
    
    // A guid with the format "01234567-89ab-cdef-0123-456789abcdef"
    // If the guid string is invalid the resulting guid is an empty guid.
    // Note: The first three fields of the guid are stored in a host byte order.
    //       and the last two fields are stored in a single array (big endian)
    Guid operator "" _guid (const char* s, std::size_t n)
    {
        // Hexadecimal character test.
        struct IsXDigit
        {
            bool result = true;
            IsXDigit(const char*& p, unsigned n)
            {
                while(n--) {
                    char c =  *p++;
                    // char may be signed or unsigned
                    if(c < 0 || 128 <= c || ! std::isxdigit(c)) {
                        result = false;
                        break;
                    }
                }
            }
            operator bool () const { return result; }
        };
    
        Guid result;
    
        // Syntax
        const char* p = s;
        if( ! IsXDigit(p,  8)) goto Failure;
        if(*p++ != '-') goto Failure;
        if( ! IsXDigit(p,  4)) goto Failure;
        if(*p++ != '-') goto Failure;
        if( ! IsXDigit(p,  4)) goto Failure;
        if(*p++ != '-') goto Failure;
        if( ! IsXDigit(p,  4)) goto Failure;
        if(*p++ != '-') goto Failure;
        if( ! IsXDigit(p, 12)) goto Failure;
        if(*p)  goto Failure;
    
        // Data
        result.data1 = std::uint32_t(std::strtoul(s, nullptr, 16));
        result.data2 = std::uint16_t(std::strtoul(s + 9, nullptr, 16));
        result.data3 = std::uint16_t(std::strtoul(s + 14, nullptr, 16));
        char buffer[3];
        buffer[2] = 0;
        for(unsigned dst = 0, src = 19; src < 23; ++dst, src += 2)
        {
            buffer[0] = s[src];
            buffer[1] = s[src + 1];
            result.data4[dst] =  std::uint8_t(std::strtoul(buffer, nullptr, 16));
        }
        for(unsigned dst = 2, src = 24; src < 36; ++dst, src += 2)
        {
            buffer[0] = s[src];
            buffer[1] = s[src + 1];
            result.data4[dst] =  std::uint8_t(std::strtoul(buffer, nullptr, 16));
        }
        return result;
    
        Failure:
        std::memset(&result, 0, sizeof(result));
        return result;
    }
    
    
    #include <iostream>
    #include <iomanip>
    
    int main()
    {
        const Guid guid = "6C26245E-F79A-416C-8C73-BEA3EC18BB6E"_guid;
        std::cout.fill('0');
        std::cout
            << std::hex
            << "6C26245E-F79A-416C-8C73-BEA3EC18BB6E\n"
            << std::setw(8) << guid.data1 << "-"
            << std::setw(4) << guid.data2 << "-"
            << std::setw(4) << guid.data3 << "-";
        for(unsigned i = 0; i < 2; ++i)
            std::cout << std::setw(2) << unsigned(guid.data4[i]);
        std::cout << "-";
        for(unsigned i = 2; i < 8; ++i)
            std::cout << std::setw(2) << unsigned(guid.data4[i]);
        std::cout << '\n';
    }
    
    #包括
    #包括
    #包括
    #包括
    #包括
    #pragma包(推送,0)
    结构Guid
    {
    标准:uint32_t数据1;
    标准:uint16_t数据2;
    标准:uint16_t数据3;
    std::数组数据4;
    };
    #布拉格语包(流行语)
    //格式为“01234567-89ab-cdef-0123-456789abcdef”的guid
    //如果guid字符串无效,则生成的guid为空guid。
    //注意:guid的前三个字段以主机字节顺序存储。
    //最后两个字段存储在一个数组中(big-endian)
    Guid运算符“”\u Guid(常量字符*s,标准::大小\u t n)
    {
    //十六进制字符测试。
    结构IsXDigit
    {
    布尔结果=真;
    IsXDigit(常量字符*&p,无符号n)
    {
    而(n--){
    字符c=*p++;
    //字符可以是有符号的,也可以是无符号的
    
    如果(c<0 | | 128因为您只是以不同的格式从一个文本转换到另一个文本,那么Regex find and replace将非常适用于此。以下是在Notepad++中开发和测试的。不同的编辑器(如Visual Studio)可能有不同的Regex规则,但基本原理是相同的

    搜索:

    const ([\w]+)\: TGUID = '\{(.{8})-(.{4})-(.{4})-(..)(..)-(..)(..)(..)(..)(..)(..)\}';
    
    替换为:

    static const GUID $1 = {0x$2, 0x$3, 0x$4, { 0x$5, 0x$6, 0x$7, 0x$8, 0x$9, 0x$10, 0x$11, 0x$12} };
    
    我无法解释使用正则表达式搜索的所有细节,但需要了解的基本情况是,搜索字符串“capture”中的括号是行的匹配区域,在替换字符串$1、$2等中插入捕获的内容

    例如,第一组括号是
    ([\w]+)
    。它用于捕获GUID的名称(
    GUID\u PLUGIN\u ABC\u V1
    )。要分解它,
    [\w]
    表示“匹配所有单词字符”,而
    +
    表示“匹配一个或多个前面的字符”。括号捕获它,$1将名称添加到替换字符串中。
    ({8})
    组是“匹配任意字符8次”,而
    (…)
    是猪鼻子…但是说真的,
    表示“任意字符”,所以
    (…)
    只匹配两个字符

    请注意,此regex find and replace选项假定所有传入的GUID字符串都有效,并遵循以下格式:

    const <GUID NAME>: TGUID = '{<GUID STRING>}';
    
    const:TGUID='{}';
    

    如果有任何变化,对正则表达式的轻微更改可以解释这些变化。最糟糕的情况是,您有一些不同的搜索和替换字符串,基于您的各种GUID格式。

    看看这篇SO帖子,它似乎有您要找的答案:@DavidHaim这条评论绝对没有必要,也没有帮助。在VC++中问题也一样。关于Dev-C++:它是一个很好的工具,适用于小项目,尤其是插件,它们只有一个小的DLL文件。与VC++相比,Dev-C++总是开箱即用地运行和编译(感谢MinGW GCC编译器)。@YePhIcK,尽管这个函数在我的计算机(Win10)上工作微软声明这是针对CLSID的,但是我的GUID与COM无关,因此没有注册。该方法可能会失败。这将有助于GUIDFromString的功能,但微软出于某些原因表示不赞成。将Delphi格式转换成新的C++格式的代码可以用基本的,尽管长的正则表达式实现。关于查找和替换。让我看看是否可以创建它并作为答案发布。我不太了解运算符
    \u guid
    的作用。我要转换的guid已经用此方法写入。因此guid在代码中是3倍,2倍为字符串,1倍为拆分结构(我希望避免)。因此,此方法转换已转换为硬编码的内容?此代码允许您复制和粘贴Delphi GUI,但您必须将其替换为“和append _GUID实际的问题是我不想手动编写像
    result.a=0x6C26245E;
    这样的东西。@如果您必须解析字符串,我忽略了在上面的示例中,我试图将您的函数用于实际的数据类型GUID(在WinAPI的guiddef.h中定义),其定义如下:。因此,我将签名更改为
    GUID operator”“\u GUID(const char*s,std::size\t n)
    ,但我得到的编译器错误[error]与“operator=”不匹配(操作数类型为“GUID{aka_GUID}”和“const char[39]”