2016-04-28 10 views
8

में सी फंक्शंस के लिए पूर्ण फ़ंक्शन प्वाइंटर्स का प्रतिनिधित्व करना निजी-अभी-तरह के दस्तावेज कोको सी फ़ंक्शन _NSLogCStringFunction() और _NSSetLogCStringFunction() पर विचार करें। _NSLogCStringFunction()NSLog() के लिए ऑब्जेक्टिव-सी रनटाइम के पीछे-दृश्यों द्वारा उपयोग किए गए सी फ़ंक्शन में फ़ंक्शन पॉइंटर लौटाता है, और _NSSetLogCStringFunction() डेवलपर्स को लॉगिंग के लिए अपना स्वयं का फ़ंक्शन निर्दिष्ट करने की अनुमति देता है। इन दोनों कार्यों पर अधिक जानकारी this Stack Overflow question और this WebObjects support article में मिल सकती है।स्विफ्ट

सी में, मैं _NSSetLogCStringFunction() करने के लिए एक शून्य समारोह सूचक में पारित कर सकते हैं:

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

_NSSetLogCStringFunction(NULL); // valid 

हालांकि, मैं कुछ मुद्दों में चल रहा हूँ जब मैं शुद्ध स्विफ्ट में ऐसा करने का प्रयास करें:

/// 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 

मैं (void *) या स्विफ्ट में (void(*)(const char *, unsigned, BOOL))/(UnsafePointer<Int8>, UInt32, Bool) -> Void करने के लिए एक NULL समारोह सूचक कैसे प्रतिनिधित्व करते हैं?

+3

lol, जो भी कारण के लिए तत्काल downvote - वहाँ भी समय पूरे प्रश्न पढ़ने के लिए नहीं था। – luk2302

+1

@ luk2302 मान लीजिए मेरे पास एक प्रशंसक है :) यह मेरे लिए एक नया रिकॉर्ड है, -1 44 सेकंड में। – JAL

उत्तर

5

(Objective-) सी घोषणा

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

की स्विफ्ट मानचित्रण

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

सबसे आसान समाधान एक ऑब्जेक्टिव-सी हैडर में ऑब्जेक्टिव-सी extern घोषणा डाल करने के लिए होगा फ़ाइल और ब्रिजिंग हेडर से शामिल करें।

वैकल्पिक रूप से, शुद्ध स्विफ्ट में यह

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

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

या तो मामले में होना चाहिए, समारोह पैरामीटर, एक परोक्ष unwrapped वैकल्पिक है और आप 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 
+0

उह, वास्तव में? मुझे बस इतना करना था कि 'बूल' को 'ओब्जेकूल' में बदल दिया जाए? -_- स्विफ्ट में बहुत सारे बूल प्रकार हैं। धन्यवाद मार्टिन। – JAL

+0

@JAL: और '@ कन्वेंशन (सी) 'और निहित अनचाहे पैरामीटर। –

+0

असल में, मुझे नहीं लगता कि 'ObjCBool' की आवश्यकता है। ऐसा लगता है कि मैं सिर्फ '@ कन्वेंशन (सी) 'और निहित अनचाहे पैरामीटर खो रहा था। अन्य दो के साथ 'बूल' का उपयोग करना प्रतीत होता है। क्या आप एक ही चीज़ देख रहे हैं? – JAL