swift @objc 和选择器:从选择器返回类型的编译器错误
swift @objc and selector : compiler error with type returned from selector
在 MacOS 10.14.6、Swift 和 XCode 11.0、VLCKit 3.3.0 上,
我尝试在 class 中使用 @objc 函数创建回调。
但是使用#selector 指向我的@objc func,编译器产生错误
这些是我在 class
中声明的 2 个函数
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) 中,仍然在同一个 class 中,我准备回调
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*
)
// ...
}
我在带有 #selector 的两行中收到编译器错误:
第一:
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>>')
第二个:
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);
欢迎任何建议。
选择器与 C 函数不同。您需要提供闭包或函数指针。
只需尝试删除您提供的函数周围的#selector()。
只能将全局函数或闭包(不捕获上下文)传递给回调参数的 C 函数。与 How to use instance method as callback for function which takes only func or literal closure 类似,您可以通过将回调函数 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回调就存在,否则必须保留指针。
在 MacOS 10.14.6、Swift 和 XCode 11.0、VLCKit 3.3.0 上, 我尝试在 class 中使用 @objc 函数创建回调。 但是使用#selector 指向我的@objc func,编译器产生错误
这些是我在 class
中声明的 2 个函数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) 中,仍然在同一个 class 中,我准备回调
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*
)
// ...
}
我在带有 #selector 的两行中收到编译器错误: 第一:
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>>')
第二个:
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);
欢迎任何建议。
选择器与 C 函数不同。您需要提供闭包或函数指针。
只需尝试删除您提供的函数周围的#selector()。
只能将全局函数或闭包(不捕获上下文)传递给回调参数的 C 函数。与 How to use instance method as callback for function which takes only func or literal closure 类似,您可以通过将回调函数 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回调就存在,否则必须保留指针。