2015-12-26 6 views
22

Das ist eine Art von einer seltsamen und un-schnell-thonic Frage, also ertragen Sie mit mir.
Ich möchte in Swift so etwas machen, was ich gerade in Objective-C/C++ mache, also fange ich damit an, das zu beschreiben.Swift: Makro für __attribute __ ((Abschnitt))

Ich habe einige vorhandenen C++ - Code, der ein Makro definiert, das bei der Verwendung in einem Ausdruck irgendwo im Code einen Eintrag in eine Tabelle in der Binärdatei zur Kompilierzeit einfügen wird. Mit anderen Worten, schreibt der Benutzer etwas wie folgt aus:

#include "magic.h" 

void foo(bool b) { 
    if (b) { 
     printf("%d\n", MAGIC(xyzzy)); 
    } 
} 

und dank der Definition

#define MAGIC(Name) \ 
    []{ static int __attribute__((used, section("DATA,magical"))) Name; return Name; }() 

was bei der Kompilierung tatsächlich passiert ist, dass eine statische Variable genannt xyzzy (Modulo name-Mangeln) wird erstellt und in den speziellen Bereich magical meiner Mach-O-Binärdatei zugewiesen, so dass nm -m foo.o ausgeführt wird, um die Symbole auszugeben, zeigt etwas in der folgenden Reihenfolge:

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 

Durch die Magie von getsectbynamefromheader(), kann ich die Symboltabelle für den magical Abschnitt lädt dann, Scan durch, und finden Sie heraus (durch Demangling jedes Symbols finde ich) zu einem bestimmten Zeitpunkt in dem Code des Benutzers, dass er MAGIC(xyzzy) nennt. Eureka!


kann ich die ganze zweite Hälfte dieses Workflow ganz gut in Swift replizieren - mit dem getsectbynamefromheader() Teil beginnen. Der erste Teil hat mich jedoch ratlos gemacht.

  • Swift hat keine Präprozessor, so die Magie Schreibweise so elegant wie MAGIC(someidentifier) unmöglich ist. Ich möchte aber nicht, dass es zu hässlich ist.

  • So weit ich weiß, hat Swift keine Möglichkeit, Symbole in einen bestimmten Abschnitt einzufügen - kein Äquivalent von __attribute__((section)). Dies ist jedoch in Ordnung, da nichts in meinem Plan erfordert einen dedizierten Abschnitt; dieser Teil erleichtert die zweite Hälfte.

  • Soweit ich weiß, ist die einzige Möglichkeit, ein Symbol in die Symboltabelle in Swift zu bekommen, über eine lokale Strukturdefinition. Etwas wie folgt aus:

    func foo(b: Bool) -> Void { 
        struct Local { static var xyzzy = 0; }; 
        println(Local.xyzzy); 
    } 
    

das funktioniert, aber es ist ein bisschen mehr schreiben, und kann nicht inline in einem Ausdruck durchgeführt werden (nicht, dass das wird wichtig, wenn wir keine MAGIC machen Makro in Swift sowieso), und ich bin besorgt, dass der Swift-Compiler es optimieren könnte.


So gibt es drei Fragen hier, alles darüber, wie Swift machen Dinge zu tun, die Swift will nicht tun: Makros, Attribute und Symbole zu schaffen, der Compiler-Optimierung resistent sind.

Ich bin bewusst, @asmname aber ich denke nicht, dass es mir hilft, da ich schon mit dem Entmutigen allein fertig werden kann.

Ich bin mir bewusst, dass Swift "Generika" hat, aber sie scheinen näher an Java-Generics als an C++ - Vorlagen zu sein; Ich glaube nicht, dass sie in diesem speziellen Fall als Ersatz für Makros verwendet werden können.

Ich bin mir bewusst, dass der Code für den Swift-Compiler is now open-source; Ich habe Teile davon umsonst überflogen; aber ich kann nicht lesen alle davon auf der Suche nach Tricks, die möglicherweise nicht da sein.

+0

Ich fühle Swift ist einfach zu hoch für solche Art von Arbeit. C existiert aus einem bestimmten Grund. –

+0

@BryanChen: Die Lösung darf den Aufruf einer C/ObjC-Funktion beinhalten. Aber es muss von Swift benutzbar sein, denn das ist die Sprache, in der der Anwendungs-/Geschäftslogik-Code geschrieben ist, und die Anwendungs-/Geschäftslogik ist diejenige, die die "MAGIC" verwenden muss. Das heißt: "Teile der Implementierung von MAGIC in Objective-C schreiben" ist in diesem Zusammenhang eine akzeptable Antwort (aber die Details der Implementierung müssen offensichtlich konkretisiert werden). "Schreiben Sie weiterhin Ihre gesamte Anwendungslogik in Objective-C, so dass Sie weiterhin die alte MAGIC verwenden können" ist * keine * akzeptable Antwort in diesem Zusammenhang. – Quuxplusone

Antwort

1

Hier ist die Antwort auf Ihre Frage zu Präprozessor (und Makros).

Swift hat keinen Präprozessor, daher ist das Buchstabieren der Magie so elegant wie MAGIC (someidentifier) ​​unmöglich. Ich möchte aber nicht, dass es zu hässlich ist.

Swift-Projekt hat einen Präprozessor (aber, AFAIK, ist es nicht mit Swifts binär verteilt).

Von swift-users Mailingliste:

What are .swift.gyb files?

Es ist ein Präprozessor die Swift Team geschrieben, so dass, wenn sie bauen benötigt, sagen wir, zehn fast identische Varianten von Int, sie wouldn‘ Ich muss den Code zehnmal kopieren und einfügen. Wenn Sie eine dieser Dateien öffnen, werden Sie feststellen, dass sie hauptsächlich Swift-Code sind, aber mit einigen Codezeilen vermischt, die in Python geschrieben sind.

Es ist nicht so schön wie C-Makros, aber, IMHO, ist leistungsfähiger. Sie können die verfügbaren Befehle mit dem Befehl ./swift/utils/gyb --help nach dem Klonen des Swift's Git Repos sehen.

$ swift/utils/gyb --help 

Nutzung, etc (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. - 

Mein Beispiel GYB Verwendung GitHub.Gist zur Verfügung steht. Für komplexere Beispiele suchen Sie nach *.swift.gyb Dateien in @apple/swift/stdlib/public/core.

Verwandte Themen