2 votes

Quel est l'équivalent en Swift de offsetof(struct, member) en C ?

Voici une structure en Swift :

struct A {
    var x
    var y
    var z
}

Que dois-je faire pour obtenir le décalage de y dans la structure A tout comme offsetof(A, y) en C ?

Merci :)

5voto

rickster Points 19870

Swift ne définit pas actuellement de disposition mémoire standard pour les structures définies en Swift. Cela signifie que tout code que vous écrivez pour décomposer une structure via les mathématiques des pointeurs n'est pas garanti de fonctionner sur les futures versions, ou même sur les mises à jour mineures du compilateur Swift. (Comme le note @robmayoff, cela fait partie de l'obtention par Swift d'une ABI stable, l'un des objectifs du projet Swift pour la version 5 cette année).

Cependant, si votre structure est définie en C et importée via un en-tête de transition, Swift respecte la disposition binaire de sa mémoire en C. Dans ce cas, l'en-tête MemoryLayout fournit des équivalents au type C sizeof opérateur et autres utilitaires similaires. Il n'y a toujours pas offsetof mais vous pouvez faire le calcul du pointeur vous-même en ajoutant l'élément stride des types de membres dans l'ordre de déclaration C.

Par exemple, les documents d'Apple pour SCNGeometrySource avoir un exemple de création d'un objet 3D à partir d'un tampon de données entrelacées de coordonnées de vertex/normales/textures. Mais il est (actuellement) écrit en ObjC, avec l'utilisation de sizeof y strideof pour indiquer à SceneKit où trouver chaque type de données dans le tampon. L'équivalent en Swift utiliserait MemoryLayout<Float>.size à la place de sizeof(float) etc., et au lieu de offsetof(MyVertex, nx) vous devez observer qu'il y a trois flottants dans la structure avant la balise nx et écrire MemoryLayout<Float>.stride * 3 .

2voto

rob mayoff Points 124153

Vous ne pouvez pas obtenir le décalage de y de manière fiable, car Swift ne prend pas encore en charge cette opération. Elle sera éventuellement prise en charge après la mise en œuvre de la " stabilité ABI ".

L'approche actuellement recommandée consiste à définir le struct en C, et définissent également des fonctions C pour retourner les décalages des champs.

2voto

Martin R Points 105727

MemoryLayout.offset(of:) a été ajouté dans Swift 4.2, avec l'implémentation de la fonction

Exemple :

struct A {
    var x: Int8
    var y: Int16
    var z: Int64
}

MemoryLayout.offset(of: \A.x) // 0
MemoryLayout.offset(of: \A.y) // 2
MemoryLayout.offset(of: \A.z) // 8

Remarques : Cela devrait fonctionner également, mais (à partir de Swift 4.2) ne compile pas (bug SR-8335 ) :

MemoryLayout<A>.offset(of: \.y)
// error: Expression type 'Int?' is ambiguous without more context

Prograide.com

Prograide est une communauté de développeurs qui cherche à élargir la connaissance de la programmation au-delà de l'anglais.
Pour cela nous avons les plus grands doutes résolus en français et vous pouvez aussi poser vos propres questions ou résoudre celles des autres.

Powered by:

X