Objective-C方法中布尔类型参数的奇怪“选择器混淆”

3

我需要在运行时通过反射调用动态恢复方法名称,但是对于某些方法得到了奇怪的结果。

我的 TestClass 包含一个类似以下的方法:

- (void)testMethod6_NSRect:(NSRect)a1 int:(int)a2 int:(int)a3 bool:(Boolean)a4 {
    ...
}

当使用class_copyMethodList()枚举上述类的方法并通过method_getName()获取方法选择器时,我得到:

"testMethod6_NSRect:int:int:_Bool:" 

因此,选择器在某种程度上被重写(由gcc?)以从“bool”生成“_Bool”。就我所测试的而言,这似乎仅针对“bool”选择器部分完成 - 如果我将其更改为int:(int),如下所示:
- (void)testMethod1_int:(int)a1 int:(int)a2 int:(int)a3 int:(int)a4 {
    ...
}

我得到了预期的结果:

"testMethod1_int:int:int:int:"

问: 有人知道这个“选择器重写”的规则,或者我可以在哪里找到这些规则的指针吗?这只适用于“bool”吗? 我还需要知道这种行为是否取决于gcc版本、osx版本或运行时库版本。

我正在使用(gcc --version): i686-apple-darwin10-gcc-4.2.1(GCC)4.2.1(Apple Inc.构建5666)(点3) 在一个(uname -a) 10.8.0 Darwin内核版本10.8.0:


这很有趣;我猜测GCC看到bool并将其转换为其底层类型名称,没有意识到它是选择器的一部分。你尝试过切换到Clang编译器吗? - Dave DeLong
1
尝试在方法中打印_cmd。此外,如果可能的话,应该使用llvm。 - bbum
2个回答

4
问题出在C99标准头文件<stdbool.h>中一个丑陋的预处理器技巧上:
#define bool _Bool

C99定义了一个名为_Bool的类型,它的行为类似于C++中的bool类型。 这个定义是为了能够在C中使用它,但保留了C++标识符。

解决方案:

#undef bool

谢谢 - 这就是问题所在;虽然我认为这是gcc的一个bug,让选择器部分通过预处理器进行翻译 - 而不是整个选择器... 但是由于我无法控制加载的类(二进制),我可能不得不假设,这已经发生在任何已编译的类中...(我想知道还有多少这样的错误翻译已经进入了二进制文件中...) - blabla999
这是所有符合 cpp(C 预处理器)实现的问题:预处理器根本不理解语言。您可以轻松找到其他示例,其中它不会执行您期望的操作。因此,不,这不是一个错误,而是预期且依赖的行为。尽管很烦人,但仍然如此。 - Nikolai Ruhe
2
如果你打算通过预处理器指令来翻译选择器会怎么样?预处理器就是它本身,一个不了解语言的文本处理器。这不是一个 bug,它按照规定的方式运行。 - ipmcc

0
尝试使用BOOL而不是Boolean。

相同的行为。这似乎是选择器的一个功能,而不是参数类型。另外,由于我无法控制需要反映的代码,因此我无法防止出现具有这种名称的方法(即使它确实有所区别,它看起来也不像是解决我的问题的通用解决方案)... - blabla999

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接