可以将新的Clang Objective-C文字重定向到自定义类吗?

时间:2012-06-28 20:28:41

标签: objective-c clang objective-c-literals

虽然@的超载开始在危险的领域上进行,但我喜欢在Clang 3.1中添加新的Objective-C文字。不幸的是,新的文字对我来说是有限的用途。除了代码需要与AppKit接口的情况之外,我大多放弃使用Foundation类来支持我自己的自定义框架(出于各种原因;其中大部分是我需要直接控制所使用的内存分配模式通过对象)。

我总是可以使用一些运行时技巧来将新创建的对象作为我的自定义类传递(并且我已经与字符串对象文字有关,因为只有非Apple GCC运行时才支持-fconstantstring=class flag),但这是一个充其量的黑客,并且通过替换等效的Foundation类来获得我获得的所有好处。

与字符串对象文字不同,新文字Clang实现实际上不是常量类(内存布局是硬编码的);而是将适当的消息发送到它们各自的类,以在运行时创建和初始化新对象。效果与您自己创建对象的效果没什么不同。理论上,它意味着使用的类和新文字调用的方法不是硬编码的。在实践中我找不到任何方法来改变它们以指向我自己的自定义类和方法(实际上我只是想指向一个自定义类;在运行时将虚拟方法指向实际方法并不困难)。

当我第一次看到这个时,我真的希望找到一组可以用来做我要求的标志,但是由于我没有发现任何标志,我希望有人有解决方案。

2 个答案:

答案 0 :(得分:12)

您可以使用@compatibility_alias关键字技巧替换某些Objective-C文字的类。

这是一个例子。

@compatibility_alias NSNumber AAA;

当然,您应该为新班级提供适当的实施。

#import <Foundation/NSObject.h>

@interface  AAA : NSObject
+ (id)numberWithInt:(int)num;
@end

@implementation AAA
+ (id)numberWithInt:(int)num
{
    return  @"AAAAA!!!";    // Abused type system just to check result.
}
@end

@compatibility_alias NSNumber AAA;

现在,Clang将为您完成这项工作。我确认这适用于数字,数组,字典文字。不幸的是,字符串文字似乎是静态发出的,所以它不起作用。

有关@compatibility_alias关键字的更多信息,see here

注意

因为@compatibility_alias关键字是适用于当前编译单元的编译器指令,所以需要将编译单元分开以避免与Apple的Foundation Kit中的NSObject类重复符号。我就是这样做的。

的main.m

#import "test.h" // Comes before Foundation Kit.
#import <Foundation/Foundation.h>

int main(int argc, const char * argv[])
{
    @autoreleasepool
    {
        NSLog(@"return of test = %@", test());
        // insert code here...
        NSLog(@"Hello, World!");

    }
    return 0;
}

test.h

id test();

test.m

#import "test.h"
#import <Foundation/NSObject.h>

@interface  
AAA : NSObject
+ (id)numberWithInt:(int)v;
+ (id)arrayWithObjects:(id*)pobj count:(int)c;
+ (id)dictionaryWithObjects:(id*)pvals forKeys:(id*)pkeys count:(int)c;
@end
@implementation AAA
+ (id)numberWithInt:(int)v
{
    return  @"AAAAA as number!!!";
}
+ (id)arrayWithObjects:(id*)pobj count:(int)c
{
    return  @"AAAAA as array!!!";
}
+ (id)dictionaryWithObjects:(id*)pvals forKeys:(id*)pkeys count:(int)c
{
    return  @"AAAAA as dictionary!!!";
}
@end



@compatibility_alias NSDictionary AAA;
@compatibility_alias NSArray AAA;
@compatibility_alias NSNumber AAA;



id test()
{
//  return  @{};
//  return  @[];
    return  @55;
}

结果。

2013-03-23 08:54:42.793 return of test = AAAAA!!!
2013-03-23 08:54:42.796 Hello, World!

答案 1 :(得分:11)

这些评论都是正确的,但总结一下:

  • 没有

Apple的@{}@[]@""文字的含义被硬编码到Clang中。你可以在这里看到它:http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/AST/NSAPI.cpp?view=markup它完全是模块化的,这意味着Clang黑客不难添加她自己的文字语法......但“模块化”并不意味着“可以从外部访问” ”。添加新语法甚至将现有语法重定向到新类肯定需要自己重建Clang。

这是一篇博客文章,介绍如何通过黑客入侵其内部来向Clang添加NSURL文字:http://www.stuartcarnie.com/2012/06/llvm-clang-hacking-part-3.html(谢谢@Josh Caswell)


如果您愿意使用带有C ++ 11扩展的Objective-C ++,您可以使用“用户定义的文字”,这样您就可以编写类似

的内容
NSURL *operator ""URL (const char *s) { return [NSURL URLWithString: @(s)]; }

int main() {
    ...
    NSURL *myurl = "ftp://foo"URL;
    ...
}

Mike Ash博客的评论中提到了这一点。 http://www.mikeash.com/pyblog/friday-qa-2012-06-22-objective-c-literals.html但这看起来不是很客观C-ish(或非常C ++ ish!),它只适用于Objective-C ++ 11编译器,一般请不要这样做。 :)