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