Swift:__attribute的宏__((section))

时间:2015-12-26 04:26:32

标签: swift swift2 metaprogramming mach-o

这是一个奇怪的,不是斯威夫特式的问题,所以请耐心等待 我想在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静态变量(模名称修改)并将其分配到我的Mach的特殊magical部分O二进制,因此运行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);
    }
    

虽然有效,但它有点额外打字,并且无法在表达式中内联完成(如果我们无法生成{{1,那就不重要了无论如何,在Swift中都有宏),我担心Swift编译器可能会优化它。

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

我知道MAGIC但我不认为它对我有帮助,因为我已经可以自己解决这个问题。

我知道Swift有#34; generics",但它们似乎更接近Java泛型而不是C ++模板;在这种特殊情况下,我不认为它们可以用作宏的替代品。

我知道Swift编译器is now open-source的代码;我徒劳地撇去了一些东西;但是我无法通过所有来阅读它甚至可能不存在的技巧。

1 个答案:

答案 0 :(得分:2)

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

  

Swift没有预处理器,因此像MAGIC(someidentifier)一样优雅地拼写魔法是不可能的。不过,我不希望它过于丑陋。

Swift项目有一个预处理器(但是,AFAIK,它没有随Swift的二进制文件一起发布)。

来自swift-users邮件列表:

What are .swift.gyb files?

  

这是Swift的预处理器   团队写作,以便当他们需要建立,比如,十几乎相同   Int的变体,他们不必逐字复制和粘贴相同的   代码十次。如果你打开其中一个文件,你会发现它们是   主要是Swift代码,但有一些代码行混合在一起,用Python编写。

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

$ swift/utils/gyb --help

用法等(TL; DR)...

Example template:

      - Hello -
    %{
         x = 42
         def succ(a):
             return a+1
    }%

    I can assure you that ${x} < ${succ(x)}

    % if int(y) > 7:
    %    for i in range(3):
    y is greater than seven!
    %    end
    % else:
    y is less than or equal to seven
    % end

      - The End. -

When run with "gyb -Dy=9", the output is

      - Hello -

    I can assure you that 42 < 43

    y is greater than seven!
    y is greater than seven!
    y is greater than seven!

      - The End. -

我在GitHub.Gist上提供了GYB使用示例。

有关更复杂的示例,请在@apple/swift/stdlib/public/core中查找*.swift.gyb个文件。