Смешивание Swift и C: как проще всего объявить C-функцию как параметр в функции Swift - PullRequest
1 голос
/ 26 июня 2019

Используя 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){ ... }

Опять же, было бы неплохо, чтобы компилятор автоматически выводил "перевод".

1 Ответ

0 голосов
/ 27 июня 2019

Мне неизвестно о чистом решении Swift.В случае отдельной функции вы можете определить псевдоним типа в заголовочном файле C

typedef typeof(cFunction) cFunctionType; 

, чтобы объявление функции Swift упростилось до

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