首页 > 解决方案 > 将 C 回调(无上下文)包装到 Swift 闭包中

问题描述

我正在尝试通过使用 GLFW 的包装器来学习 Swift

GLFW 允许添加错误回调:

GLFWAPI GLFWerrorfun glfwSetErrorCallback(GLFWerrorfun cbfun);

在哪里

typedef void (* GLFWerrorfun)(int,const char*);

我尝试了谷歌搜索,但许多解决方案都提到回调期望代表上下文的最终参数。

不幸的是我在这里没有上下文参数。

似乎应该起作用(尽管 OP 明确要求类似于我的情况,没有上下文参数):

class glfw {
   typealias ErrorFun = (Int, _ description: String) -> Void
   func setErrorCallback(cbFun: ErrorFun) {
        // Void pointer to `self`:
        let observer = UnsafeRawPointer(Unmanaged.passUnretained(self).toOpaque())

        glfwSetErrorCallback { err, desc in

            // Extract pointer to `self` from void pointer:
            let mySelf = Unmanaged<glfw>.fromOpaque(observer).takeUnretainedValue()
            ...
        }
    }
}

但它一直在发射:

错误:不能从捕获上下文的闭包中形成 C 函数指针

一旦我尝试observer在回调中使用,上下文似乎被捕获

我该如何解决?

标签: cswiftcallbackclosuresfunction-pointers

解决方案


通过使用全局变量解决

public struct glfw {
    static func setErrorCallback(cbFun: @escaping ErrorFun) {
        _g.errorCB = cbFun
        glfwSetErrorCallback { err, desc in
            _g.errorCB!(Error(rawValue: err)!, String(utf8String: desc!)!)
        }        
    }
    var errorCB: ErrorFun?
}
var _g = glfw()

推荐阅读