这是一个奇怪的和un-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
(modulo name-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)
。Eureka 了
我可以在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
,但我不认为它对我有帮助,因为我已经可以自己处理demangling了。
我知道Swift有“泛型”,但它们似乎更接近Java泛型,而不是C++模板;我不认为在这种特殊情况下它们可以代替宏。
我知道Swift编译器的代码is now open-source;我已经白读了一点但是我不能通读所有的内容来寻找可能根本不存在的技巧。
2条答案
按热度按时间qco9c6ql1#
下面是关于预处理器(和宏)的问题的答案。
Swift没有预处理器,所以不可能像MAGIC(someidentifier)那样优雅地拼写magic。但我不想弄得太难看
Swift项目有一个预处理器(但是,AFAIK,它没有与Swift的二进制文件一起分发)。
来自
swift-users
邮件列表:What are .swift.gyb files?
这是Swift团队编写的一个预处理器,这样当他们需要构建10个几乎相同的Int变体时,他们就不必复制和粘贴相同的代码10次。如果你打开其中一个文件,你会看到它们主要是Swift代码,但是有一些代码行是用Python编写的。
它不像C宏那么漂亮,但是,恕我直言,它更强大。你可以在克隆Swift的git repo后使用
./swift/utils/gyb --help
命令查看可用的命令。用法等(TL; DR)...
我的GYB使用示例可以在GitHub.Gist上获得。
更复杂的例子可以在@apple/swift/stdlib/public/core中查找
*.swift.gyb
文件。oknrviil2#
Recently添加了两个带下划线的属性
@_used
和@_section
,它们分别相当于__attribute__(used)
和__attribute__(section)
。据我所知,这只是swift的开发快照,并由实验性功能标志SymbolLinkageMarkers
保护。