Considérez les fonctions Cocoa C privées et encore documentées _NSLogCSsortingngFunction()
et _NSSetLogCSsortingngFunction()
. _NSLogCSsortingngFunction()
renvoie un pointeur de fonction sur la fonction C utilisée par l’arrière-plan Objective-C pour NSLog()
, et _NSSetLogCSsortingngFunction()
permet aux développeurs de spécifier leur propre fonction C pour la journalisation. Vous trouverez plus d’informations sur ces deux fonctions dans cette question relative au dépassement de capacité et à cet article de support WebObjects .
En C, je peux passer un pointeur de fonction NULL sur _NSSetLogCSsortingngFunction()
:
extern void _NSSetLogCSsortingngFunction(void(*)(const char*, unsigned, BOOL)); _NSSetLogCSsortingngFunction(NULL); // valid
Cependant, je rencontre des problèmes lorsque j’essaie de faire cela dans Swift pur:
/// Represents the C function signature used under-the-hood by NSLog typealias NSLogCSsortingngFunc = (UnsafePointer, UInt32, Bool) -> Void /// Sets the C function used by NSLog @_silgen_name("_NSSetLogCSsortingngFunction") func _NSSetLogCSsortingngFunction(_: NSLogCSsortingngFunc) -> Void _NSSetLogCSsortingngFunction(nil) // Error: nil is not compatible with expected argument type 'NSLogCSsortingngFunc' (aka '(UnsafePointer, UInt32, Bool) -> ()')
Si j’essaie de contourner cet avertissement lors de la unsafeBitCast
avec unsafeBitCast
, mon programme se bloque juste avec EXC_BAD_INSTRUCTION
(comme prévu, car la signature est fausse):
let nullPtr: UnsafePointer = nil let nullFuncPtr = unsafeBitCast(nullPtr, NSLogCSsortingngFunc.self) _NSSetLogCSsortingngFunction(nullFuncPtr) // crash
Comment représenter un pointeur de fonction NULL
sur (void *)
ou (void(*)(const char *, unsigned, BOOL))
/ (UnsafePointer, UInt32, Bool) -> Void
in Swift?
Cartographie Swift de la déclaration (Objective-) C
extern void _NSSetLogCSsortingngFunction(void(*)(const char*, unsigned, BOOL));
est
public func _NSSetLogCSsortingngFunction(_: (@convention(c) (UnsafePointer, UInt32, ObjCBool) -> Void)!)
La solution la plus simple serait de placer la déclaration extern
Objective-C dans un fichier d’en-tête Objective-C et de l’inclure à partir de l’en-tête de pontage.
Alternativement, en pur Swift, il devrait être
typealias NSLogCSsortingngFunc = @convention(c) (UnsafePointer, UInt32, ObjCBool) -> Void @_silgen_name("_NSSetLogCSsortingngFunction") func _NSSetLogCSsortingngFunction(_: NSLogCSsortingngFunc!) -> Void
Dans les deux cas, le paramètre de fonction est une option implicitement non enveloppée que vous pouvez appeler avec nil
. Exemple:
func myLogger(message: UnsafePointer, _ length: UInt32, _ withSysLogBanner: ObjCBool) -> Void { print(Ssortingng(format:"myLogger: %s", message)) } _NSSetLogCSsortingngFunction(myLogger) // Set NSLog hook. NSLog("foo") _NSSetLogCSsortingngFunction(nil) // Reset to default. NSLog("bar")
Sortie:
myLogger: foo 2016-04-27 18: 24: 05.492 prog [29953: 444704] bar