Используя Swift 5 (и, возможно, даже раньше), я могу легко вызывать функции C из Swift без особых сложностей:
// 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-logic вручную. Фактически, если вы просто поместите мусор в объявление 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){ ... }
Опять же, было бы неплохо, чтобы компилятор автоматически выводил "перевод".