web-dev-qa-db-fra.com

Nouveau @convention (c) dans Swift 2: Comment puis-je l'utiliser?

Après la migration vers Swift 2, je reçois ce problème avec une erreur indiquant que je devrais maintenant utiliser @convention (c) (T) -> U. J'ai essayé les permutations mais jusqu'à présent non la chance.

func foo(context: AnyObject?, width: CGFloat) -> Int {

}

let bar = unsafeBitCast(foo, CFunctionPointer<(UnsafeMutablePointer<Void>, Float) -> Int>.self)
31
Laurent

Vous n'avez plus besoin de créer un CFunctionPointer dans Swift 2. Au lieu de cela, vous pouvez annoter votre type en appelant la convention, dans ce cas c, et l'utiliser directement.

typealias CFunction = @convention(c) (UnsafeMutablePointer<Void>, Float) -> Int
let bar = unsafeBitCast(foo, CFunction.self)

Les bits pertinents du @convention description dans la section Attributs de type de Le Swift sont:

L'argument c est utilisé pour indiquer une référence de fonction C. La valeur de la fonction ne porte aucun contexte et utilise la convention d'appel C.

19
Mick MacCallum

Passer un Swift fermeture à une fonction C en prenant un paramètre de pointeur de fonction est maintenant pris en charge dans Swift 2, et, comme vous l'avez remarqué, les types de fonctions sont spécifiés avec le @convention(c) attribut.

Si vous passez directement une fermeture comme argument à la fonction C, cet attribut est automatiquement déduit.

Comme exemple simple, si vous avez cette fonction C

CGFloat myCFunction(CGFloat (callback)(CGFloat x, CGFloat y)) {
    return callback(1.1, 2.2);
}

alors vous pouvez l'appeler depuis Swift as

let result = myCFunction( {
    (x, y) -> CGFloat in
    return x + y
} )
print(result) // 3.3

qui fait exactement la même chose que le plus verbeux

let swiftCallback : @convention(c) (CGFloat, CGFloat) -> CGFloat = {
    (x, y) -> CGFloat in
    return x + y
} 

let result = myCFunction( swiftCallback )
print(result) // 3.3
25
Martin R