Swift:属性(节)的宏

Swift:属性(节)的宏,swift,swift2,metaprogramming,mach-o,Swift,Swift2,Metaprogramming,Mach O,这是一个奇怪而不快速的通灵问题,请耐心听我说。 我想在Swift中做一些类似于我目前在Objective-C/C++中所做的事情,所以我将从描述它开始 我有一些C++代码,定义了宏,当它在代码中的任何地方使用时,会在编译时在二进制表中插入一个条目。换句话说,用户编写的内容如下: #include "magic.h" void foo(bool b) { if (b) { printf("%d\n", MAGIC(xyzzy)); } } 00000000000

这是一个奇怪而不快速的通灵问题,请耐心听我说。
我想在Swift中做一些类似于我目前在Objective-C/C++中所做的事情,所以我将从描述它开始

我有一些C++代码,定义了宏,当它在代码中的任何地方使用时,会在编译时在二进制表中插入一个条目。换句话说,用户编写的内容如下:

#include "magic.h"

void foo(bool b) {
    if (b) {
        printf("%d\n", MAGIC(xyzzy));
    }
}
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
func foo(b: Bool) -> Void {
    struct Local { static var xyzzy = 0; };
    println(Local.xyzzy);
}
多亏了这个定义

#define MAGIC(Name) \
  []{ static int __attribute__((used, section("DATA,magical"))) Name; return Name; }()
编译时实际发生的情况是,创建一个名为
xyzy
(modulo name mangling)的静态变量,并将其分配到Mach-O二进制文件的特殊
magical
部分,因此运行
nm-m foo.O
转储符号时会显示如下情况:

#include "magic.h"

void foo(bool b) {
    if (b) {
        printf("%d\n", MAGIC(xyzzy));
    }
}
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
func foo(b: Bool) -> Void {
    struct Local { static var xyzzy = 0; };
    println(Local.xyzzy);
}
通过
getsectbynamefromheader()
的魔力,我可以加载
magic
部分的符号表,扫描它,并发现(通过对我找到的每个符号进行求索)在用户代码的某个点,他调用了
magic(xyzy)
。尤里卡


我可以在Swift中很好地复制整个工作流的后半部分-从
getsectbynamefromheader()
部分开始。然而,第一部分让我感到困惑

  • Swift没有预处理器,因此无法像
    magic(someidentifier)
    那样优雅地拼写魔法。不过我不想太难看

  • 据我所知,Swift无法将符号插入到给定的节中-没有与
    \uuuuu attribute\uuuuu((节))
    等效的符号。不过这没关系,因为我的计划中没有什么需要专门的章节;这一部分只会让下半场更容易

  • 据我所知,在Swift中将符号放入符号表的唯一方法是通过本地结构定义。大概是这样的:

    #include "magic.h"
    
    void foo(bool b) {
        if (b) {
            printf("%d\n", MAGIC(xyzzy));
        }
    }
    
    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
    
    func foo(b: Bool) -> Void {
        struct Local { static var xyzzy = 0; };
        println(Local.xyzzy);
    }
    
这是可行的,但需要额外键入一点内容,并且不能在表达式中内联完成(如果我们不能在Swift中生成
MAGIC
宏,这并不重要),我担心Swift编译器可能会对其进行优化


所以,这里有三个问题,都是关于如何让Swift做Swift不想做的事情:宏、属性和创建抵抗编译器优化的符号

我知道
@asmname
,但我认为这对我没有帮助,因为我已经可以自己处理需求了

<>我知道Swift有“泛型”,但它们似乎比java模板更接近C++模板;我认为在这种特殊情况下,它们不能替代宏


我知道Swift编译器的代码;我白白地略过了一点点;但我无法通读所有的内容,寻找可能根本不存在的技巧。

以下是关于预处理器(和宏)的问题的答案

斯威夫特没有预处理器,因此不可能像magic(someidentifier)一样优雅地拼写magic。不过我不想太难看

Swift项目有一个预处理器(但是,恕我直言,它不是用Swift的二进制文件分发的)

来自
swift用户
邮件列表:

它是Swift的预处理器 团队这样写,当他们需要构建,比如说,十个几乎相同的 Int的变体,它们不必复制和粘贴相同的内容 编码十次。如果你打开其中一个文件,你会看到它们是 主要是Swift代码,但混合了一些用Python编写的代码行

它没有C宏那么漂亮,但是更强大。 克隆swift的git repo后,您可以使用
/swift/utils/gyb--help
命令查看可用的命令

$ swift/utils/gyb --help
用法等(TL;DR)

示例模板:
-你好-
%{
x=42
def成功(a):
返回a+1
}%
我可以向你保证${x}<${such(x)}
%如果int(y)>7:
%对于范围(3)中的i:
y大于7!
%结束
%其他:
y小于或等于7
%结束
-结束-
当以“gyb-Dy=9”运行时,输出为
-你好-
我可以向你保证42<43
y大于7!
y大于7!
y大于7!
-结束-
我的GYB使用示例可以在上找到


有关更复杂的示例,请在中查找
*.swift.gyb
文件。

我觉得swift对于此类工作来说太高了。C的存在是有原因的。@BryanChen:该解决方案允许调用C/ObjC函数。但是它必须可以从Swift中使用,因为这是应用程序/业务逻辑代码编写的语言,而应用程序/业务逻辑是需要使用
MAGIC
的语言。也就是说:“在Objective-C中编写
MAGIC
的部分实现”在这种情况下是可以接受的答案(但显然需要充实实现细节)。“继续在Objective-C中编写所有应用程序逻辑,以便继续使用旧的
MAGIC
”在这种情况下是不可接受的答案。