La conversion d'un C char tableau à une Chaîne
J'ai une Swift programme qui ne interop avec un C de la bibliothèque. Cette bibliothèque C renvoie une structure avec un char[]
tableau à l'intérieur, comme ceci:
struct record
{
char name[8];
};
La définition est correctement importé en Swift. Cependant, le champ est interprété comme un tuple de 8 Int8
éléments (tapé (Int8, Int8, Int8, Int8, Int8, Int8, Int8, Int8)
), dont je n'ai aucune idée de comment le transformer en un String
avec Swift.
Il n'y a pas de String
initialiseur qui accepte un Int8
tuple, et il ne semble pas possible d'obtenir un pointeur vers le premier élément du tuple (depuis que les types peuvent être hétérogènes, ce n'est pas vraiment surprenant).
Droit maintenant, ma meilleure idée est de créer une petite fonction C qui accepte un pointeur vers la structure elle-même et de retour name
comme un char*
pointeur au lieu d'un tableau, d'aller et avec qui.
Est là, cependant, sont un pur moyen rapide de le faire?
si j'étais à la recherche de comment convertir un char du C tableau à une Swift chaîne, j'aurais l'air pour les balises "c" et "swift" pour sûr.
Il n'y a rien C sur que de tableau d'octets, mais vous avoir une description valide en C, C++, objective-C, objective-C++ et ainsi de suite. Ne pas en faire une C question.
Je ne connais pas un seul qui se réfère à ces "C++ tableaux" ou "Objective-C des tableaux" ou "Objective-C++ tableaux", et je ne connais pas d'autre définition de "C tableau". Lorsque j'ai cherché une solution, j'ai utilisé "C tableau" dans mes termes de recherche, et si je suis une exception, je crois que la prochaine personne avec le même problème que va faire la même chose. Je pense que les balises sont les plus importants pour les demandes de recherche, et que leur catégorisation but vient qu'en second.
Si quoi que ce soit souvent décrit à l'aide de C comme synonyme de bas niveau et natif a été marqué C, qui serait d'anéantir le C de la balise avec à peu près tout avoir à faire avec les indigènes de l'interopérabilité. Très mauvaise idée.
OriginalL'auteur zneak | 2014-12-13
Vous devez vous connecter pour publier un commentaire.
Le C tableau
char name[8]
est importé de Swift comme un n-uplet:L'adresse de
name
est la même que l'adresse dename[0]
, etSwift conserve la disposition de la mémoire de structures importées à partir de C, comme
confirmée par Apple ingénieur Joe Groff:
En conséquence, nous pouvons nous passer l'adresse de
record.name
,converti en
UInt8
pointeur, àla Chaîne de l'initialiseur:
REMARQUE: Il est supposé que les octets dans
name[]
sont valides NUL de terminaison UTF-8 séquence.record
besoins pour être mutables (déclarée avecvar
) ou la Swift compilateur tire une erreur bizarre.Vous avez raison, j'ai ajouté cette information pour la réponse.
Je crois que cela va fonctionner, mais est-il documenté que les tuples sont contigus en mémoire? Avec les tableaux, il n'y a pas d'assurance, à moins que vous appelez
withUnsafeBufferPointer
, mais tuple de la mise en œuvre n'a pas été documenté autant que je peux dire.C'est une bonne question. Il semble plausible pour moi parce que le n-uplet est (dans ce cas particulier) le point de vue de Swift d'un C tableau
char name[8]
.En fait c' est de la garantie si la structure est importé de C. j'ai mis à jour la réponse en conséquence, avec une référence et a simplifié le code.
OriginalL'auteur Martin R
Vous pouvez réellement recueillir un tuple dans un tableau en utilisant Swift variadic la syntaxe de paramètre:
Ce concept est
let (int8s: Int8...)
? Estlet (name : type) = exp
généralement la même quelet name : type = expr
?Dans ce cas, vous auriez besoin de le faire à la volée, car avec une fonction, vous aurez à taper le bon nombre d'éléments pour correspondre à chaque tuple arité. J'ai modifié ma réponse à montrer ce que vous pouvez faire.
Le nom est n-uplet de décomposition. Vous pouvez tirer les choses de manière intéressante à l'aide de cette technique, essayez:
let (_, second, _, fourth, theRest: Int...) = (1, 2, 3, 4, 5, 6, 7, 8, 9, 10)
Comme de Swift 2 dans Xcode 7b1 bêta, cela ne fonctionne plus.
OriginalL'auteur Nate Cook
Je suis intéressé à travailler pour mes propres fins, j'ai donc ajouté une nouvelle fonction:
J'appelle cette fonction avec:
le résultat est:
testSwiftString = test
OriginalL'auteur jwlaughton
Swift 3. Seulement utilise la réflexion. Cette version arrête la création de la chaîne quand elle rencontre un octet nul. Testés.
OriginalL'auteur rosstulloch
Que je viens de vivre une situation semblable, l'utilisation de Swift 3. (3.0.2). J'étais en train d'essayer de convertir un Tableau de CChar, [CChar] pour une Chaîne de Swift. Il s'avère Swift 3 est une Chaîne d'initialiseur qui prendra une cString.
Exemple:
résultats dans
un = en Option([97, 98, 99, 0])
b = en Option("abc")
Noter que le cString fonction de la Chaîne de résultats dans une Option. Il doit être force déballé quand utilisé dans la Chaîne.la fonction init de la création de b. Et b est également en Option... ce qui veut dire à la fois risque d'être nul, de sorte qu'une vérification d'erreur devrait également être utilisés.
OriginalL'auteur Steve Rogers
Essayez ceci:
UnsafePointer<UInt8>
, c'est un n-uplet de 8Int8
éléments, de sorte que cette méthode ne résout pas mon problème. En outre, laString
classe a uninit?(UTF8String: UnsafePointer<CChar>)
failable initialiseur qui fait cela exactement.Dans mon application j'ai besoin de vous connecter à la version d'OpenGL pour être sûr que le format de pixel a été correctement définie. Je le fais avec laissez glVersionCString:UnsafePointer<UInt8> = glGetString(GLenum(GL_VERSION)). Le compilateur ne me laisse pas jeté le retour de glGetString comme un UnsafePointer<CChar>, donc je ne peux pas utiliser la Swift de la Chaîne d'initialiseur. C'est la raison pour laquelle cette fonction.
Je ne suis pas convaincue de l'utilité de votre fonction dans votre cas d'utilisation spécifiques, mais il ne s'applique pas ici. Cela fonctionne pour vous, parce que
glGetString
retourne un pointeur. Lestruct
je traite avec a une matrice de champ, ce qui est très différent d'un pointeur de champ. Comme je l'ai dit, le type du champ vu par Swift est(Int8, Int8, Int8, Int8, Int8, Int8, Int8, Int8)
, pasUnsafePointer<UInt8>
.OriginalL'auteur jwlaughton
Voici une solution je suis venu avec qui utilise la réflexion pour en fait de convertir le tuple dans une [Int8] (voir De toute façon pour réitérer un tuple dans swift?), puis le convertit en une chaîne à l'aide de fromCString...() méthodes.
OriginalL'auteur joeybladb