【发布时间】:2016-03-31 19:48:42
【问题描述】:
这是一个奇怪且非 Swift-thonic 的问题,请耐心等待。
我想在 Swift 中做一些与我目前在 Objective-C/C++ 中做的事情一样的事情,所以我将首先描述它。
我有一些现有的 C++ 代码定义了一个宏,当在表达式代码中的任何位置 中使用该宏时,将在编译时将一个条目插入到二进制文件的表中。换句话说,用户写的是这样的:
#include "magic.h"
void foo(bool b) {
if (b) {
printf("%d\n", MAGIC(xyzzy));
}
}
感谢定义
#define MAGIC(Name) \
[]{ static int __attribute__((used, section("DATA,magical"))) Name; return Name; }()
在编译时实际发生的是一个名为xyzzy(模名称-mangling)的静态变量被创建并分配到我的Mach-O二进制文件的特殊magical部分,所以运行nm -m foo.o 来转储符号显示了很多类似这样的内容:
0000000000000098 (__TEXT,__eh_frame) non-external EH_frame0
0000000000000050 (__TEXT,__cstring) non-external L_.str
0000000000000000 (__TEXT,__text) external __Z3foob
00000000000000b0 (__TEXT,__eh_frame) external __Z3foob.eh
0000000000000040 (__TEXT,__text) non-external __ZZ3foobENK3$_0clEv
00000000000000d8 (__TEXT,__eh_frame) non-external __ZZ3foobENK3$_0clEv.eh
0000000000000054 (__DATA,magical) non-external [no dead strip] __ZZZ3foobENK3$_0clEvE5xyzzy
(undefined) external _printf
通过getsectbynamefromheader() 的魔力,我可以加载magical 部分的符号表,扫描它,并找出(通过分解我找到的每个符号)在用户代码中的某个位置,他致电MAGIC(xyzzy)。尤里卡!
我可以在 Swift 中很好地复制整个工作流程的后半部分——从 getsectbynamefromheader() 部分开始。然而,第一部分让我很难过。
Swift 没有预处理器,因此不可能像
MAGIC(someidentifier)那样优雅地拼写魔法。不过,我不希望它太丑。据我所知,Swift 无法将符号插入给定的部分——没有
__attribute__((section))的等价物。不过这没关系,因为我的计划中没有任何内容需要专门的部分;那部分只是让下半场变得更容易。-
据我所知,在 Swift 中将符号放入符号表的唯一方法是通过本地结构定义。像这样的:
func foo(b: Bool) -> Void { struct Local { static var xyzzy = 0; }; println(Local.xyzzy); }
这行得通,但它有点额外的输入,并且不能在表达式中内联完成(如果我们无论如何都不能在 Swift 中创建 MAGIC 宏,那就没关系了),而且我'我担心 Swift 编译器可能会将其优化掉。
所以,这里有三个问题,都是关于如何让 Swift 做 Swift 不想做的事情:宏、属性和创建抵抗编译器优化的符号。
我知道@asmname,但我认为这对我没有帮助,因为我已经可以自己处理解构了。
我知道 Swift 有“泛型”,但它们似乎更接近于 Java 泛型而不是 C++ 模板;在这种特殊情况下,我认为它们不能用作宏的替代品。
我知道 Swift 编译器的代码 is now open-source;我徒劳地浏览了一些内容;但我无法通读全部,寻找可能根本不存在的技巧。
【问题讨论】:
-
我觉得 Swift 对于这样的工作来说水平太高了。 C 的存在是有原因的。
-
@BryanChen:允许解决方案涉及调用 C/ObjC 函数。但它必须可以从 Swift 中使用,因为这是编写应用程序/业务逻辑代码的语言,而应用程序/业务逻辑是需要使用
MAGIC的语言。也就是说:“在 Objective-C 中编写MAGIC的部分实现”在这种情况下是可以接受的答案(但显然需要充实实现细节)。 “继续在 Objective-C 中编写所有应用程序逻辑,以便您可以继续使用旧的MAGIC”在这种情况下不是可接受的答案。
标签: swift swift2 metaprogramming mach-o