【问题标题】:Implementing a c function callback in Swift 2.0?在 Swift 2.0 中实现一个 c 函数回调?
【发布时间】:2015-07-02 02:22:12
【问题描述】:

CFReadStreamSetClient 的初始化器中有一个 C 函数回调 (CFReadStreamClientCallBack),

CFReadStreamClientCallback 看起来像这样:

typealias CFReadStreamClientCallBack = (CFReadStream!,
        CFStreamEventType, UnsafeMutablePointer<Void>) -> Void

我有一个方法尝试处理CFReadStreamClientCallBack C 函数回调:

func callback(stream: CFReadStreamRef,
        eventType: CFStreamEventType,
        inClientInfo: UnsafeMutablePointer<Void>) {
    }

但是当我尝试如下在CFReadStreamCallback 中设置回调时,它不会编译。

CFReadStreamSetClient(stream, registeredEvents, callback, clientContextPtr)

我知道 Swift 2.0 有一种方法可以将 Swift 闭包与 C-Function 回调一起使用,但我似乎无法让它工作。有谁知道在这种情况下怎么做?

【问题讨论】:

    标签: ios c swift callback swift2


    【解决方案1】:

    你可以像这样创建一个闭包来完成你在函数中所做的事情:

    CFReadStreamSetClient(stream, registeredEvents, { readStream, event, data -> Void in 
        // Do stuff here.
    }, clientContextPtr)
    

    另请注意,C 函数块不能有上下文,因此您无法从块外部访问 self 或任何其他变量。 如果这不起作用,您可以在问题中包含编译器错误吗?

    【讨论】:

    • 这行得通,非常感谢。我想知道你是否也知道如何处理这个? :AURenderCallbackStruct( inputProc: , inputProcRefCon: &amp;selfPtr )
    • 我没有过多地使用 AudioUnit,但我猜你通过使用 unsafeAddressOf(self) 获得了 selfPtr 并且那个位正在工作。除此之外,您还需要这个:AURenderCallbackStruct(inputProc: { inRefCon, ioActionFlags, inTimeStamp, inBusNumber, inNumberFrames, ioData -&gt; OSStatus in // TODO: Stuff that returns an OSStatus }, inputProcRefCon: &amp;selfPtr)
    【解决方案2】:

    斯威夫特 2.0:

    给定一个带有函数指针和上下文的函数:

    void c_func_with_callback(void *context, void (*callback)(void *context))
    

    从 Swift 中调用它很容易,但是无法访问封闭类的变量:

    c_func_with_callback(nil) { context in
        print("Callback in Swift!") // OK
        self.xxx // error
    }
    

    如果需要访问块外的变量,可以使用上下文来存储指向类的指针:

    class MyClass {
        func hello() {
            print("MyClass.hello()")
        }
    
        func classMethodAsCallback() {
            let context = unsafeBitCast(self, UnsafeMutablePointer<Void>.self)
            c_func_with_callback(context) { context in
                let caller = unsafeBitCast(context, MyClass.self)
                caller.hello()
            }
        }
    }
    let myClass = MyClass()
    myClass.classMethodAsCallback()
    

    甚至可以使用 ANY 闭包作为回调:

    class MyClass {
        typealias Closure = ()->()
    
        func anySwiftClosureAsCallback(closure: Closure) {
            var c = closure
            // closure won't fit in a pointer, so take it's address first
            let context = withUnsafePointer(&c) {
                    //(ptr: UnsafePointer<Closure>) -> UnsafeMutablePointer<Void> in
                    ptr in
                return unsafeBitCast(ptr, UnsafeMutablePointer<Void>.self)
            }
            c_func_with_callback(context) { context in
                let ptr = unsafeBitCast(context, UnsafePointer<Closure>.self)
                let closure = ptr.memory // dereference the address
                closure()
            }
        }
    }
    let myClass = MyClass()
    myClass.anySwiftClosureAsCallback {
        print("Swift closure called")
    }
    

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2016-04-10
      • 1970-01-01
      相关资源
      最近更新 更多