【问题标题】:Mixing Swift and C: how to declare C-function as a parameter in Swift function the easiest way混合 Swift 和 C:如何以最简单的方式在 Swift 函数中将 C 函数声明为参数
【发布时间】:2019-06-26 06:57:35
【问题描述】:

使用 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){ ... }

同样,最好让编译器自动推断“翻译”。

【问题讨论】:

  • 你想简化什么? Swift 函数声明的(UnsafeMutablePointer&lt;UInt8&gt;?, UInt8, UnsafeMutablePointer&lt;UInt8&gt;?)-&gt;error_t 部分?您希望简化后的代码是什么样的?
  • 我想将它声明为 C 风格。请参阅已编辑的问题。
  • 我认为这在纯 Swift 中是不可能的。但是你可以在C头文件中添加typedef typeof(cFunction) cFunctionType;,然后在Swift中定义func callcFunction(_ cFunctionAsParameter: cFunctionType) { ... }
  • 太棒了!这将是对原始问题的可接受答案。但是我还有一个问题,到目前为止我没有提到:有不止一个 C 函数,除了上面提到的参数之外,它们还有一个参数,其类型不同(float,int,...) .通过显式代码,我可以使用 Swift 的泛型 来处理它。 typedef 显然无法处理这个问题。
  • 我建议用一个具体的例子来更新你的问题。

标签: c swift callback function-pointers


【解决方案1】:

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

typedef typeof(cFunction) cFunctionType; 

以便 Swift 函数声明简化为

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

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2019-01-15
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2021-10-30
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多