2015-06-09 3 views
28

Dopo la migrazione a Swift 2, ricevo questo problema con un errore che indica che ora dovrei usare @convention (c) (T) -> U. Ho provato le permutazioni ma finora non ho avuto fortuna.Nuovo @convention (c) in Swift 2: Come posso usarlo?

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

} 

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

Penso che dovrebbe essere possibile evitare completamente il non sicuro BitCast. Potete fornire ulteriori informazioni? Come viene dichiarata la funzione C, cosa viene passato come oggetto contesto, ...? –

+0

Ciò può anche essere utile per passare i puntatori agli oggetti tramite callback C: http://stackoverflow.com/questions/30786883/swift-2-unsafemutablepointervoid-to-object. –

+0

'CGFloat' non è uguale a' Float'. Sulle piattaforme a 64 bit _ (vale a dire ogni dispositivo Apple negli ultimi anni) _ è un 'Double' e su piattaforme a 32 bit è un' Float'. Comunque, in Objective-C 'CGFloat' è solo un semplice' C 'typedef', quindi dovresti semplicemente usare' CGFloat' qui. –

risposta

17

Non è più necessario creare un CFunctionPointer a Swift 2. Invece, è possibile annotare il tipo da convenzione di chiamata, in questo caso c, e usarlo direttamente.

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

I bit rilevanti della descrizione @convention nella Tipo Attributi sezione The Swift Programming Language sono:

L'argomento c viene utilizzato per indicare un riferimento funzione C. Il valore della funzione non ha contesto e utilizza la convenzione di chiamata C.

+3

Grazie. Allo stesso tempo, ho avuto modo di lavorare con let = foo come @convention (c) (AnyObject ?, CGFloat) -> Int – Laurent

+2

Er, @convention (c) (UnsafeMutablePointer ?, CGFloat) -> Int perché AnyObject? non è convertibile a quanto pare. Ho dovuto unsafebitcast anche nella mia firma del metodo chiamata. – Laurent

+0

Cosa significa .self quando viene chiamato direttamente da un tipo come CFunction.self? –

18

Passando una chiusura Swift a una funzione C prendendo un parametro funzione pointer è ora supportata in Swift 2, e, come notato, funzione vengono specificati con l'attributo @convention(c).

Se si passa una chiusura direttamente come argomento alla funzione C, allora questo attributo viene dedotto automaticamente da .

Come semplice esempio, se si dispone di questa funzione C

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

allora si può chiamare da Swift come

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

che fa esattamente lo stesso del più prolisso

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

let result = myCFunction(swiftCallback) 
print(result) // 3.3 
+0

Come fare con il char array? –