Représenter des fonctions NULL Pointeurs vers des fonctions C dans Swift

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