2016-04-28 18 views
8

Hãy xem xét các hàm C Cacao riêng tư chưa được sắp xếp tài liệu _NSLogCStringFunction()_NSSetLogCStringFunction(). _NSLogCStringFunction() trả về một con trỏ hàm đến hàm C được sử dụng bởi thời gian chạy Objective-C phía sau hậu trường cho NSLog()_NSSetLogCStringFunction() cho phép các nhà phát triển chỉ định hàm C của riêng họ để ghi nhật ký. Bạn có thể tìm thêm thông tin về cả hai chức năng này trong this Stack Overflow questionthis WebObjects support article.Trình bày các con trỏ hàm chức năng NULL cho hàm C trong Swift

Trong C, tôi có thể vượt qua trong một con trỏ hàm NULL để _NSSetLogCStringFunction():

extern void _NSSetLogCStringFunction(void(*)(const char*, unsigned, BOOL)); 

_NSSetLogCStringFunction(NULL); // valid 

Tuy nhiên, tôi đang chạy vào một số vấn đề khi tôi cố gắng để làm điều này trong tinh khiết 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) ->()') 

Nếu tôi thử bỏ qua cảnh báo thời gian biên dịch này với unsafeBitCast, chương trình của tôi chỉ gặp sự cố với EXC_BAD_INSTRUCTION (như dự kiến, vì chữ ký sai):

let nullPtr: UnsafePointer<Void> = nil 
let nullFuncPtr = unsafeBitCast(nullPtr, NSLogCStringFunc.self) 
_NSSetLogCStringFunction(nullFuncPtr) // crash 

Làm cách nào để biểu thị con trỏ hàm NULL tới (void *) hoặc (void(*)(const char *, unsigned, BOOL))/(UnsafePointer<Int8>, UInt32, Bool) -> Void trong Swift?

+3

lol, downvote ngay lập tức vì lý do gì - chẳng có thậm chí thời gian để đọc toàn bộ câu hỏi. – luk2302

+1

@ luk2302 Đoán tôi có một fan hâm mộ :) Đó là một kỷ lục mới cho tôi, -1 trong 44 giây. – JAL

Trả lời

5

Việc lập bản đồ Swift của (Objective-) khai C

extern void _NSSetLogCStringFunction(void(*)(const char*, unsigned, BOOL)); 

public func _NSSetLogCStringFunction(_: (@convention(c) (UnsafePointer<Int8>, UInt32, ObjCBool) -> Void)!) 

Giải pháp đơn giản nhất sẽ được đưa Objective-C extern khai thành một tiêu đề Objective-C và bao gồm từ tiêu đề bắc cầu.

Ngoài ra, trong Swift tinh khiết nó phải được

typealias NSLogCStringFunc = @convention(c) (UnsafePointer<Int8>, UInt32, ObjCBool) -> Void 

@_silgen_name("_NSSetLogCStringFunction") 
func _NSSetLogCStringFunction(_: NSLogCStringFunc!) -> Void 

Trong cả hai trường hợp, các thông số chức năng là một ngầm nào không bắt buộc, và bạn có thể gọi nó với nil. Ví dụ:

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") 

Output:

 
myLogger: foo 
2016-04-28 18:24:05.492 prog[29953:444704] bar 
+0

Ugh, thật sao? Tất cả những gì tôi cần làm là thay đổi 'Bool' thành' ObjCBool'? -_- Có quá nhiều loại Bool trong Swift. Cảm ơn Martin. – JAL

+0

@JAL: Và '@convention (c)' và tham số không được khai báo hoàn toàn. –

+0

Thực ra, tôi không nghĩ rằng 'ObjCBool' là bắt buộc. Có vẻ như tôi đã bỏ lỡ '@convention (C)' và tham số không được khai báo hoàn toàn. Sử dụng 'Bool' với hai cái khác dường như hoạt động. Bạn có thấy điều tương tự không? – JAL

Các vấn đề liên quan