Как обрабатывать функцию обратного вызова c enum в Swift

#c #swift #callback

#c #swift #обратный вызов

Вопрос:

Я хочу установить пользовательскую функцию обратного вызова swift следующим образом

 codecCtx.get_format = negotiatePixelFormat
 

где функция обратного вызова C get_format объявляется следующим образом

 var get_format: (@convention(c) (UnsafeMutablePointer<AVCodecContext>?, UnsafePointer<AVPixelFormat>?) -> AVPixelFormat)!
 

и моя пользовательская функция swift function выглядит так

 private func negotiatePixelFormat(codecContext:AVCodecContext,pixelFormat:AVPixelFormat)->AVPixelFormat{
        while pixelFormat == AV_PIX_FMT_NONE {
            if pixelFormat == AV_PIX_FMT_VIDEOTOOLBOX{
                if codecContext.hwaccel_context == nil{
                    return codecContext.pix_fmt //TBD
                }
            }
            return pixelFormat //TBD
        }
        return AV_PIX_FMT_NONE //TBD
    }
 

Но я понятия не имею, как объединить эти типы функций вместе, ни там, где я могу искать какую-то документацию.


Исходный весь код C выглядит следующим образом

 codecCtx->get_format = negotiatePixelFormat
 

где пользовательская функция обратного вызова такая

 static enum AVPixelFormat negotiate_pixel_format(struct AVCodecContext *s, const enum AVPixelFormat *fmt) {
    while (*fmt != AV_PIX_FMT_NONE) {
        if (*fmt == AV_PIX_FMT_VIDEOTOOLBOX) {  
            if (s->hwaccel_context == NULL) {
                int result = av_videotoolbox_default_init(s);
                if (result < 0) {
                    return s->pix_fmt;
                }
            }
            return *fmt;
        }
          fmt;
    }
    return s->pix_fmt;
}
 

Ответ №1:

Когда вы знаете, что тип обратного вызова импортируется как:

 var get_format: (@convention(c) (UnsafeMutablePointer<AVCodecContext>?, UnsafePointer<AVPixelFormat>?) -> AVPixelFormat)!
 

вам нужно определить функцию, которая принимает (UnsafeMutablePointer<AVCodecContext>?, UnsafePointer<AVPixelFormat>?) и возвращает AVPixelFormat .

Итак, вам может потребоваться объявить функцию Swift, такую как:

 func negotiatePixelFormat(_ s: UnsafeMutablePointer<AVCodecContext>?, _ fmt: UnsafePointer<AVPixelFormat>?) -> AVPixelFormat {
    //...
}
 

Насколько я вижу, ваша функция обратного вызова в C будет выглядеть следующим образом в Swift:

 func negotiatePixelFormat(_ s: UnsafeMutablePointer<AVCodecContext>?, _ fmt: UnsafePointer<AVPixelFormat>?) -> AVPixelFormat {
    guard let s = s, var fmt = fmt else {
        return AV_PIX_FMT_NONE
    }
    while fmt.pointee != AV_PIX_FMT_NONE {
        if fmt.pointee == AV_PIX_FMT_VIDEOTOOLBOX {
            if s.pointee.hwaccel_context == nil {
                let result = av_videotoolbox_default_init(s)
                if result < 0 {
                    return s.pointee.pix_fmt
                }
            }
            return fmt.pointee
        }
        fmt  = 1
    }
    return s.pointee.pix_fmt
}
 

В приведенной вами информации отсутствуют некоторые детали, поэтому вам может потребоваться исправить некоторые части этого кода.

Комментарии:

1. Пока все выглядит хорошо, но теперь я получаю сообщение об ошибке «Указатель на функцию C может быть сформирован только из ссылки на «функцию» или буквальное замыкание» Редактировать: объявил его как глобальную функцию, теперь ошибка устранена.