Consider the private-yet-sort-of-documented Cocoa C functions _NSLogCStringFunction()
and _NSSetLogCStringFunction()
. _NSLogCStringFunction()
returns a function pointer to the C function used by the Objective-C runtime behind-the-scenes for NSLog()
, and _NSSetLogCStringFunction()
allows developers to specify their own C function for logging. More information on both of these functions can be found in this Stack Overflow question and this WebObjects support article.
In C, I can pass in a NULL function pointer to _NSSetLogCStringFunction()
:
extern void _NSSetLogCStringFunction(void(*)(const char*, unsigned, BOOL));
_NSSetLogCStringFunction(NULL); // valid
However, I'm running into some issues when I try to do this in pure Swift:
/// Represents the C function signature used under-the-hood by NSLog
typealias NSLogCStringFunc = (UnsafePointer<Int8>, UInt32, Bool) -> Void
/// Sets the C function used by NSLog
@_silgen_name("_NSSetLogCStringFunction")
func _NSSetLogCStringFunction(_: NSLogCStringFunc) -> Void
_NSSetLogCStringFunction(nil) // Error: nil is not compatible with expected argument type 'NSLogCStringFunc' (aka '(UnsafePointer<Int8>, UInt32, Bool) -> ()')
If I try bypass this compile-time warning with unsafeBitCast
, my program just crashes with EXC_BAD_INSTRUCTION
(as expected, since the signature is wrong):
let nullPtr: UnsafePointer<Void> = nil
let nullFuncPtr = unsafeBitCast(nullPtr, NSLogCStringFunc.self)
_NSSetLogCStringFunction(nullFuncPtr) // crash
How do I represent a NULL
function pointer to (void *)
or (void(*)(const char *, unsigned, BOOL))
/(UnsafePointer<Int8>, UInt32, Bool) -> Void
in Swift?
The Swift mapping of the (Objective-)C declaration
is
The easiest solution would be to put the Objective-C
extern
declaration into an Objective-C header file and include that from the bridging header.Alternatively, in pure Swift it should be
In either case, the function parameter is an implicitly unwrapped optional, and you can call it with
nil
. Example:Output: