Travailler avec des chaînes C dans Swift, ou: Comment faire pour convertir UnsafePointer<CChar> pour CString

Tout en jouant avec le Standard de fonctions de la Bibliothèque C dans Swift, je suis tombé sur des problèmes
en passant C des chaînes autour de. Un exemple simple (juste pour illustrer le problème), la Bibliothèque Standard C de la fonction

char * strdup(const char *s1);

est exposé à Swift comme

func strdup(_: CString) -> UnsafePointer<CChar>

ce qui signifie que la valeur de retour de strdup() ne peut pas être transmis à une autre strdup() appel:

let s1 : CString = "abc"
let s2 = strdup(s1) //OK, s2 is a UnsafePointer<CChar>
let s3 = strdup(s2) // error: could not find an overload for '__conversion' that accepts the supplied arguments

Ma question est: Comment créer un Swift CString à partir d'un UnsafePointer<CChar>,
de sorte que le C de la chaîne retournée par une fonction de la bibliothèque standard peut être transmis à une autre fonction?

La seule façon que j'ai pu trouver est (en utilisant le code de Comment convertir une Chaîne de caractères à une CString de la Swift de la Langue?):

let s2a = String.fromCString(s2).bridgeToObjectiveC().UTF8String
let s3 = strdup(s2a)

Mais je ne trouve pas cela satisfaisant pour deux raisons:

  • C'est trop compliqué pour une simple tâche.
  • (Raison:) ci-dessus conversions ne fonctionne que si la chaîne C est un UTF-8 valide
    chaîne, sinon elle échoue avec une exception d'exécution. Mais une chaîne C est un arbitraire
    séquence de caractères délimitées par un caractère NUL.

Remarques/Contexte: bien sûr, des fonctions de haut niveau à l'aide de haut-niveau des structures de données comme Swift String ou Objective-C NSString sont préférables. Mais il y a des fonctions BSD dans le
Bibliothèque Standard C qui n'ont pas un équivalent exact dans la Fondation des cadres.

Je suis tombé sur ce problème tout en essayant de répondre à L'accès au répertoire temp en Swift.
Ici, mkdtemp() est un BSD fonction pour laquelle aucune NSFileManager de remplacement existe
(autant que je sache).
mkdtemp() renvoie une UnsafePointer<CChar> qui doit être transmis à la
NSFileManager fonction stringWithFileSystemRepresentation qui prend un CString
argument.


Mise à jour: de Xcode 6 beta 6, ce problème n'existe plus car la cartographie de C-Strings en Swift a été simplifiée. Il vous suffit d'écrire

let s1 = "abc"      //String
let s2 = strdup(s1) //UnsafeMutablePointer<Int8>
let s3 = strdup(s2) //UnsafeMutablePointer<Int8>
let s4 = String.fromCString(s3) // String
  • Merci à l'anonyme downvoter qui m'a rappelé, à porter la question à jour 🙂
InformationsquelleAutor Martin R | 2014-06-25