Swift 如何将CFunctionPointer转换为EventHandlerUPP?
我有一个名为Foo_C_Func的C函数,需要将其用作回调函数。应用程序的其余部分用Swift编码。据我所知,下面的代码应该可以工作,但是我得到了一个编译器错误Swift 如何将CFunctionPointer转换为EventHandlerUPP?,swift,callback,event-handling,Swift,Callback,Event Handling,我有一个名为Foo_C_Func的C函数,需要将其用作回调函数。应用程序的其余部分用Swift编码。据我所知,下面的代码应该可以工作,但是我得到了一个编译器错误 // typealias makes our function signature easier to read typealias Sig = ( EventHandlerCallRef, EventRef, UnsafeMutablePointer<Void>) -> OSStatus // We need
// typealias makes our function signature easier to read
typealias Sig = ( EventHandlerCallRef, EventRef, UnsafeMutablePointer<Void>) -> OSStatus
// We need to make a CFunctionPointer to the C function
var ptr = UnsafeMutablePointer<Sig>.alloc(1)
ptr.initialize( Foo_C_Func )
let c_ptr = COpaquePointer( ptr )
let proc_ptr = CFunctionPointer<Sig>( c_ptr ) as EventHandlerProcPtr
// now we should be able to create the EventHandlerUPP
let handler_upp = NewEventHandlerUPP( proc_ptr )
//typealias使函数签名更易于阅读
typealias Sig=(EventHandlerCallRef、EventRef、UnsafeMutablePointer)->OSStatus
//我们需要制作一个指向C函数的CFunctionPointer
var ptr=unsafemeutablepointer.alloc(1)
ptr.initialize(Foo_C_Func)
设c_ptr=COpaquePointer(ptr)
让proc_ptr=CFunctionPointer(c_ptr)作为EventHandlerProcPtr
//现在我们应该能够创建EventHandlerUPP了
let handler\u upp=NewEventHandlerUPP(proc\u ptr)
尝试生成此文件失败,出现以下错误:
架构x86_64的未定义符号:
“_Foo_C_Func”,引用自:
__演示中的TTOFSC10Foo_C_函数ftvss14opaquepointers_gvss20unsafemtablepointert____VSs5Int32
“\u NewEventHandlerUPP”,引用自:
__演示中的TFC17DemocfMS0_FT_S0_u
ld:找不到架构x86_64的符号
我还注意到,当我将鼠标悬停在最后一行时,Xcode工具提示将NewEventHandlerUpp的返回类型显示为(EventHandlerProcPtr),而不是EventHandlerProcPtr
我是做错了,还是无法在Swift中创建一个EventHandlerUPP?我为用户MAH发布这篇文章,尽管我已经放弃了原来的项目。以下代码在Swift 3中编译。除此之外,我还没有检查它是否有效
import Carbon
func hotkey_callback( _:EventHandlerCallRef?, _ event:EventRef?, _ context:UnsafeMutablePointer<Void>? ) -> OSStatus {
// Do stuff
return noErr
}
let handler_ref_ptr = UnsafeMutablePointer<EventHandlerRef?>( allocatingCapacity: 1 )
let spec_ptr = UnsafeMutablePointer<EventTypeSpec>( allocatingCapacity: 1 )
spec_ptr.pointee = EventTypeSpec( eventClass: OSType( kEventClassKeyboard ), eventKind: UInt32( kEventHotKeyPressed ) )
let hotkey_callback_pointer = hotkey_callback as! EventHandlerUPP
let status = InstallEventHandler( GetEventDispatcherTarget(), hotkey_callback_pointer, 1, spec_ptr, nil, handler_ref_ptr )
进口碳
func热键\回调(\ uU:EventHandlerCallRef?,\ uEvent:EventRef?,\ uContext:UnsafeMutablePointer?)->OSStatus{
//做事
返回noErr
}
let handler_ref_ptr=UnsafeMutablePointer(分配容量:1)
let spec_ptr=UnsafeMutablePointer(分配容量:1)
spec_ptr.pointee=EventTypeSpec(eventClass:OSType(kEventClassKeyboard),eventKind:UInt32(KeventThotKeypressed))
让热键回调指针=热键回调为!EventHandlerUPP
让status=InstallEventHandler(GetEventDispatcherTarget(),热键回调指针,1,规范ptr,nil,处理程序ref\ptr)
如果您使用的是Swift 3,这里有一个备选答案。Swift 2与Swift 3不同,前者很糟糕,而后者可用
let hotkey_callback: EventHandlerUPP = { _, _, _ in
// Do stuff
return noErr
}
var handler: EventHandlerRef? = nil
var spec = EventTypeSpec(
eventClass: OSType(kEventClassKeyboard), eventKind: UInt32(kEventHotKeyPressed)
)
let status = InstallEventHandler(
GetEventDispatcherTarget(), hotkey_callback, 1, &spec, nil, &handler
)
请注意,我们现在可以使用“&”来避免手动分配指针,并注意遵守非正式的“EventHandlerUPP”协议现在是显式的,不需要手动声明每个参数的类型。阅读起来容易多了:)到目前为止,我还无法在Swift 3中找到解决方法。向苹果发送了一份关于它的错误报告,因为它也缺少文档。我很确定这些天(Swift 2和更高版本)你可以直接使用该函数(在你的C头文件中声明为“extern”,如果Swift抱怨该类型,则使用“as?EventHandlerUPP”)。此外,你真的想用C而不是Swift来实现这一点吗?我相信在我最初的Xcode项目中,一旦Swift 2发布,我就重构了不存在的C文件。如果我没记错的话,现在可以使用Swift函数来创建这样的指针。我在2.0中通过Swift轻松地实现了这一点,但Swift 3似乎改变了一切。我不能使用
作为?EventHandlerUPP
@MAH,我得到了一个旧文件,在那里我可以毫不费力地编译它,但我还没有测试它。虽然这个文件确实可以编译,但不幸的是它在上的EXC\u BAD\u指令
使热键回调指针=热键回调为!EventHandlerUPP
我隐约记得我的原始版本中存在一些访问问题。您正在使用的功能是全局的还是“公共的”?谢谢您的帮助。是的。此问题仅限于Swift 3。我想这可能是苹果的一个缺陷。但是将公共函数强制转换为EventHandlerUPP似乎不起作用。是的,可能是个bug。作为一种解决方法,使用“让热键回调指针=unsafeBitCast(热键回调,EventHandlerUPP.self)”有效吗?刚刚尝试过,看起来是相同的崩溃。非常令人沮丧。看起来这样行得通。我认为这是一个苹果不断改变哪些值是可选的,哪些值不是的问题。现在我想它的设置是Swift3。谢谢