Port C-Code mit vielen Typecasts zu Swift

Mit Swift können Sie vorhandene C-Bibliotheksaufrufe und Systemaufrufe normal aufrufen. Dies ist aus der Sicht der Verwendung früherer Assets richtig, aber da Swift typenstrenger als C ist, ist es nicht ungewöhnlich, dass Probleme beim Aufrufen von C-Funktionen auftreten.

Dieses Mal habe ich das dritte Argument start_routine von pthread_create von der C-Funktion bis zum Schließen von Swift umgeschrieben. Ich hoffe, es ist hilfreich zu sehen, was mit dem Code passiert, der in C in Swift typisiert wird.

(Da ich ein Anfänger von Swift bin, lassen Sie mich bitte wissen, wenn es Fehler gibt.)

Vorausgesetztes Wissen

pthread_create erstellt einen neuen Thread und übergibt den Funktionszeiger der im neuen Thread auszuführenden Funktion mit dem dritten Argument start_routine. Die Funktionsargumente und Rückgabewerte sind "void *". Wenn Sie also verschiedene Arten von Argumenten und Rückgabewerten verwenden möchten, müssen Sie sowohl für den Aufrufer als auch für den Angerufenen eine Typumwandlung durchführen.

Es ist eine C-ähnliche Idee, etwas "ungültig" zu machen, aber natürlich passt es nicht gut zu Swift.

Original C Quellcode

Dieses Mal wollte ich eine Funktion verwenden, die "int" und "char **" als Argumente verwendet und "int" (kurz gesagt, es ist eine "main" -Funktion) von "pthread_create" zurückgibt, daher habe ich dafür eine Wrapper-Funktion verwendet. Ich habe es in C geschrieben.

void *pthread_main_routine(void *_arg)
{
    void **arg = (void **)_arg;
    int argc = (int)arg[0];
    char **argv = (char**)arg[1];
    void *retval = (void *)(long)orig_main(argc, argv);
    return retval;
}

Auf der Swift-Seite wurde dies wie folgt genannt.

    var thread_arg = [
        UnsafeMutablePointer<Void>(bitPattern: args.pointers.count-1),
        UnsafeMutablePointer<Void>(args.pointers)
    ]
    pthread_create(&thread, nil, pthread_main_routine, &thread_arg)

Ich habe versucht, es mit Swifts Schließung umzuschreiben

Es funktionierte auch im obigen Code, aber aus verschiedenen Gründen habe ich die C-Funktion durch einen Swift-Verschluss ersetzt.

    typealias VoidPtr = UnsafeMutablePointer<Void>
    typealias VoidPtrArray = [UnsafeMutablePointer<Void>]
    typealias CharPtrArray = [UnsafeMutablePointer<CChar>]
    let thread_arg = [
        unsafeBitCast(args.pointers.count-1, VoidPtr.self),
        unsafeBitCast(args.pointers, VoidPtr.self),
    ]
    pthread_create(&thread, nil, {_arg in
        let arg = unsafeBitCast(_arg, VoidPtrArray.self)
        let argc = Int32(unsafeBitCast(arg[0], Int.self))
        let argv = unsafeBitCast(arg[1], CharPtrArray.self)
        let retval = unsafeBitCast(Int(orig_main(argc, argv)), VoidPtr.self)
        return retval
        }, unsafeBitCast(thread_arg, VoidPtr.self))

Ich habe es geschafft, etwas zu machen, das mit viel "unsafeBitCast" funktioniert, aber der Code ist ziemlich langweilig und schwer zu lesen. Code, der in C einfacher zu schreiben ist, sollte in C geschrieben werden.

Beachten Sie übrigens, dass die zu übergebenden Inhalte geringfügig unterschiedlich sind, je nachdem, ob das Swift-Array in den beiden Codes in "void *" oder "char **" in "void *" konvertiert wird.

Beschwerden etc.

Die Behandlung von C-Funktionen in Swift2 ist nicht gut, und nur der globale Funktionsname selbst oder das Abschlussliteral können in das dritte Argument dieses pthread_create eingefügt werden. Wenn Sie einer Variablen eine Funktion zuweisen und diese Variable als Argument angeben, wird wie folgt ein Kompilierungsfehler angezeigt.

A C function pointer can only be formed from a reference to a 'func' or a literal closure

Schreiben Sie auch keinen Code, der von der Umgebung abhängt, auch wenn es sich um ein Abschlussliteral handelt. Wenn Sie beispielsweise innerhalb des Abschlusses auf eine Instanzvariable verweisen, wird ein Kompilierungsfehler angezeigt (siehe unten).

