swift @objc и селектор: ошибка компилятора с типом, возвращаемым из селектора - PullRequest
0 голосов
/ 31 октября 2019

в MacOS 10.14.6, Swift и XCode 11.0, VLCKit 3.3.0, я пытаюсь создать обратные вызовы с функциями @objc внутри класса. Но используя #selector для указания на мой @objc func, компилятор генерирует ошибку

. Это две функции, которые я объявляю в своем классе

class VLCStreamProcessor {
// ...

@objc func lock_frame(
    opaque: UnsafeMutableRawPointer? ,
    planes: UnsafeMutablePointer<UnsafeMutableRawPointer?>?)
    -> UnsafeMutableRawPointer? 
{ // ...
    return UnsafeMutableRawPointer(user_data.pic)
}

@objc func unlock_frame(
    opaque: UnsafeMutableRawPointer?,
    picture: UnsafeMutableRawPointer?,
    planes: UnsafePointer<UnsafeMutableRawPointer?>?)
{ // ...
}

, затем в другой функции (myVLCProcessing)все еще в том же классе я готовлю свои обратные вызовы

func myVLCProcessing() 
{ // ...

  libvlc_video_set_callbacks( 
    mplayerPtr, // type libvlc_media_player_t*
    #selector( lock_frame(opaque:planes:) ), // type libvlc_video_lock_cb <- 1st error
    #selector( unlock_frame(opaque:picture:planes: )), // type libvlc_video_unlock_cb <- 2nd error
    0,  // type libvlc_video_display_cb
    opaque // type void*
    ) 

  // ...
}

там я получаю ошибку компилятора, в 2 строках с #selector: first:

Cannot convert value of type 'Selector' to expected argument type 'libvlc_video_lock_cb?' (aka 'Optional<@convention(c)(Optional<UnsafeMutableRawPointer>, Optional<UnsafeMutablePointer<Optional<UnsafeMutableRawPointer>>>) -> Optional<UnsafeMutableRawPointer>>')

second:

Cannot convert value of type 'Selector' to specified type 'libvlc_video_unlock_cb' (aka '@convention(c) (Optional<UnsafeMutableRawPointer>, Optional<UnsafeMutableRawPointer>, Optional<UnsafePointer<Optional<UnsafeMutableRawPointer>>>) -> ()')

из libvlc (libvlc_media_player.h) ожидается, что 2 C-функции будут:

typedef void *(*libvlc_video_lock_cb)(void *opaque, void **planes);

typedef void (*libvlc_video_unlock_cb)(void *opaque, void *picture,
                                   void *const *planes);

любой совет приветствуется.

Ответы [ 2 ]

1 голос
/ 01 ноября 2019

Только глобальные функции или замыкания (которые не захватывают контекст) могут быть переданы в функцию C для аргументов обратного вызова. Как и в Как использовать метод экземпляра в качестве обратного вызова для функции, которая принимает только закрытие функции или литерала , вы можете «туннелировать» self (указатель на экземпляр) к функциям обратного вызова, преобразовав его в void указатель и обратно. Функция обратного вызова может затем вызвать метод экземпляра:

class VLCStreamProcessor {
    func lock_frame(
        planes: UnsafeMutablePointer<UnsafeMutableRawPointer?>?)
        -> UnsafeMutableRawPointer?
    { // ...
    }

    func unlock_frame(
        picture: UnsafeMutableRawPointer?,
        planes: UnsafePointer<UnsafeMutableRawPointer?>?)
    { // ...
    }

    func myVLCProcessing()  {
        // ...

        let opaque = UnsafeMutableRawPointer(Unmanaged.passUnretained(self).toOpaque())
        libvlc_video_set_callbacks(mplayerPtr, { (opaque, planes) -> UnsafeMutableRawPointer? in
            let mySelf = Unmanaged<VLCStreamProcessor>.fromOpaque(opaque!).takeUnretainedValue()
            return mySelf.lock_frame(planes: planes)
        }, { (opaque, picture, planes) in
            let mySelf = Unmanaged<VLCStreamProcessor>.fromOpaque(opaque!).takeUnretainedValue()
            mySelf.unlock_frame(picture: picture, planes: planes)
        }, nil, opaque)

    }
}

Здесь предполагается, что VLCStreamProcessor существует до тех пор, пока установлены обратные вызовы libvlc, в противном случае указатели должны быть сохранены.

0 голосов
/ 01 ноября 2019

Селектор не совпадает с C-функцией. Вместо этого вам нужно указать замыкание или указатель на функцию.

Просто попробуйте удалить #selector () вокруг функций, которые вы предоставляете.

...