混合 Swift 和 C:如何以最简单的方式将 C 函数声明为 Swift 函数中的参数

Mixing Swift and C: how to declare C-function as a parameter in Swift function the easiest way

使用 Swift 5(甚至可能更早),我可以毫不费力地从 Swift 轻松调用 C 函数:

// C function:
    error_t cFunction(uint8_t * const outputBuffer, uint8_t const outputBufferMaxSize, uint8_t * const outputBufferUsedBytes);

// called from Swift:
        let outputBufferMaxSize: UInt8 = 10
        var outputBuffer = [UInt8](repeating: 0, count: Int(outputBufferMaxSize))
        var outputBufferUsedBytes: UInt8 = 0 

        let err = cFunction(&outputBuffer, outputBufferMaxSize, &outputBufferUsedBytes);

桥接完全自动进行。

现在我想将 cFunction 传递给另一个 Swift-func(就像 C 中的函数指针)。这似乎只有在我手动执行翻译时才有效:

// Swift function with C-style function as parameter
    func callcFunction(_ cFunctionAsParameter:(UnsafeMutablePointer<UInt8>?, UInt8, UnsafeMutablePointer<UInt8>?)->error_t) {
                let outputBufferMaxSize: UInt8 = 10
                var outputBuffer = [UInt8](repeating: 0, count: Int(outputBufferMaxSize))
                var outputBufferUsedBytes: UInt8 = 0 

                let err = cFunctionAsParameter(&outputBuffer, outputBufferMaxSize, &outputBufferUsedBytes);

        }

    callcFunction(cFunction)

这可行,但我必须手动找出 UnsafeMutablePointer 逻辑。事实上,如果您只是简单地在 callcFunction 声明中放入垃圾,编译器会吐出一条错误消息,告诉您完全正确的语法。

那么有没有办法避免手动做这个声明呢? 比如,使用原始 C 风格声明它

error_t (* cFunctionAsParameter) (uint8_t * const, uint8_t const, uint8_t * const) 

(上面的内容应该以某种方式进入 Swift 函数声明的参数列表)并让编译器自己找出 UnsafeMutablePointer 的东西,就像第一个例子中那样?

扩展问题:

让事情变得更复杂,假设有几个 C 函数在附加的单个参数(第一个)的类型上有所不同:

error_t cFunctionFloat(float value, uint8_t * const outputBuffer, uint8_t const outputBufferMaxSize, uint8_t * const outputBufferUsedBytes);
error_t cFunctionInt(int value, uint8_t * const outputBuffer, uint8_t const outputBufferMaxSize, uint8_t * const outputBufferUsedBytes);

可以在 Swift 中使用以下单个声明:

func callcFunction<T>(_ cFunctionAsParameter:(T, UnsafeMutablePointer<UInt8>?, UInt8, UnsafeMutablePointer<UInt8>?)->error_t){ ... }

同样,让编译器自动推断 "translation" 会很好。

我不知道一个纯粹的 Swift 解决方案。在单个函数的情况下,您可以在 C 头文件中定义类型别名

typedef typeof(cFunction) cFunctionType; 

以便 Swift 函数声明简化为

func callcFunction(_ cFunctionAsParameter: cFunctionType) { ... }