将Objective-C枚举常量转换为字符串名称

时间:2013-08-06 18:41:12

标签: objective-c xcode llvm lldb

以前,这是不可能的(你必须手工编写全部/创建静态数组/将所有值放入字典并将其读回...等等)

但我注意到最新的Xcode的lldb(4.6,也许早期的版本)会自动将枚举常量转换为字符串。

我的问题是我们使用了很多库 - 包括Apple自己的库! - 使用烦人的公共枚举,没有提供“价值到字符串”的方法。所以我最终不得不(多次,多次)做“好吧,因为图书馆作者先生没有这样做,现在我必须为他们制作静态数组......”。

我一直希望苹果公司能够提供一条出路 - 这最终会在这里吗?或者这只是调试器可以做的一些技巧 - 仅运行时代码无法访问它吗?

2 个答案:

答案 0 :(得分:3)

lldb没有关于打印枚举名称的任何特殊功能。我认为你所看到的是枚举值记录在调试信息中的结果(或不是)。例如,

enum myenums {a = 0, b, c};
int main ()
{
 enum myenums var = b;
 return (int) var;  // break here
}

% xcrun clang -g a.c
% xcrun lldb a.out
(lldb) br s -p break
Breakpoint 1: where = a.out`main + 18 at a.c:5, address = 0x0000000100000f92
(lldb) r
[...]
-> 5     return (int) var;  // break here
   6    }
(lldb) p var
(myenums) $0 = b
(lldb) p (myenums) 0
(myenums) $1 = a
(lldb) 

如果查看此二进制文件的调试信息(dwarfdump a.out.dSYM),您会看到变量var的类型为myenums,调试信息包含这些值的值枚举类型:

0x0000005a:     TAG_enumeration_type [5] *
                 AT_name( "myenums" )
                 AT_byte_size( 0x04 )
                 AT_decl_file( "/private/tmp/a.c" )
                 AT_decl_line( 1 )

0x00000062:         TAG_enumerator [6]  
                     AT_name( "a" )
                     AT_const_value( 0x0000000000000000 )

0x00000068:         TAG_enumerator [6]  
                     AT_name( "b" )
                     AT_const_value( 0x0000000000000001 )

0x0000006e:         TAG_enumerator [6]  
                     AT_name( "c" )
                     AT_const_value( 0x0000000000000002 )

如果我在我的示例文件中添加了另一个枚举,但未在任何地方使用,

enum myenums {a = 0, b, c};
enum otherenums {d = 0, e, f}; // unused in this CU
int main ()
{
 enum myenums var = b;
 return (int) var;  // break here
}

重新编译并通过dwarfdump再次查看DWARF,我找不到任何描述otherenums的调试信息 - 它未被使用(在此编译单元中),因此它被省略。< / p>

答案 1 :(得分:3)

如前所述,除了调试器之外,编译后无法访问常量名称。我想,H2CO3对TO_STR()宏的建议可以帮助你完成大部分用途。

我最近在研究libclang并决定通过解决你关于从枚举值转换为字符串的苦差事的投诉来解决这个问题(你必须手工编写所有内容/创建静态数组/将所有值放入一本字典,然后把它们读回......等等)“。

这是一个Python脚本,它将解析Cocoa文件,找到枚举(包括用NS_OPTIONSNS_ENUM定义的那些),并吐出一个数组或一个函数(使用{{1 })来做映射。数组选项利用名为"designated (array) initializers"的C功能,从而可以将数组成员与特定索引显式配对:

switch

请注意,这是稀疏数组 - 仍然创建最后一个之前的任何非指定索引,并使用0进行初始化。这意味着枚举旨在用作位掩码,其中值为int arr[] = { [1] = 2, [3] = 8, [7] = 12 }; 1 << 21 << 3等等,将为相对较少的已使用值创建相当大的数组。在这些情况下,函数可能是更好的选择。

匿名1 << 4(我认为它们都是单一成员,至少在基金会中)使用常量名称直接转换为单个enum。我已经尝试过自动处理负值的常量,比如NSString - 数组初始化程序中的负索引将无法编译,但函数/ NSOrderedAscending替代方法可以正常工作;你只需要为这几种情况手动选择。

脚本为up on GitHub,此处为完整版。麻省理工学院许可证,你也喜欢它。我很乐意听到任何修改。

switch