A C function pointer cannot be formed from a closure that captures context

Ich habe das Gefühl, dass dem letzteren nicht geholfen werden kann, aber was ist mit dem ersteren? Ich fühle mich so. Ich hoffe, dass Swift3 hier einfacher zu handhaben ist.

Recommended Posts

Port C-Code mit vielen Typecasts zu Swift
[swift5] So ändern Sie die Farbe der TabBar oder die Farbe des TabBar-Elements mit Code
Konvertieren Sie eine Zeichenfolge mit swift in ein zeichenweises Array
Übergang zu einem View Controller mit Swift WebKit
So erhalten Sie die ID eines Benutzers, der sich in Swift bei Firebase authentifiziert hat
So implementieren Sie UICollectionView mit Code nur in Swift
Fügen Sie Ihrem Projekt mit Swift PM ein lokales Swift-Paket hinzu
Eine Geschichte, die von String () von Interface abhängig ist und von JdkDynamicAopProxy vertreten wird
Eine Reihe von Schritten zum Erstellen von Ergebnissen für Portfolios mit Rails
So verschieben Sie eine andere Klasse mit einer Schaltflächenaktion einer anderen Klasse.
Ein Memo zum Starten der Java-Programmierung mit VS Code (Version 2020-04)
Übergeben Sie C-Sprache char * an Swift
Verschwenderische Verarbeitung von Sammlungen - ich möchte Ihnen die Möglichkeit geben, guten Code zu schreiben. 5 [C # Refactoring Sample]
Versuchen Sie, die Idee eines zweidimensionalen Arrays mit einem eindimensionalen Array nachzuahmen
Eine Geschichte über die Verbindung zu einem CentOS 8-Server mit einem alten Ansible
Erstellen Sie einen C-Compiler zur Verwendung mit Rust x CLion mit Docker
Beispielcode zum Testen eines Spring Boot-Controllers mit MockMvc
[Mit Beispielcode] Grundlagen von Spring JDBC mit der Blog-App gelernt
So öffnen Sie eine Skriptdatei von Ubuntu mit VS-Code
[Swift] So senden Sie eine Benachrichtigung
Um auf einfach zu lesenden Code zu achten
Rufen Sie C-Sprachfunktionen von Swift aus auf
Konvertieren Sie das 2D-Array von Swift in das 2D-Array von C.
Eine Aufzeichnung zum Einrichten einer Java-Entwicklungsumgebung mit Visual Studio Code
[iOS] Ich habe versucht, mit Swift eine insta-ähnliche Verarbeitungsanwendung zu erstellen
Schienen c starten nicht und es tritt eine große Anzahl von Leitungsfehlern auf
So erstellen Sie eine App mit einem Plug-In-Mechanismus [C # und Java]
[Swift] Konvertiert eine Ganzzahl vom Typ UInt64 in [UInt8]
Konvertieren Sie die C-Sprache mit Emscripten in JavaScript
Verknüpfen Sie Java- und C ++ - Code mit SWIG
[Swift 5] Implementierung der Mitgliederregistrierung in Firebase
So rufen Sie Swift 5.3-Code von Objective-C auf
Extrahieren Sie einen Teil einer Zeichenfolge in Ruby
[Swift5] So erstellen Sie einen Begrüßungsbildschirm
So führen Sie Blazor (C #) mit Docker aus
Ich habe versucht, mit HCE-F von Android eine Funktion zu implementieren, die Felica Lite entspricht
Volume, das viele logische Operatoren in der if-Anweisung verwenden möchte
Der Name ist und das Alter ist Senden Sie eine Benachrichtigung an Slack mit der Java-freien Version von Sentry (mit Lambda)
Rails6 Ich möchte ein Array von Werten mit einem Kontrollkästchen erstellen
Durchbrechen Sie gewaltsam das C-Problem "* 3 oder / 2" von [AtCoder Problem-ABC100] mit Java [Code]
[Spring Boot] Wenn Sie Spring Boot verwenden, war es praktisch, viele Dienstprogramme zu verwenden.
Ich habe versucht, eine Webanwendung voller Fehler mit Spring Boot zu klonen
Vom Erstellen eines Spring Boot-Projekts bis zum Ausführen einer Anwendung mit VS Code
[Swift] Ich habe bereits viele Informationen, aber ich habe versucht, die Besetzung (as, as !, As?) Auf meine eigene Weise zusammenzufassen.