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