在 Swift 中表示指向 C 函数的 NULL 函数指针
Representing NULL Function Pointers to C Functions in Swift
考虑私有但文档化的 Cocoa C 函数 _NSLogCStringFunction()
和 _NSSetLogCStringFunction()
。 _NSLogCStringFunction()
returns NSLog()
Objective-C 运行时在幕后使用的 C 函数的函数指针,_NSSetLogCStringFunction()
允许开发人员指定他们自己的用于记录的 C 函数。有关这两个函数的更多信息,请参见 this Stack Overflow question and this WebObjects support article.
在 C 中,我可以将 NULL 函数指针传递给 _NSSetLogCStringFunction()
:
extern void _NSSetLogCStringFunction(void(*)(const char*, unsigned, BOOL));
_NSSetLogCStringFunction(NULL); // valid
但是,当我尝试在纯 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) -> ()')
如果我尝试使用 unsafeBitCast
绕过此编译时警告,我的程序将崩溃并显示 EXC_BAD_INSTRUCTION
(正如预期的那样,因为签名错误):
let nullPtr: UnsafePointer<Void> = nil
let nullFuncPtr = unsafeBitCast(nullPtr, NSLogCStringFunc.self)
_NSSetLogCStringFunction(nullFuncPtr) // crash
如何在 Swift 中表示指向 (void *)
或 (void(*)(const char *, unsigned, BOOL))
/(UnsafePointer<Int8>, UInt32, Bool) -> Void
的 NULL
函数指针?
(Objective-)C声明的Swift映射
extern void _NSSetLogCStringFunction(void(*)(const char*, unsigned, BOOL));
是
public func _NSSetLogCStringFunction(_: (@convention(c) (UnsafePointer<Int8>, UInt32, ObjCBool) -> Void)!)
最简单的解决方案是将 Objective-C extern
声明到 Objective-C 头文件中并包含它
来自桥接头。
或者,在纯 Swift 中应该是
typealias NSLogCStringFunc = @convention(c) (UnsafePointer<Int8>, UInt32, ObjCBool) -> Void
@_silgen_name("_NSSetLogCStringFunction")
func _NSSetLogCStringFunction(_: NSLogCStringFunc!) -> Void
在任何一种情况下,函数参数都是隐式解包的可选参数,
你可以用 nil
调用它。示例:
func myLogger(message: UnsafePointer<Int8>, _ length: UInt32, _ withSysLogBanner: ObjCBool) -> Void {
print(String(format:"myLogger: %s", message))
}
_NSSetLogCStringFunction(myLogger) // Set NSLog hook.
NSLog("foo")
_NSSetLogCStringFunction(nil) // Reset to default.
NSLog("bar")
输出:
myLogger: foo
2016-04-28 18:24:05.492 prog[29953:444704] bar
考虑私有但文档化的 Cocoa C 函数 _NSLogCStringFunction()
和 _NSSetLogCStringFunction()
。 _NSLogCStringFunction()
returns NSLog()
Objective-C 运行时在幕后使用的 C 函数的函数指针,_NSSetLogCStringFunction()
允许开发人员指定他们自己的用于记录的 C 函数。有关这两个函数的更多信息,请参见 this Stack Overflow question and this WebObjects support article.
在 C 中,我可以将 NULL 函数指针传递给 _NSSetLogCStringFunction()
:
extern void _NSSetLogCStringFunction(void(*)(const char*, unsigned, BOOL));
_NSSetLogCStringFunction(NULL); // valid
但是,当我尝试在纯 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) -> ()')
如果我尝试使用 unsafeBitCast
绕过此编译时警告,我的程序将崩溃并显示 EXC_BAD_INSTRUCTION
(正如预期的那样,因为签名错误):
let nullPtr: UnsafePointer<Void> = nil
let nullFuncPtr = unsafeBitCast(nullPtr, NSLogCStringFunc.self)
_NSSetLogCStringFunction(nullFuncPtr) // crash
如何在 Swift 中表示指向 (void *)
或 (void(*)(const char *, unsigned, BOOL))
/(UnsafePointer<Int8>, UInt32, Bool) -> Void
的 NULL
函数指针?
(Objective-)C声明的Swift映射
extern void _NSSetLogCStringFunction(void(*)(const char*, unsigned, BOOL));
是
public func _NSSetLogCStringFunction(_: (@convention(c) (UnsafePointer<Int8>, UInt32, ObjCBool) -> Void)!)
最简单的解决方案是将 Objective-C extern
声明到 Objective-C 头文件中并包含它
来自桥接头。
或者,在纯 Swift 中应该是
typealias NSLogCStringFunc = @convention(c) (UnsafePointer<Int8>, UInt32, ObjCBool) -> Void
@_silgen_name("_NSSetLogCStringFunction")
func _NSSetLogCStringFunction(_: NSLogCStringFunc!) -> Void
在任何一种情况下,函数参数都是隐式解包的可选参数,
你可以用 nil
调用它。示例:
func myLogger(message: UnsafePointer<Int8>, _ length: UInt32, _ withSysLogBanner: ObjCBool) -> Void {
print(String(format:"myLogger: %s", message))
}
_NSSetLogCStringFunction(myLogger) // Set NSLog hook.
NSLog("foo")
_NSSetLogCStringFunction(nil) // Reset to default.
NSLog("bar")
输出:
myLogger: foo 2016-04-28 18:24:05.492 prog[29953:444704] bar